From 7c2eac2b9dd24c2a50eba53cdd6670bba2f51f8c Mon Sep 17 00:00:00 2001 From: R0GUE Date: Fri, 5 Apr 2024 17:58:06 +0200 Subject: [PATCH 001/161] feat: pallet assets pop api integration --- Cargo.lock | 312 +++++------ .../examples/trust_backed_assets/.gitignore | 9 + .../examples/trust_backed_assets/Cargo.toml | 25 + pop-api/examples/trust_backed_assets/lib.rs | 69 +++ pop-api/src/lib.rs | 6 +- pop-api/src/v0/assets/mod.rs | 1 + pop-api/src/v0/assets/trust_backed.rs | 519 ++++++++++++++++++ pop-api/src/v0/mod.rs | 3 + pop-api/src/v0/nfts.rs | 2 +- primitives/src/lib.rs | 6 +- primitives/src/storage_keys.rs | 7 + runtime/devnet/src/config/assets.rs | 16 +- runtime/devnet/src/extensions.rs | 139 ++++- runtime/devnet/src/lib.rs | 103 ++-- runtime/testnet/src/config/assets.rs | 16 +- runtime/testnet/src/extensions.rs | 150 ++++- runtime/testnet/src/lib.rs | 103 ++-- 17 files changed, 1221 insertions(+), 265 deletions(-) create mode 100755 pop-api/examples/trust_backed_assets/.gitignore create mode 100755 pop-api/examples/trust_backed_assets/Cargo.toml create mode 100755 pop-api/examples/trust_backed_assets/lib.rs create mode 100644 pop-api/src/v0/assets/mod.rs create mode 100644 pop-api/src/v0/assets/trust_backed.rs diff --git a/Cargo.lock b/Cargo.lock index 4dc89da6..e43d2b18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,7 +214,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -578,16 +578,16 @@ checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" dependencies = [ "concurrent-queue", "event-listener 5.2.0", - "event-listener-strategy 0.5.0", + "event-listener-strategy 0.5.1", "futures-core", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] name = "async-executor" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +checksum = "10b3e585719c2358d2660232671ca8ca4ddb4be4ce8a1842d6c2dc8685303316" dependencies = [ "async-lock 3.3.0", "async-task", @@ -676,7 +676,7 @@ checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ "event-listener 4.0.3", "event-listener-strategy 0.4.0", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -768,7 +768,7 @@ checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -781,7 +781,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -899,7 +899,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -1526,9 +1526,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1610,7 +1610,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim 0.11.1", "terminal_size", ] @@ -1623,7 +1623,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -2337,7 +2337,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -2658,7 +2658,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -2698,7 +2698,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -2715,7 +2715,7 @@ checksum = "b404f596046b0bb2d903a9c786b875a126261b52b7c3a64bbb66382c41c771df" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -2763,7 +2763,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -2785,7 +2785,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core 0.20.8", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -2816,9 +2816,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -2869,6 +2869,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -2968,31 +2979,31 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] name = "docify" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc4fd38aaa9fb98ac70794c82a00360d1e165a87fbf96a8a91f9dfc602aaee2" +checksum = "43a2f138ad521dc4a2ced1a4576148a6a610b4c5923933b062a263130a6802ce" dependencies = [ "docify_macros", ] [[package]] name = "docify_macros" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63fa215f3a0d40fb2a221b3aa90d8e1fbb8379785a990cb60d62ac71ebdc6460" +checksum = "1a081e51fb188742f5a7a1164ad752121abcb22874b21e2c3b0dd040c515fdad" dependencies = [ "common-path", - "derive-syn-parse", + "derive-syn-parse 0.2.0", "once_cell", "proc-macro2", "quote", "regex", - "syn 2.0.55", + "syn 2.0.58", "termcolor", "toml 0.8.12", "walkdir", @@ -3204,7 +3215,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -3215,7 +3226,7 @@ checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -3331,7 +3342,7 @@ checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -3342,7 +3353,7 @@ checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -3353,7 +3364,7 @@ checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -3363,17 +3374,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ "event-listener 4.0.3", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] name = "event-listener-strategy" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" dependencies = [ "event-listener 5.2.0", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -3408,7 +3419,7 @@ dependencies = [ "prettier-please", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -3673,7 +3684,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -3761,9 +3772,9 @@ dependencies = [ [[package]] name = "frame-support" -version = "29.0.0" +version = "29.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b24824d29c43d0af94be3356bbf30338ededed649f6841d315a9ae067ce872" +checksum = "b8e52c84b611d2049d9253f83a62ab0f093e4be5c42a7ef42ea5bb16d6611e32" dependencies = [ "aquamarine", "array-bytes 6.2.2", @@ -3809,7 +3820,7 @@ checksum = "3bf1d648c4007d421b9677b3c893256913498fff159dc2d85022cdd9cc432f3c" dependencies = [ "Inflector", "cfg-expr", - "derive-syn-parse", + "derive-syn-parse 0.1.5", "expander 2.1.0", "frame-support-procedural-tools", "itertools 0.10.5", @@ -3818,7 +3829,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -3831,7 +3842,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -3842,7 +3853,7 @@ checksum = "68672b9ec6fe72d259d3879dc212c5e42e977588cdac830c76f54d9f492aeb58" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -4010,7 +4021,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "waker-fn", ] @@ -4024,7 +4035,7 @@ dependencies = [ "futures-core", "futures-io", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -4035,7 +4046,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -4080,7 +4091,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "pin-utils", "slab", ] @@ -4404,7 +4415,7 @@ checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -4447,8 +4458,8 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.13", - "socket2 0.4.10", + "pin-project-lite 0.2.14", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -4806,9 +4817,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" @@ -5125,9 +5136,9 @@ dependencies = [ [[package]] name = "landlock" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1530c5b973eeed4ac216af7e24baf5737645a6272e361f1fb95710678b67d9cc" +checksum = "9baa9eeb6e315942429397e617a190f4fdc696ef1ee0342939d641029cbb4ea7" dependencies = [ "enumflags2", "libc", @@ -5563,13 +5574,12 @@ dependencies = [ [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.5.0", "libc", - "redox_syscall 0.4.1", ] [[package]] @@ -5805,7 +5815,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -5815,11 +5825,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "468155613a44cfd825f1fb0ffa532b018253920d404e6fca1e8d43155198a46d" dependencies = [ "const-random", - "derive-syn-parse", + "derive-syn-parse 0.1.5", "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -5830,7 +5840,7 @@ checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -5841,7 +5851,7 @@ checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -5892,9 +5902,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memfd" @@ -6229,9 +6239,9 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.4" +version = "0.32.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4541eb06dce09c0241ebbaab7102f0a01a0c8994afed2e5d0d66775016e25ac2" +checksum = "3ea4908d4f23254adda3daa60ffef0f1ac7b8c3e9a864cf3cc154b251908a2ef" dependencies = [ "approx", "matrixmultiply", @@ -6324,9 +6334,9 @@ dependencies = [ [[package]] name = "netlink-sys" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307" dependencies = [ "bytes", "futures", @@ -6763,9 +6773,9 @@ dependencies = [ [[package]] name = "pallet-balances" -version = "29.0.0" +version = "29.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942007f4f7aace74b77009db1675e7ca98683a42dde5e2d85bba2a9f404d2e5a" +checksum = "e27946a57494d7c6231ae8909275bbd3cb5460ee3d27b7a5774a8b8e64d3ab92" dependencies = [ "docify", "frame-benchmarking", @@ -7045,7 +7055,7 @@ checksum = "3163c6bc21b55a0ccb74c546ba784d9c9e69beb9240c059d28a3052f4cbce509" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -7682,9 +7692,9 @@ dependencies = [ [[package]] name = "pallet-staking" -version = "29.0.0" +version = "29.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a94127295cf027a26e933ea6788b0824e9fedd90740013673e2d36b5d707efe" +checksum = "668b7d28c499f0d9f295fad26cf6c342472e21842e3b13bcaaac8536358b2d6c" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7713,7 +7723,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -8274,9 +8284,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" dependencies = [ "memchr", "thiserror", @@ -8285,9 +8295,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" +checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" dependencies = [ "pest", "pest_generator", @@ -8295,22 +8305,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" +checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] name = "pest_meta" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" +checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" dependencies = [ "once_cell", "pest", @@ -8344,7 +8354,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -8355,9 +8365,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -8394,9 +8404,9 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "platforms" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" [[package]] name = "polkadot-approval-distribution" @@ -9524,7 +9534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6380dbe1fb03ecc74ad55d841cfc75480222d153ba69ddcb00977866cbdabdb8" dependencies = [ "polkavm-derive-impl", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -9536,7 +9546,7 @@ dependencies = [ "polkavm-common", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -9551,7 +9561,7 @@ dependencies = [ "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "windows-sys 0.48.0", ] @@ -9564,7 +9574,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "rustix 0.38.32", "tracing", "windows-sys 0.52.0", @@ -9710,19 +9720,16 @@ dependencies = [ "pallet-collator-selection", "pallet-contracts", "pallet-message-queue", - "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-preimage", - "pallet-proxy", "pallet-scheduler", "pallet-session", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", - "pallet-utility", "pallet-xcm", "parachains-common", "parity-scale-codec", @@ -9783,19 +9790,16 @@ dependencies = [ "pallet-collator-selection", "pallet-contracts", "pallet-message-queue", - "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-preimage", - "pallet-proxy", "pallet-scheduler", "pallet-session", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", - "pallet-utility", "pallet-xcm", "parachains-common", "parity-scale-codec", @@ -9880,7 +9884,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3" dependencies = [ "proc-macro2", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -9900,7 +9904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" dependencies = [ "proc-macro2", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -9994,7 +9998,7 @@ checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -10040,7 +10044,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -10108,7 +10112,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -10327,9 +10331,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom 0.2.12", "libredox", @@ -10365,7 +10369,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -10389,7 +10393,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -10409,7 +10413,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -10420,9 +10424,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "resolv-conf" @@ -11025,7 +11029,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -12039,7 +12043,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -12205,7 +12209,7 @@ dependencies = [ "proc-macro2", "quote", "scale-info", - "syn 2.0.55", + "syn 2.0.58", "thiserror", ] @@ -12358,9 +12362,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -12371,9 +12375,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -12438,14 +12442,14 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -13057,7 +13061,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -13323,7 +13327,7 @@ checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -13344,7 +13348,7 @@ checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -13593,7 +13597,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -13800,7 +13804,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -14044,9 +14048,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -14086,7 +14090,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -14262,7 +14266,7 @@ dependencies = [ "scale-info", "scale-typegen", "subxt-metadata", - "syn 2.0.55", + "syn 2.0.58", "thiserror", "tokio", ] @@ -14296,7 +14300,7 @@ dependencies = [ "quote", "scale-typegen", "subxt-codegen", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -14347,9 +14351,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.55" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -14479,7 +14483,7 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -14490,7 +14494,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -14619,7 +14623,7 @@ dependencies = [ "mio", "num_cpus", "parking_lot 0.12.1", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "signal-hook-registry", "socket2 0.5.6", "tokio-macros", @@ -14634,7 +14638,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -14676,7 +14680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tokio", "tokio-util", ] @@ -14691,7 +14695,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tokio", "tracing", ] @@ -14781,7 +14785,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tower-layer", "tower-service", "tracing", @@ -14800,7 +14804,7 @@ dependencies = [ "http", "http-body", "http-range-header", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tower-layer", "tower-service", ] @@ -14824,7 +14828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tracing-attributes", "tracing-core", ] @@ -14837,7 +14841,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -14882,7 +14886,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -15308,7 +15312,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", "wasm-bindgen-shared", ] @@ -15342,7 +15346,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -15364,9 +15368,9 @@ dependencies = [ [[package]] name = "wasm-opt" -version = "0.116.0" +version = "0.116.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc942673e7684671f0c5708fc18993569d184265fd5223bb51fc8e5b9b6cfd52" +checksum = "2fd87a4c135535ffed86123b6fb0f0a5a0bc89e50416c942c5f0662c645f679c" dependencies = [ "anyhow", "libc", @@ -16222,7 +16226,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -16271,7 +16275,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -16291,7 +16295,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.58", ] [[package]] @@ -16334,9 +16338,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.10+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" dependencies = [ "cc", "pkg-config", diff --git a/pop-api/examples/trust_backed_assets/.gitignore b/pop-api/examples/trust_backed_assets/.gitignore new file mode 100755 index 00000000..8de8f877 --- /dev/null +++ b/pop-api/examples/trust_backed_assets/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/pop-api/examples/trust_backed_assets/Cargo.toml b/pop-api/examples/trust_backed_assets/Cargo.toml new file mode 100755 index 00000000..3c3716fc --- /dev/null +++ b/pop-api/examples/trust_backed_assets/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "pop_api_trust_backed_assets_example" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { version = "5.0.0", default-features = false } +pop-api = { path = "../../../pop-api", default-features = false } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "pop-api/std", + "scale/std", + "scale-info/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/pop-api/examples/trust_backed_assets/lib.rs b/pop-api/examples/trust_backed_assets/lib.rs new file mode 100755 index 00000000..8b2fbda6 --- /dev/null +++ b/pop-api/examples/trust_backed_assets/lib.rs @@ -0,0 +1,69 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +use pop_api::assets::trust_backed as trust_backed_assets; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum ContractError { + TrustBackedAssetsError(trust_backed_assets::Error), + UnknownAsset, +} + +impl From for ContractError { + fn from(value: trust_backed_assets::Error) -> Self { + ContractError::TrustBackedAssetsError(value) + } +} + +#[ink::contract(env = pop_api::Environment)] +mod pop_api_extension_demo { + use super::*; + + #[ink(storage)] + #[derive(Default)] + pub struct PopApiExtensionDemo; + + impl PopApiExtensionDemo { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("Contract::new"); + Default::default() + } + + #[ink(message)] + pub fn mint_asset_through_runtime( + &mut self, + id: u32, + beneficiary: AccountId, + amount: Balance, + ) -> Result<(), ContractError> { + ink::env::debug_println!( + "Contract::mint_asset_through_runtime: id: {:?} beneficiary: {:?} amount: {:?}", + id, + beneficiary, + amount + ); + + // Check if asset doesn't exist. + if !trust_backed_assets::asset_exists(id)? { + return Err(ContractError::UnknownAsset); + } + + // Mint asset via pop api. + trust_backed_assets::mint(id, beneficiary, amount)?; + ink::env::debug_println!("Contract::mint_asset_through_runtime: asset(s) minted successfully"); + Ok(()) + } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[ink::test] + fn default_works() { + PopApiExtensionDemo::new(); + } + } +} + diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index e4590c89..68ce6906 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -3,12 +3,12 @@ pub mod primitives; pub mod v0; -use crate::PopApiError::{Balances, Nfts, UnknownStatusCode}; +use crate::PopApiError::{Balances, Nfts, TrustBackedAssets, UnknownStatusCode}; use ink::{prelude::vec::Vec, ChainExtensionInstance}; use primitives::{cross_chain::*, storage_keys::*}; pub use sp_runtime::{BoundedVec, MultiAddress, MultiSignature}; use v0::RuntimeCall; -pub use v0::{balances, cross_chain, nfts, relay_chain_block_number, state}; +pub use v0::{balances, cross_chain, nfts, relay_chain_block_number, state, assets}; type AccountId = ::AccountId; type Balance = ::Balance; @@ -26,6 +26,7 @@ pub enum PopApiError { SystemCallFiltered, Balances(balances::Error), Nfts(nfts::Error), + TrustBackedAssets(assets::trust_backed::Error), Xcm(cross_chain::Error), } @@ -37,6 +38,7 @@ impl ink::env::chain_extension::FromStatusCode for PopApiError { 5 => Err(PopApiError::SystemCallFiltered), 10_000..=10_999 => Err(Balances((status_code - 10_000).try_into()?)), 50_000..=50_999 => Err(Nfts((status_code - 50_000).try_into()?)), + 52_000..=52_999 => Err(TrustBackedAssets((status_code - 52_000).try_into()?)), _ => Err(UnknownStatusCode(status_code)), } } diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs new file mode 100644 index 00000000..7ad40f15 --- /dev/null +++ b/pop-api/src/v0/assets/mod.rs @@ -0,0 +1 @@ +pub mod trust_backed; \ No newline at end of file diff --git a/pop-api/src/v0/assets/trust_backed.rs b/pop-api/src/v0/assets/trust_backed.rs new file mode 100644 index 00000000..fb413413 --- /dev/null +++ b/pop-api/src/v0/assets/trust_backed.rs @@ -0,0 +1,519 @@ +use crate::{Balance, PopApiError::UnknownStatusCode, RuntimeCall, *}; +use ink::prelude::vec::Vec; +use primitives::{AssetId, MultiAddress}; +use scale::{Compact, Encode}; + +type Result = core::result::Result; + +/// https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/lib.rs +/// +/// Extrinsics within pallet assets (TrustBackedAssets Instance) that can be used via the pop api on Pop Network: +/// 1. create +/// 2. start_destroy +/// 3. destroy_accounts +/// 4. destroy_approvals +/// 5. finish_destroy +/// 6. mint +/// 7. burn +/// 8. transfer +/// 9. transfer_keep_alive +/// 10. force_transfer +/// 11. freeze +/// 12. thaw +/// 13. freeze_asset +/// 14. thaw_asset +/// 15. transfer_ownership +/// 16. set_team +/// 17. set_metadata +/// 18. clear_metadata +/// 19. approve_transfer +/// 20. cancel_approval +/// 21. force_cancel_approval +/// 22. transfer_approved +/// 23. touch +/// 24. refund +/// 25. set_min_balance +/// 26. touch_other +/// 27. refund_other +/// 28. block + + +/// Issue a new class of fungible assets from a public origin. +pub fn create( + id: AssetId, + admin: impl Into>, + min_balance: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Create { + id: id.into(), + admin: admin.into(), + min_balance: Compact(min_balance), + }))?) +} + +/// Start the process of destroying a fungible asset class. +pub fn start_destroy(id: AssetId) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::StartDestroy { + id: id.into(), + }))?) +} + +/// Destroy all accounts associated with a given asset. +pub fn destroy_accounts(id: AssetId) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::DestroyAccounts { + id: id.into(), + }))?) +} + +/// Destroy all approvals associated with a given asset up to the max (see runtime configuration TrustBackedAssets `RemoveItemsLimit`). +pub fn destroy_approvals(id: AssetId) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::DestroyApprovals { + id: id.into(), + }))?) +} + +/// Complete destroying asset and unreserve currency. +pub fn finish_destroy(id: AssetId) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::FinishDestroy { + id: id.into(), + }))?) +} + +/// Mint assets of a particular class. +pub fn mint( + id: AssetId, + beneficiary: impl Into>, + amount: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Mint { + id: id.into(), + beneficiary: beneficiary.into(), + amount: Compact(amount), + }))?) +} + +/// Reduce the balance of `who` by as much as possible up to `amount` assets of `id`. +pub fn burn( + id: AssetId, + who: impl Into>, + amount: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Burn { + id: id.into(), + who: who.into(), + amount: Compact(amount), + }))?) +} + +/// Move some assets from the sender account to another. +pub fn transfer( + id: AssetId, + target: impl Into>, + amount: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Transfer { + id: id.into(), + target: target.into(), + amount: Compact(amount), + }))?) +} + +/// Move some assets from the sender account to another, keeping the sender account alive. +pub fn transfer_keep_alive( + id: AssetId, + target: impl Into>, + amount: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::TransferKeepAlive { + id: id.into(), + target: target.into(), + amount: Compact(amount), + }))?) +} + +/// Move some assets from one account to another. Sender should be the Admin of the asset `id`. +pub fn force_transfer( + id: AssetId, + source: impl Into>, + dest: impl Into>, + amount: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ForceTransfer { + id: id.into(), + source: source.into(), + dest: dest.into(), + amount: Compact(amount), + }))?) +} + +/// Disallow further unprivileged transfers of an asset `id` from an account `who`. `who` +/// must already exist as an entry in `Account`s of the asset. If you want to freeze an +/// account that does not have an entry, use `touch_other` first. +pub fn freeze(id: AssetId, who: impl Into>) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Freeze { + id: id.into(), + who: who.into(), + }))?) +} + +/// Allow unprivileged transfers to and from an account again. +pub fn thaw(id: AssetId, who: impl Into>) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Thaw { + id: id.into(), + who: who.into(), + }))?) +} + +/// Disallow further unprivileged transfers for the asset class. +pub fn freeze_asset(id: AssetId) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::FreezeAsset { + id: id.into(), + }))?) +} + +/// Allow unprivileged transfers for the asset again. +pub fn thaw_asset(id: AssetId) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ThawAsset { + id: id.into(), + }))?) +} + +/// Change the Owner of an asset. +pub fn transfer_ownership( + id: AssetId, + owner: impl Into>, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::TransferOwnership { + id: id.into(), + owner: owner.into(), + }))?) +} + +/// Change the Issuer, Admin and Freezer of an asset. +pub fn set_team( + id: AssetId, + issuer: impl Into>, + admin: impl Into>, + freezer: impl Into>, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::SetTeam { + id: id.into(), + issuer: issuer.into(), + admin: admin.into(), + freezer: freezer.into(), + }))?) +} + +/// Set the metadata for an asset. +pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::SetMetadata { + id: id.into(), + name, + symbol, + decimals, + }))?) +} + +/// Clear the metadata for an asset. +pub fn clear_metadata(id: AssetId) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ClearMetadata { + id: id.into(), + }))?) +} + +/// Approve an amount of asset for transfer by a delegated third-party account. +pub fn approve_transfer( + id: AssetId, + delegate: impl Into>, + amount: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ApproveTransfer { + id: id.into(), + delegate: delegate.into(), + amount: Compact(amount), + }))?) +} + +/// Cancel all of some asset approved for delegated transfer by a third-party account. +pub fn cancel_approval( + id: AssetId, + delegate: impl Into>, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::CancelApproval { + id: id.into(), + delegate: delegate.into(), + }))?) +} + +/// Cancel all of some asset approved for delegated transfer by a third-party account. +pub fn force_cancel_approval( + id: AssetId, + owner: impl Into>, + delegate: impl Into>, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ForceCancelApproval { + id: id.into(), + owner: owner.into(), + delegate: delegate.into(), + }))?) +} + +/// Transfer some asset balance from a previously delegated account to some third-party +/// account. +pub fn transfer_approved( + id: AssetId, + owner: impl Into>, + destination: impl Into>, + amount: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::TransferApproved { + id: id.into(), + owner: owner.into(), + destination: destination.into(), + amount: Compact(amount), + }))?) +} + +/// Create an asset account for non-provider assets. +pub fn touch(id: AssetId) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Touch { + id: id.into(), + }))?) +} + +/// Return the deposit (if any) of an asset account or a consumer reference (if any) of an +/// account. +pub fn refund(id: AssetId, allow_burn: bool) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Refund { + id: id.into(), + allow_burn, + }))?) +} + +/// Sets the minimum balance of an asset. +pub fn set_min_balance(id: AssetId, min_balance: Balance) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::SetMinBalance { + id: id.into(), + min_balance: Compact(min_balance), + }))?) +} + +/// Create an asset account for `who`. +pub fn touch_other(id: AssetId, who: impl Into>) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::TouchOther { + id: id.into(), + who: who.into(), + }))?) +} + +/// Return the deposit (if any) of a target asset account. Useful if you are the depositor. +pub fn refund_other(id: AssetId, who: impl Into>) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::RefundOther { + id: id.into(), + who: who.into(), + }))?) +} + +/// Disallow further unprivileged transfers of an asset `id` to and from an account `who`. +pub fn block(id: AssetId, who: impl Into>) -> Result<()> { + Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Block { + id: id.into(), + who: who.into(), + }))?) +} + +pub fn asset_exists(id: AssetId) -> Result { + Ok(state::read(RuntimeStateKeys::TrustBackedAssets(TrustBackedAssetsKeys::AssetExists(id)))?) +} + +// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected +// to be compact encoded. The pop api handles that for the developer. +// +// reference: https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development +// +// Asset id that is compact encoded. +type AssetIdParameter = Compact; +// Balance amount that is compact encoded. +type BalanceParameter = Compact; + +#[derive(Encode)] +pub(crate) enum TrustBackedAssetsCalls { + #[codec(index = 0)] + Create { + id: AssetIdParameter, + admin: MultiAddress, + min_balance: BalanceParameter, + }, + #[codec(index = 2)] + StartDestroy { id: AssetIdParameter }, + #[codec(index = 3)] + DestroyAccounts { id: AssetIdParameter }, + #[codec(index = 4)] + DestroyApprovals { id: AssetIdParameter }, + #[codec(index = 5)] + FinishDestroy { id: AssetIdParameter }, + #[codec(index = 6)] + Mint { + id: AssetIdParameter, + beneficiary: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 7)] + Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, + #[codec(index = 8)] + Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, + #[codec(index = 9)] + TransferKeepAlive { + id: AssetIdParameter, + target: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 10)] + ForceTransfer { + id: AssetIdParameter, + source: MultiAddress, + dest: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 11)] + Freeze { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 12)] + Thaw { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 13)] + FreezeAsset { id: AssetIdParameter }, + #[codec(index = 14)] + ThawAsset { id: AssetIdParameter }, + #[codec(index = 15)] + TransferOwnership { id: AssetIdParameter, owner: MultiAddress }, + #[codec(index = 16)] + SetTeam { + id: AssetIdParameter, + issuer: MultiAddress, + admin: MultiAddress, + freezer: MultiAddress, + }, + #[codec(index = 17)] + SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, + #[codec(index = 18)] + ClearMetadata { id: AssetIdParameter }, + #[codec(index = 22)] + ApproveTransfer { + id: AssetIdParameter, + delegate: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 23)] + CancelApproval { id: AssetIdParameter, delegate: MultiAddress }, + #[codec(index = 24)] + ForceCancelApproval { + id: AssetIdParameter, + owner: MultiAddress, + delegate: MultiAddress, + }, + #[codec(index = 25)] + TransferApproved { + id: AssetIdParameter, + owner: MultiAddress, + destination: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 26)] + Touch { id: AssetIdParameter }, + #[codec(index = 27)] + Refund { id: AssetIdParameter, allow_burn: bool }, + #[codec(index = 28)] + SetMinBalance { id: AssetIdParameter, min_balance: BalanceParameter }, + #[codec(index = 29)] + TouchOther { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 30)] + RefundOther { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 31)] + Block { id: AssetIdParameter, who: MultiAddress }, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum Error { + /// Account balance must be greater than or equal to the transfer amount. + BalanceLow, + /// The account to alter does not exist. + NoAccount, + /// The signing account has no permission to do the operation. + NoPermission, + /// The given asset ID is unknown. + Unknown, + /// The origin account is frozen. + Frozen, + /// The asset ID is already taken. + InUse, + /// Invalid witness data given. + BadWitness, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// Unable to increment the consumer reference counters on the account. Either no provider + /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one + /// fewer then the maximum number of consumers has been reached. + UnavailableConsumer, + /// Invalid metadata given. + BadMetadata, + /// No approval exists that would allow the transfer. + Unapproved, + /// The source account would not survive the transfer and it needs to stay alive. + WouldDie, + /// The asset-account already exists. + AlreadyExists, + /// The asset-account doesn't have an associated deposit. + NoDeposit, + /// The operation would result in funds being burned. + WouldBurn, + /// The asset is a live asset and is actively being used. Usually emit for operations such + /// as `start_destroy` which require the asset to be in a destroying state. + LiveAsset, + /// The asset is not live, and likely being destroyed. + AssetNotLive, + /// The asset status is not the expected status. + IncorrectStatus, + /// The asset should be frozen before the given operation. + NotFrozen, + /// Callback action resulted in error + CallbackFailed, +} + +impl TryFrom for Error { + type Error = PopApiError; + + fn try_from(status_code: u32) -> core::result::Result { + use Error::*; + match status_code { + 0 => Ok(BalanceLow), + 1 => Ok(NoAccount), + 2 => Ok(NoPermission), + 3 => Ok(Unknown), + 4 => Ok(Frozen), + 5 => Ok(InUse), + 6 => Ok(BadWitness), + 7 => Ok(MinBalanceZero), + 8 => Ok(UnavailableConsumer), + 9 => Ok(BadMetadata), + 10 => Ok(Unapproved), + 11 => Ok(WouldDie), + 12 => Ok(AlreadyExists), + 13 => Ok(NoDeposit), + 14 => Ok(WouldBurn), + 15 => Ok(LiveAsset), + 16 => Ok(AssetNotLive), + 17 => Ok(IncorrectStatus), + 18 => Ok(NotFrozen), + _ => Err(UnknownStatusCode(status_code)), + } + } +} + +impl From for Error { + fn from(error: PopApiError) -> Self { + match error { + PopApiError::TrustBackedAssets(e) => e, + _ => panic!("Unexpected pallet assets error. This error is unknown to pallet assets"), + } + } +} diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 2ae0b821..d914db24 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -7,6 +7,7 @@ pub mod balances; pub mod cross_chain; pub mod nfts; pub mod state; +pub mod assets; pub fn relay_chain_block_number() -> Result { state::read(RuntimeStateKeys::ParachainSystem(ParachainSystemKeys::LastRelayChainBlockNumber)) @@ -18,4 +19,6 @@ pub(crate) enum RuntimeCall { Balances(balances::BalancesCall), #[codec(index = 50)] Nfts(nfts::NftCalls), + #[codec(index = 52)] + TrustBackedAssets(assets::trust_backed::TrustBackedAssetsCalls), } diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs index 3db08cd1..5a55154f 100644 --- a/pop-api/src/v0/nfts.rs +++ b/pop-api/src/v0/nfts.rs @@ -669,7 +669,7 @@ impl From for Error { fn from(error: PopApiError) -> Self { match error { PopApiError::Nfts(e) => e, - _ => panic!("expected nfts error"), + _ => panic!("unexpected pallet nfts error. This error is unknown to pallet nfts"), } } } diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 8ad74ade..ebad36d3 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -1,14 +1,12 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] pub use bounded_collections::{BoundedBTreeMap, BoundedBTreeSet, BoundedVec, ConstU32}; -//use scale::{Decode, Encode, MaxEncodedLen}; pub mod cross_chain; pub mod storage_keys; -// /// Some way of identifying an account on the chain. -// #[derive(Encode, Decode, Debug, MaxEncodedLen)] -// pub struct AccountId([u8; 32]); +// Identifier for the class of asset. +pub type AssetId = u32; // Id used for identifying non-fungible collections. pub type CollectionId = u32; // Id used for identifying non-fungible items. diff --git a/primitives/src/storage_keys.rs b/primitives/src/storage_keys.rs index 2bcb41ec..a03b3a09 100644 --- a/primitives/src/storage_keys.rs +++ b/primitives/src/storage_keys.rs @@ -5,6 +5,7 @@ use scale::{Decode, Encode, MaxEncodedLen}; pub enum RuntimeStateKeys { Nfts(NftsKeys), ParachainSystem(ParachainSystemKeys), + TrustBackedAssets(TrustBackedAssetsKeys), } #[derive(Encode, Decode, Debug, MaxEncodedLen)] @@ -33,3 +34,9 @@ pub enum NftsKeys { /// Get the attribute value of `item` of `collection` corresponding to `key`. CollectionAttribute(CollectionId, BoundedVec), } + +#[derive(Encode, Decode, Debug, MaxEncodedLen)] +pub enum TrustBackedAssetsKeys { + /// Check if the asset exists. + AssetExists(AssetId), +} diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 34035c1f..f51f8875 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -1,6 +1,6 @@ use crate::{ - deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, - RuntimeHoldReason, DAYS, EXISTENTIAL_DEPOSIT, UNIT, + deposit, AccountId, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, + RuntimeHoldReason, TrustBackedAssets, DAYS, EXISTENTIAL_DEPOSIT, UNIT, }; use frame_support::{ parameter_types, @@ -84,9 +84,9 @@ impl pallet_nft_fractionalization::Config for Runtime { type StringLimit = AssetsStringLimit; type NftCollectionId = ::CollectionId; type NftId = ::ItemId; - type AssetBalance = >::Balance; - type AssetId = >::AssetId; - type Assets = Assets; + type AssetBalance = >::Balance; + type AssetId = >::AssetId; + type Assets = TrustBackedAssets; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight; @@ -95,9 +95,9 @@ impl pallet_nft_fractionalization::Config for Runtime { type BenchmarkHelper = (); } -pub type TrustBackedAssets = pallet_assets::Instance1; -pub type TrustBackedAssetsCall = pallet_assets::Call; -impl pallet_assets::Config for Runtime { +pub type TrustBackedAssetsInstance = pallet_assets::Instance1; +pub(crate) type TrustBackedAssetsCall = pallet_assets::Call; +impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type AssetId = AssetIdForTrustBackedAssets; diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions.rs index 7e2a53c0..c8e88eb2 100644 --- a/runtime/devnet/src/extensions.rs +++ b/runtime/devnet/src/extensions.rs @@ -3,15 +3,15 @@ use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, - traits::nonfungibles_v2::Inspect, + traits::{fungibles::Inspect, nonfungibles_v2::Inspect as NonFungiblesInspect}, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, }; use pop_primitives::{ cross_chain::CrossChainMessage, - storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, - CollectionId, ItemId, + storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys, TrustBackedAssetsKeys}, + AssetId, CollectionId, ItemId, }; use sp_core::crypto::UncheckedFrom; use sp_runtime::{ @@ -24,7 +24,10 @@ use xcm::{ VersionedXcm, }; -use crate::{AccountId, AllowedApiCalls, RuntimeCall, RuntimeOrigin, UNIT}; +use crate::{ + assets_config::TrustBackedAssetsInstance, AccountId, AllowedPopApiCalls, RuntimeCall, + RuntimeOrigin, UNIT, +}; const LOG_TARGET: &str = "pop-api::extension"; @@ -37,6 +40,7 @@ impl ChainExtension for PopApiExtension where T: pallet_contracts::Config + pallet_xcm::Config + + pallet_assets::Config + pallet_nfts::Config + cumulus_pallet_parachain_system::Config + frame_system::Config< @@ -120,7 +124,7 @@ where log::debug!(target:LOG_TARGET, "{} inputted RuntimeCall: {:?}", log_prefix, call); - origin.add_filter(AllowedApiCalls::contains); + origin.add_filter(AllowedPopApiCalls::contains); match call.dispatch(origin) { Ok(info) => { @@ -192,6 +196,7 @@ where fn read_state(env: Environment) -> Result<(), DispatchError> where T: pallet_contracts::Config + + pallet_assets::Config + pallet_nfts::Config + cumulus_pallet_parachain_system::Config + frame_system::Config, @@ -217,6 +222,9 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, + RuntimeStateKeys::TrustBackedAssets(key) => { + read_trust_backed_assets_state::(key, &mut env) + }, }? .encode(); @@ -292,6 +300,23 @@ where } } +fn read_trust_backed_assets_state( + key: TrustBackedAssetsKeys, + env: &mut Environment, +) -> Result, DispatchError> +where + T: pallet_contracts::Config + + pallet_assets::Config, + E: Ext, +{ + match key { + TrustBackedAssetsKeys::AssetExists(id) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_assets::Pallet::::asset_exists(id).encode()) + }, + } +} + fn send_xcm(env: Environment) -> Result<(), DispatchError> where T: pallet_contracts::Config @@ -828,6 +853,110 @@ mod tests { }); } + #[test] + #[ignore] + fn dispatch_trust_backed_assets_mint_from_contract_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + + let (wasm_binary, _) = load_wasm_module::( + "../../pop-api/examples/trust_backed_assets/target/ink/pop_api_trust_backed_assets_example.wasm", + ) + .unwrap(); + + let init_value = 100; + + let result = Contracts::bare_instantiate( + ALICE, + init_value, + GAS_LIMIT, + None, + Code::Upload(wasm_binary), + function_selector("new"), + vec![], + DEBUG_OUTPUT, + pallet_contracts::CollectEvents::Skip, + ) + .result + .unwrap(); + + assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); + let addr = result.account_id; + + let asset_id: u32 = 1; + let min_balance = 1; + let amount: u128 = 100 * UNIT; + let function = function_selector("mint_asset_through_runtime"); + let params = [function, asset_id.encode(), BOB.encode(), amount.encode()].concat(); + + // Mint asset which does not exist. + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + GAS_LIMIT, + None, + params.clone(), + DEBUG_OUTPUT, + pallet_contracts::CollectEvents::Skip, + pallet_contracts::Determinism::Enforced, + ); + + if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { + log::debug!( + "Contract debug buffer - {:?}", + String::from_utf8(result.debug_message.clone()) + ); + log::debug!("result: {:?}", result); + } + + // Check for revert. + assert!(result.result.unwrap().did_revert(), "Contract should have been reverted!"); + + // Create asset with contract as owner. + assert_eq!( + TrustBackedAssets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + addr.clone().into(), + true, + min_balance, + ), + Ok(()) + ); + + // Check Bob's asset balance before minting through contract. + let bob_balance_before = TrustBackedAssets::balance(asset_id, &BOB); + assert_eq!(bob_balance_before, 0); + + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + GAS_LIMIT, + None, + params, + DEBUG_OUTPUT, + pallet_contracts::CollectEvents::Skip, + pallet_contracts::Determinism::Enforced, + ); + + if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { + log::debug!( + "Contract debug buffer - {:?}", + String::from_utf8(result.debug_message.clone()) + ); + log::debug!("result: {:?}", result); + } + + // Check for revert + assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); + + let bob_balance_after = TrustBackedAssets::balance(asset_id, &BOB); + assert_eq!(bob_balance_after, bob_balance_before + amount); + }); + } + #[test] #[ignore] fn allow_call_filter_blocks_call() { diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index ffca8a12..52a0938f 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -251,46 +251,77 @@ impl Contains for FilteredCalls { } /// A type to identify allowed calls to the Runtime from contracts. Used by Pop API -pub struct AllowedApiCalls; -impl Contains for crate::AllowedApiCalls { +pub struct AllowedPopApiCalls; +impl Contains for crate::AllowedPopApiCalls { fn contains(c: &RuntimeCall) -> bool { + use assets_config::TrustBackedAssetsCall; use pallet_nfts::Call as NftsCall; matches!( c, RuntimeCall::Balances(BalancesCall::transfer_keep_alive { .. }) - | RuntimeCall::Nfts( - NftsCall::create { .. } - | NftsCall::destroy { .. } - | NftsCall::mint { .. } | NftsCall::burn { .. } - | NftsCall::transfer { .. } - | NftsCall::redeposit { .. } - | NftsCall::lock_item_transfer { .. } - | NftsCall::unlock_item_transfer { .. } - | NftsCall::lock_collection { .. } - | NftsCall::transfer_ownership { .. } - | NftsCall::set_team { .. } - | NftsCall::approve_transfer { .. } - | NftsCall::cancel_approval { .. } - | NftsCall::clear_all_transfer_approvals { .. } - | NftsCall::lock_item_properties { .. } - | NftsCall::set_attribute { .. } - | NftsCall::clear_attribute { .. } - | NftsCall::approve_item_attributes { .. } - | NftsCall::cancel_item_attributes_approval { .. } - | NftsCall::set_metadata { .. } - | NftsCall::clear_metadata { .. } - | NftsCall::set_collection_metadata { .. } - | NftsCall::clear_collection_metadata { .. } - | NftsCall::set_accept_ownership { .. } - | NftsCall::set_collection_max_supply { .. } - | NftsCall::update_mint_settings { .. } - | NftsCall::set_price { .. } - | NftsCall::buy_item { .. } - | NftsCall::pay_tips { .. } - | NftsCall::create_swap { .. } - | NftsCall::cancel_swap { .. } - | NftsCall::claim_swap { .. } - ) + | RuntimeCall::TrustBackedAssets( + TrustBackedAssetsCall::create { .. } + | TrustBackedAssetsCall::start_destroy { .. } + | TrustBackedAssetsCall::destroy_accounts { .. } + | TrustBackedAssetsCall::destroy_approvals { .. } + | TrustBackedAssetsCall::finish_destroy { .. } + | TrustBackedAssetsCall::mint { .. } + | TrustBackedAssetsCall::burn { .. } + | TrustBackedAssetsCall::transfer { .. } + | TrustBackedAssetsCall::transfer_keep_alive { .. } + | TrustBackedAssetsCall::force_transfer { .. } + | TrustBackedAssetsCall::freeze { .. } + | TrustBackedAssetsCall::thaw { .. } + | TrustBackedAssetsCall::freeze_asset { .. } + | TrustBackedAssetsCall::thaw_asset { .. } + | TrustBackedAssetsCall::transfer_ownership { .. } + | TrustBackedAssetsCall::set_team { .. } + | TrustBackedAssetsCall::set_metadata { .. } + | TrustBackedAssetsCall::clear_metadata { .. } + | TrustBackedAssetsCall::approve_transfer { .. } + | TrustBackedAssetsCall::cancel_approval { .. } + | TrustBackedAssetsCall::force_cancel_approval { .. } + | TrustBackedAssetsCall::transfer_approved { .. } + | TrustBackedAssetsCall::touch { .. } + | TrustBackedAssetsCall::refund { .. } + | TrustBackedAssetsCall::set_min_balance { .. } + | TrustBackedAssetsCall::touch_other { .. } + | TrustBackedAssetsCall::refund_other { .. } + | TrustBackedAssetsCall::block { .. } + ) | RuntimeCall::Nfts( + NftsCall::create { .. } + | NftsCall::destroy { .. } + | NftsCall::mint { .. } + | NftsCall::burn { .. } + | NftsCall::transfer { .. } + | NftsCall::redeposit { .. } + | NftsCall::lock_item_transfer { .. } + | NftsCall::unlock_item_transfer { .. } + | NftsCall::lock_collection { .. } + | NftsCall::transfer_ownership { .. } + | NftsCall::set_team { .. } + | NftsCall::approve_transfer { .. } + | NftsCall::cancel_approval { .. } + | NftsCall::clear_all_transfer_approvals { .. } + | NftsCall::lock_item_properties { .. } + | NftsCall::set_attribute { .. } + | NftsCall::clear_attribute { .. } + | NftsCall::approve_item_attributes { .. } + | NftsCall::cancel_item_attributes_approval { .. } + | NftsCall::set_metadata { .. } + | NftsCall::clear_metadata { .. } + | NftsCall::set_collection_metadata { .. } + | NftsCall::clear_collection_metadata { .. } + | NftsCall::set_accept_ownership { .. } + | NftsCall::set_collection_max_supply { .. } + | NftsCall::update_mint_settings { .. } + | NftsCall::set_price { .. } + | NftsCall::buy_item { .. } + | NftsCall::pay_tips { .. } + | NftsCall::create_swap { .. } + | NftsCall::cancel_swap { .. } + | NftsCall::claim_swap { .. } + ) ) } } @@ -631,7 +662,7 @@ construct_runtime!( // Assets Nfts: pallet_nfts = 50, NftFractionalization: pallet_nft_fractionalization = 51, - Assets: pallet_assets:: = 52, + TrustBackedAssets: pallet_assets:: = 52, } ); diff --git a/runtime/testnet/src/config/assets.rs b/runtime/testnet/src/config/assets.rs index 34035c1f..f51f8875 100644 --- a/runtime/testnet/src/config/assets.rs +++ b/runtime/testnet/src/config/assets.rs @@ -1,6 +1,6 @@ use crate::{ - deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, - RuntimeHoldReason, DAYS, EXISTENTIAL_DEPOSIT, UNIT, + deposit, AccountId, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, + RuntimeHoldReason, TrustBackedAssets, DAYS, EXISTENTIAL_DEPOSIT, UNIT, }; use frame_support::{ parameter_types, @@ -84,9 +84,9 @@ impl pallet_nft_fractionalization::Config for Runtime { type StringLimit = AssetsStringLimit; type NftCollectionId = ::CollectionId; type NftId = ::ItemId; - type AssetBalance = >::Balance; - type AssetId = >::AssetId; - type Assets = Assets; + type AssetBalance = >::Balance; + type AssetId = >::AssetId; + type Assets = TrustBackedAssets; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight; @@ -95,9 +95,9 @@ impl pallet_nft_fractionalization::Config for Runtime { type BenchmarkHelper = (); } -pub type TrustBackedAssets = pallet_assets::Instance1; -pub type TrustBackedAssetsCall = pallet_assets::Call; -impl pallet_assets::Config for Runtime { +pub type TrustBackedAssetsInstance = pallet_assets::Instance1; +pub(crate) type TrustBackedAssetsCall = pallet_assets::Call; +impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type AssetId = AssetIdForTrustBackedAssets; diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index d6f2d656..0d552090 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -3,23 +3,25 @@ use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, - traits::nonfungibles_v2::Inspect, + traits::{fungibles::Inspect, nonfungibles_v2::Inspect as NonFungiblesInspect}, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, }; use pop_primitives::{ - storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, - CollectionId, ItemId, + storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys, TrustBackedAssetsKeys}, + AssetId, CollectionId, ItemId, }; use sp_core::crypto::UncheckedFrom; use sp_runtime::{ traits::{BlockNumberProvider, Dispatchable}, DispatchError, }; -use sp_std::vec::Vec; -use crate::{AccountId, AllowedApiCalls, RuntimeCall, RuntimeOrigin}; +use crate::{ + assets_config::TrustBackedAssetsInstance, AccountId, AllowedPopApiCalls, RuntimeCall, + RuntimeOrigin, +}; const LOG_TARGET: &str = "pop-api::extension"; @@ -32,6 +34,7 @@ impl ChainExtension for PopApiExtension where T: pallet_contracts::Config + pallet_xcm::Config + + pallet_assets::Config + pallet_nfts::Config + cumulus_pallet_parachain_system::Config + frame_system::Config< @@ -109,7 +112,7 @@ where log::debug!(target:LOG_TARGET, "{} inputted RuntimeCall: {:?}", log_prefix, call); - origin.add_filter(AllowedApiCalls::contains); + origin.add_filter(AllowedPopApiCalls::contains); match call.dispatch(origin) { Ok(info) => { @@ -181,6 +184,7 @@ where fn read_state(env: Environment) -> Result<(), DispatchError> where T: pallet_contracts::Config + + pallet_assets::Config + pallet_nfts::Config + cumulus_pallet_parachain_system::Config + frame_system::Config, @@ -206,6 +210,9 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, + RuntimeStateKeys::TrustBackedAssets(key) => { + read_trust_backed_assets_state::(key, &mut env) + }, }? .encode(); @@ -281,6 +288,23 @@ where } } +fn read_trust_backed_assets_state( + key: TrustBackedAssetsKeys, + env: &mut Environment, +) -> Result, DispatchError> +where + T: pallet_contracts::Config + + pallet_assets::Config, + E: Ext, +{ + match key { + TrustBackedAssetsKeys::AssetExists(id) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_assets::Pallet::::asset_exists(id).encode()) + }, + } +} + #[cfg(test)] mod tests { pub use super::*; @@ -481,7 +505,7 @@ mod tests { log::debug!("result: {:?}", result); } - // check for revert + // Check for revert. assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); assert_eq!(Nfts::owner(collection_id, item_id), Some(BOB.into())); @@ -546,7 +570,7 @@ mod tests { log::debug!("result: {:?}", result); } - // check for revert with expected error + // Check for revert with expected error. let result = result.result.unwrap(); assert!(result.did_revert()); }); @@ -606,7 +630,7 @@ mod tests { log::debug!("result: {:?}", result); } - // check for revert + // Check for revert. assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); }); } @@ -669,7 +693,7 @@ mod tests { log::debug!("result: {:?}", result); } - // check for revert + // Check for revert. assert!( result.result.is_err(), "Contract execution should have failed - unimplemented runtime call!" @@ -677,6 +701,110 @@ mod tests { }); } + #[test] + #[ignore] + fn dispatch_trust_backed_assets_mint_from_contract_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + + let (wasm_binary, _) = load_wasm_module::( + "../../pop-api/examples/trust_backed_assets/target/ink/pop_api_trust_backed_assets_example.wasm", + ) + .unwrap(); + + let init_value = 100; + + let result = Contracts::bare_instantiate( + ALICE, + init_value, + GAS_LIMIT, + None, + Code::Upload(wasm_binary), + function_selector("new"), + vec![], + DEBUG_OUTPUT, + pallet_contracts::CollectEvents::Skip, + ) + .result + .unwrap(); + + assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); + let addr = result.account_id; + + let asset_id: u32 = 1; + let min_balance = 1; + let amount: u128 = 100 * UNIT; + let function = function_selector("mint_asset_through_runtime"); + let params = [function, asset_id.encode(), BOB.encode(), amount.encode()].concat(); + + // Mint asset which does not exist. + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + GAS_LIMIT, + None, + params.clone(), + DEBUG_OUTPUT, + pallet_contracts::CollectEvents::Skip, + pallet_contracts::Determinism::Enforced, + ); + + if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { + log::debug!( + "Contract debug buffer - {:?}", + String::from_utf8(result.debug_message.clone()) + ); + log::debug!("result: {:?}", result); + } + + // Check for revert. + assert!(result.result.unwrap().did_revert(), "Contract should have been reverted!"); + + // Create asset with contract as owner. + assert_eq!( + TrustBackedAssets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + addr.clone().into(), + true, + min_balance, + ), + Ok(()) + ); + + // Check Bob's asset balance before minting through contract. + let bob_balance_before = TrustBackedAssets::balance(asset_id, &BOB); + assert_eq!(bob_balance_before, 0); + + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + GAS_LIMIT, + None, + params, + DEBUG_OUTPUT, + pallet_contracts::CollectEvents::Skip, + pallet_contracts::Determinism::Enforced, + ); + + if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { + log::debug!( + "Contract debug buffer - {:?}", + String::from_utf8(result.debug_message.clone()) + ); + log::debug!("result: {:?}", result); + } + + // Check for revert + assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); + + let bob_balance_after = TrustBackedAssets::balance(asset_id, &BOB); + assert_eq!(bob_balance_after, bob_balance_before + amount); + }); + } + #[test] #[ignore] fn allow_call_filter_blocks_call() { @@ -731,7 +859,7 @@ mod tests { log::debug!("filtered result: {:?}", result); } - // check for revert + // Check for revert. assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); }); } diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index 37f378f7..312d9b50 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -250,46 +250,77 @@ impl Contains for FilteredCalls { } /// A type to identify allowed calls to the Runtime from contracts. Used by Pop API -pub struct AllowedApiCalls; -impl Contains for crate::AllowedApiCalls { +pub struct AllowedPopApiCalls; +impl Contains for crate::AllowedPopApiCalls { fn contains(c: &RuntimeCall) -> bool { + use assets_config::TrustBackedAssetsCall; use pallet_nfts::Call as NftsCall; matches!( c, RuntimeCall::Balances(BalancesCall::transfer_keep_alive { .. }) - | RuntimeCall::Nfts( - NftsCall::create { .. } - | NftsCall::destroy { .. } - | NftsCall::mint { .. } | NftsCall::burn { .. } - | NftsCall::transfer { .. } - | NftsCall::redeposit { .. } - | NftsCall::lock_item_transfer { .. } - | NftsCall::unlock_item_transfer { .. } - | NftsCall::lock_collection { .. } - | NftsCall::transfer_ownership { .. } - | NftsCall::set_team { .. } - | NftsCall::approve_transfer { .. } - | NftsCall::cancel_approval { .. } - | NftsCall::clear_all_transfer_approvals { .. } - | NftsCall::lock_item_properties { .. } - | NftsCall::set_attribute { .. } - | NftsCall::clear_attribute { .. } - | NftsCall::approve_item_attributes { .. } - | NftsCall::cancel_item_attributes_approval { .. } - | NftsCall::set_metadata { .. } - | NftsCall::clear_metadata { .. } - | NftsCall::set_collection_metadata { .. } - | NftsCall::clear_collection_metadata { .. } - | NftsCall::set_accept_ownership { .. } - | NftsCall::set_collection_max_supply { .. } - | NftsCall::update_mint_settings { .. } - | NftsCall::set_price { .. } - | NftsCall::buy_item { .. } - | NftsCall::pay_tips { .. } - | NftsCall::create_swap { .. } - | NftsCall::cancel_swap { .. } - | NftsCall::claim_swap { .. } - ) + | RuntimeCall::TrustBackedAssets( + TrustBackedAssetsCall::create { .. } + | TrustBackedAssetsCall::start_destroy { .. } + | TrustBackedAssetsCall::destroy_accounts { .. } + | TrustBackedAssetsCall::destroy_approvals { .. } + | TrustBackedAssetsCall::finish_destroy { .. } + | TrustBackedAssetsCall::mint { .. } + | TrustBackedAssetsCall::burn { .. } + | TrustBackedAssetsCall::transfer { .. } + | TrustBackedAssetsCall::transfer_keep_alive { .. } + | TrustBackedAssetsCall::force_transfer { .. } + | TrustBackedAssetsCall::freeze { .. } + | TrustBackedAssetsCall::thaw { .. } + | TrustBackedAssetsCall::freeze_asset { .. } + | TrustBackedAssetsCall::thaw_asset { .. } + | TrustBackedAssetsCall::transfer_ownership { .. } + | TrustBackedAssetsCall::set_team { .. } + | TrustBackedAssetsCall::set_metadata { .. } + | TrustBackedAssetsCall::clear_metadata { .. } + | TrustBackedAssetsCall::approve_transfer { .. } + | TrustBackedAssetsCall::cancel_approval { .. } + | TrustBackedAssetsCall::force_cancel_approval { .. } + | TrustBackedAssetsCall::transfer_approved { .. } + | TrustBackedAssetsCall::touch { .. } + | TrustBackedAssetsCall::refund { .. } + | TrustBackedAssetsCall::set_min_balance { .. } + | TrustBackedAssetsCall::touch_other { .. } + | TrustBackedAssetsCall::refund_other { .. } + | TrustBackedAssetsCall::block { .. } + ) | RuntimeCall::Nfts( + NftsCall::create { .. } + | NftsCall::destroy { .. } + | NftsCall::mint { .. } + | NftsCall::burn { .. } + | NftsCall::transfer { .. } + | NftsCall::redeposit { .. } + | NftsCall::lock_item_transfer { .. } + | NftsCall::unlock_item_transfer { .. } + | NftsCall::lock_collection { .. } + | NftsCall::transfer_ownership { .. } + | NftsCall::set_team { .. } + | NftsCall::approve_transfer { .. } + | NftsCall::cancel_approval { .. } + | NftsCall::clear_all_transfer_approvals { .. } + | NftsCall::lock_item_properties { .. } + | NftsCall::set_attribute { .. } + | NftsCall::clear_attribute { .. } + | NftsCall::approve_item_attributes { .. } + | NftsCall::cancel_item_attributes_approval { .. } + | NftsCall::set_metadata { .. } + | NftsCall::clear_metadata { .. } + | NftsCall::set_collection_metadata { .. } + | NftsCall::clear_collection_metadata { .. } + | NftsCall::set_accept_ownership { .. } + | NftsCall::set_collection_max_supply { .. } + | NftsCall::update_mint_settings { .. } + | NftsCall::set_price { .. } + | NftsCall::buy_item { .. } + | NftsCall::pay_tips { .. } + | NftsCall::create_swap { .. } + | NftsCall::cancel_swap { .. } + | NftsCall::claim_swap { .. } + ) ) } } @@ -630,7 +661,7 @@ construct_runtime!( // Assets Nfts: pallet_nfts = 50, NftFractionalization: pallet_nft_fractionalization = 51, - Assets: pallet_assets:: = 52, + TrustBackedAssets: pallet_assets:: = 52, } ); From 418aa6311498112ec43a23ea72962a43464826b3 Mon Sep 17 00:00:00 2001 From: R0GUE Date: Fri, 12 Apr 2024 15:33:32 +0200 Subject: [PATCH 002/161] style: renaming assets example --- pop-api/examples/trust_backed_assets/lib.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/pop-api/examples/trust_backed_assets/lib.rs b/pop-api/examples/trust_backed_assets/lib.rs index 8b2fbda6..3606f852 100755 --- a/pop-api/examples/trust_backed_assets/lib.rs +++ b/pop-api/examples/trust_backed_assets/lib.rs @@ -1,5 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] +// Utilizing Trust Backed Assets with the Pop API. +// +// This example demonstrates interaction with trust backed assets via the assets pallet. Trust backed assets are originated +// and managed within Pop Network, harnessing the platform's inherent trust, security, and governance models. use pop_api::assets::trust_backed as trust_backed_assets; #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] @@ -16,14 +20,14 @@ impl From for ContractError { } #[ink::contract(env = pop_api::Environment)] -mod pop_api_extension_demo { +mod pop_api_tb_assets_example { use super::*; #[ink(storage)] #[derive(Default)] - pub struct PopApiExtensionDemo; + pub struct PopApiTBAssetsExample; - impl PopApiExtensionDemo { + impl PopApiTBAssetsExample { #[ink(constructor, payable)] pub fn new() -> Self { ink::env::debug_println!("Contract::new"); @@ -45,13 +49,15 @@ mod pop_api_extension_demo { ); // Check if asset doesn't exist. - if !trust_backed_assets::asset_exists(id)? { + if !trust_backed_assets::asset_exists(id)? { return Err(ContractError::UnknownAsset); } // Mint asset via pop api. trust_backed_assets::mint(id, beneficiary, amount)?; - ink::env::debug_println!("Contract::mint_asset_through_runtime: asset(s) minted successfully"); + ink::env::debug_println!( + "Contract::mint_asset_through_runtime: asset(s) minted successfully" + ); Ok(()) } } @@ -62,8 +68,7 @@ mod pop_api_extension_demo { #[ink::test] fn default_works() { - PopApiExtensionDemo::new(); + PopApiTBAssetsExample::new(); } } } - From 3d385df789e84a678badd94a70a6833d61329437 Mon Sep 17 00:00:00 2001 From: R0GUE Date: Mon, 22 Apr 2024 15:05:31 +0200 Subject: [PATCH 003/161] refactor: chain extension tests --- Cargo.lock | 8 + pop-api/Cargo.toml | 2 +- .../.gitignore | 0 .../Cargo.toml | 2 +- pop-api/examples/fungibles/expanded.rs | 2766 +++++++++++++++++ pop-api/examples/fungibles/lib.rs | 176 ++ pop-api/examples/trust_backed_assets/lib.rs | 74 - pop-api/src/lib.rs | 15 +- pop-api/src/v0/assets/fungibles.rs | 554 ++++ pop-api/src/v0/assets/mod.rs | 2 +- pop-api/src/v0/assets/trust_backed.rs | 519 ---- pop-api/src/v0/balances.rs | 2 +- pop-api/src/v0/contracts.rs | 156 + pop-api/src/v0/mod.rs | 3 +- primitives/Cargo.toml | 14 +- primitives/src/lib.rs | 12 + primitives/src/storage_keys.rs | 14 +- runtime/devnet/Cargo.toml | 2 +- runtime/devnet/src/config/assets.rs | 8 +- runtime/devnet/src/config/mod.rs | 2 +- runtime/devnet/src/config/proxy.rs | 40 +- runtime/devnet/src/extensions.rs | 1018 ------ runtime/devnet/src/extensions/mod.rs | 896 ++++++ .../src/extensions/tests/local_fungibles.rs | 302 ++ runtime/devnet/src/extensions/tests/mod.rs | 86 + runtime/devnet/src/lib.rs | 62 +- runtime/testnet/Cargo.toml | 2 +- runtime/testnet/src/config/assets.rs | 8 +- runtime/testnet/src/config/proxy.rs | 40 +- runtime/testnet/src/extensions.rs | 138 +- runtime/testnet/src/lib.rs | 99 +- 31 files changed, 5116 insertions(+), 1906 deletions(-) rename pop-api/examples/{trust_backed_assets => fungibles}/.gitignore (100%) rename pop-api/examples/{trust_backed_assets => fungibles}/Cargo.toml (93%) create mode 100644 pop-api/examples/fungibles/expanded.rs create mode 100755 pop-api/examples/fungibles/lib.rs delete mode 100755 pop-api/examples/trust_backed_assets/lib.rs create mode 100644 pop-api/src/v0/assets/fungibles.rs delete mode 100644 pop-api/src/v0/assets/trust_backed.rs create mode 100644 pop-api/src/v0/contracts.rs delete mode 100644 runtime/devnet/src/extensions.rs create mode 100644 runtime/devnet/src/extensions/mod.rs create mode 100644 runtime/devnet/src/extensions/tests/local_fungibles.rs create mode 100644 runtime/devnet/src/extensions/tests/mod.rs diff --git a/Cargo.lock b/Cargo.lock index e43d2b18..17cc70e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9673,6 +9673,8 @@ version = "0.0.0" dependencies = [ "bounded-collections 0.1.9", "parity-scale-codec", + "scale-decode", + "scale-encode", "scale-info", ] @@ -9720,16 +9722,19 @@ dependencies = [ "pallet-collator-selection", "pallet-contracts", "pallet-message-queue", + "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-preimage", + "pallet-proxy", "pallet-scheduler", "pallet-session", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", + "pallet-utility", "pallet-xcm", "parachains-common", "parity-scale-codec", @@ -9790,16 +9795,19 @@ dependencies = [ "pallet-collator-selection", "pallet-contracts", "pallet-message-queue", + "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-preimage", + "pallet-proxy", "pallet-scheduler", "pallet-session", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", + "pallet-utility", "pallet-xcm", "parachains-common", "parity-scale-codec", diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 0fa1119c..80818235 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -13,7 +13,7 @@ scale-info = { version = "2.6", default-features = false, features = ["derive"] sp-io = { version = "23.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } sp-runtime = { version = "24.0", default-features = false } -pop-primitives = { path = "../primitives", default-features = false } +pop-primitives = { path = "../primitives", features = ["devnet"], default-features = false } [lib] name = "pop_api" diff --git a/pop-api/examples/trust_backed_assets/.gitignore b/pop-api/examples/fungibles/.gitignore similarity index 100% rename from pop-api/examples/trust_backed_assets/.gitignore rename to pop-api/examples/fungibles/.gitignore diff --git a/pop-api/examples/trust_backed_assets/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml similarity index 93% rename from pop-api/examples/trust_backed_assets/Cargo.toml rename to pop-api/examples/fungibles/Cargo.toml index 3c3716fc..1fe32d6d 100755 --- a/pop-api/examples/trust_backed_assets/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pop_api_trust_backed_assets_example" +name = "fungibles" version = "0.1.0" authors = ["[your_name] <[your_email]>"] edition = "2021" diff --git a/pop-api/examples/fungibles/expanded.rs b/pop-api/examples/fungibles/expanded.rs new file mode 100644 index 00000000..c73cdeb7 --- /dev/null +++ b/pop-api/examples/fungibles/expanded.rs @@ -0,0 +1,2766 @@ +#![feature(prelude_import)] +#[prelude_import] +use std::prelude::rust_2021::*; +#[macro_use] +extern crate std; +use pop_api::{ + primitives::{AccountId as AccountId32, AssetId}, + assets::fungibles::*, +}; +pub enum FungiblesError { + /// Not enough balance to fulfill a request is available. + InsufficientBalance, + /// Not enough allowance to fulfill a request is available. + InsufficientAllowance, + /// The asset status is not the expected status. + IncorrectStatus, + /// The asset ID is already taken. + InUse, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// The signing account has no permission to do the operation. + NoPermission, + /// The given asset ID is unknown. + Unknown, + /// Recipient's address is zero. + ZeroRecipientAddress, + /// Sender's address is zero. + ZeroSenderAddress, +} +#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] +const _: () = { + impl ::scale_info::TypeInfo for FungiblesError { + type Identity = Self; + fn type_info() -> ::scale_info::Type { + ::scale_info::Type::builder() + .path( + ::scale_info::Path::new_with_replace( + "FungiblesError", + "fungibles", + &[], + ), + ) + .type_params(::alloc::vec::Vec::new()) + .variant( + ::scale_info::build::Variants::new() + .variant( + "InsufficientBalance", + |v| { + v + .index(0usize as ::core::primitive::u8) + .docs( + &["Not enough balance to fulfill a request is available."], + ) + }, + ) + .variant( + "InsufficientAllowance", + |v| { + v + .index(1usize as ::core::primitive::u8) + .docs( + &["Not enough allowance to fulfill a request is available."], + ) + }, + ) + .variant( + "IncorrectStatus", + |v| { + v + .index(2usize as ::core::primitive::u8) + .docs(&["The asset status is not the expected status."]) + }, + ) + .variant( + "InUse", + |v| { + v + .index(3usize as ::core::primitive::u8) + .docs(&["The asset ID is already taken."]) + }, + ) + .variant( + "MinBalanceZero", + |v| { + v + .index(4usize as ::core::primitive::u8) + .docs(&["Minimum balance should be non-zero."]) + }, + ) + .variant( + "NoPermission", + |v| { + v + .index(5usize as ::core::primitive::u8) + .docs( + &[ + "The signing account has no permission to do the operation.", + ], + ) + }, + ) + .variant( + "Unknown", + |v| { + v + .index(6usize as ::core::primitive::u8) + .docs(&["The given asset ID is unknown."]) + }, + ) + .variant( + "ZeroRecipientAddress", + |v| { + v + .index(7usize as ::core::primitive::u8) + .docs(&["Recipient's address is zero."]) + }, + ) + .variant( + "ZeroSenderAddress", + |v| { + v + .index(8usize as ::core::primitive::u8) + .docs(&["Sender's address is zero."]) + }, + ), + ) + } + } +}; +#[automatically_derived] +impl ::core::fmt::Debug for FungiblesError { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str( + f, + match self { + FungiblesError::InsufficientBalance => "InsufficientBalance", + FungiblesError::InsufficientAllowance => "InsufficientAllowance", + FungiblesError::IncorrectStatus => "IncorrectStatus", + FungiblesError::InUse => "InUse", + FungiblesError::MinBalanceZero => "MinBalanceZero", + FungiblesError::NoPermission => "NoPermission", + FungiblesError::Unknown => "Unknown", + FungiblesError::ZeroRecipientAddress => "ZeroRecipientAddress", + FungiblesError::ZeroSenderAddress => "ZeroSenderAddress", + }, + ) + } +} +#[automatically_derived] +impl ::core::marker::Copy for FungiblesError {} +#[automatically_derived] +impl ::core::clone::Clone for FungiblesError { + #[inline] + fn clone(&self) -> FungiblesError { + *self + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for FungiblesError {} +#[automatically_derived] +impl ::core::cmp::PartialEq for FungiblesError { + #[inline] + fn eq(&self, other: &FungiblesError) -> bool { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + __self_tag == __arg1_tag + } +} +#[automatically_derived] +impl ::core::cmp::Eq for FungiblesError { + #[inline] + #[doc(hidden)] + #[coverage(off)] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[allow(deprecated)] +const _: () = { + #[automatically_derived] + impl ::scale::Encode for FungiblesError { + fn size_hint(&self) -> usize { + 1_usize + + match *self { + FungiblesError::InsufficientBalance => 0_usize, + FungiblesError::InsufficientAllowance => 0_usize, + FungiblesError::IncorrectStatus => 0_usize, + FungiblesError::InUse => 0_usize, + FungiblesError::MinBalanceZero => 0_usize, + FungiblesError::NoPermission => 0_usize, + FungiblesError::Unknown => 0_usize, + FungiblesError::ZeroRecipientAddress => 0_usize, + FungiblesError::ZeroSenderAddress => 0_usize, + _ => 0_usize, + } + } + fn encode_to<__CodecOutputEdqy: ::scale::Output + ?::core::marker::Sized>( + &self, + __codec_dest_edqy: &mut __CodecOutputEdqy, + ) { + match *self { + FungiblesError::InsufficientBalance => { + #[allow(clippy::unnecessary_cast)] + __codec_dest_edqy.push_byte(0usize as ::core::primitive::u8); + } + FungiblesError::InsufficientAllowance => { + #[allow(clippy::unnecessary_cast)] + __codec_dest_edqy.push_byte(1usize as ::core::primitive::u8); + } + FungiblesError::IncorrectStatus => { + #[allow(clippy::unnecessary_cast)] + __codec_dest_edqy.push_byte(2usize as ::core::primitive::u8); + } + FungiblesError::InUse => { + #[allow(clippy::unnecessary_cast)] + __codec_dest_edqy.push_byte(3usize as ::core::primitive::u8); + } + FungiblesError::MinBalanceZero => { + #[allow(clippy::unnecessary_cast)] + __codec_dest_edqy.push_byte(4usize as ::core::primitive::u8); + } + FungiblesError::NoPermission => { + #[allow(clippy::unnecessary_cast)] + __codec_dest_edqy.push_byte(5usize as ::core::primitive::u8); + } + FungiblesError::Unknown => { + #[allow(clippy::unnecessary_cast)] + __codec_dest_edqy.push_byte(6usize as ::core::primitive::u8); + } + FungiblesError::ZeroRecipientAddress => { + #[allow(clippy::unnecessary_cast)] + __codec_dest_edqy.push_byte(7usize as ::core::primitive::u8); + } + FungiblesError::ZeroSenderAddress => { + #[allow(clippy::unnecessary_cast)] + __codec_dest_edqy.push_byte(8usize as ::core::primitive::u8); + } + _ => {} + } + } + } + #[automatically_derived] + impl ::scale::EncodeLike for FungiblesError {} +}; +#[allow(deprecated)] +const _: () = { + #[automatically_derived] + impl ::scale::Decode for FungiblesError { + fn decode<__CodecInputEdqy: ::scale::Input>( + __codec_input_edqy: &mut __CodecInputEdqy, + ) -> ::core::result::Result { + match __codec_input_edqy + .read_byte() + .map_err(|e| { + e + .chain( + "Could not decode `FungiblesError`, failed to read variant byte", + ) + })? + { + #[allow(clippy::unnecessary_cast)] + __codec_x_edqy if __codec_x_edqy == 0usize as ::core::primitive::u8 => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Ok(FungiblesError::InsufficientBalance) + })(); + } + #[allow(clippy::unnecessary_cast)] + __codec_x_edqy if __codec_x_edqy == 1usize as ::core::primitive::u8 => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Ok(FungiblesError::InsufficientAllowance) + })(); + } + #[allow(clippy::unnecessary_cast)] + __codec_x_edqy if __codec_x_edqy == 2usize as ::core::primitive::u8 => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Ok(FungiblesError::IncorrectStatus) + })(); + } + #[allow(clippy::unnecessary_cast)] + __codec_x_edqy if __codec_x_edqy == 3usize as ::core::primitive::u8 => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Ok(FungiblesError::InUse) + })(); + } + #[allow(clippy::unnecessary_cast)] + __codec_x_edqy if __codec_x_edqy == 4usize as ::core::primitive::u8 => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Ok(FungiblesError::MinBalanceZero) + })(); + } + #[allow(clippy::unnecessary_cast)] + __codec_x_edqy if __codec_x_edqy == 5usize as ::core::primitive::u8 => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Ok(FungiblesError::NoPermission) + })(); + } + #[allow(clippy::unnecessary_cast)] + __codec_x_edqy if __codec_x_edqy == 6usize as ::core::primitive::u8 => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Ok(FungiblesError::Unknown) + })(); + } + #[allow(clippy::unnecessary_cast)] + __codec_x_edqy if __codec_x_edqy == 7usize as ::core::primitive::u8 => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Ok(FungiblesError::ZeroRecipientAddress) + })(); + } + #[allow(clippy::unnecessary_cast)] + __codec_x_edqy if __codec_x_edqy == 8usize as ::core::primitive::u8 => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Ok(FungiblesError::ZeroSenderAddress) + })(); + } + _ => { + #[allow(clippy::redundant_closure_call)] + return (move || { + ::core::result::Result::Err( + <_ as ::core::convert::Into< + _, + >>::into( + "Could not decode `FungiblesError`, variant doesn't exist", + ), + ) + })(); + } + } + } + } +}; +impl From for FungiblesError { + fn from(error: Error) -> Self { + match error { + Error::InUse => FungiblesError::InUse, + Error::MinBalanceZero => FungiblesError::MinBalanceZero, + Error::Unknown => FungiblesError::Unknown, + _ => ::core::panicking::panic("not yet implemented"), + } + } +} +/// The fungibles result type. +pub type Result = core::result::Result; +mod fungibles { + impl ::ink::env::ContractEnv for Fungibles { + type Env = pop_api::Environment; + } + type Environment = ::Env; + type AccountId = <::Env as ::ink::env::Environment>::AccountId; + type Balance = <::Env as ::ink::env::Environment>::Balance; + type Hash = <::Env as ::ink::env::Environment>::Hash; + type Timestamp = <::Env as ::ink::env::Environment>::Timestamp; + type BlockNumber = <::Env as ::ink::env::Environment>::BlockNumber; + type ChainExtension = <::Env as ::ink::env::Environment>::ChainExtension; + const MAX_EVENT_TOPICS: usize = <::Env as ::ink::env::Environment>::MAX_EVENT_TOPICS; + const _: () = { + struct Check { + salt: (), + } + }; + #[scale_info(crate = ::ink::scale_info)] + #[cfg(not(feature = "__ink_dylint_Storage"))] + pub struct Fungibles {} + const _: () = { + impl< + __ink_generic_salt: ::ink::storage::traits::StorageKey, + > ::ink::storage::traits::StorableHint<__ink_generic_salt> for Fungibles { + type Type = Fungibles; + type PreferredKey = ::ink::storage::traits::AutoKey; + } + }; + const _: () = { + impl ::ink::storage::traits::StorageKey for Fungibles { + const KEY: ::ink::primitives::Key = <() as ::ink::storage::traits::StorageKey>::KEY; + } + }; + const _: () = { + impl ::ink::storage::traits::Storable for Fungibles { + #[inline(always)] + #[allow(non_camel_case_types)] + fn decode<__ink_I: ::ink::scale::Input>( + __input: &mut __ink_I, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Fungibles {}) + } + #[inline(always)] + #[allow(non_camel_case_types)] + fn encode<__ink_O: ::ink::scale::Output + ?::core::marker::Sized>( + &self, + __dest: &mut __ink_O, + ) { + match self { + Fungibles {} => {} + } + } + #[inline(always)] + #[allow(non_camel_case_types)] + fn encoded_size(&self) -> ::core::primitive::usize { + match self { + Fungibles {} => ::core::primitive::usize::MIN, + } + } + } + }; + #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] + const _: () = { + impl ::ink::scale_info::TypeInfo for Fungibles { + type Identity = Self; + fn type_info() -> ::ink::scale_info::Type { + ::ink::scale_info::Type::builder() + .path( + ::ink::scale_info::Path::new_with_replace( + "Fungibles", + "fungibles::fungibles", + &[], + ), + ) + .type_params(::alloc::vec::Vec::new()) + .composite(::ink::scale_info::build::Fields::named()) + } + } + }; + const _: () = { + impl ::ink::storage::traits::StorageLayout for Fungibles { + fn layout( + __key: &::ink::primitives::Key, + ) -> ::ink::metadata::layout::Layout { + ::ink::metadata::layout::Layout::Struct( + ::ink::metadata::layout::StructLayout::new("Fungibles", []), + ) + } + } + }; + #[automatically_derived] + impl ::core::default::Default for Fungibles { + #[inline] + fn default() -> Fungibles { + Fungibles {} + } + } + const _: () = { + impl ::ink::reflect::ContractName for Fungibles { + const NAME: &'static str = "Fungibles"; + } + }; + const _: () = { + impl<'a> ::ink::codegen::Env for &'a Fungibles { + type EnvAccess = ::ink::EnvAccess< + 'a, + ::Env, + >; + fn env(self) -> Self::EnvAccess { + <::EnvAccess as ::core::default::Default>::default() + } + } + impl<'a> ::ink::codegen::StaticEnv for Fungibles { + type EnvAccess = ::ink::EnvAccess< + 'static, + ::Env, + >; + fn env() -> Self::EnvAccess { + <::EnvAccess as ::core::default::Default>::default() + } + } + }; + const _: () = { + #[allow(unused_imports)] + use ::ink::codegen::{Env as _, StaticEnv as _}; + }; + impl ::ink::reflect::DispatchableConstructorInfo<0x9BAE9D5E_u32> for Fungibles { + type Input = (); + type Output = Self; + type Storage = Fungibles; + type Error = <::ink::reflect::ConstructorOutputValue< + Self, + > as ::ink::reflect::ConstructorOutput>::Error; + const IS_RESULT: ::core::primitive::bool = <::ink::reflect::ConstructorOutputValue< + Self, + > as ::ink::reflect::ConstructorOutput>::IS_RESULT; + const CALLABLE: fn(Self::Input) -> Self::Output = |_| { Fungibles::new() }; + const PAYABLE: ::core::primitive::bool = true; + const SELECTOR: [::core::primitive::u8; 4usize] = [ + 0x9B_u8, + 0xAE_u8, + 0x9D_u8, + 0x5E_u8, + ]; + const LABEL: &'static ::core::primitive::str = "new"; + } + impl ::ink::reflect::DispatchableMessageInfo<0xDB6375A8_u32> for Fungibles { + type Input = AssetId; + type Output = Result; + type Storage = Fungibles; + const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | + storage, + __ink_binding_0| + { Fungibles::total_supply(storage, __ink_binding_0) }; + const SELECTOR: [::core::primitive::u8; 4usize] = [ + 0xDB_u8, + 0x63_u8, + 0x75_u8, + 0xA8_u8, + ]; + const PAYABLE: ::core::primitive::bool = false; + const MUTATES: ::core::primitive::bool = false; + const LABEL: &'static ::core::primitive::str = "total_supply"; + } + impl ::ink::reflect::DispatchableMessageInfo<0x0F755A56_u32> for Fungibles { + type Input = (AssetId, AccountId32); + type Output = Result; + type Storage = Fungibles; + const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | + storage, + (__ink_binding_0, __ink_binding_1)| + { Fungibles::balance_of(storage, __ink_binding_0, __ink_binding_1) }; + const SELECTOR: [::core::primitive::u8; 4usize] = [ + 0x0F_u8, + 0x75_u8, + 0x5A_u8, + 0x56_u8, + ]; + const PAYABLE: ::core::primitive::bool = false; + const MUTATES: ::core::primitive::bool = false; + const LABEL: &'static ::core::primitive::str = "balance_of"; + } + impl ::ink::reflect::DispatchableMessageInfo<0x6A00165E_u32> for Fungibles { + type Input = (AssetId, AccountId32, AccountId32); + type Output = Result; + type Storage = Fungibles; + const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | + storage, + (__ink_binding_0, __ink_binding_1, __ink_binding_2)| + { + Fungibles::allowance( + storage, + __ink_binding_0, + __ink_binding_1, + __ink_binding_2, + ) + }; + const SELECTOR: [::core::primitive::u8; 4usize] = [ + 0x6A_u8, + 0x00_u8, + 0x16_u8, + 0x5E_u8, + ]; + const PAYABLE: ::core::primitive::bool = false; + const MUTATES: ::core::primitive::bool = false; + const LABEL: &'static ::core::primitive::str = "allowance"; + } + impl ::ink::reflect::DispatchableMessageInfo<0xAA6B65DB_u32> for Fungibles { + type Input = AssetId; + type Output = Result; + type Storage = Fungibles; + const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | + storage, + __ink_binding_0| + { Fungibles::asset_exists(storage, __ink_binding_0) }; + const SELECTOR: [::core::primitive::u8; 4usize] = [ + 0xAA_u8, + 0x6B_u8, + 0x65_u8, + 0xDB_u8, + ]; + const PAYABLE: ::core::primitive::bool = false; + const MUTATES: ::core::primitive::bool = false; + const LABEL: &'static ::core::primitive::str = "asset_exists"; + } + impl ::ink::reflect::DispatchableMessageInfo<0x1F8E8E22_u32> for Fungibles { + type Input = (u32, AccountId32, Balance); + type Output = Result<()>; + type Storage = Fungibles; + const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | + storage, + (__ink_binding_0, __ink_binding_1, __ink_binding_2)| + { + Fungibles::mint_asset( + storage, + __ink_binding_0, + __ink_binding_1, + __ink_binding_2, + ) + }; + const SELECTOR: [::core::primitive::u8; 4usize] = [ + 0x1F_u8, + 0x8E_u8, + 0x8E_u8, + 0x22_u8, + ]; + const PAYABLE: ::core::primitive::bool = false; + const MUTATES: ::core::primitive::bool = false; + const LABEL: &'static ::core::primitive::str = "mint_asset"; + } + const _: () = { + #[allow(non_camel_case_types)] + pub enum __ink_ConstructorDecoder { + Constructor0( + >::Input, + ), + } + impl ::ink::reflect::DecodeDispatch for __ink_ConstructorDecoder { + fn decode_dispatch( + input: &mut I, + ) -> ::core::result::Result + where + I: ::ink::scale::Input, + { + const CONSTRUCTOR_0: [::core::primitive::u8; 4usize] = >::SELECTOR; + match <[::core::primitive::u8; 4usize] as ::ink::scale::Decode>::decode( + input, + ) + .map_err(|_| ::ink::reflect::DispatchError::InvalidSelector)? + { + CONSTRUCTOR_0 => { + ::core::result::Result::Ok( + Self::Constructor0( + <>::Input as ::ink::scale::Decode>::decode(input) + .map_err(|_| { + ::ink::reflect::DispatchError::InvalidParameters + })?, + ), + ) + } + _invalid => { + ::core::result::Result::Err( + ::ink::reflect::DispatchError::UnknownSelector, + ) + } + } + } + } + impl ::ink::scale::Decode for __ink_ConstructorDecoder { + fn decode( + input: &mut I, + ) -> ::core::result::Result + where + I: ::ink::scale::Input, + { + ::decode_dispatch(input) + .map_err(::core::convert::Into::into) + } + } + impl ::ink::reflect::ExecuteDispatchable for __ink_ConstructorDecoder { + #[allow(clippy::nonminimal_bool)] + fn execute_dispatchable( + self, + ) -> ::core::result::Result<(), ::ink::reflect::DispatchError> { + match self { + Self::Constructor0(input) => { + if { + false + || { + let constructor_0 = false; + let constructor_0 = >::PAYABLE; + constructor_0 + } + } + && !>::PAYABLE + { + ::ink::codegen::deny_payment::< + ::Env, + >()?; + } + let result: >::Output = >::CALLABLE(input); + let output_value = ::ink::reflect::ConstructorOutputValue::new( + result, + ); + let output_result = <::ink::reflect::ConstructorOutputValue< + >::Output, + > as ::ink::reflect::ConstructorOutput< + Fungibles, + >>::as_result(&output_value); + if let ::core::result::Result::Ok(contract) = output_result + .as_ref() + { + ::ink::env::set_contract_storage::< + ::ink::primitives::Key, + Fungibles, + >( + &::KEY, + contract, + ); + } + let mut flag = ::ink::env::ReturnFlags::empty(); + if output_result.is_err() { + flag = ::ink::env::ReturnFlags::REVERT; + } + ::ink::env::return_value::< + ::ink::ConstructorResult< + ::core::result::Result< + (), + &<::ink::reflect::ConstructorOutputValue< + >::Output, + > as ::ink::reflect::ConstructorOutput>::Error, + >, + >, + >( + flag, + &::ink::ConstructorResult::Ok(output_result.map(|_| ())), + ); + } + } + } + } + impl ::ink::reflect::ContractConstructorDecoder for Fungibles { + type Type = __ink_ConstructorDecoder; + } + }; + const _: () = { + #[allow(non_camel_case_types)] + pub enum __ink_MessageDecoder { + Message0( + >::Input, + ), + Message1( + >::Input, + ), + Message2( + >::Input, + ), + Message3( + >::Input, + ), + Message4( + >::Input, + ), + } + impl ::ink::reflect::DecodeDispatch for __ink_MessageDecoder { + fn decode_dispatch( + input: &mut I, + ) -> ::core::result::Result + where + I: ::ink::scale::Input, + { + const MESSAGE_0: [::core::primitive::u8; 4usize] = >::SELECTOR; + const MESSAGE_1: [::core::primitive::u8; 4usize] = >::SELECTOR; + const MESSAGE_2: [::core::primitive::u8; 4usize] = >::SELECTOR; + const MESSAGE_3: [::core::primitive::u8; 4usize] = >::SELECTOR; + const MESSAGE_4: [::core::primitive::u8; 4usize] = >::SELECTOR; + match <[::core::primitive::u8; 4usize] as ::ink::scale::Decode>::decode( + input, + ) + .map_err(|_| ::ink::reflect::DispatchError::InvalidSelector)? + { + MESSAGE_0 => { + ::core::result::Result::Ok( + Self::Message0( + <>::Input as ::ink::scale::Decode>::decode(input) + .map_err(|_| { + ::ink::reflect::DispatchError::InvalidParameters + })?, + ), + ) + } + MESSAGE_1 => { + ::core::result::Result::Ok( + Self::Message1( + <>::Input as ::ink::scale::Decode>::decode(input) + .map_err(|_| { + ::ink::reflect::DispatchError::InvalidParameters + })?, + ), + ) + } + MESSAGE_2 => { + ::core::result::Result::Ok( + Self::Message2( + <>::Input as ::ink::scale::Decode>::decode(input) + .map_err(|_| { + ::ink::reflect::DispatchError::InvalidParameters + })?, + ), + ) + } + MESSAGE_3 => { + ::core::result::Result::Ok( + Self::Message3( + <>::Input as ::ink::scale::Decode>::decode(input) + .map_err(|_| { + ::ink::reflect::DispatchError::InvalidParameters + })?, + ), + ) + } + MESSAGE_4 => { + ::core::result::Result::Ok( + Self::Message4( + <>::Input as ::ink::scale::Decode>::decode(input) + .map_err(|_| { + ::ink::reflect::DispatchError::InvalidParameters + })?, + ), + ) + } + _invalid => { + ::core::result::Result::Err( + ::ink::reflect::DispatchError::UnknownSelector, + ) + } + } + } + } + impl ::ink::scale::Decode for __ink_MessageDecoder { + fn decode( + input: &mut I, + ) -> ::core::result::Result + where + I: ::ink::scale::Input, + { + ::decode_dispatch(input) + .map_err(::core::convert::Into::into) + } + } + fn push_contract(contract: ::core::mem::ManuallyDrop, mutates: bool) { + if mutates { + ::ink::env::set_contract_storage::< + ::ink::primitives::Key, + Fungibles, + >(&::KEY, &contract); + } + } + impl ::ink::reflect::ExecuteDispatchable for __ink_MessageDecoder { + #[allow(clippy::nonminimal_bool, clippy::let_unit_value)] + fn execute_dispatchable( + self, + ) -> ::core::result::Result<(), ::ink::reflect::DispatchError> { + let key = ::KEY; + let mut contract: ::core::mem::ManuallyDrop = ::core::mem::ManuallyDrop::new( + match ::ink::env::get_contract_storage(&key) { + ::core::result::Result::Ok( + ::core::option::Option::Some(value), + ) => value, + ::core::result::Result::Ok(::core::option::Option::None) => { + ::core::panicking::panic_fmt( + format_args!("storage entry was empty"), + ); + } + ::core::result::Result::Err(_) => { + ::core::panicking::panic_fmt( + format_args!("could not properly decode storage entry"), + ); + } + }, + ); + match self { + Self::Message0(input) => { + if { + false + || { + let message_0 = false; + let message_0 = >::PAYABLE; + message_0 + } + || { + let message_1 = false; + let message_1 = >::PAYABLE; + message_1 + } + || { + let message_2 = false; + let message_2 = >::PAYABLE; + message_2 + } + || { + let message_3 = false; + let message_3 = >::PAYABLE; + message_3 + } + || { + let message_4 = false; + let message_4 = >::PAYABLE; + message_4 + } + } + && !>::PAYABLE + { + ::ink::codegen::deny_payment::< + ::Env, + >()?; + } + let result: >::Output = >::CALLABLE(&mut contract, input); + let is_reverted = { + #[allow(unused_imports)] + use ::ink::result_info::IsResultTypeFallback as _; + ::ink::result_info::IsResultType::< + >::Output, + >::VALUE + } + && { + #[allow(unused_imports)] + use ::ink::result_info::IsResultErrFallback as _; + ::ink::result_info::IsResultErr(&result).value() + }; + let mut flag = ::ink::env::ReturnFlags::REVERT; + if !is_reverted { + flag = ::ink::env::ReturnFlags::empty(); + push_contract( + contract, + >::MUTATES, + ); + } + ::ink::env::return_value::< + ::ink::MessageResult< + >::Output, + >, + >(flag, &::ink::MessageResult::Ok(result)) + } + Self::Message1(input) => { + if { + false + || { + let message_0 = false; + let message_0 = >::PAYABLE; + message_0 + } + || { + let message_1 = false; + let message_1 = >::PAYABLE; + message_1 + } + || { + let message_2 = false; + let message_2 = >::PAYABLE; + message_2 + } + || { + let message_3 = false; + let message_3 = >::PAYABLE; + message_3 + } + || { + let message_4 = false; + let message_4 = >::PAYABLE; + message_4 + } + } + && !>::PAYABLE + { + ::ink::codegen::deny_payment::< + ::Env, + >()?; + } + let result: >::Output = >::CALLABLE(&mut contract, input); + let is_reverted = { + #[allow(unused_imports)] + use ::ink::result_info::IsResultTypeFallback as _; + ::ink::result_info::IsResultType::< + >::Output, + >::VALUE + } + && { + #[allow(unused_imports)] + use ::ink::result_info::IsResultErrFallback as _; + ::ink::result_info::IsResultErr(&result).value() + }; + let mut flag = ::ink::env::ReturnFlags::REVERT; + if !is_reverted { + flag = ::ink::env::ReturnFlags::empty(); + push_contract( + contract, + >::MUTATES, + ); + } + ::ink::env::return_value::< + ::ink::MessageResult< + >::Output, + >, + >(flag, &::ink::MessageResult::Ok(result)) + } + Self::Message2(input) => { + if { + false + || { + let message_0 = false; + let message_0 = >::PAYABLE; + message_0 + } + || { + let message_1 = false; + let message_1 = >::PAYABLE; + message_1 + } + || { + let message_2 = false; + let message_2 = >::PAYABLE; + message_2 + } + || { + let message_3 = false; + let message_3 = >::PAYABLE; + message_3 + } + || { + let message_4 = false; + let message_4 = >::PAYABLE; + message_4 + } + } + && !>::PAYABLE + { + ::ink::codegen::deny_payment::< + ::Env, + >()?; + } + let result: >::Output = >::CALLABLE(&mut contract, input); + let is_reverted = { + #[allow(unused_imports)] + use ::ink::result_info::IsResultTypeFallback as _; + ::ink::result_info::IsResultType::< + >::Output, + >::VALUE + } + && { + #[allow(unused_imports)] + use ::ink::result_info::IsResultErrFallback as _; + ::ink::result_info::IsResultErr(&result).value() + }; + let mut flag = ::ink::env::ReturnFlags::REVERT; + if !is_reverted { + flag = ::ink::env::ReturnFlags::empty(); + push_contract( + contract, + >::MUTATES, + ); + } + ::ink::env::return_value::< + ::ink::MessageResult< + >::Output, + >, + >(flag, &::ink::MessageResult::Ok(result)) + } + Self::Message3(input) => { + if { + false + || { + let message_0 = false; + let message_0 = >::PAYABLE; + message_0 + } + || { + let message_1 = false; + let message_1 = >::PAYABLE; + message_1 + } + || { + let message_2 = false; + let message_2 = >::PAYABLE; + message_2 + } + || { + let message_3 = false; + let message_3 = >::PAYABLE; + message_3 + } + || { + let message_4 = false; + let message_4 = >::PAYABLE; + message_4 + } + } + && !>::PAYABLE + { + ::ink::codegen::deny_payment::< + ::Env, + >()?; + } + let result: >::Output = >::CALLABLE(&mut contract, input); + let is_reverted = { + #[allow(unused_imports)] + use ::ink::result_info::IsResultTypeFallback as _; + ::ink::result_info::IsResultType::< + >::Output, + >::VALUE + } + && { + #[allow(unused_imports)] + use ::ink::result_info::IsResultErrFallback as _; + ::ink::result_info::IsResultErr(&result).value() + }; + let mut flag = ::ink::env::ReturnFlags::REVERT; + if !is_reverted { + flag = ::ink::env::ReturnFlags::empty(); + push_contract( + contract, + >::MUTATES, + ); + } + ::ink::env::return_value::< + ::ink::MessageResult< + >::Output, + >, + >(flag, &::ink::MessageResult::Ok(result)) + } + Self::Message4(input) => { + if { + false + || { + let message_0 = false; + let message_0 = >::PAYABLE; + message_0 + } + || { + let message_1 = false; + let message_1 = >::PAYABLE; + message_1 + } + || { + let message_2 = false; + let message_2 = >::PAYABLE; + message_2 + } + || { + let message_3 = false; + let message_3 = >::PAYABLE; + message_3 + } + || { + let message_4 = false; + let message_4 = >::PAYABLE; + message_4 + } + } + && !>::PAYABLE + { + ::ink::codegen::deny_payment::< + ::Env, + >()?; + } + let result: >::Output = >::CALLABLE(&mut contract, input); + let is_reverted = { + #[allow(unused_imports)] + use ::ink::result_info::IsResultTypeFallback as _; + ::ink::result_info::IsResultType::< + >::Output, + >::VALUE + } + && { + #[allow(unused_imports)] + use ::ink::result_info::IsResultErrFallback as _; + ::ink::result_info::IsResultErr(&result).value() + }; + let mut flag = ::ink::env::ReturnFlags::REVERT; + if !is_reverted { + flag = ::ink::env::ReturnFlags::empty(); + push_contract( + contract, + >::MUTATES, + ); + } + ::ink::env::return_value::< + ::ink::MessageResult< + >::Output, + >, + >(flag, &::ink::MessageResult::Ok(result)) + } + }; + } + } + impl ::ink::reflect::ContractMessageDecoder for Fungibles { + type Type = __ink_MessageDecoder; + } + }; + const _: () = { + use ::ink::codegen::{Env as _, StaticEnv as _}; + const _: ::ink::codegen::utils::IsSameType = ::ink::codegen::utils::IsSameType::< + Fungibles, + >::new(); + impl Fungibles { + #[cfg(not(feature = "__ink_dylint_Constructor"))] + pub fn new() -> Self { + ::ink_env::debug_message( + &{ + let res = ::alloc::fmt::format( + format_args!( + "{0}\n", + { + let res = ::alloc::fmt::format( + format_args!("PopApiAssetsExample::new"), + ); + res + }, + ), + ); + res + }, + ); + Default::default() + } + pub fn total_supply(&self, id: AssetId) -> Result { + total_supply(id).map_err(From::from) + } + pub fn balance_of( + &self, + id: AssetId, + owner: AccountId32, + ) -> Result { + balance_of(id, owner).map_err(From::from) + } + pub fn allowance( + &self, + id: AssetId, + owner: AccountId32, + spender: AccountId32, + ) -> Result { + allowance(id, owner, spender).map_err(From::from) + } + pub fn asset_exists(&self, id: AssetId) -> Result { + asset_exists(id).map_err(From::from) + } + pub fn mint_asset( + &self, + id: u32, + beneficiary: AccountId32, + amount: Balance, + ) -> Result<()> { + ::ink_env::debug_message( + &{ + let res = ::alloc::fmt::format( + format_args!( + "{0}\n", + { + let res = ::alloc::fmt::format( + format_args!( + "PopApiAssetsExample::mint_asset_through_runtime: id: {0:?} beneficiary: {1:?} amount: {2:?}", + id, + beneficiary, + amount, + ), + ); + res + }, + ), + ); + res + }, + ); + let result = mint(id, beneficiary, amount)?; + ::ink_env::debug_message( + &{ + let res = ::alloc::fmt::format( + format_args!( + "{0}\n", + { + let res = ::alloc::fmt::format( + format_args!("Result: {0:?}", result), + ); + res + }, + ), + ); + res + }, + ); + Ok(()) + } + } + const _: () = { + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchInput, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchOutput>, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchInput, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchInput, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchOutput>, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchInput, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchInput, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchInput, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchOutput>, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchInput, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchOutput>, + >(); + ::ink::codegen::utils::consume_type::<::ink::codegen::DispatchInput>(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchInput, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchInput, + >(); + ::ink::codegen::utils::consume_type::< + ::ink::codegen::DispatchOutput>, + >(); + }; + }; + const _: () = { + #[codec(crate = ::ink::scale)] + #[scale_info(crate = ::ink::scale_info)] + /// The ink! smart contract's call builder. + /// + /// Implements the underlying on-chain calling of the ink! smart contract + /// messages and trait implementations in a type safe way. + #[repr(transparent)] + pub struct CallBuilder { + account_id: AccountId, + } + #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] + const _: () = { + impl ::ink::scale_info::TypeInfo for CallBuilder { + type Identity = Self; + fn type_info() -> ::ink::scale_info::Type { + ::ink::scale_info::Type::builder() + .path( + ::ink::scale_info::Path::new_with_replace( + "CallBuilder", + "fungibles::fungibles", + &[], + ), + ) + .type_params(::alloc::vec::Vec::new()) + .docs( + &[ + "The ink! smart contract's call builder.", + "", + "Implements the underlying on-chain calling of the ink! smart contract", + "messages and trait implementations in a type safe way.", + ], + ) + .composite( + ::ink::scale_info::build::Fields::named() + .field(|f| { + f + .ty::() + .name("account_id") + .type_name("AccountId") + }), + ) + } + } + }; + #[allow(deprecated)] + const _: () = { + #[automatically_derived] + impl ::ink::scale::Decode for CallBuilder { + fn decode<__CodecInputEdqy: ::ink::scale::Input>( + __codec_input_edqy: &mut __CodecInputEdqy, + ) -> ::core::result::Result { + ::core::result::Result::Ok(CallBuilder { + account_id: { + let __codec_res_edqy = ::decode( + __codec_input_edqy, + ); + match __codec_res_edqy { + ::core::result::Result::Err(e) => { + return ::core::result::Result::Err( + e.chain("Could not decode `CallBuilder::account_id`"), + ); + } + ::core::result::Result::Ok(__codec_res_edqy) => { + __codec_res_edqy + } + } + }, + }) + } + fn decode_into<__CodecInputEdqy: ::ink::scale::Input>( + __codec_input_edqy: &mut __CodecInputEdqy, + dst_: &mut ::core::mem::MaybeUninit, + ) -> ::core::result::Result< + ::ink::scale::DecodeFinished, + ::ink::scale::Error, + > { + match ( + &::core::mem::size_of::(), + &::core::mem::size_of::(), + ) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::None, + ); + } + } + }; + if !(if ::core::mem::size_of::() > 0 { 1 } else { 0 } + <= 1) + { + ::core::panicking::panic( + "assertion failed: if ::core::mem::size_of::() > 0 { 1 } else { 0 } <= 1", + ) + } + { + let dst_: &mut ::core::mem::MaybeUninit = dst_; + let dst_: &mut ::core::mem::MaybeUninit = unsafe { + &mut *dst_ + .as_mut_ptr() + .cast::<::core::mem::MaybeUninit>() + }; + ::decode_into( + __codec_input_edqy, + dst_, + )?; + } + unsafe { + ::core::result::Result::Ok( + ::ink::scale::DecodeFinished::assert_decoding_finished(), + ) + } + } + } + }; + #[allow(deprecated)] + const _: () = { + #[automatically_derived] + impl ::ink::scale::Encode for CallBuilder { + fn size_hint(&self) -> usize { + ::ink::scale::Encode::size_hint(&&self.account_id) + } + fn encode_to< + __CodecOutputEdqy: ::ink::scale::Output + ?::core::marker::Sized, + >(&self, __codec_dest_edqy: &mut __CodecOutputEdqy) { + ::ink::scale::Encode::encode_to(&&self.account_id, __codec_dest_edqy) + } + fn encode( + &self, + ) -> ::ink::scale::alloc::vec::Vec<::core::primitive::u8> { + ::ink::scale::Encode::encode(&&self.account_id) + } + fn using_encoded< + __CodecOutputReturn, + __CodecUsingEncodedCallback: ::core::ops::FnOnce( + &[::core::primitive::u8], + ) -> __CodecOutputReturn, + >(&self, f: __CodecUsingEncodedCallback) -> __CodecOutputReturn { + ::ink::scale::Encode::using_encoded(&&self.account_id, f) + } + } + #[automatically_derived] + impl ::ink::scale::EncodeLike for CallBuilder {} + }; + #[automatically_derived] + impl ::core::fmt::Debug for CallBuilder { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field1_finish( + f, + "CallBuilder", + "account_id", + &&self.account_id, + ) + } + } + #[automatically_derived] + impl ::core::hash::Hash for CallBuilder { + #[inline] + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.account_id, state) + } + } + #[automatically_derived] + impl ::core::marker::StructuralPartialEq for CallBuilder {} + #[automatically_derived] + impl ::core::cmp::PartialEq for CallBuilder { + #[inline] + fn eq(&self, other: &CallBuilder) -> bool { + self.account_id == other.account_id + } + } + #[automatically_derived] + impl ::core::cmp::Eq for CallBuilder { + #[inline] + #[doc(hidden)] + #[coverage(off)] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq; + } + } + #[automatically_derived] + impl ::core::clone::Clone for CallBuilder { + #[inline] + fn clone(&self) -> CallBuilder { + CallBuilder { + account_id: ::core::clone::Clone::clone(&self.account_id), + } + } + } + const _: () = { + impl ::ink::storage::traits::StorageLayout for CallBuilder { + fn layout( + __key: &::ink::primitives::Key, + ) -> ::ink::metadata::layout::Layout { + ::ink::metadata::layout::Layout::Struct( + ::ink::metadata::layout::StructLayout::new( + "CallBuilder", + [ + ::ink::metadata::layout::FieldLayout::new( + "account_id", + ::layout( + __key, + ), + ), + ], + ), + ) + } + } + }; + const _: () = { + impl ::ink::codegen::ContractCallBuilder for Fungibles { + type Type = CallBuilder; + } + impl ::ink::env::ContractEnv for CallBuilder { + type Env = ::Env; + } + }; + impl ::ink::env::call::FromAccountId for CallBuilder { + #[inline] + fn from_account_id(account_id: AccountId) -> Self { + Self { account_id } + } + } + impl ::ink::ToAccountId for CallBuilder { + #[inline] + fn to_account_id(&self) -> AccountId { + ::clone(&self.account_id) + } + } + impl ::core::convert::AsRef for CallBuilder { + fn as_ref(&self) -> &AccountId { + &self.account_id + } + } + impl ::core::convert::AsMut for CallBuilder { + fn as_mut(&mut self) -> &mut AccountId { + &mut self.account_id + } + } + impl CallBuilder { + #[allow(clippy::type_complexity)] + #[inline] + pub fn total_supply( + &self, + __ink_binding_0: AssetId, + ) -> ::ink::env::call::CallBuilder< + Environment, + ::ink::env::call::utils::Set<::ink::env::call::Call>, + ::ink::env::call::utils::Set< + ::ink::env::call::ExecutionInput< + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::EmptyArgumentList, + >, + >, + >, + ::ink::env::call::utils::Set< + ::ink::env::call::utils::ReturnType>, + >, + > { + ::ink::env::call::build_call::() + .call(::ink::ToAccountId::to_account_id(self)) + .exec_input( + ::ink::env::call::ExecutionInput::new( + ::ink::env::call::Selector::new([ + 0xDB_u8, + 0x63_u8, + 0x75_u8, + 0xA8_u8, + ]), + ) + .push_arg(__ink_binding_0), + ) + .returns::>() + } + #[allow(clippy::type_complexity)] + #[inline] + pub fn balance_of( + &self, + __ink_binding_0: AssetId, + __ink_binding_1: AccountId32, + ) -> ::ink::env::call::CallBuilder< + Environment, + ::ink::env::call::utils::Set<::ink::env::call::Call>, + ::ink::env::call::utils::Set< + ::ink::env::call::ExecutionInput< + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::EmptyArgumentList, + >, + >, + >, + >, + ::ink::env::call::utils::Set< + ::ink::env::call::utils::ReturnType>, + >, + > { + ::ink::env::call::build_call::() + .call(::ink::ToAccountId::to_account_id(self)) + .exec_input( + ::ink::env::call::ExecutionInput::new( + ::ink::env::call::Selector::new([ + 0x0F_u8, + 0x75_u8, + 0x5A_u8, + 0x56_u8, + ]), + ) + .push_arg(__ink_binding_0) + .push_arg(__ink_binding_1), + ) + .returns::>() + } + #[allow(clippy::type_complexity)] + #[inline] + pub fn allowance( + &self, + __ink_binding_0: AssetId, + __ink_binding_1: AccountId32, + __ink_binding_2: AccountId32, + ) -> ::ink::env::call::CallBuilder< + Environment, + ::ink::env::call::utils::Set<::ink::env::call::Call>, + ::ink::env::call::utils::Set< + ::ink::env::call::ExecutionInput< + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::EmptyArgumentList, + >, + >, + >, + >, + >, + ::ink::env::call::utils::Set< + ::ink::env::call::utils::ReturnType>, + >, + > { + ::ink::env::call::build_call::() + .call(::ink::ToAccountId::to_account_id(self)) + .exec_input( + ::ink::env::call::ExecutionInput::new( + ::ink::env::call::Selector::new([ + 0x6A_u8, + 0x00_u8, + 0x16_u8, + 0x5E_u8, + ]), + ) + .push_arg(__ink_binding_0) + .push_arg(__ink_binding_1) + .push_arg(__ink_binding_2), + ) + .returns::>() + } + #[allow(clippy::type_complexity)] + #[inline] + pub fn asset_exists( + &self, + __ink_binding_0: AssetId, + ) -> ::ink::env::call::CallBuilder< + Environment, + ::ink::env::call::utils::Set<::ink::env::call::Call>, + ::ink::env::call::utils::Set< + ::ink::env::call::ExecutionInput< + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::EmptyArgumentList, + >, + >, + >, + ::ink::env::call::utils::Set< + ::ink::env::call::utils::ReturnType>, + >, + > { + ::ink::env::call::build_call::() + .call(::ink::ToAccountId::to_account_id(self)) + .exec_input( + ::ink::env::call::ExecutionInput::new( + ::ink::env::call::Selector::new([ + 0xAA_u8, + 0x6B_u8, + 0x65_u8, + 0xDB_u8, + ]), + ) + .push_arg(__ink_binding_0), + ) + .returns::>() + } + #[allow(clippy::type_complexity)] + #[inline] + pub fn mint_asset( + &self, + __ink_binding_0: u32, + __ink_binding_1: AccountId32, + __ink_binding_2: Balance, + ) -> ::ink::env::call::CallBuilder< + Environment, + ::ink::env::call::utils::Set<::ink::env::call::Call>, + ::ink::env::call::utils::Set< + ::ink::env::call::ExecutionInput< + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::ArgumentList< + ::ink::env::call::utils::Argument, + ::ink::env::call::utils::EmptyArgumentList, + >, + >, + >, + >, + >, + ::ink::env::call::utils::Set< + ::ink::env::call::utils::ReturnType>, + >, + > { + ::ink::env::call::build_call::() + .call(::ink::ToAccountId::to_account_id(self)) + .exec_input( + ::ink::env::call::ExecutionInput::new( + ::ink::env::call::Selector::new([ + 0x1F_u8, + 0x8E_u8, + 0x8E_u8, + 0x22_u8, + ]), + ) + .push_arg(__ink_binding_0) + .push_arg(__ink_binding_1) + .push_arg(__ink_binding_2), + ) + .returns::>() + } + } + }; + #[codec(crate = ::ink::scale)] + #[scale_info(crate = ::ink::scale_info)] + pub struct FungiblesRef { + inner: ::Type, + } + #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] + const _: () = { + impl ::ink::scale_info::TypeInfo for FungiblesRef { + type Identity = Self; + fn type_info() -> ::ink::scale_info::Type { + ::ink::scale_info::Type::builder() + .path( + ::ink::scale_info::Path::new_with_replace( + "FungiblesRef", + "fungibles::fungibles", + &[], + ), + ) + .type_params(::alloc::vec::Vec::new()) + .composite( + ::ink::scale_info::build::Fields::named() + .field(|f| { + f + .ty::< + ::Type, + >() + .name("inner") + .type_name( + "::Type", + ) + }), + ) + } + } + }; + #[allow(deprecated)] + const _: () = { + #[automatically_derived] + impl ::ink::scale::Decode for FungiblesRef { + fn decode<__CodecInputEdqy: ::ink::scale::Input>( + __codec_input_edqy: &mut __CodecInputEdqy, + ) -> ::core::result::Result { + ::core::result::Result::Ok(FungiblesRef { + inner: { + let __codec_res_edqy = <::Type as ::ink::scale::Decode>::decode( + __codec_input_edqy, + ); + match __codec_res_edqy { + ::core::result::Result::Err(e) => { + return ::core::result::Result::Err( + e.chain("Could not decode `FungiblesRef::inner`"), + ); + } + ::core::result::Result::Ok(__codec_res_edqy) => { + __codec_res_edqy + } + } + }, + }) + } + } + }; + #[allow(deprecated)] + const _: () = { + #[automatically_derived] + impl ::ink::scale::Encode for FungiblesRef { + fn size_hint(&self) -> usize { + ::ink::scale::Encode::size_hint(&&self.inner) + } + fn encode_to< + __CodecOutputEdqy: ::ink::scale::Output + ?::core::marker::Sized, + >(&self, __codec_dest_edqy: &mut __CodecOutputEdqy) { + ::ink::scale::Encode::encode_to(&&self.inner, __codec_dest_edqy) + } + fn encode(&self) -> ::ink::scale::alloc::vec::Vec<::core::primitive::u8> { + ::ink::scale::Encode::encode(&&self.inner) + } + fn using_encoded< + __CodecOutputReturn, + __CodecUsingEncodedCallback: ::core::ops::FnOnce( + &[::core::primitive::u8], + ) -> __CodecOutputReturn, + >(&self, f: __CodecUsingEncodedCallback) -> __CodecOutputReturn { + ::ink::scale::Encode::using_encoded(&&self.inner, f) + } + } + #[automatically_derived] + impl ::ink::scale::EncodeLike for FungiblesRef {} + }; + #[automatically_derived] + impl ::core::fmt::Debug for FungiblesRef { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field1_finish( + f, + "FungiblesRef", + "inner", + &&self.inner, + ) + } + } + #[automatically_derived] + impl ::core::hash::Hash for FungiblesRef { + #[inline] + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.inner, state) + } + } + #[automatically_derived] + impl ::core::marker::StructuralPartialEq for FungiblesRef {} + #[automatically_derived] + impl ::core::cmp::PartialEq for FungiblesRef { + #[inline] + fn eq(&self, other: &FungiblesRef) -> bool { + self.inner == other.inner + } + } + #[automatically_derived] + impl ::core::cmp::Eq for FungiblesRef { + #[inline] + #[doc(hidden)] + #[coverage(off)] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq< + ::Type, + >; + } + } + #[automatically_derived] + impl ::core::clone::Clone for FungiblesRef { + #[inline] + fn clone(&self) -> FungiblesRef { + FungiblesRef { + inner: ::core::clone::Clone::clone(&self.inner), + } + } + } + const _: () = { + impl ::ink::storage::traits::StorageLayout for FungiblesRef { + fn layout( + __key: &::ink::primitives::Key, + ) -> ::ink::metadata::layout::Layout { + ::ink::metadata::layout::Layout::Struct( + ::ink::metadata::layout::StructLayout::new( + "FungiblesRef", + [ + ::ink::metadata::layout::FieldLayout::new( + "inner", + <::Type as ::ink::storage::traits::StorageLayout>::layout( + __key, + ), + ), + ], + ), + ) + } + } + }; + const _: () = { + impl ::ink::env::ContractReference for Fungibles { + type Type = FungiblesRef; + } + impl ::ink::env::call::ConstructorReturnType for Fungibles { + type Output = FungiblesRef; + type Error = (); + fn ok(value: FungiblesRef) -> Self::Output { + value + } + } + impl ::ink::env::call::ConstructorReturnType + for ::core::result::Result + where + E: ::ink::scale::Decode, + { + const IS_RESULT: bool = true; + type Output = ::core::result::Result; + type Error = E; + fn ok(value: FungiblesRef) -> Self::Output { + ::core::result::Result::Ok(value) + } + fn err(err: Self::Error) -> ::core::option::Option { + ::core::option::Option::Some(::core::result::Result::Err(err)) + } + } + impl ::ink::env::ContractEnv for FungiblesRef { + type Env = ::Env; + } + }; + impl FungiblesRef { + #[inline] + #[allow(clippy::type_complexity)] + pub fn new() -> ::ink::env::call::CreateBuilder< + Environment, + Self, + ::ink::env::call::utils::Unset, + ::ink::env::call::utils::Set< + ::ink::env::call::LimitParamsV2< + ::Env, + >, + >, + ::ink::env::call::utils::Unset, + ::ink::env::call::utils::Set< + ::ink::env::call::ExecutionInput< + ::ink::env::call::utils::EmptyArgumentList, + >, + >, + ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, + ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType>, + > { + ::ink::env::call::build_create::() + .exec_input( + ::ink::env::call::ExecutionInput::new( + ::ink::env::call::Selector::new([ + 0x9B_u8, + 0xAE_u8, + 0x9D_u8, + 0x5E_u8, + ]), + ), + ) + .returns::() + } + #[inline] + pub fn total_supply(&self, id: AssetId) -> Result { + self.try_total_supply(id) + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "total_supply", + error, + ), + ); + }) + } + #[inline] + pub fn try_total_supply( + &self, + id: AssetId, + ) -> ::ink::MessageResult> { + ::call(self) + .total_supply(id) + .try_invoke() + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "total_supply", + error, + ), + ); + }) + } + #[inline] + pub fn balance_of(&self, id: AssetId, owner: AccountId32) -> Result { + self.try_balance_of(id, owner) + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "balance_of", + error, + ), + ); + }) + } + #[inline] + pub fn try_balance_of( + &self, + id: AssetId, + owner: AccountId32, + ) -> ::ink::MessageResult> { + ::call(self) + .balance_of(id, owner) + .try_invoke() + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "balance_of", + error, + ), + ); + }) + } + #[inline] + pub fn allowance( + &self, + id: AssetId, + owner: AccountId32, + spender: AccountId32, + ) -> Result { + self.try_allowance(id, owner, spender) + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "allowance", + error, + ), + ); + }) + } + #[inline] + pub fn try_allowance( + &self, + id: AssetId, + owner: AccountId32, + spender: AccountId32, + ) -> ::ink::MessageResult> { + ::call(self) + .allowance(id, owner, spender) + .try_invoke() + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "allowance", + error, + ), + ); + }) + } + #[inline] + pub fn asset_exists(&self, id: AssetId) -> Result { + self.try_asset_exists(id) + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "asset_exists", + error, + ), + ); + }) + } + #[inline] + pub fn try_asset_exists( + &self, + id: AssetId, + ) -> ::ink::MessageResult> { + ::call(self) + .asset_exists(id) + .try_invoke() + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "asset_exists", + error, + ), + ); + }) + } + #[inline] + pub fn mint_asset( + &self, + id: u32, + beneficiary: AccountId32, + amount: Balance, + ) -> Result<()> { + self.try_mint_asset(id, beneficiary, amount) + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "mint_asset", + error, + ), + ); + }) + } + #[inline] + pub fn try_mint_asset( + &self, + id: u32, + beneficiary: AccountId32, + amount: Balance, + ) -> ::ink::MessageResult> { + ::call(self) + .mint_asset(id, beneficiary, amount) + .try_invoke() + .unwrap_or_else(|error| { + ::core::panicking::panic_fmt( + format_args!( + "encountered error while calling {0}::{1}: {2:?}", + "Fungibles", + "mint_asset", + error, + ), + ); + }) + } + } + const _: () = { + impl ::ink::codegen::TraitCallBuilder for FungiblesRef { + type Builder = ::Type; + #[inline] + fn call(&self) -> &Self::Builder { + &self.inner + } + #[inline] + fn call_mut(&mut self) -> &mut Self::Builder { + &mut self.inner + } + } + }; + impl ::ink::env::call::FromAccountId for FungiblesRef { + #[inline] + fn from_account_id(account_id: AccountId) -> Self { + Self { + inner: <::Type as ::ink::env::call::FromAccountId< + Environment, + >>::from_account_id(account_id), + } + } + } + impl ::ink::ToAccountId for FungiblesRef { + #[inline] + fn to_account_id(&self) -> AccountId { + <::Type as ::ink::ToAccountId< + Environment, + >>::to_account_id(&self.inner) + } + } + impl ::core::convert::AsRef for FungiblesRef { + fn as_ref(&self) -> &AccountId { + <_ as ::core::convert::AsRef>::as_ref(&self.inner) + } + } + impl ::core::convert::AsMut for FungiblesRef { + fn as_mut(&mut self) -> &mut AccountId { + <_ as ::core::convert::AsMut>::as_mut(&mut self.inner) + } + } + #[cfg(feature = "std")] + #[cfg(not(feature = "ink-as-dependency"))] + const _: () = { + #[no_mangle] + pub fn __ink_generate_metadata() -> ::ink::metadata::InkProject { + let layout = ::ink::metadata::layout::Layout::Root( + ::ink::metadata::layout::RootLayout::new( + <::ink::metadata::layout::LayoutKey as ::core::convert::From< + ::ink::primitives::Key, + >>::from(::KEY), + ::layout( + &::KEY, + ), + ::ink::scale_info::meta_type::(), + ), + ); + ::ink::metadata::layout::ValidateLayout::validate(&layout) + .unwrap_or_else(|error| { + { + ::core::panicking::panic_fmt( + format_args!("metadata ink! generation failed: {0}", error), + ); + } + }); + ::ink::metadata::InkProject::new( + layout, + ::ink::metadata::ContractSpec::new() + .constructors([ + ::ink::metadata::ConstructorSpec::from_label("new") + .selector([0x9B_u8, 0xAE_u8, 0x9D_u8, 0x5E_u8]) + .args([]) + .payable(true) + .default(false) + .returns( + ::ink::metadata::ReturnTypeSpec::new( + if >::IS_RESULT { + ::ink::metadata::TypeSpec::with_name_str::< + ::ink::ConstructorResult< + ::core::result::Result< + (), + >::Error, + >, + >, + >("ink_primitives::ConstructorResult") + } else { + ::ink::metadata::TypeSpec::with_name_str::< + ::ink::ConstructorResult<()>, + >("ink_primitives::ConstructorResult") + }, + ), + ) + .docs([]) + .done(), + ]) + .messages([ + ::ink::metadata::MessageSpec::from_label("total_supply") + .selector([0xDB_u8, 0x63_u8, 0x75_u8, 0xA8_u8]) + .args([ + ::ink::metadata::MessageParamSpec::new("id") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + AssetId, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["AssetId"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ]) + .returns( + ::ink::metadata::ReturnTypeSpec::new( + ::ink::metadata::TypeSpec::with_name_segs::< + ::ink::MessageResult>, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter([ + "ink", + "MessageResult", + ]), + ::core::convert::AsRef::as_ref, + ), + ), + ), + ) + .mutates(false) + .payable(false) + .default(false) + .docs([]) + .done(), + ::ink::metadata::MessageSpec::from_label("balance_of") + .selector([0x0F_u8, 0x75_u8, 0x5A_u8, 0x56_u8]) + .args([ + ::ink::metadata::MessageParamSpec::new("id") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + AssetId, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["AssetId"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ::ink::metadata::MessageParamSpec::new("owner") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + AccountId32, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["AccountId32"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ]) + .returns( + ::ink::metadata::ReturnTypeSpec::new( + ::ink::metadata::TypeSpec::with_name_segs::< + ::ink::MessageResult>, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter([ + "ink", + "MessageResult", + ]), + ::core::convert::AsRef::as_ref, + ), + ), + ), + ) + .mutates(false) + .payable(false) + .default(false) + .docs([]) + .done(), + ::ink::metadata::MessageSpec::from_label("allowance") + .selector([0x6A_u8, 0x00_u8, 0x16_u8, 0x5E_u8]) + .args([ + ::ink::metadata::MessageParamSpec::new("id") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + AssetId, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["AssetId"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ::ink::metadata::MessageParamSpec::new("owner") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + AccountId32, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["AccountId32"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ::ink::metadata::MessageParamSpec::new("spender") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + AccountId32, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["AccountId32"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ]) + .returns( + ::ink::metadata::ReturnTypeSpec::new( + ::ink::metadata::TypeSpec::with_name_segs::< + ::ink::MessageResult>, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter([ + "ink", + "MessageResult", + ]), + ::core::convert::AsRef::as_ref, + ), + ), + ), + ) + .mutates(false) + .payable(false) + .default(false) + .docs([]) + .done(), + ::ink::metadata::MessageSpec::from_label("asset_exists") + .selector([0xAA_u8, 0x6B_u8, 0x65_u8, 0xDB_u8]) + .args([ + ::ink::metadata::MessageParamSpec::new("id") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + AssetId, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["AssetId"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ]) + .returns( + ::ink::metadata::ReturnTypeSpec::new( + ::ink::metadata::TypeSpec::with_name_segs::< + ::ink::MessageResult>, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter([ + "ink", + "MessageResult", + ]), + ::core::convert::AsRef::as_ref, + ), + ), + ), + ) + .mutates(false) + .payable(false) + .default(false) + .docs([]) + .done(), + ::ink::metadata::MessageSpec::from_label("mint_asset") + .selector([0x1F_u8, 0x8E_u8, 0x8E_u8, 0x22_u8]) + .args([ + ::ink::metadata::MessageParamSpec::new("id") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + u32, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["u32"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ::ink::metadata::MessageParamSpec::new("beneficiary") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + AccountId32, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["AccountId32"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ::ink::metadata::MessageParamSpec::new("amount") + .of_type( + ::ink::metadata::TypeSpec::with_name_segs::< + Balance, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["Balance"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .done(), + ]) + .returns( + ::ink::metadata::ReturnTypeSpec::new( + ::ink::metadata::TypeSpec::with_name_segs::< + ::ink::MessageResult>, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter([ + "ink", + "MessageResult", + ]), + ::core::convert::AsRef::as_ref, + ), + ), + ), + ) + .mutates(false) + .payable(false) + .default(false) + .docs([]) + .done(), + ]) + .collect_events() + .docs([]) + .lang_error( + ::ink::metadata::TypeSpec::with_name_segs::< + ::ink::LangError, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["ink", "LangError"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .environment( + ::ink::metadata::EnvironmentSpec::new() + .account_id( + ::ink::metadata::TypeSpec::with_name_segs::< + AccountId, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["AccountId"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .balance( + ::ink::metadata::TypeSpec::with_name_segs::< + Balance, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["Balance"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .hash( + ::ink::metadata::TypeSpec::with_name_segs::< + Hash, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["Hash"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .timestamp( + ::ink::metadata::TypeSpec::with_name_segs::< + Timestamp, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["Timestamp"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .block_number( + ::ink::metadata::TypeSpec::with_name_segs::< + BlockNumber, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["BlockNumber"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .chain_extension( + ::ink::metadata::TypeSpec::with_name_segs::< + ChainExtension, + _, + >( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["ChainExtension"]), + ::core::convert::AsRef::as_ref, + ), + ), + ) + .max_event_topics(MAX_EVENT_TOPICS) + .static_buffer_size(::ink::env::BUFFER_SIZE) + .done(), + ) + .done(), + ) + } + }; + use super::*; +} diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs new file mode 100755 index 00000000..9c0ae754 --- /dev/null +++ b/pop-api/examples/fungibles/lib.rs @@ -0,0 +1,176 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +// Fungibles wrapper contract to allow contracts to interact with local fungibles without the pop api. +use ink::prelude::vec::Vec; +use pop_api::{ + assets::fungibles::*, + primitives::{AccountId as AccountId32, AssetId}, +}; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum ContractError { + // AssetsError(Error), + // /// The origin of the call doesn't have the right permission. + // BadOrigin, + // /// Custom error type for cases in which an implementation adds its own restrictions. + // Custom(String), + /// Not enough balance to fulfill a request is available. + InsufficientBalance, + /// Not enough allowance to fulfill a request is available. + InsufficientAllowance, + /// The asset status is not the expected status. + IncorrectStatus, + /// The asset ID is already taken. + InUse, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// The signing account has no permission to do the operation. + NoPermission, + // /// Safe transfer check fails (e.g. if the receiving contract does not accept tokens). + // SafeTransferCheckFailed(String), + /// The given asset ID is unknown. + Unknown, + /// Recipient's address is zero. + ZeroRecipientAddress, + /// Sender's address is zero. + ZeroSenderAddress, + UndefinedError, +} + +impl From for ContractError { + fn from(error: FungiblesError) -> Self { + match error { + // Error::BalanceLow => Err(InsufficientBalance), + FungiblesError::InUse => ContractError::InUse, + FungiblesError::MinBalanceZero => ContractError::MinBalanceZero, + FungiblesError::Unknown => ContractError::Unknown, + _ => ContractError::UndefinedError, + } + } +} + +/// The fungibles result type. +pub type Result = core::result::Result; + +#[ink::contract(env = pop_api::Environment)] +mod fungibles { + use super::*; + + #[ink(storage)] + #[derive(Default)] + pub struct Fungibles; + + impl Fungibles { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("PopApiAssetsExample::new"); + Default::default() + } + + #[ink(message)] + pub fn total_supply(&self, id: AssetId) -> Result { + total_supply(id).map_err(From::from) + } + + #[ink(message)] + pub fn balance_of(&self, id: AssetId, owner: AccountId32) -> Result { + balance_of(id, owner).map_err(From::from) + } + + #[ink(message)] + pub fn allowance( + &self, + id: AssetId, + owner: AccountId32, + spender: AccountId32, + ) -> Result { + allowance(id, owner, spender).map_err(From::from) + } + + #[ink(message)] + pub fn asset_exists(&self, id: AssetId) -> Result { + asset_exists(id).map_err(From::from) + } + + #[ink(message)] + pub fn create(&self, id: AssetId, admin: AccountId32, min_balance: Balance) -> Result<()> { + // create(id, admin, min_balance).map_err(From::from) + ink::env::debug_println!( + "PopApiAssetsExample::create: id: {:?} admin: {:?} min_balance: {:?}", + id, + admin, + min_balance, + ); + let result = create(id, admin, min_balance); + ink::env::debug_println!("Result: {:?}", result); + result.map_err(From::from) + } + + #[ink(message)] + pub fn set_metadata( + &self, + id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()> { + // set_metadata(id, name, symbol, decimals).map_err(From::from) + ink::env::debug_println!( + "PopApiAssetsExample::set_metadata: id: {:?} name: {:?} symbol: {:?}, decimals: {:?}", + id, + name, + symbol, + decimals, + ); + let result = set_metadata(id, name, symbol, decimals); + ink::env::debug_println!("Result: {:?}", result); + result.map_err(From::from) + } + + #[ink(message)] + pub fn mint(&self, id: AssetId, beneficiary: AccountId32, amount: Balance) -> Result<()> { + ink::env::debug_println!( + "PopApiAssetsExample::mint: id: {:?}, beneficiary: {:?} amount: {:?}", + id, + beneficiary, + amount, + ); + + let result = mint(id, beneficiary, amount); + ink::env::debug_println!("Result: {:?}", result); + result.map_err(From::from) + } + + // #[ink(message)] + // pub fn transfer_from( + // id: AssetId, + // from: Option, + // to: Option, + // value: Balance, + // data: [u8], + // ) -> Result<()> { + // ink::env::debug_println!( + // "PopApiAssetsExample::transfer_from: id: {:?}, from: {:?}, to: {:?} value: {:?}", + // id, + // from, + // to, + // value, + // ); + // + // let result = transfer_from(id, from, to, value)?; + // ink::env::debug_println!("Result: {:?}", result); + // result + // } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[ink::test] + fn default_works() { + PopApiAssetsExample::new(); + } + } +} diff --git a/pop-api/examples/trust_backed_assets/lib.rs b/pop-api/examples/trust_backed_assets/lib.rs deleted file mode 100755 index 3606f852..00000000 --- a/pop-api/examples/trust_backed_assets/lib.rs +++ /dev/null @@ -1,74 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -// Utilizing Trust Backed Assets with the Pop API. -// -// This example demonstrates interaction with trust backed assets via the assets pallet. Trust backed assets are originated -// and managed within Pop Network, harnessing the platform's inherent trust, security, and governance models. -use pop_api::assets::trust_backed as trust_backed_assets; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum ContractError { - TrustBackedAssetsError(trust_backed_assets::Error), - UnknownAsset, -} - -impl From for ContractError { - fn from(value: trust_backed_assets::Error) -> Self { - ContractError::TrustBackedAssetsError(value) - } -} - -#[ink::contract(env = pop_api::Environment)] -mod pop_api_tb_assets_example { - use super::*; - - #[ink(storage)] - #[derive(Default)] - pub struct PopApiTBAssetsExample; - - impl PopApiTBAssetsExample { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("Contract::new"); - Default::default() - } - - #[ink(message)] - pub fn mint_asset_through_runtime( - &mut self, - id: u32, - beneficiary: AccountId, - amount: Balance, - ) -> Result<(), ContractError> { - ink::env::debug_println!( - "Contract::mint_asset_through_runtime: id: {:?} beneficiary: {:?} amount: {:?}", - id, - beneficiary, - amount - ); - - // Check if asset doesn't exist. - if !trust_backed_assets::asset_exists(id)? { - return Err(ContractError::UnknownAsset); - } - - // Mint asset via pop api. - trust_backed_assets::mint(id, beneficiary, amount)?; - ink::env::debug_println!( - "Contract::mint_asset_through_runtime: asset(s) minted successfully" - ); - Ok(()) - } - } - - #[cfg(test)] - mod tests { - use super::*; - - #[ink::test] - fn default_works() { - PopApiTBAssetsExample::new(); - } - } -} diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 68ce6906..0ca4a817 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -3,14 +3,15 @@ pub mod primitives; pub mod v0; -use crate::PopApiError::{Balances, Nfts, TrustBackedAssets, UnknownStatusCode}; +use crate::PopApiError::{Assets, Balances, Contracts, Nfts, UnknownStatusCode}; use ink::{prelude::vec::Vec, ChainExtensionInstance}; -use primitives::{cross_chain::*, storage_keys::*}; +use primitives::{cross_chain::*, storage_keys::*, AccountId as AccountId32}; pub use sp_runtime::{BoundedVec, MultiAddress, MultiSignature}; use v0::RuntimeCall; -pub use v0::{balances, cross_chain, nfts, relay_chain_block_number, state, assets}; +pub use v0::{assets, balances, contracts, cross_chain, nfts, relay_chain_block_number, state}; -type AccountId = ::AccountId; +// type AccountId = ::AccountId; +type AccountId = AccountId32; type Balance = ::Balance; type BlockNumber = ::BlockNumber; type StringLimit = u32; @@ -25,8 +26,9 @@ pub enum PopApiError { DecodingFailed, SystemCallFiltered, Balances(balances::Error), + Contracts(contracts::Error), Nfts(nfts::Error), - TrustBackedAssets(assets::trust_backed::Error), + Assets(assets::fungibles::AssetsError), Xcm(cross_chain::Error), } @@ -37,8 +39,9 @@ impl ink::env::chain_extension::FromStatusCode for PopApiError { // CallFiltered originates from `frame_system` with pallet-index 0. The CallFiltered error is at index 5 5 => Err(PopApiError::SystemCallFiltered), 10_000..=10_999 => Err(Balances((status_code - 10_000).try_into()?)), + 40_000..=40_999 => Err(Contracts((status_code - 40_000).try_into()?)), 50_000..=50_999 => Err(Nfts((status_code - 50_000).try_into()?)), - 52_000..=52_999 => Err(TrustBackedAssets((status_code - 52_000).try_into()?)), + 52_000..=52_999 => Err(Assets((status_code - 52_000).try_into()?)), _ => Err(UnknownStatusCode(status_code)), } } diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs new file mode 100644 index 00000000..f2d87a0e --- /dev/null +++ b/pop-api/src/v0/assets/fungibles.rs @@ -0,0 +1,554 @@ +use crate::{AccountId, Balance, PopApiError::UnknownStatusCode, RuntimeCall, *}; +use ink::prelude::vec::Vec; +use primitives::AssetId; +use scale::{Compact, Encode}; + +type Result = core::result::Result; + +/// Local Fungibles: +/// 1. PSP-22 Interface +/// 2. PSP-22 Metadata Interface +/// 3. Asset Management + +/// 1. PSP-22 Interface: +/// - total_supply +/// - balance_of +/// - allowance +/// - transfer +/// - transfer_from +/// - approve +/// - increase_allowance +/// - decrease_allowance + +/// Returns the total token supply for a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// The total supply of the token, or an error if the operation fails. +pub fn total_supply(id: AssetId) -> Result { + Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id)))?) +} + +/// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if +/// the account is non-existent. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `owner` - The account whose balance is being queried. +/// +/// # Returns +/// The balance of the specified account, or an error if the operation fails. +pub fn balance_of(id: AssetId, owner: AccountId) -> Result { + Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner)))?) +} + +/// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given +/// asset ID. Returns `0` if no allowance has been set. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `owner` - The account that owns the tokens. +/// * `spender` - The account that is allowed to spend the tokens. +/// +/// # Returns +/// The remaining allowance, or an error if the operation fails. +pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { + Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender)))?) +} + +/// Create a new token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `admin` - The account that will administer the asset. +/// * `min_balance` - The minimum balance required for accounts holding this asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the creation fails. +// pub fn create(id: AssetId, admin: impl Into>, min_balance: Balance) -> Result<()> { +pub fn create( + id: AssetId, + admin: impl Into>, + min_balance: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::Assets(AssetsCall::Create { + id: id.into(), + admin: admin.into(), + min_balance, + }))?) +} + +/// Transfers `value` amount of tokens from the caller's account to account `to`, with additional +/// `data` in unspecified format. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `to` - The recipient account. +/// * `value` - The number of tokens to transfer. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the transfer fails. +// #[allow(unused_variables)] +// pub fn transfer( +// id: AssetId, +// to: impl Into>, +// value: Balance, +// ) -> Result<()> { +// todo!() +// // TODO: transfer or transfer_keep_alive +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::Transfer { +// // id: id.into(), +// // target: target.into(), +// // amount: Compact(amount), +// // }))?) +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { +// // id: id.into(), +// // target: target.into(), +// // amount: Compact(amount), +// // }))?) +// } + +/// Transfers `value` tokens on the behalf of `from` to the account `to` with additional `data` +/// in unspecified format. This can be used to allow a contract to transfer tokens on ones behalf +/// and/or to charge fees in sub-currencies, for example. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `from` - The account from which the tokens are transferred. +/// * `to` - The recipient account. +/// * `value` - The number of tokens to transfer. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the transfer fails. +// pub fn transfer_from( +// id: AssetId, +// from: impl Into>, +// to: impl Into>, +// value: Balance, +// ) -> Result<()> { +//todo!() +// TODO: depending on `from` and `to`, decide whether to mint, burn or transfer_approved. +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::Mint { +// id: id.into(), +// beneficiary: beneficiary.into(), +// amount: Compact(amount), +// }))?) +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::Burn { +// id: id.into(), +// who: who.into(), +// amount: Compact(amount), +// }))?) +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::TransferApproved { +// id: id.into(), +// owner: from.into(), +// destination: to.into(), +// amount: Compact(value), +// }))?) +// } + +/// Mint assets of a particular class. +pub fn mint( + id: AssetId, + beneficiary: impl Into>, + amount: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::Assets(AssetsCall::Mint { + id: id.into(), + beneficiary: beneficiary.into(), + amount: Compact(amount), + }))?) +} + +/// Approves an account to spend a specified number of tokens on behalf of the caller. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `spender` - The account that is allowed to spend the tokens. +/// * `value` - The number of tokens to approve. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the approval fails. +// #[allow(unused_variables)] +// fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { +// todo!() +// // TODO: read allowance and increase or decrease. +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { +// // id: id.into(), +// // delegate: spender.into(), +// // amount: Compact(value), +// // }))?) +// } + +/// Increases the allowance of a spender. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `spender` - The account that is allowed to spend the tokens. +/// * `value` - The number of tokens to increase the allowance by. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { +// id: id.into(), +// delegate: spender.into(), +// amount: Compact(value), +// }))?) +// } + +/// Decreases the allowance of a spender. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `spender` - The account that is allowed to spend the tokens. +/// * `value` - The number of tokens to decrease the allowance by. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// #[allow(unused_variables)] +// fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { +// todo!() +// // TODO: cancel_approval + approve_transfer +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::CancelApproval { +// // id: id.into(), +// // delegate: delegate.into(), +// // }))?) +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { +// // id: id.into(), +// // delegate: spender.into(), +// // amount: Compact(value), +// // }))?) +// } + +/// 2. PSP-22 Metadata Interface: +/// - token_name +/// - token_symbol +/// - token_decimals + +/// Returns the token name for a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// The name of the token as a byte vector, or an error if the operation fails. +// #[allow(unused_variables)] +// pub fn token_name(id: AssetId) -> Result>> { +// todo!() +// // Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenName(id)))?) +// } + +/// Returns the token symbol for a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// The symbol of the token as a byte vector, or an error if the operation fails. +// #[allow(unused_variables)] +// fn token_symbol(id: AssetId) -> Result>> { +// todo!() +// } + +/// Returns the token decimals for a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// The number of decimals of the token as a byte vector, or an error if the operation fails. +// #[allow(unused_variables)] +// fn token_decimals(id: AssetId) -> Result>> { +// todo!() +// } + +/// 3. Asset Management: +/// - create +/// - start_destroy +/// - destroy_accounts +/// - destroy_approvals +/// - finish_destroy +/// - set_metadata +/// - clear_metadata + +/// Start the process of destroying a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn start_destroy(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { +// id: id.into(), +// }))?) +// } + +/// Destroy all accounts associated with a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn destroy_accounts(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { +// id: id.into(), +// }))?) +// } + +/// Destroy all approvals associated with a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn destroy_approvals(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { +// id: id.into(), +// }))?) +// } + +/// Complete the process of destroying a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn finish_destroy(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { +// id: id.into(), +// }))?) +// } + +/// Set the metadata for a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { + Ok(dispatch(RuntimeCall::Assets(AssetsCall::SetMetadata { + id: id.into(), + name, + symbol, + decimals, + }))?) +} + +/// Clear the metadata for a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn clear_metadata(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { +// id: id.into(), +// }))?) +// } + +pub fn asset_exists(id: AssetId) -> Result { + Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id)))?) +} + +// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected +// to be compact encoded. The pop api handles that for the developer. +// +// reference: https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development +// +// Asset id that is compact encoded. +type AssetIdParameter = Compact; +// Balance amount that is compact encoded. +type BalanceParameter = Compact; + +#[allow(warnings, unused)] +#[derive(Encode)] +pub(crate) enum AssetsCall { + #[codec(index = 0)] + Create { id: AssetIdParameter, admin: MultiAddress, min_balance: Balance }, + #[codec(index = 2)] + StartDestroy { id: AssetIdParameter }, + #[codec(index = 3)] + DestroyAccounts { id: AssetIdParameter }, + #[codec(index = 4)] + DestroyApprovals { id: AssetIdParameter }, + #[codec(index = 5)] + FinishDestroy { id: AssetIdParameter }, + #[codec(index = 6)] + Mint { + id: AssetIdParameter, + beneficiary: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 7)] + Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, + // TODO: ED or not + // #[codec(index = 8)] + // Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, + #[codec(index = 9)] + TransferKeepAlive { + id: AssetIdParameter, + target: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 17)] + SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, + #[codec(index = 18)] + ClearMetadata { id: AssetIdParameter }, + #[codec(index = 22)] + ApproveTransfer { + id: AssetIdParameter, + delegate: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 23)] + CancelApproval { id: AssetIdParameter, delegate: MultiAddress }, + #[codec(index = 25)] + TransferApproved { + id: AssetIdParameter, + owner: MultiAddress, + destination: MultiAddress, + amount: BalanceParameter, + }, +} + +// TODO: remove unnecessary errors +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub(crate) enum AssetsError { + /// Account balance must be greater than or equal to the transfer amount. + BalanceLow, + /// The account to alter does not exist. + NoAccount, + /// The signing account has no permission to do the operation. + NoPermission, + /// The given asset ID is unknown. + Unknown, + /// The origin account is frozen. + Frozen, + /// The asset ID is already taken. + InUse, + /// Invalid witness data given. + BadWitness, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// Unable to increment the consumer reference counters on the account. Either no provider + /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one + /// fewer then the maximum number of consumers has been reached. + UnavailableConsumer, + /// Invalid metadata given. + BadMetadata, + /// No approval exists that would allow the transfer. + Unapproved, + /// The source account would not survive the transfer and it needs to stay alive. + WouldDie, + /// The asset-account already exists. + AlreadyExists, + /// The asset-account doesn't have an associated deposit. + NoDeposit, + /// The operation would result in funds being burned. + WouldBurn, + /// The asset is a live asset and is actively being used. Usually emit for operations such + /// as `start_destroy` which require the asset to be in a destroying state. + LiveAsset, + /// The asset is not live, and likely being destroyed. + AssetNotLive, + /// The asset status is not the expected status. + IncorrectStatus, + /// The asset should be frozen before the given operation. + NotFrozen, + /// Callback action resulted in error + CallbackFailed, +} + +impl From for AssetsError { + fn from(error: PopApiError) -> Self { + match error { + PopApiError::Assets(e) => e, + _ => panic!("Expected AssetsError"), + } + } +} + +impl TryFrom for AssetsError { + type Error = PopApiError; + + fn try_from(status_code: u32) -> core::result::Result { + use AssetsError::*; + match status_code { + 0 => Ok(BalanceLow), + 1 => Ok(NoAccount), + 2 => Ok(NoPermission), + 3 => Ok(Unknown), + 4 => Ok(Frozen), + 5 => Ok(InUse), + 6 => Ok(BadWitness), + 7 => Ok(MinBalanceZero), + 8 => Ok(UnavailableConsumer), + 9 => Ok(BadMetadata), + 10 => Ok(Unapproved), + 11 => Ok(WouldDie), + 12 => Ok(AlreadyExists), + 13 => Ok(NoDeposit), + 14 => Ok(WouldBurn), + 15 => Ok(LiveAsset), + 16 => Ok(AssetNotLive), + 17 => Ok(IncorrectStatus), + 18 => Ok(NotFrozen), + _ => Err(UnknownStatusCode(status_code)), + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum FungiblesError { + /// The signing account has no permission to do the operation. + NoPermission, + /// The given asset ID is unknown. + Unknown, + InsufficientBalance, + /// The asset ID is already taken. + InUse, + /// Minimum balance should be non-zero. + MinBalanceZero, +} + +impl From for FungiblesError { + fn from(error: balances::Error) -> Self { + match error { + balances::Error::InsufficientBalance => FungiblesError::InsufficientBalance, + _ => panic!("Unexpected pallet assets error. This error is unknown to pallet assets"), + } + } +} + +impl From for FungiblesError { + fn from(error: AssetsError) -> Self { + match error { + AssetsError::InUse => FungiblesError::InUse, + _ => panic!("Unexpected pallet assets error. This error is unknown to pallet assets"), + } + } +} + +impl From for FungiblesError { + fn from(error: PopApiError) -> Self { + match error { + PopApiError::Assets(e) => e.into(), + // PopApiError::Balances(e) => todo!("balances: {:?}", e), + PopApiError::Balances(e) => e.into(), + // PopApiError::Contracts(_e) => todo!("contracts"), + // PopApiError::SystemCallFiltered => 100, + // PopApiError::UnknownStatusCode(u) => u, + _ => panic!("Unexpected pallet assets error. This error is unknown to pallet assets"), + } + } +} diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 7ad40f15..d6b0261c 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1 +1 @@ -pub mod trust_backed; \ No newline at end of file +pub mod fungibles; \ No newline at end of file diff --git a/pop-api/src/v0/assets/trust_backed.rs b/pop-api/src/v0/assets/trust_backed.rs deleted file mode 100644 index fb413413..00000000 --- a/pop-api/src/v0/assets/trust_backed.rs +++ /dev/null @@ -1,519 +0,0 @@ -use crate::{Balance, PopApiError::UnknownStatusCode, RuntimeCall, *}; -use ink::prelude::vec::Vec; -use primitives::{AssetId, MultiAddress}; -use scale::{Compact, Encode}; - -type Result = core::result::Result; - -/// https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/lib.rs -/// -/// Extrinsics within pallet assets (TrustBackedAssets Instance) that can be used via the pop api on Pop Network: -/// 1. create -/// 2. start_destroy -/// 3. destroy_accounts -/// 4. destroy_approvals -/// 5. finish_destroy -/// 6. mint -/// 7. burn -/// 8. transfer -/// 9. transfer_keep_alive -/// 10. force_transfer -/// 11. freeze -/// 12. thaw -/// 13. freeze_asset -/// 14. thaw_asset -/// 15. transfer_ownership -/// 16. set_team -/// 17. set_metadata -/// 18. clear_metadata -/// 19. approve_transfer -/// 20. cancel_approval -/// 21. force_cancel_approval -/// 22. transfer_approved -/// 23. touch -/// 24. refund -/// 25. set_min_balance -/// 26. touch_other -/// 27. refund_other -/// 28. block - - -/// Issue a new class of fungible assets from a public origin. -pub fn create( - id: AssetId, - admin: impl Into>, - min_balance: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Create { - id: id.into(), - admin: admin.into(), - min_balance: Compact(min_balance), - }))?) -} - -/// Start the process of destroying a fungible asset class. -pub fn start_destroy(id: AssetId) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::StartDestroy { - id: id.into(), - }))?) -} - -/// Destroy all accounts associated with a given asset. -pub fn destroy_accounts(id: AssetId) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::DestroyAccounts { - id: id.into(), - }))?) -} - -/// Destroy all approvals associated with a given asset up to the max (see runtime configuration TrustBackedAssets `RemoveItemsLimit`). -pub fn destroy_approvals(id: AssetId) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::DestroyApprovals { - id: id.into(), - }))?) -} - -/// Complete destroying asset and unreserve currency. -pub fn finish_destroy(id: AssetId) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::FinishDestroy { - id: id.into(), - }))?) -} - -/// Mint assets of a particular class. -pub fn mint( - id: AssetId, - beneficiary: impl Into>, - amount: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Mint { - id: id.into(), - beneficiary: beneficiary.into(), - amount: Compact(amount), - }))?) -} - -/// Reduce the balance of `who` by as much as possible up to `amount` assets of `id`. -pub fn burn( - id: AssetId, - who: impl Into>, - amount: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Burn { - id: id.into(), - who: who.into(), - amount: Compact(amount), - }))?) -} - -/// Move some assets from the sender account to another. -pub fn transfer( - id: AssetId, - target: impl Into>, - amount: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Transfer { - id: id.into(), - target: target.into(), - amount: Compact(amount), - }))?) -} - -/// Move some assets from the sender account to another, keeping the sender account alive. -pub fn transfer_keep_alive( - id: AssetId, - target: impl Into>, - amount: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::TransferKeepAlive { - id: id.into(), - target: target.into(), - amount: Compact(amount), - }))?) -} - -/// Move some assets from one account to another. Sender should be the Admin of the asset `id`. -pub fn force_transfer( - id: AssetId, - source: impl Into>, - dest: impl Into>, - amount: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ForceTransfer { - id: id.into(), - source: source.into(), - dest: dest.into(), - amount: Compact(amount), - }))?) -} - -/// Disallow further unprivileged transfers of an asset `id` from an account `who`. `who` -/// must already exist as an entry in `Account`s of the asset. If you want to freeze an -/// account that does not have an entry, use `touch_other` first. -pub fn freeze(id: AssetId, who: impl Into>) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Freeze { - id: id.into(), - who: who.into(), - }))?) -} - -/// Allow unprivileged transfers to and from an account again. -pub fn thaw(id: AssetId, who: impl Into>) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Thaw { - id: id.into(), - who: who.into(), - }))?) -} - -/// Disallow further unprivileged transfers for the asset class. -pub fn freeze_asset(id: AssetId) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::FreezeAsset { - id: id.into(), - }))?) -} - -/// Allow unprivileged transfers for the asset again. -pub fn thaw_asset(id: AssetId) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ThawAsset { - id: id.into(), - }))?) -} - -/// Change the Owner of an asset. -pub fn transfer_ownership( - id: AssetId, - owner: impl Into>, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::TransferOwnership { - id: id.into(), - owner: owner.into(), - }))?) -} - -/// Change the Issuer, Admin and Freezer of an asset. -pub fn set_team( - id: AssetId, - issuer: impl Into>, - admin: impl Into>, - freezer: impl Into>, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::SetTeam { - id: id.into(), - issuer: issuer.into(), - admin: admin.into(), - freezer: freezer.into(), - }))?) -} - -/// Set the metadata for an asset. -pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::SetMetadata { - id: id.into(), - name, - symbol, - decimals, - }))?) -} - -/// Clear the metadata for an asset. -pub fn clear_metadata(id: AssetId) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ClearMetadata { - id: id.into(), - }))?) -} - -/// Approve an amount of asset for transfer by a delegated third-party account. -pub fn approve_transfer( - id: AssetId, - delegate: impl Into>, - amount: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ApproveTransfer { - id: id.into(), - delegate: delegate.into(), - amount: Compact(amount), - }))?) -} - -/// Cancel all of some asset approved for delegated transfer by a third-party account. -pub fn cancel_approval( - id: AssetId, - delegate: impl Into>, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::CancelApproval { - id: id.into(), - delegate: delegate.into(), - }))?) -} - -/// Cancel all of some asset approved for delegated transfer by a third-party account. -pub fn force_cancel_approval( - id: AssetId, - owner: impl Into>, - delegate: impl Into>, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::ForceCancelApproval { - id: id.into(), - owner: owner.into(), - delegate: delegate.into(), - }))?) -} - -/// Transfer some asset balance from a previously delegated account to some third-party -/// account. -pub fn transfer_approved( - id: AssetId, - owner: impl Into>, - destination: impl Into>, - amount: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::TransferApproved { - id: id.into(), - owner: owner.into(), - destination: destination.into(), - amount: Compact(amount), - }))?) -} - -/// Create an asset account for non-provider assets. -pub fn touch(id: AssetId) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Touch { - id: id.into(), - }))?) -} - -/// Return the deposit (if any) of an asset account or a consumer reference (if any) of an -/// account. -pub fn refund(id: AssetId, allow_burn: bool) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Refund { - id: id.into(), - allow_burn, - }))?) -} - -/// Sets the minimum balance of an asset. -pub fn set_min_balance(id: AssetId, min_balance: Balance) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::SetMinBalance { - id: id.into(), - min_balance: Compact(min_balance), - }))?) -} - -/// Create an asset account for `who`. -pub fn touch_other(id: AssetId, who: impl Into>) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::TouchOther { - id: id.into(), - who: who.into(), - }))?) -} - -/// Return the deposit (if any) of a target asset account. Useful if you are the depositor. -pub fn refund_other(id: AssetId, who: impl Into>) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::RefundOther { - id: id.into(), - who: who.into(), - }))?) -} - -/// Disallow further unprivileged transfers of an asset `id` to and from an account `who`. -pub fn block(id: AssetId, who: impl Into>) -> Result<()> { - Ok(dispatch(RuntimeCall::TrustBackedAssets(TrustBackedAssetsCalls::Block { - id: id.into(), - who: who.into(), - }))?) -} - -pub fn asset_exists(id: AssetId) -> Result { - Ok(state::read(RuntimeStateKeys::TrustBackedAssets(TrustBackedAssetsKeys::AssetExists(id)))?) -} - -// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected -// to be compact encoded. The pop api handles that for the developer. -// -// reference: https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development -// -// Asset id that is compact encoded. -type AssetIdParameter = Compact; -// Balance amount that is compact encoded. -type BalanceParameter = Compact; - -#[derive(Encode)] -pub(crate) enum TrustBackedAssetsCalls { - #[codec(index = 0)] - Create { - id: AssetIdParameter, - admin: MultiAddress, - min_balance: BalanceParameter, - }, - #[codec(index = 2)] - StartDestroy { id: AssetIdParameter }, - #[codec(index = 3)] - DestroyAccounts { id: AssetIdParameter }, - #[codec(index = 4)] - DestroyApprovals { id: AssetIdParameter }, - #[codec(index = 5)] - FinishDestroy { id: AssetIdParameter }, - #[codec(index = 6)] - Mint { - id: AssetIdParameter, - beneficiary: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 7)] - Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, - #[codec(index = 8)] - Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, - #[codec(index = 9)] - TransferKeepAlive { - id: AssetIdParameter, - target: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 10)] - ForceTransfer { - id: AssetIdParameter, - source: MultiAddress, - dest: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 11)] - Freeze { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 12)] - Thaw { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 13)] - FreezeAsset { id: AssetIdParameter }, - #[codec(index = 14)] - ThawAsset { id: AssetIdParameter }, - #[codec(index = 15)] - TransferOwnership { id: AssetIdParameter, owner: MultiAddress }, - #[codec(index = 16)] - SetTeam { - id: AssetIdParameter, - issuer: MultiAddress, - admin: MultiAddress, - freezer: MultiAddress, - }, - #[codec(index = 17)] - SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, - #[codec(index = 18)] - ClearMetadata { id: AssetIdParameter }, - #[codec(index = 22)] - ApproveTransfer { - id: AssetIdParameter, - delegate: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 23)] - CancelApproval { id: AssetIdParameter, delegate: MultiAddress }, - #[codec(index = 24)] - ForceCancelApproval { - id: AssetIdParameter, - owner: MultiAddress, - delegate: MultiAddress, - }, - #[codec(index = 25)] - TransferApproved { - id: AssetIdParameter, - owner: MultiAddress, - destination: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 26)] - Touch { id: AssetIdParameter }, - #[codec(index = 27)] - Refund { id: AssetIdParameter, allow_burn: bool }, - #[codec(index = 28)] - SetMinBalance { id: AssetIdParameter, min_balance: BalanceParameter }, - #[codec(index = 29)] - TouchOther { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 30)] - RefundOther { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 31)] - Block { id: AssetIdParameter, who: MultiAddress }, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum Error { - /// Account balance must be greater than or equal to the transfer amount. - BalanceLow, - /// The account to alter does not exist. - NoAccount, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given asset ID is unknown. - Unknown, - /// The origin account is frozen. - Frozen, - /// The asset ID is already taken. - InUse, - /// Invalid witness data given. - BadWitness, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// Unable to increment the consumer reference counters on the account. Either no provider - /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one - /// fewer then the maximum number of consumers has been reached. - UnavailableConsumer, - /// Invalid metadata given. - BadMetadata, - /// No approval exists that would allow the transfer. - Unapproved, - /// The source account would not survive the transfer and it needs to stay alive. - WouldDie, - /// The asset-account already exists. - AlreadyExists, - /// The asset-account doesn't have an associated deposit. - NoDeposit, - /// The operation would result in funds being burned. - WouldBurn, - /// The asset is a live asset and is actively being used. Usually emit for operations such - /// as `start_destroy` which require the asset to be in a destroying state. - LiveAsset, - /// The asset is not live, and likely being destroyed. - AssetNotLive, - /// The asset status is not the expected status. - IncorrectStatus, - /// The asset should be frozen before the given operation. - NotFrozen, - /// Callback action resulted in error - CallbackFailed, -} - -impl TryFrom for Error { - type Error = PopApiError; - - fn try_from(status_code: u32) -> core::result::Result { - use Error::*; - match status_code { - 0 => Ok(BalanceLow), - 1 => Ok(NoAccount), - 2 => Ok(NoPermission), - 3 => Ok(Unknown), - 4 => Ok(Frozen), - 5 => Ok(InUse), - 6 => Ok(BadWitness), - 7 => Ok(MinBalanceZero), - 8 => Ok(UnavailableConsumer), - 9 => Ok(BadMetadata), - 10 => Ok(Unapproved), - 11 => Ok(WouldDie), - 12 => Ok(AlreadyExists), - 13 => Ok(NoDeposit), - 14 => Ok(WouldBurn), - 15 => Ok(LiveAsset), - 16 => Ok(AssetNotLive), - 17 => Ok(IncorrectStatus), - 18 => Ok(NotFrozen), - _ => Err(UnknownStatusCode(status_code)), - } - } -} - -impl From for Error { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::TrustBackedAssets(e) => e, - _ => panic!("Unexpected pallet assets error. This error is unknown to pallet assets"), - } - } -} diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs index bf029178..bc48711e 100644 --- a/pop-api/src/v0/balances.rs +++ b/pop-api/src/v0/balances.rs @@ -28,7 +28,7 @@ pub(crate) enum BalancesCall { #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum Error { +pub(crate) enum Error { /// Vesting balance too high to send value. VestingBalance, /// Account liquidity restrictions prevent withdrawal. diff --git a/pop-api/src/v0/contracts.rs b/pop-api/src/v0/contracts.rs new file mode 100644 index 00000000..d7a1a5dd --- /dev/null +++ b/pop-api/src/v0/contracts.rs @@ -0,0 +1,156 @@ +use crate::{ + PopApiError, + PopApiError::UnknownStatusCode, +}; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum Error { + /// Invalid schedule supplied, e.g. with zero weight of a basic operation. + InvalidSchedule, + /// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`. + InvalidCallFlags, + /// The executed contract exhausted its gas limit. + OutOfGas, + /// The output buffer supplied to a contract API call was too small. + OutputBufferTooSmall, + /// Performing the requested transfer failed. Probably because there isn't enough + /// free balance in the sender's account. + TransferFailed, + /// Performing a call was denied because the calling depth reached the limit + /// of what is specified in the schedule. + MaxCallDepthReached, + /// No contract was found at the specified address. + ContractNotFound, + /// The code supplied to `instantiate_with_code` exceeds the limit specified in the + /// current schedule. + CodeTooLarge, + /// No code could be found at the supplied code hash. + CodeNotFound, + /// No code info could be found at the supplied code hash. + CodeInfoNotFound, + /// A buffer outside of sandbox memory was passed to a contract API function. + OutOfBounds, + /// Input passed to a contract API function failed to decode as expected type. + DecodingFailed, + /// Contract trapped during execution. + ContractTrapped, + /// The size defined in `T::MaxValueSize` was exceeded. + ValueTooLarge, + /// Termination of a contract is not allowed while the contract is already + /// on the call stack. Can be triggered by `seal_terminate`. + TerminatedWhileReentrant, + /// `seal_call` forwarded this contracts input. It therefore is no longer available. + InputForwarded, + /// The subject passed to `seal_random` exceeds the limit. + RandomSubjectTooLong, + /// The amount of topics passed to `seal_deposit_events` exceeds the limit. + TooManyTopics, + /// The chain does not provide a chain extension. Calling the chain extension results + /// in this error. Note that this usually shouldn't happen as deploying such contracts + /// is rejected. + NoChainExtension, + /// Failed to decode the XCM program. + XCMDecodeFailed, + /// A contract with the same AccountId already exists. + DuplicateContract, + /// A contract self destructed in its constructor. + /// + /// This can be triggered by a call to `seal_terminate`. + TerminatedInConstructor, + /// A call tried to invoke a contract that is flagged as non-reentrant. + /// The only other cause is that a call from a contract into the runtime tried to call back + /// into `pallet-contracts`. This would make the whole pallet reentrant with regard to + /// contract code execution which is not supported. + ReentranceDenied, + /// Origin doesn't have enough balance to pay the required storage deposits. + StorageDepositNotEnoughFunds, + /// More storage was created than allowed by the storage deposit limit. + StorageDepositLimitExhausted, + /// Code removal was denied because the code is still in use by at least one contract. + CodeInUse, + /// The contract ran to completion but decided to revert its storage changes. + /// Please note that this error is only returned from extrinsics. When called directly + /// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags + /// to determine whether a reversion has taken place. + ContractReverted, + /// The contract's code was found to be invalid during validation. + /// + /// The most likely cause of this is that an API was used which is not supported by the + /// node. This happens if an older node is used with a new version of ink!. Try updating + /// your node to the newest available version. + /// + /// A more detailed error can be found on the node console if debug messages are enabled + /// by supplying `-lruntime::contracts=debug`. + CodeRejected, + /// An indeterministic code was used in a context where this is not permitted. + Indeterministic, + /// A pending migration needs to complete before the extrinsic can be called. + MigrationInProgress, + /// Migrate dispatch call was attempted but no migration was performed. + NoMigrationPerformed, + /// The contract has reached its maximum number of delegate dependencies. + MaxDelegateDependenciesReached, + /// The dependency was not found in the contract's delegate dependencies. + DelegateDependencyNotFound, + /// The contract already depends on the given delegate dependency. + DelegateDependencyAlreadyExists, + /// Can not add a delegate dependency to the code hash of the contract itself. + CannotAddSelfAsDelegateDependency, +} + + +impl TryFrom for Error { + type Error = PopApiError; + + fn try_from(status_code: u32) -> core::result::Result { + use Error::*; + match status_code { + 0 => Ok(InvalidSchedule), + 1 => Ok(InvalidCallFlags), + 2 => Ok(OutOfGas), + 3 => Ok(OutputBufferTooSmall), + 4 => Ok(TransferFailed), + 5 => Ok(MaxCallDepthReached), + 6 => Ok(ContractNotFound), + 7 => Ok(CodeTooLarge), + 8 => Ok(CodeNotFound), + 9 => Ok(CodeInfoNotFound), + 10 => Ok(OutOfBounds), + 11 => Ok(DecodingFailed), + 12 => Ok(ContractTrapped), + 13 => Ok(ValueTooLarge), + 14 => Ok(TerminatedWhileReentrant), + 15 => Ok(InputForwarded), + 16 => Ok(RandomSubjectTooLong), + 17 => Ok(TooManyTopics), + 18 => Ok(NoChainExtension), + 19 => Ok(XCMDecodeFailed), + 20 => Ok(DuplicateContract), + 21 => Ok(TerminatedInConstructor), + 22 => Ok(ReentranceDenied), + 23 => Ok(StorageDepositNotEnoughFunds), + 24 => Ok(StorageDepositLimitExhausted), + 25 => Ok(CodeInUse), + 26 => Ok(ContractReverted), + 27 => Ok(CodeRejected), + 28 => Ok(Indeterministic), + 29 => Ok(MigrationInProgress), + 30 => Ok(NoMigrationPerformed), + 31 => Ok(MaxDelegateDependenciesReached), + 32 => Ok(DelegateDependencyNotFound), + 33 => Ok(DelegateDependencyAlreadyExists), + 34 => Ok(CannotAddSelfAsDelegateDependency), + _ => Err(UnknownStatusCode(status_code)), + } + } +} + +impl From for Error { + fn from(error: PopApiError) -> Self { + match error { + PopApiError::Contracts(e) => e, + _ => panic!("expected balances error"), + } + } +} \ No newline at end of file diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index d914db24..def37e55 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -4,6 +4,7 @@ use crate::{ }; pub mod balances; +pub mod contracts; pub mod cross_chain; pub mod nfts; pub mod state; @@ -20,5 +21,5 @@ pub(crate) enum RuntimeCall { #[codec(index = 50)] Nfts(nfts::NftCalls), #[codec(index = 52)] - TrustBackedAssets(assets::trust_backed::TrustBackedAssetsCalls), + Assets(assets::fungibles::AssetsCall), } diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index b6f9adaa..1098b557 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -6,13 +6,25 @@ edition = "2021" [dependencies] bounded-collections = { version = "0.1", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } + +scale = { package = "parity-scale-codec", version = "3.6.9", default-features = false, features = ["derive"] } +scale-decode = { version = "0.10.0", default-features = false, features = ["derive"], optional = true } +scale-encode = { version = "0.5.0", default-features = false, features = ["derive"], optional = true } scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +#scale = { workspace = true, features = ["max-encoded-len"] } +#scale-decode = { workspace = true, features = ["derive"], optional = true } +#scale-encode = { workspace = true, features = ["derive"], optional = true } +#scale-info = { workspace = true, features = ["derive"], optional = true } + [features] default = ["std"] std = [ "bounded-collections/std", "scale/std", + "scale-decode/std", + "scale-encode/std", "scale-info/std", ] +devnet = [] +testnet = [] \ No newline at end of file diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index ebad36d3..7c1672b8 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -1,10 +1,22 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] pub use bounded_collections::{BoundedBTreeMap, BoundedBTreeSet, BoundedVec, ConstU32}; +use scale::{Decode, Encode, MaxEncodedLen}; +#[cfg(feature = "std")] +use { + scale_decode::DecodeAsType, + scale_encode::EncodeAsType, + scale_info::TypeInfo, +}; + pub mod cross_chain; pub mod storage_keys; +#[derive(Encode, Decode, Debug, MaxEncodedLen, Eq, PartialEq, Ord, PartialOrd)] +#[cfg_attr(feature = "std", derive(TypeInfo, DecodeAsType, EncodeAsType))] +pub struct AccountId(pub [u8; 32]); + // Identifier for the class of asset. pub type AssetId = u32; // Id used for identifying non-fungible collections. diff --git a/primitives/src/storage_keys.rs b/primitives/src/storage_keys.rs index a03b3a09..67448842 100644 --- a/primitives/src/storage_keys.rs +++ b/primitives/src/storage_keys.rs @@ -1,11 +1,12 @@ use super::*; -use scale::{Decode, Encode, MaxEncodedLen}; +// use scale::{Decode, Encode, MaxEncodedLen}; #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum RuntimeStateKeys { Nfts(NftsKeys), ParachainSystem(ParachainSystemKeys), - TrustBackedAssets(TrustBackedAssetsKeys), + #[cfg(feature = "devnet")] + Assets(AssetsKeys), } #[derive(Encode, Decode, Debug, MaxEncodedLen)] @@ -35,8 +36,15 @@ pub enum NftsKeys { CollectionAttribute(CollectionId, BoundedVec), } +/// The required input for state queries in pallet assets. +#[cfg(feature = "devnet")] #[derive(Encode, Decode, Debug, MaxEncodedLen)] -pub enum TrustBackedAssetsKeys { +pub enum AssetsKeys { + Allowance(AssetId, AccountId, AccountId), /// Check if the asset exists. AssetExists(AssetId), + /// Check balance. + BalanceOf(AssetId, AccountId), + /// Returns the total token supply for a given asset ID. + TotalSupply(AssetId), } diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index 55d9942d..d4fe2923 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -22,7 +22,7 @@ scale-info.workspace = true smallvec.workspace = true # Local -pop-primitives.workspace = true +pop-primitives = { workspace = true, default-features = false, features = ["devnet"] } pop-runtime-common = { workspace = true, default-features = false } # Substrate diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index f51f8875..2c8ea952 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -1,6 +1,6 @@ use crate::{ - deposit, AccountId, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, - RuntimeHoldReason, TrustBackedAssets, DAYS, EXISTENTIAL_DEPOSIT, UNIT, + deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, + RuntimeHoldReason, DAYS, EXISTENTIAL_DEPOSIT, UNIT, }; use frame_support::{ parameter_types, @@ -86,7 +86,7 @@ impl pallet_nft_fractionalization::Config for Runtime { type NftId = ::ItemId; type AssetBalance = >::Balance; type AssetId = >::AssetId; - type Assets = TrustBackedAssets; + type Assets = Assets; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight; @@ -96,7 +96,7 @@ impl pallet_nft_fractionalization::Config for Runtime { } pub type TrustBackedAssetsInstance = pallet_assets::Instance1; -pub(crate) type TrustBackedAssetsCall = pallet_assets::Call; +pub(crate) type AssetsCall = pallet_assets::Call; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; diff --git a/runtime/devnet/src/config/mod.rs b/runtime/devnet/src/config/mod.rs index a3a64c92..c370bb1d 100644 --- a/runtime/devnet/src/config/mod.rs +++ b/runtime/devnet/src/config/mod.rs @@ -1,4 +1,4 @@ -mod assets; +pub(crate) mod assets; mod contracts; mod proxy; // Public due to integration tests crate. diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index a4fd479a..07d5f0f8 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -1,4 +1,4 @@ -use super::assets::TrustBackedAssetsCall; +use super::assets::AssetsCall; use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; use frame_support::traits::InstanceFilter; use pop_runtime_common::proxy::{ @@ -34,16 +34,16 @@ impl InstanceFilter for ProxyType { }, ProxyType::AssetOwner => matches!( c, - RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) + RuntimeCall::Assets(AssetsCall::create { .. }) + | RuntimeCall::Assets(AssetsCall::start_destroy { .. }) + | RuntimeCall::Assets(AssetsCall::destroy_accounts { .. }) + | RuntimeCall::Assets(AssetsCall::destroy_approvals { .. }) + | RuntimeCall::Assets(AssetsCall::finish_destroy { .. }) + | RuntimeCall::Assets(AssetsCall::transfer_ownership { .. }) + | RuntimeCall::Assets(AssetsCall::set_team { .. }) + | RuntimeCall::Assets(AssetsCall::set_metadata { .. }) + | RuntimeCall::Assets(AssetsCall::clear_metadata { .. }) + | RuntimeCall::Assets(AssetsCall::set_min_balance { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) @@ -56,15 +56,15 @@ impl InstanceFilter for ProxyType { ), ProxyType::AssetManager => matches!( c, - RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) + RuntimeCall::Assets(AssetsCall::mint { .. }) + | RuntimeCall::Assets(AssetsCall::burn { .. }) + | RuntimeCall::Assets(AssetsCall::freeze { .. }) + | RuntimeCall::Assets(AssetsCall::block { .. }) + | RuntimeCall::Assets(AssetsCall::thaw { .. }) + | RuntimeCall::Assets(AssetsCall::freeze_asset { .. }) + | RuntimeCall::Assets(AssetsCall::thaw_asset { .. }) + | RuntimeCall::Assets(AssetsCall::touch_other { .. }) + | RuntimeCall::Assets(AssetsCall::refund_other { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions.rs deleted file mode 100644 index c8e88eb2..00000000 --- a/runtime/devnet/src/extensions.rs +++ /dev/null @@ -1,1018 +0,0 @@ -use cumulus_pallet_parachain_system::RelaychainDataProvider; -use frame_support::traits::{Contains, OriginTrait}; -use frame_support::{ - dispatch::{GetDispatchInfo, RawOrigin}, - pallet_prelude::*, - traits::{fungibles::Inspect, nonfungibles_v2::Inspect as NonFungiblesInspect}, -}; -use pallet_contracts::chain_extension::{ - BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, -}; -use pop_primitives::{ - cross_chain::CrossChainMessage, - storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys, TrustBackedAssetsKeys}, - AssetId, CollectionId, ItemId, -}; -use sp_core::crypto::UncheckedFrom; -use sp_runtime::{ - traits::{BlockNumberProvider, Dispatchable}, - DispatchError, -}; -use sp_std::{boxed::Box, vec::Vec}; -use xcm::{ - latest::{prelude::*, OriginKind::SovereignAccount}, - VersionedXcm, -}; - -use crate::{ - assets_config::TrustBackedAssetsInstance, AccountId, AllowedPopApiCalls, RuntimeCall, - RuntimeOrigin, UNIT, -}; - -const LOG_TARGET: &str = "pop-api::extension"; - -type ContractSchedule = ::Schedule; - -#[derive(Default)] -pub struct PopApiExtension; - -impl ChainExtension for PopApiExtension -where - T: pallet_contracts::Config - + pallet_xcm::Config - + pallet_assets::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config - + frame_system::Config< - RuntimeOrigin = RuntimeOrigin, - AccountId = AccountId, - RuntimeCall = RuntimeCall, - >, - T::AccountId: UncheckedFrom + AsRef<[u8]>, -{ - fn call(&mut self, env: Environment) -> Result - where - E: Ext, - T::AccountId: UncheckedFrom + AsRef<[u8]>, - { - log::debug!(target:LOG_TARGET, " extension called "); - match v0::FuncId::try_from(env.func_id())? { - v0::FuncId::Dispatch => { - match dispatch::(env) { - Ok(()) => Ok(RetVal::Converging(0)), - Err(DispatchError::Module(error)) => { - // encode status code = pallet index in runtime + error index, allowing for - // 999 errors - Ok(RetVal::Converging( - (error.index as u32 * 1_000) + u32::from_le_bytes(error.error), - )) - }, - Err(e) => Err(e), - } - }, - v0::FuncId::ReadState => { - read_state::(env)?; - Ok(RetVal::Converging(0)) - }, - v0::FuncId::SendXcm => { - send_xcm::(env)?; - Ok(RetVal::Converging(0)) - }, - } - } -} - -pub mod v0 { - #[derive(Debug)] - pub enum FuncId { - Dispatch, - ReadState, - SendXcm, - } -} - -impl TryFrom for v0::FuncId { - type Error = DispatchError; - - fn try_from(func_id: u16) -> Result { - let id = match func_id { - 0x0 => Self::Dispatch, - 0x1 => Self::ReadState, - 0x2 => Self::SendXcm, - _ => { - log::error!("called an unregistered `func_id`: {:}", func_id); - return Err(DispatchError::Other("unimplemented func_id")); - }, - }; - - Ok(id) - } -} - -fn dispatch_call( - env: &mut Environment, - call: RuntimeCall, - mut origin: RuntimeOrigin, - log_prefix: &str, -) -> Result<(), DispatchError> -where - T: frame_system::Config, - RuntimeOrigin: From>, - E: Ext, -{ - let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; - - log::debug!(target:LOG_TARGET, "{} inputted RuntimeCall: {:?}", log_prefix, call); - - origin.add_filter(AllowedPopApiCalls::contains); - - match call.dispatch(origin) { - Ok(info) => { - log::debug!(target:LOG_TARGET, "{} success, actual weight: {:?}", log_prefix, info.actual_weight); - - // refund weight if the actual weight is less than the charged weight - if let Some(actual_weight) = info.actual_weight { - env.adjust_weight(charged_dispatch_weight, actual_weight); - } - - Ok(()) - }, - Err(err) => { - log::debug!(target:LOG_TARGET, "{} failed: error: {:?}", log_prefix, err.error); - Err(err.error) - }, - } -} - -fn charge_overhead_weight( - env: &mut Environment, - len: u32, - log_prefix: &str, -) -> Result -where - T: pallet_contracts::Config, - E: Ext, -{ - let contract_host_weight = ContractSchedule::::get().host_fn_weights; - - // calculate weight for reading bytes of `len` - // reference: https://github.com/paritytech/polkadot-sdk/blob/117a9433dac88d5ac00c058c9b39c511d47749d2/substrate/frame/contracts/src/wasm/runtime.rs#L267 - let base_weight: Weight = contract_host_weight.return_per_byte.saturating_mul(len.into()); - - // debug_message weight is a good approximation of the additional overhead of going - // from contract layer to substrate layer. - // reference: https://github.com/paritytech/ink-examples/blob/b8d2caa52cf4691e0ddd7c919e4462311deb5ad0/psp22-extension/runtime/psp22-extension-example.rs#L236 - let overhead = contract_host_weight.debug_message; - - let charged_weight = env.charge_weight(base_weight.saturating_add(overhead))?; - log::debug!(target: LOG_TARGET, "{} charged weight: {:?}", log_prefix, charged_weight); - - Ok(charged_weight) -} - -fn dispatch(env: Environment) -> Result<(), DispatchError> -where - T: pallet_contracts::Config - + frame_system::Config, - RuntimeOrigin: From>, - E: Ext, -{ - const LOG_PREFIX: &str = " dispatch |"; - - let mut env = env.buf_in_buf_out(); - let len = env.in_len(); - - charge_overhead_weight::(&mut env, len, LOG_PREFIX)?; - - // read the input as RuntimeCall - let call: RuntimeCall = env.read_as_unbounded(len)?; - - // contract is the origin by default - let origin: RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); - - dispatch_call::(&mut env, call, origin, LOG_PREFIX) -} - -fn read_state(env: Environment) -> Result<(), DispatchError> -where - T: pallet_contracts::Config - + pallet_assets::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config - + frame_system::Config, - E: Ext, -{ - const LOG_PREFIX: &str = " read_state |"; - - let mut env = env.buf_in_buf_out(); - - // To be conservative, we charge the weight for reading the input bytes of a fixed-size type. - let base_weight: Weight = ContractSchedule::::get() - .host_fn_weights - .return_per_byte - .saturating_mul(env.in_len().into()); - let charged_weight = env.charge_weight(base_weight)?; - - log::debug!(target:LOG_TARGET, "{} charged weight: {:?}", LOG_PREFIX, charged_weight); - - let key: RuntimeStateKeys = env.read_as()?; - - let result = match key { - RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, &mut env), - RuntimeStateKeys::ParachainSystem(key) => { - read_parachain_system_state::(key, &mut env) - }, - RuntimeStateKeys::TrustBackedAssets(key) => { - read_trust_backed_assets_state::(key, &mut env) - }, - }? - .encode(); - - log::trace!( - target:LOG_TARGET, - "{} result: {:?}.", LOG_PREFIX, result - ); - env.write(&result, false, None).map_err(|e| { - log::trace!(target: LOG_TARGET, "{:?}", e); - DispatchError::Other("unable to write results to contract memory") - }) -} - -fn read_parachain_system_state( - key: ParachainSystemKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + cumulus_pallet_parachain_system::Config, - E: Ext, -{ - match key { - ParachainSystemKeys::LastRelayChainBlockNumber => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(RelaychainDataProvider::::current_block_number().encode()) - }, - } -} - -fn read_nfts_state( - key: NftsKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + pallet_nfts::Config, - E: Ext, -{ - match key { - NftsKeys::Collection(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Collection::::get(collection).encode()) - }, - NftsKeys::CollectionOwner(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_owner(collection).encode()) - }, - NftsKeys::Item(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Item::::get(collection, item).encode()) - }, - NftsKeys::Owner(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::owner(collection, item).encode()) - }, - NftsKeys::Attribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::attribute(&collection, &item, &key).encode()) - }, - // NftsKeys::CustomAttribute(account, collection, item, key) => { - // env.charge_weight(T::DbWeight::get().reads(1_u64))?; - // Ok(pallet_nfts::Pallet::::custom_attribute(&account, &collection, &item, &key) - // .encode()) - // }, - NftsKeys::SystemAttribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::system_attribute(&collection, item.as_ref(), &key) - .encode()) - }, - NftsKeys::CollectionAttribute(collection, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_attribute(&collection, &key).encode()) - }, - } -} - -fn read_trust_backed_assets_state( - key: TrustBackedAssetsKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config - + pallet_assets::Config, - E: Ext, -{ - match key { - TrustBackedAssetsKeys::AssetExists(id) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_assets::Pallet::::asset_exists(id).encode()) - }, - } -} - -fn send_xcm(env: Environment) -> Result<(), DispatchError> -where - T: pallet_contracts::Config - + frame_system::Config< - RuntimeOrigin = RuntimeOrigin, - AccountId = AccountId, - RuntimeCall = RuntimeCall, - >, - E: Ext, -{ - const LOG_PREFIX: &str = " send_xcm |"; - - let mut env = env.buf_in_buf_out(); - let len = env.in_len(); - - let _ = charge_overhead_weight::(&mut env, len, LOG_PREFIX)?; - - // read the input as CrossChainMessage - let xc_call: CrossChainMessage = env.read_as::()?; - - // Determine the call to dispatch - let (dest, message) = match xc_call { - CrossChainMessage::Relay(message) => { - let dest = Location::parent().into_versioned(); - let assets: Asset = (Here, 10 * UNIT).into(); - let beneficiary: Location = - AccountId32 { id: (env.ext().address().clone()).into(), network: None }.into(); - let message = Xcm::builder() - .withdraw_asset(assets.clone().into()) - .buy_execution(assets.clone(), Unlimited) - .transact( - SovereignAccount, - Weight::from_parts(250_000_000, 10_000), - message.encode().into(), - ) - .refund_surplus() - .deposit_asset(assets.into(), beneficiary) - .build(); - (dest, message) - }, - }; - - // TODO: revisit to replace with signed contract origin - let origin: RuntimeOrigin = RawOrigin::Root.into(); - - // Generate runtime call to dispatch - let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::send { - dest: Box::new(dest), - message: Box::new(VersionedXcm::V4(message)), - }); - - dispatch_call::(&mut env, call, origin, LOG_PREFIX) -} - -#[cfg(test)] -mod tests { - pub use super::*; - pub use crate::*; - use enumflags2::BitFlags; - pub use pallet_contracts::Code; - use pallet_nfts::{CollectionConfig, CollectionSetting, CollectionSettings, MintSettings}; - use parachains_common::CollectionId; - pub use sp_runtime::{traits::Hash, AccountId32}; - - const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; - - const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); - const BOB: AccountId32 = AccountId32::new([2_u8; 32]); - const INITIAL_AMOUNT: u128 = 100_000 * UNIT; - const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); - - fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default() - .build_storage() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INITIAL_AMOUNT), (BOB, INITIAL_AMOUNT)], - } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } - - fn load_wasm_module(path: &str) -> std::io::Result<(Vec, ::Output)> - where - T: frame_system::Config, - { - let wasm_binary = std::fs::read(path)?; - let code_hash = T::Hashing::hash(&wasm_binary); - Ok((wasm_binary, code_hash)) - } - - fn function_selector(name: &str) -> Vec { - let hash = sp_io::hashing::blake2_256(name.as_bytes()); - [hash[0..4].to_vec()].concat() - } - - // NFT helper functions - fn collection_config_from_disabled_settings( - settings: BitFlags, - ) -> CollectionConfig { - CollectionConfig { - settings: CollectionSettings::from_disabled(settings), - max_supply: None, - mint_settings: MintSettings::default(), - } - } - - fn default_collection_config() -> CollectionConfig { - collection_config_from_disabled_settings(CollectionSetting::DepositRequired.into()) - } - - #[test] - #[ignore] - fn dispatch_balance_transfer_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/balance-transfer/target/ink/balance_transfer.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("transfer_through_runtime"); - let value_to_send: u128 = 10 * UNIT; - let params = [function, BOB.encode(), value_to_send.encode()].concat(); - - let bob_balance_before = Balances::free_balance(&BOB); - assert_eq!(bob_balance_before, INITIAL_AMOUNT); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - let bob_balance_after = Balances::free_balance(&BOB); - assert_eq!(bob_balance_before + value_to_send, bob_balance_after); - }); - } - - // Create a test for tesing create_nft_collection - #[test] - #[ignore] - fn dispatch_nfts_create_nft_collection() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/nfts/target/ink/pop_api_nft_example.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("create_nft_collection"); - - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check that the nft collection was created - assert_eq!(Nfts::collection_owner(0), Some(addr.clone().into())); - - // test reading the collection - let function = function_selector("read_collection"); - - let params = [function, 0.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // assert that the collection was read successfully - assert_eq!(result.result.clone().unwrap().data, vec![1, 1]); - }); - } - - #[test] - #[ignore] - fn dispatch_nfts_mint_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = - load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let collection_id: u32 = 0; - let item_id: u32 = 1; - - // create nft collection with contract as owner - assert_eq!( - Nfts::force_create( - RuntimeOrigin::root(), - addr.clone().into(), - default_collection_config() - ), - Ok(()) - ); - - assert_eq!(Nfts::collection_owner(collection_id), Some(addr.clone().into())); - // assert that the item does not exist yet - assert_eq!(Nfts::owner(collection_id, item_id), None); - - let function = function_selector("mint_through_runtime"); - - let params = - [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - assert_eq!(Nfts::owner(collection_id, item_id), Some(BOB.into())); - }); - } - - #[test] - #[ignore] - fn nfts_mint_surfaces_error() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = - load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let collection_id: u32 = 0; - let item_id: u32 = 1; - - let function = function_selector("mint_through_runtime"); - - let params = - [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert with expected error - let result = result.result.unwrap(); - assert!(result.did_revert()); - }); - } - - #[test] - #[ignore] - fn reading_last_relay_chain_block_number_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/read-runtime-state/target/ink/read_relay_blocknumber.wasm", - ) - .unwrap(); - - let init_value = 100; - - let contract = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!contract.result.did_revert(), "deploying contract reverted {:?}", contract); - - let addr = contract.account_id; - - let function = function_selector("read_relay_block_number"); - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::UnsafeCollect, - pallet_contracts::Determinism::Relaxed, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } - - #[test] - #[ignore] - fn place_spot_order_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/place-spot-order/target/ink/spot_order.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("place_spot_order"); - - let max_amount = 1 * UNIT; - let para_id = 2000; - - let params = [function, max_amount.encode(), para_id.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } - - #[test] - #[ignore] - fn dispatch_trust_backed_assets_mint_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/trust_backed_assets/target/ink/pop_api_trust_backed_assets_example.wasm", - ) - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - let addr = result.account_id; - - let asset_id: u32 = 1; - let min_balance = 1; - let amount: u128 = 100 * UNIT; - let function = function_selector("mint_asset_through_runtime"); - let params = [function, asset_id.encode(), BOB.encode(), amount.encode()].concat(); - - // Mint asset which does not exist. - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - GAS_LIMIT, - None, - params.clone(), - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // Check for revert. - assert!(result.result.unwrap().did_revert(), "Contract should have been reverted!"); - - // Create asset with contract as owner. - assert_eq!( - TrustBackedAssets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - addr.clone().into(), - true, - min_balance, - ), - Ok(()) - ); - - // Check Bob's asset balance before minting through contract. - let bob_balance_before = TrustBackedAssets::balance(asset_id, &BOB); - assert_eq!(bob_balance_before, 0); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - GAS_LIMIT, - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // Check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - let bob_balance_after = TrustBackedAssets::balance(asset_id, &BOB); - assert_eq!(bob_balance_after, bob_balance_before + amount); - }); - } - - #[test] - #[ignore] - fn allow_call_filter_blocks_call() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../tests/contracts/filtered-call/target/ink/pop_api_filtered_call.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("get_filtered"); - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("filtered result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } -} diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs new file mode 100644 index 00000000..096f21c9 --- /dev/null +++ b/runtime/devnet/src/extensions/mod.rs @@ -0,0 +1,896 @@ +use cumulus_pallet_parachain_system::RelaychainDataProvider; +use frame_support::traits::{Contains, OriginTrait}; +use frame_support::{ + dispatch::{GetDispatchInfo, RawOrigin}, + pallet_prelude::*, + traits::{ + fungibles::{approvals::Inspect as ApprovalInspect, Inspect}, + nonfungibles_v2::Inspect as NonFungiblesInspect, + }, +}; +use pallet_contracts::chain_extension::{ + BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, +}; +use pop_primitives::{ + cross_chain::CrossChainMessage, + storage_keys::{AssetsKeys, NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, + AssetId, CollectionId, ItemId, +}; +use sp_core::crypto::UncheckedFrom; +use sp_runtime::{ + traits::{BlockNumberProvider, Dispatchable}, + DispatchError, +}; +use sp_std::{boxed::Box, vec::Vec}; +use xcm::{ + latest::{prelude::*, OriginKind::SovereignAccount}, + VersionedXcm, +}; + +use crate::{ + config::assets::TrustBackedAssetsInstance, AccountId, AllowedPopApiCalls, RuntimeCall, + RuntimeOrigin, UNIT, +}; + +#[cfg(test)] +mod tests; + +const LOG_TARGET: &str = "pop-api::extension"; + +type ContractSchedule = ::Schedule; + +#[derive(Default)] +pub struct PopApiExtension; + +impl ChainExtension for PopApiExtension +where + T: pallet_contracts::Config + + pallet_xcm::Config + + pallet_assets::Config + + pallet_nfts::Config + + cumulus_pallet_parachain_system::Config + + frame_system::Config< + RuntimeOrigin = RuntimeOrigin, + AccountId = AccountId, + RuntimeCall = RuntimeCall, + >, + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ + fn call(&mut self, env: Environment) -> Result + where + E: Ext, + // T::AccountId: UncheckedFrom + AsRef<[u8]>, + { + log::debug!(target:LOG_TARGET, " extension called "); + match v0::FuncId::try_from(env.func_id())? { + v0::FuncId::Dispatch => { + match dispatch::(env) { + Ok(()) => Ok(RetVal::Converging(0)), + Err(DispatchError::Module(error)) => { + // encode status code = pallet index in runtime + error index, allowing for + // 999 errors + Ok(RetVal::Converging( + (error.index as u32 * 1_000) + u32::from_le_bytes(error.error), + )) + }, + Err(e) => Err(e), + } + }, + v0::FuncId::ReadState => { + read_state::(env)?; + Ok(RetVal::Converging(0)) + }, + v0::FuncId::SendXcm => { + send_xcm::(env)?; + Ok(RetVal::Converging(0)) + }, + } + } +} + +pub mod v0 { + #[derive(Debug)] + pub enum FuncId { + Dispatch, + ReadState, + SendXcm, + } +} + +impl TryFrom for v0::FuncId { + type Error = DispatchError; + + fn try_from(func_id: u16) -> Result { + let id = match func_id { + 0x0 => Self::Dispatch, + 0x1 => Self::ReadState, + 0x2 => Self::SendXcm, + _ => { + log::error!("called an unregistered `func_id`: {:}", func_id); + return Err(DispatchError::Other("unimplemented func_id")); + }, + }; + + Ok(id) + } +} + +fn dispatch_call( + env: &mut Environment, + call: RuntimeCall, + mut origin: RuntimeOrigin, + log_prefix: &str, +) -> Result<(), DispatchError> +where + T: frame_system::Config, + RuntimeOrigin: From>, + E: Ext, +{ + let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; + + log::debug!(target:LOG_TARGET, "{} Inputted RuntimeCall: {:?}", log_prefix, call); + + origin.add_filter(AllowedPopApiCalls::contains); + + match call.dispatch(origin) { + Ok(info) => { + log::debug!(target:LOG_TARGET, "{} success, actual weight: {:?}", log_prefix, info.actual_weight); + + // refund weight if the actual weight is less than the charged weight + if let Some(actual_weight) = info.actual_weight { + env.adjust_weight(charged_dispatch_weight, actual_weight); + } + + Ok(()) + }, + Err(err) => { + log::debug!(target:LOG_TARGET, "{} failed: error: {:?}", log_prefix, err.error); + Err(err.error) + }, + } +} + +fn charge_overhead_weight( + env: &mut Environment, + len: u32, + log_prefix: &str, +) -> Result +where + T: pallet_contracts::Config, + E: Ext, +{ + let contract_host_weight = ContractSchedule::::get().host_fn_weights; + + // calculate weight for reading bytes of `len` + // reference: https://github.com/paritytech/polkadot-sdk/blob/117a9433dac88d5ac00c058c9b39c511d47749d2/substrate/frame/contracts/src/wasm/runtime.rs#L267 + let base_weight: Weight = contract_host_weight.return_per_byte.saturating_mul(len.into()); + + // debug_message weight is a good approximation of the additional overhead of going + // from contract layer to substrate layer. + // reference: https://github.com/paritytech/ink-examples/blob/b8d2caa52cf4691e0ddd7c919e4462311deb5ad0/psp22-extension/runtime/psp22-extension-example.rs#L236 + let overhead = contract_host_weight.debug_message; + + let charged_weight = env.charge_weight(base_weight.saturating_add(overhead))?; + log::debug!(target: LOG_TARGET, "{} charged weight: {:?}", log_prefix, charged_weight); + + Ok(charged_weight) +} + +fn dispatch(env: Environment) -> Result<(), DispatchError> +where + T: pallet_contracts::Config + + frame_system::Config, + RuntimeOrigin: From>, + E: Ext, +{ + const LOG_PREFIX: &str = " dispatch |"; + + let mut env = env.buf_in_buf_out(); + let len = env.in_len(); + + charge_overhead_weight::(&mut env, len, LOG_PREFIX)?; + + // read the input as RuntimeCall + let call: RuntimeCall = env.read_as_unbounded(len)?; + + log::debug!(target: LOG_TARGET, "Read input as call successfully"); + + // contract is the origin by default + let origin: RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); + + dispatch_call::(&mut env, call, origin, LOG_PREFIX) +} + +fn read_state(env: Environment) -> Result<(), DispatchError> +where + T: pallet_contracts::Config + + pallet_assets::Config + + pallet_nfts::Config + + cumulus_pallet_parachain_system::Config + + frame_system::Config, + E: Ext, +{ + const LOG_PREFIX: &str = " read_state |"; + + let mut env = env.buf_in_buf_out(); + + // To be conservative, we charge the weight for reading the input bytes of a fixed-size type. + let base_weight: Weight = ContractSchedule::::get() + .host_fn_weights + .return_per_byte + .saturating_mul(env.in_len().into()); + let charged_weight = env.charge_weight(base_weight)?; + + log::debug!(target:LOG_TARGET, "{} charged weight: {:?}", LOG_PREFIX, charged_weight); + + let key: RuntimeStateKeys = env.read_as()?; + + let result = match key { + RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, &mut env), + RuntimeStateKeys::ParachainSystem(key) => { + read_parachain_system_state::(key, &mut env) + }, + RuntimeStateKeys::Assets(key) => read_trust_backed_assets_state::(key, &mut env), + }? + .encode(); + + log::trace!( + target:LOG_TARGET, + "{} result: {:?}.", LOG_PREFIX, result + ); + env.write(&result, false, None).map_err(|e| { + log::trace!(target: LOG_TARGET, "{:?}", e); + DispatchError::Other("unable to write results to contract memory") + }) +} + +fn read_parachain_system_state( + key: ParachainSystemKeys, + env: &mut Environment, +) -> Result, DispatchError> +where + T: pallet_contracts::Config + cumulus_pallet_parachain_system::Config, + E: Ext, +{ + match key { + ParachainSystemKeys::LastRelayChainBlockNumber => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(RelaychainDataProvider::::current_block_number().encode()) + }, + } +} + +fn read_nfts_state( + key: NftsKeys, + env: &mut Environment, +) -> Result, DispatchError> +where + T: pallet_contracts::Config + pallet_nfts::Config, + E: Ext, +{ + match key { + NftsKeys::Collection(collection) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_nfts::Collection::::get(collection).encode()) + }, + NftsKeys::CollectionOwner(collection) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_nfts::Pallet::::collection_owner(collection).encode()) + }, + NftsKeys::Item(collection, item) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_nfts::Item::::get(collection, item).encode()) + }, + NftsKeys::Owner(collection, item) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_nfts::Pallet::::owner(collection, item).encode()) + }, + NftsKeys::Attribute(collection, item, key) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_nfts::Pallet::::attribute(&collection, &item, &key).encode()) + }, + // NftsKeys::CustomAttribute(account, collection, item, key) => { + // env.charge_weight(T::DbWeight::get().reads(1_u64))?; + // Ok(pallet_nfts::Pallet::::custom_attribute(&account, &collection, &item, &key) + // .encode()) + // }, + NftsKeys::SystemAttribute(collection, item, key) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_nfts::Pallet::::system_attribute(&collection, item.as_ref(), &key) + .encode()) + }, + NftsKeys::CollectionAttribute(collection, key) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_nfts::Pallet::::collection_attribute(&collection, &key).encode()) + }, + } +} + +fn read_trust_backed_assets_state( + key: AssetsKeys, + env: &mut Environment, +) -> Result, DispatchError> +where + T: pallet_contracts::Config + + pallet_assets::Config, + E: Ext, + T: frame_system::Config, +{ + match key { + AssetsKeys::Allowance(id, owner, spender) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_assets::Pallet::::allowance( + id, + &owner.0.into(), + &spender.0.into(), + ) + .encode()) + }, + AssetsKeys::AssetExists(id) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_assets::Pallet::::asset_exists(id).encode()) + }, + AssetsKeys::BalanceOf(id, owner) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_assets::Pallet::::balance(id, &owner.0.into()) + .encode()) + }, + AssetsKeys::TotalSupply(id) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_assets::Pallet::::total_supply(id).encode()) + }, + } +} + +fn send_xcm(env: Environment) -> Result<(), DispatchError> +where + T: pallet_contracts::Config + + frame_system::Config< + RuntimeOrigin = RuntimeOrigin, + AccountId = AccountId, + RuntimeCall = RuntimeCall, + >, + E: Ext, +{ + const LOG_PREFIX: &str = " send_xcm |"; + + let mut env = env.buf_in_buf_out(); + let len = env.in_len(); + + let _ = charge_overhead_weight::(&mut env, len, LOG_PREFIX)?; + + // read the input as CrossChainMessage + let xc_call: CrossChainMessage = env.read_as::()?; + + // Determine the call to dispatch + let (dest, message) = match xc_call { + CrossChainMessage::Relay(message) => { + let dest = Location::parent().into_versioned(); + let assets: Asset = (Here, 10 * UNIT).into(); + let beneficiary: Location = + AccountId32 { id: (env.ext().address().clone()).into(), network: None }.into(); + let message = Xcm::builder() + .withdraw_asset(assets.clone().into()) + .buy_execution(assets.clone(), Unlimited) + .transact( + SovereignAccount, + Weight::from_parts(250_000_000, 10_000), + message.encode().into(), + ) + .refund_surplus() + .deposit_asset(assets.into(), beneficiary) + .build(); + (dest, message) + }, + }; + + // TODO: revisit to replace with signed contract origin + let origin: RuntimeOrigin = RawOrigin::Root.into(); + + // Generate runtime call to dispatch + let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::send { + dest: Box::new(dest), + message: Box::new(VersionedXcm::V4(message)), + }); + + dispatch_call::(&mut env, call, origin, LOG_PREFIX) +} + +// use enumflags2::BitFlags; +// use pallet_nfts::{CollectionConfig, CollectionSetting, CollectionSettings, MintSettings}; +// use parachains_common::CollectionId; +// { +// // NFT helper functions +// fn collection_config_from_disabled_settings( +// settings: BitFlags, +// ) -> CollectionConfig { +// CollectionConfig { +// settings: CollectionSettings::from_disabled(settings), +// max_supply: None, +// mint_settings: MintSettings::default(), +// } +// } +// +// fn default_collection_config() -> CollectionConfig { +// collection_config_from_disabled_settings(CollectionSetting::DepositRequired.into()) +// } +// +// #[test] +// #[ignore] +// fn dispatch_balance_transfer_from_contract_works() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// +// let (wasm_binary, _) = load_wasm_module::( +// "../../pop-api/examples/balance-transfer/target/ink/balance_transfer.wasm", +// ) +// .unwrap(); +// +// let init_value = 100 * UNIT; +// +// let result = Contracts::bare_instantiate( +// ALICE, +// init_value, +// GAS_LIMIT, +// None, +// Code::Upload(wasm_binary), +// function_selector("new"), +// vec![], +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// ) +// .result +// .unwrap(); +// +// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); +// +// let addr = result.account_id; +// +// let function = function_selector("transfer_through_runtime"); +// let value_to_send: u128 = 10 * UNIT; +// let params = [function, BOB.encode(), value_to_send.encode()].concat(); +// +// let bob_balance_before = Balances::free_balance(&BOB); +// assert_eq!(bob_balance_before, INITIAL_AMOUNT); +// +// let result = Contracts::bare_call( +// ALICE, +// addr.clone(), +// 0, +// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), +// None, +// params, +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// pallet_contracts::Determinism::Enforced, +// ); +// +// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { +// log::debug!( +// "Contract debug buffer - {:?}", +// String::from_utf8(result.debug_message.clone()) +// ); +// log::debug!("result: {:?}", result); +// } +// +// // check for revert +// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); +// +// let bob_balance_after = Balances::free_balance(&BOB); +// assert_eq!(bob_balance_before + value_to_send, bob_balance_after); +// }); +// } +// +// // Create a test for tesing create_nft_collection +// #[test] +// #[ignore] +// fn dispatch_nfts_create_nft_collection() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// +// let (wasm_binary, _) = load_wasm_module::( +// "../../pop-api/examples/nfts/target/ink/pop_api_nft_example.wasm", +// ) +// .unwrap(); +// +// let init_value = 100 * UNIT; +// +// let result = Contracts::bare_instantiate( +// ALICE, +// init_value, +// GAS_LIMIT, +// None, +// Code::Upload(wasm_binary), +// function_selector("new"), +// vec![], +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// ) +// .result +// .unwrap(); +// +// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); +// +// let addr = result.account_id; +// +// let function = function_selector("create_nft_collection"); +// +// let params = [function].concat(); +// +// let result = Contracts::bare_call( +// ALICE, +// addr.clone(), +// 0, +// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), +// None, +// params, +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// pallet_contracts::Determinism::Enforced, +// ); +// +// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { +// log::debug!( +// "Contract debug buffer - {:?}", +// String::from_utf8(result.debug_message.clone()) +// ); +// log::debug!("result: {:?}", result); +// } +// +// // check that the nft collection was created +// assert_eq!(Nfts::collection_owner(0), Some(addr.clone().into())); +// +// // test reading the collection +// let function = function_selector("read_collection"); +// +// let params = [function, 0.encode()].concat(); +// +// let result = Contracts::bare_call( +// ALICE, +// addr.clone(), +// 0, +// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), +// None, +// params, +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// pallet_contracts::Determinism::Enforced, +// ); +// +// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { +// log::debug!( +// "Contract debug buffer - {:?}", +// String::from_utf8(result.debug_message.clone()) +// ); +// log::debug!("result: {:?}", result); +// } +// +// // assert that the collection was read successfully +// assert_eq!(result.result.clone().unwrap().data, vec![1, 1]); +// }); +// } +// +// #[test] +// #[ignore] +// fn dispatch_nfts_mint_from_contract_works() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// +// let (wasm_binary, _) = +// load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") +// .unwrap(); +// +// let init_value = 100; +// +// let result = Contracts::bare_instantiate( +// ALICE, +// init_value, +// GAS_LIMIT, +// None, +// Code::Upload(wasm_binary), +// function_selector("new"), +// vec![], +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// ) +// .result +// .unwrap(); +// +// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); +// +// let addr = result.account_id; +// +// let collection_id: u32 = 0; +// let item_id: u32 = 1; +// +// // create nft collection with contract as owner +// assert_eq!( +// Nfts::force_create( +// RuntimeOrigin::root(), +// addr.clone().into(), +// default_collection_config() +// ), +// Ok(()) +// ); +// +// assert_eq!(Nfts::collection_owner(collection_id), Some(addr.clone().into())); +// // assert that the item does not exist yet +// assert_eq!(Nfts::owner(collection_id, item_id), None); +// +// let function = function_selector("mint_through_runtime"); +// +// let params = +// [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); +// +// let result = Contracts::bare_call( +// ALICE, +// addr.clone(), +// 0, +// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), +// None, +// params, +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// pallet_contracts::Determinism::Enforced, +// ); +// +// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { +// log::debug!( +// "Contract debug buffer - {:?}", +// String::from_utf8(result.debug_message.clone()) +// ); +// log::debug!("result: {:?}", result); +// } +// +// // check for revert +// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); +// +// assert_eq!(Nfts::owner(collection_id, item_id), Some(BOB.into())); +// }); +// } +// +// #[test] +// #[ignore] +// fn nfts_mint_surfaces_error() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// +// let (wasm_binary, _) = +// load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") +// .unwrap(); +// +// let init_value = 100; +// +// let result = Contracts::bare_instantiate( +// ALICE, +// init_value, +// GAS_LIMIT, +// None, +// Code::Upload(wasm_binary), +// function_selector("new"), +// vec![], +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// ) +// .result +// .unwrap(); +// +// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); +// +// let addr = result.account_id; +// +// let collection_id: u32 = 0; +// let item_id: u32 = 1; +// +// let function = function_selector("mint_through_runtime"); +// +// let params = +// [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); +// +// let result = Contracts::bare_call( +// ALICE, +// addr.clone(), +// 0, +// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), +// None, +// params, +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// pallet_contracts::Determinism::Enforced, +// ); +// +// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { +// log::debug!( +// "Contract debug buffer - {:?}", +// String::from_utf8(result.debug_message.clone()) +// ); +// log::debug!("result: {:?}", result); +// } +// +// // check for revert with expected error +// let result = result.result.unwrap(); +// assert!(result.did_revert()); +// }); +// } +// +// #[test] +// #[ignore] +// fn reading_last_relay_chain_block_number_works() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// +// let (wasm_binary, _) = load_wasm_module::( +// "../../pop-api/examples/read-runtime-state/target/ink/read_relay_blocknumber.wasm", +// ) +// .unwrap(); +// +// let init_value = 100; +// +// let contract = Contracts::bare_instantiate( +// ALICE, +// init_value, +// GAS_LIMIT, +// None, +// Code::Upload(wasm_binary), +// function_selector("new"), +// vec![], +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// ) +// .result +// .unwrap(); +// +// assert!(!contract.result.did_revert(), "deploying contract reverted {:?}", contract); +// +// let addr = contract.account_id; +// +// let function = function_selector("read_relay_block_number"); +// let params = [function].concat(); +// +// let result = Contracts::bare_call( +// ALICE, +// addr.clone(), +// 0, +// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), +// None, +// params, +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::UnsafeCollect, +// pallet_contracts::Determinism::Relaxed, +// ); +// +// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { +// log::debug!( +// "Contract debug buffer - {:?}", +// String::from_utf8(result.debug_message.clone()) +// ); +// log::debug!("result: {:?}", result); +// } +// +// // check for revert +// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); +// }); +// } +// +// #[test] +// #[ignore] +// fn place_spot_order_from_contract_works() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// +// let (wasm_binary, _) = load_wasm_module::( +// "../../pop-api/examples/place-spot-order/target/ink/spot_order.wasm", +// ) +// .unwrap(); +// +// let init_value = 100 * UNIT; +// +// let result = Contracts::bare_instantiate( +// ALICE, +// init_value, +// GAS_LIMIT, +// None, +// Code::Upload(wasm_binary), +// function_selector("new"), +// vec![], +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// ) +// .result +// .unwrap(); +// +// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); +// +// let addr = result.account_id; +// +// let function = function_selector("place_spot_order"); +// +// let max_amount = 1 * UNIT; +// let para_id = 2000; +// +// let params = [function, max_amount.encode(), para_id.encode()].concat(); +// +// let result = Contracts::bare_call( +// ALICE, +// addr.clone(), +// 0, +// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), +// None, +// params, +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// pallet_contracts::Determinism::Enforced, +// ); +// +// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { +// log::debug!( +// "Contract debug buffer - {:?}", +// String::from_utf8(result.debug_message.clone()) +// ); +// log::debug!("result: {:?}", result); +// } +// +// // check for revert +// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); +// }); +// } +// +// #[test] +// #[ignore] +// fn allow_call_filter_blocks_call() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// +// let (wasm_binary, _) = load_wasm_module::( +// "../../tests/contracts/filtered-call/target/ink/pop_api_filtered_call.wasm", +// ) +// .unwrap(); +// +// let init_value = 100 * UNIT; +// +// let result = Contracts::bare_instantiate( +// ALICE, +// init_value, +// GAS_LIMIT, +// None, +// Code::Upload(wasm_binary), +// function_selector("new"), +// vec![], +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// ) +// .result +// .unwrap(); +// +// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); +// +// let addr = result.account_id; +// +// let function = function_selector("get_filtered"); +// let params = [function].concat(); +// +// let result = Contracts::bare_call( +// ALICE, +// addr.clone(), +// 0, +// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), +// None, +// params, +// DEBUG_OUTPUT, +// pallet_contracts::CollectEvents::Skip, +// pallet_contracts::Determinism::Enforced, +// ); +// +// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { +// log::debug!( +// "Contract debug buffer - {:?}", +// String::from_utf8(result.debug_message.clone()) +// ); +// log::debug!("filtered result: {:?}", result); +// } +// +// // check for revert +// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); +// }); +// } +// } diff --git a/runtime/devnet/src/extensions/tests/local_fungibles.rs b/runtime/devnet/src/extensions/tests/local_fungibles.rs new file mode 100644 index 00000000..2d752361 --- /dev/null +++ b/runtime/devnet/src/extensions/tests/local_fungibles.rs @@ -0,0 +1,302 @@ +#![cfg(test)] + +use super::*; +use pallet_contracts::debug::ExecResult; + +#[derive(Decode, Encode, Debug, Eq, PartialEq)] +enum FungiblesError { + // AssetsError(Error), + // /// The origin of the call doesn't have the right permission. + // BadOrigin, + // /// Custom error type for cases in which an implementation adds its own restrictions. + // Custom(String), + /// Not enough balance to fulfill a request is available. + InsufficientBalance, + /// Not enough allowance to fulfill a request is available. + InsufficientAllowance, + /// The asset status is not the expected status. + IncorrectStatus, + /// The asset ID is already taken. + InUse, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// The signing account has no permission to do the operation. + NoPermission, + // /// Safe transfer check fails (e.g. if the receiving contract does not accept tokens). + // SafeTransferCheckFailed(String), + /// The given asset ID is unknown. + Unknown, + /// Recipient's address is zero. + ZeroRecipientAddress, + /// Sender's address is zero. + ZeroSenderAddress, + UndefinedError, +} + +const ASSET_ID: u32 = 1; + +fn allowance( + addr: AccountId32, + asset_id: u32, + owner: AccountId32, + spender: AccountId32, +) -> ExecReturnValue { + let function = function_selector("allowance"); + let params = [function, asset_id.encode(), owner.encode(), spender.encode()].concat(); + do_bare_call(addr, params, 0).expect("should work") +} + +// Call balance_of contract message. +fn balance_of(addr: AccountId32, asset_id: u32, owner: AccountId32) -> ExecReturnValue { + let function = function_selector("balance_of"); + let params = [function, asset_id.encode(), owner.encode()].concat(); + do_bare_call(addr, params, 0).expect("should work") +} + +// Call total_supply contract message. +fn total_supply(addr: AccountId32, asset_id: u32) -> ExecReturnValue { + let function = function_selector("total_supply"); + let params = [function, asset_id.encode()].concat(); + do_bare_call(addr, params, 0).expect("should work") +} + +fn asset_exists(addr: AccountId32, asset_id: u32) -> ExecReturnValue { + let function = function_selector("asset_exists"); + let params = [function, asset_id.encode()].concat(); + do_bare_call(addr, params, 0).expect("should work") +} + +fn create( + addr: AccountId32, + asset_id: u32, + admin: AccountId32, + min_balance: u128, +) -> ExecReturnValue { + let function = function_selector("create"); + let params = [function, asset_id.encode(), admin.encode(), min_balance.encode()].concat(); + do_bare_call(addr, params, 0).expect("should work") +} + +fn set_metadata( + addr: AccountId32, + asset_id: u32, + name: Vec, + symbol: Vec, + decimals: u8, +) -> ExecReturnValue { + let function = function_selector("set_metadata"); + let params = + [function, asset_id.encode(), name.encode(), symbol.encode(), decimals.encode()].concat(); + do_bare_call(addr, params, 0).expect("should work") +} + +fn transfer_from( + addr: AccountId32, + asset_id: u32, + _from: Option, + to: Option, + value: u128, + _data: &[u8], +) -> ExecReturnValue { + // let function = function_selector("transfer_from"); + // let params = + // [function, asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()] + // .concat(); + // do_bare_call(addr, params, 0) + let function = function_selector("mint"); + let params = [function, asset_id.encode(), to.unwrap().encode(), value.encode()].concat(); + do_bare_call(addr, params, 0).expect("should work") +} + +// Create an asset and mint to owner. +fn create_asset(asset_id: u32, owner: AccountId32) { + assert_eq!( + Assets::create(RuntimeOrigin::signed(owner.clone()), asset_id.into(), owner.into(), 1), + Ok(()) + ); +} + +// Create an asset and mint to owner. +fn create_asset_and_mint_to(asset_id: u32, owner: AccountId32, to: AccountId32, value: u128) { + create_asset(asset_id, owner.clone()); + assert_eq!( + Assets::mint(RuntimeOrigin::signed(owner.into()), asset_id.into(), to.into(), value,), + Ok(()) + ); +} + +// Create an asset, mints to, and approves spender. +fn create_asset_mint_and_approve( + asset_id: u32, + owner: AccountId32, + to: AccountId32, + mint: u128, + spender: AccountId32, + approve: u128, +) { + create_asset_and_mint_to(asset_id, owner.clone(), to.clone(), mint); + assert_eq!( + Assets::approve_transfer( + RuntimeOrigin::signed(to.into()), + asset_id.into(), + spender.into(), + approve, + ), + Ok(()) + ); +} + +#[test] +#[ignore] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = + instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + + // No tokens in circulation. + assert_eq!( + Assets::total_supply(ASSET_ID).encode(), + total_supply(addr.clone(), ASSET_ID).data[2..] + ); + + // Tokens in circulation. + create_asset_and_mint_to(ASSET_ID, addr.clone(), BOB, 100); + assert_eq!(Assets::total_supply(ASSET_ID).encode(), total_supply(addr, ASSET_ID).data[2..]); + }); +} + +#[test] +#[ignore] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = + instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + + // No tokens in circulation. + assert_eq!( + Assets::balance(ASSET_ID, BOB).encode(), + balance_of(addr.clone(), ASSET_ID, BOB).data[2..] + ); + + // Tokens in circulation. + create_asset_and_mint_to(ASSET_ID, addr.clone(), BOB, 100); + assert_eq!( + Assets::balance(ASSET_ID, BOB).encode(), + balance_of(addr, ASSET_ID, BOB).data[2..] + ); + }); +} + +#[test] +#[ignore] +fn allowance_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = + instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + + // No tokens in circulation. + assert_eq!( + Assets::allowance(ASSET_ID, &BOB, &ALICE).encode(), + allowance(addr.clone(), ASSET_ID, BOB, ALICE).data[2..] + ); + + // Tokens in circulation. + create_asset_mint_and_approve(ASSET_ID, addr.clone(), BOB, 100, ALICE, 50); + assert_eq!( + Assets::allowance(ASSET_ID, &BOB, &ALICE).encode(), + allowance(addr, ASSET_ID, BOB, ALICE).data[2..] + ); + }); +} + +#[test] +#[ignore] +fn asset_exists_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = + instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + + // No tokens in circulation. + assert_eq!( + Assets::asset_exists(ASSET_ID).encode(), + asset_exists(addr.clone(), ASSET_ID).data[2..] + ); + + // Tokens in circulation. + create_asset(ASSET_ID, addr.clone()); + assert_eq!(Assets::asset_exists(ASSET_ID).encode(), asset_exists(addr, ASSET_ID).data[2..]); + }); +} + +fn decode_error(result: ExecReturnValue) -> FungiblesError { + FungiblesError::decode(&mut &result.data[2..]).unwrap() +} + +#[test] +#[ignore] +fn create_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", 0); + let new_asset = 2; + + assert_eq!( + decode_error(create(addr.clone(), new_asset, BOB, 1)), + FungiblesError::UndefinedError + ); + // Todo: errors Badorigin, Lookup, reserve(), Callback + // create_asset(ASSET_ID, ALICE); + // // Error `InUse`. + // assert_eq!(decode_error(create(addr.clone(), ASSET_ID, BOB, 1)), FungiblesError::InUse); + // // Error `MinBalanceZero`. + // assert_eq!( + // decode_error(create(addr.clone(), new_asset, BOB, 0)), + // FungiblesError::MinBalanceZero + // ); + // assert!( + // !create(addr.clone(), new_asset, BOB, 1).did_revert(), + // "Contract should have been reverted!" + // ); + }); +} + +#[test] +#[ignore] +fn set_metadata_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = + instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + + create_asset(ASSET_ID, addr.clone()); + + let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); + assert!(!result.did_revert(), "Contract should have been reverted!"); + }); +} + +#[test] +#[ignore] +fn transfer_from_aka_mint_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = + instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + + let amount: u128 = 100 * UNIT; + // Create asset with contract as owner. + create_asset(ASSET_ID, addr.clone()); + // Check Bob's asset balance before minting through contract. + let bob_balance_before = Assets::balance(ASSET_ID, &BOB); + + let result = transfer_from(addr.clone(), ASSET_ID, None, Some(BOB), 100 * UNIT, &[0u8]); + assert!(!result.did_revert(), "Contract reverted!"); + + let bob_balance_after = Assets::balance(ASSET_ID, &BOB); + assert_eq!(bob_balance_after, bob_balance_before + amount); + }); +} diff --git a/runtime/devnet/src/extensions/tests/mod.rs b/runtime/devnet/src/extensions/tests/mod.rs new file mode 100644 index 00000000..30d1a924 --- /dev/null +++ b/runtime/devnet/src/extensions/tests/mod.rs @@ -0,0 +1,86 @@ +#![cfg(test)] +use super::*; +use crate::{Assets, Balances, Contracts, Runtime, System}; +use pallet_contracts::{Code, CollectEvents, Determinism, ExecReturnValue}; +use sp_runtime::{traits::Hash, AccountId32, BuildStorage}; + +mod local_fungibles; + +const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; + +const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); +const BOB: AccountId32 = AccountId32::new([2_u8; 32]); +const INIT_VALUE: u128 = 100_000_000 * UNIT; +const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); + +fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { + balances: vec![(ALICE, INIT_VALUE), (BOB, INIT_VALUE)], + } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +fn load_wasm_module(path: &str) -> std::io::Result<(Vec, ::Output)> +where + T: frame_system::Config, +{ + let wasm_binary = std::fs::read(path)?; + let code_hash = T::Hashing::hash(&wasm_binary); + Ok((wasm_binary, code_hash)) +} + +fn function_selector(name: &str) -> Vec { + let hash = sp_io::hashing::blake2_256(name.as_bytes()); + [hash[0..4].to_vec()].concat() +} + +fn do_bare_call( + addr: AccountId32, + input: Vec, + value: u128, +) -> Result { + let result = Contracts::bare_call( + ALICE, + addr.into(), + value.into(), + GAS_LIMIT, + None, + input, + DEBUG_OUTPUT, + CollectEvents::Skip, + Determinism::Enforced, + ); + log::debug!("Contract debug buffer - {:?}", String::from_utf8(result.debug_message.clone())); + log::debug!("result: {:?}", result); + result.result +} + +// Deploy, instantiate and return contract address. +fn instantiate(contract: &str, init_value: u128) -> AccountId32 { + let (wasm_binary, _) = + load_wasm_module::(contract).expect("could not read .wasm file"); + let result = Contracts::bare_instantiate( + ALICE, + init_value, + GAS_LIMIT, + None, + Code::Upload(wasm_binary), + function_selector("new"), + vec![], + DEBUG_OUTPUT, + CollectEvents::Skip, + ) + .result + .unwrap(); + assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); + result.account_id +} diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 52a0938f..a82be804 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -254,40 +254,40 @@ impl Contains for FilteredCalls { pub struct AllowedPopApiCalls; impl Contains for crate::AllowedPopApiCalls { fn contains(c: &RuntimeCall) -> bool { - use assets_config::TrustBackedAssetsCall; + use config::assets::AssetsCall; use pallet_nfts::Call as NftsCall; matches!( c, RuntimeCall::Balances(BalancesCall::transfer_keep_alive { .. }) - | RuntimeCall::TrustBackedAssets( - TrustBackedAssetsCall::create { .. } - | TrustBackedAssetsCall::start_destroy { .. } - | TrustBackedAssetsCall::destroy_accounts { .. } - | TrustBackedAssetsCall::destroy_approvals { .. } - | TrustBackedAssetsCall::finish_destroy { .. } - | TrustBackedAssetsCall::mint { .. } - | TrustBackedAssetsCall::burn { .. } - | TrustBackedAssetsCall::transfer { .. } - | TrustBackedAssetsCall::transfer_keep_alive { .. } - | TrustBackedAssetsCall::force_transfer { .. } - | TrustBackedAssetsCall::freeze { .. } - | TrustBackedAssetsCall::thaw { .. } - | TrustBackedAssetsCall::freeze_asset { .. } - | TrustBackedAssetsCall::thaw_asset { .. } - | TrustBackedAssetsCall::transfer_ownership { .. } - | TrustBackedAssetsCall::set_team { .. } - | TrustBackedAssetsCall::set_metadata { .. } - | TrustBackedAssetsCall::clear_metadata { .. } - | TrustBackedAssetsCall::approve_transfer { .. } - | TrustBackedAssetsCall::cancel_approval { .. } - | TrustBackedAssetsCall::force_cancel_approval { .. } - | TrustBackedAssetsCall::transfer_approved { .. } - | TrustBackedAssetsCall::touch { .. } - | TrustBackedAssetsCall::refund { .. } - | TrustBackedAssetsCall::set_min_balance { .. } - | TrustBackedAssetsCall::touch_other { .. } - | TrustBackedAssetsCall::refund_other { .. } - | TrustBackedAssetsCall::block { .. } + | RuntimeCall::Assets( + AssetsCall::create { .. } + | AssetsCall::start_destroy { .. } + | AssetsCall::destroy_accounts { .. } + | AssetsCall::destroy_approvals { .. } + | AssetsCall::finish_destroy { .. } + | AssetsCall::mint { .. } + | AssetsCall::burn { .. } + | AssetsCall::transfer { .. } + | AssetsCall::transfer_keep_alive { .. } + | AssetsCall::force_transfer { .. } + | AssetsCall::freeze { .. } + | AssetsCall::thaw { .. } + | AssetsCall::freeze_asset { .. } + | AssetsCall::thaw_asset { .. } + | AssetsCall::transfer_ownership { .. } + | AssetsCall::set_team { .. } + | AssetsCall::set_metadata { .. } + | AssetsCall::clear_metadata { .. } + | AssetsCall::approve_transfer { .. } + | AssetsCall::cancel_approval { .. } + | AssetsCall::force_cancel_approval { .. } + | AssetsCall::transfer_approved { .. } + | AssetsCall::touch { .. } + | AssetsCall::refund { .. } + | AssetsCall::set_min_balance { .. } + | AssetsCall::touch_other { .. } + | AssetsCall::refund_other { .. } + | AssetsCall::block { .. } ) | RuntimeCall::Nfts( NftsCall::create { .. } | NftsCall::destroy { .. } @@ -662,7 +662,7 @@ construct_runtime!( // Assets Nfts: pallet_nfts = 50, NftFractionalization: pallet_nft_fractionalization = 51, - TrustBackedAssets: pallet_assets:: = 52, + Assets: pallet_assets:: = 52, } ); diff --git a/runtime/testnet/Cargo.toml b/runtime/testnet/Cargo.toml index d68bfd15..43b1e310 100644 --- a/runtime/testnet/Cargo.toml +++ b/runtime/testnet/Cargo.toml @@ -22,7 +22,7 @@ scale-info.workspace = true smallvec.workspace = true # Local -pop-primitives.workspace = true +pop-primitives = { workspace = true, features = ["testnet"] } pop-runtime-common = { workspace = true, default-features = false } # Substrate diff --git a/runtime/testnet/src/config/assets.rs b/runtime/testnet/src/config/assets.rs index f51f8875..2c8ea952 100644 --- a/runtime/testnet/src/config/assets.rs +++ b/runtime/testnet/src/config/assets.rs @@ -1,6 +1,6 @@ use crate::{ - deposit, AccountId, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, - RuntimeHoldReason, TrustBackedAssets, DAYS, EXISTENTIAL_DEPOSIT, UNIT, + deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, + RuntimeHoldReason, DAYS, EXISTENTIAL_DEPOSIT, UNIT, }; use frame_support::{ parameter_types, @@ -86,7 +86,7 @@ impl pallet_nft_fractionalization::Config for Runtime { type NftId = ::ItemId; type AssetBalance = >::Balance; type AssetId = >::AssetId; - type Assets = TrustBackedAssets; + type Assets = Assets; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight; @@ -96,7 +96,7 @@ impl pallet_nft_fractionalization::Config for Runtime { } pub type TrustBackedAssetsInstance = pallet_assets::Instance1; -pub(crate) type TrustBackedAssetsCall = pallet_assets::Call; +pub(crate) type AssetsCall = pallet_assets::Call; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; diff --git a/runtime/testnet/src/config/proxy.rs b/runtime/testnet/src/config/proxy.rs index a4fd479a..07d5f0f8 100644 --- a/runtime/testnet/src/config/proxy.rs +++ b/runtime/testnet/src/config/proxy.rs @@ -1,4 +1,4 @@ -use super::assets::TrustBackedAssetsCall; +use super::assets::AssetsCall; use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; use frame_support::traits::InstanceFilter; use pop_runtime_common::proxy::{ @@ -34,16 +34,16 @@ impl InstanceFilter for ProxyType { }, ProxyType::AssetOwner => matches!( c, - RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) + RuntimeCall::Assets(AssetsCall::create { .. }) + | RuntimeCall::Assets(AssetsCall::start_destroy { .. }) + | RuntimeCall::Assets(AssetsCall::destroy_accounts { .. }) + | RuntimeCall::Assets(AssetsCall::destroy_approvals { .. }) + | RuntimeCall::Assets(AssetsCall::finish_destroy { .. }) + | RuntimeCall::Assets(AssetsCall::transfer_ownership { .. }) + | RuntimeCall::Assets(AssetsCall::set_team { .. }) + | RuntimeCall::Assets(AssetsCall::set_metadata { .. }) + | RuntimeCall::Assets(AssetsCall::clear_metadata { .. }) + | RuntimeCall::Assets(AssetsCall::set_min_balance { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) @@ -56,15 +56,15 @@ impl InstanceFilter for ProxyType { ), ProxyType::AssetManager => matches!( c, - RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) + RuntimeCall::Assets(AssetsCall::mint { .. }) + | RuntimeCall::Assets(AssetsCall::burn { .. }) + | RuntimeCall::Assets(AssetsCall::freeze { .. }) + | RuntimeCall::Assets(AssetsCall::block { .. }) + | RuntimeCall::Assets(AssetsCall::thaw { .. }) + | RuntimeCall::Assets(AssetsCall::freeze_asset { .. }) + | RuntimeCall::Assets(AssetsCall::thaw_asset { .. }) + | RuntimeCall::Assets(AssetsCall::touch_other { .. }) + | RuntimeCall::Assets(AssetsCall::refund_other { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index 0d552090..6bbfaa36 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -3,25 +3,23 @@ use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, - traits::{fungibles::Inspect, nonfungibles_v2::Inspect as NonFungiblesInspect}, + traits::nonfungibles_v2::Inspect as NonFungiblesInspect, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, }; use pop_primitives::{ - storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys, TrustBackedAssetsKeys}, - AssetId, CollectionId, ItemId, + storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, + CollectionId, ItemId, }; use sp_core::crypto::UncheckedFrom; use sp_runtime::{ traits::{BlockNumberProvider, Dispatchable}, DispatchError, }; +use sp_std::vec::Vec; -use crate::{ - assets_config::TrustBackedAssetsInstance, AccountId, AllowedPopApiCalls, RuntimeCall, - RuntimeOrigin, -}; +use crate::{AccountId, AllowedPopApiCalls, RuntimeCall, RuntimeOrigin}; const LOG_TARGET: &str = "pop-api::extension"; @@ -34,7 +32,6 @@ impl ChainExtension for PopApiExtension where T: pallet_contracts::Config + pallet_xcm::Config - + pallet_assets::Config + pallet_nfts::Config + cumulus_pallet_parachain_system::Config + frame_system::Config< @@ -184,7 +181,6 @@ where fn read_state(env: Environment) -> Result<(), DispatchError> where T: pallet_contracts::Config - + pallet_assets::Config + pallet_nfts::Config + cumulus_pallet_parachain_system::Config + frame_system::Config, @@ -210,9 +206,6 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, - RuntimeStateKeys::TrustBackedAssets(key) => { - read_trust_backed_assets_state::(key, &mut env) - }, }? .encode(); @@ -288,23 +281,6 @@ where } } -fn read_trust_backed_assets_state( - key: TrustBackedAssetsKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config - + pallet_assets::Config, - E: Ext, -{ - match key { - TrustBackedAssetsKeys::AssetExists(id) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_assets::Pallet::::asset_exists(id).encode()) - }, - } -} - #[cfg(test)] mod tests { pub use super::*; @@ -701,110 +677,6 @@ mod tests { }); } - #[test] - #[ignore] - fn dispatch_trust_backed_assets_mint_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/trust_backed_assets/target/ink/pop_api_trust_backed_assets_example.wasm", - ) - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - let addr = result.account_id; - - let asset_id: u32 = 1; - let min_balance = 1; - let amount: u128 = 100 * UNIT; - let function = function_selector("mint_asset_through_runtime"); - let params = [function, asset_id.encode(), BOB.encode(), amount.encode()].concat(); - - // Mint asset which does not exist. - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - GAS_LIMIT, - None, - params.clone(), - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // Check for revert. - assert!(result.result.unwrap().did_revert(), "Contract should have been reverted!"); - - // Create asset with contract as owner. - assert_eq!( - TrustBackedAssets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - addr.clone().into(), - true, - min_balance, - ), - Ok(()) - ); - - // Check Bob's asset balance before minting through contract. - let bob_balance_before = TrustBackedAssets::balance(asset_id, &BOB); - assert_eq!(bob_balance_before, 0); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - GAS_LIMIT, - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // Check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - let bob_balance_after = TrustBackedAssets::balance(asset_id, &BOB); - assert_eq!(bob_balance_after, bob_balance_before + amount); - }); - } - #[test] #[ignore] fn allow_call_filter_blocks_call() { diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index 312d9b50..66a5092c 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -253,74 +253,43 @@ impl Contains for FilteredCalls { pub struct AllowedPopApiCalls; impl Contains for crate::AllowedPopApiCalls { fn contains(c: &RuntimeCall) -> bool { - use assets_config::TrustBackedAssetsCall; use pallet_nfts::Call as NftsCall; matches!( c, RuntimeCall::Balances(BalancesCall::transfer_keep_alive { .. }) - | RuntimeCall::TrustBackedAssets( - TrustBackedAssetsCall::create { .. } - | TrustBackedAssetsCall::start_destroy { .. } - | TrustBackedAssetsCall::destroy_accounts { .. } - | TrustBackedAssetsCall::destroy_approvals { .. } - | TrustBackedAssetsCall::finish_destroy { .. } - | TrustBackedAssetsCall::mint { .. } - | TrustBackedAssetsCall::burn { .. } - | TrustBackedAssetsCall::transfer { .. } - | TrustBackedAssetsCall::transfer_keep_alive { .. } - | TrustBackedAssetsCall::force_transfer { .. } - | TrustBackedAssetsCall::freeze { .. } - | TrustBackedAssetsCall::thaw { .. } - | TrustBackedAssetsCall::freeze_asset { .. } - | TrustBackedAssetsCall::thaw_asset { .. } - | TrustBackedAssetsCall::transfer_ownership { .. } - | TrustBackedAssetsCall::set_team { .. } - | TrustBackedAssetsCall::set_metadata { .. } - | TrustBackedAssetsCall::clear_metadata { .. } - | TrustBackedAssetsCall::approve_transfer { .. } - | TrustBackedAssetsCall::cancel_approval { .. } - | TrustBackedAssetsCall::force_cancel_approval { .. } - | TrustBackedAssetsCall::transfer_approved { .. } - | TrustBackedAssetsCall::touch { .. } - | TrustBackedAssetsCall::refund { .. } - | TrustBackedAssetsCall::set_min_balance { .. } - | TrustBackedAssetsCall::touch_other { .. } - | TrustBackedAssetsCall::refund_other { .. } - | TrustBackedAssetsCall::block { .. } - ) | RuntimeCall::Nfts( - NftsCall::create { .. } - | NftsCall::destroy { .. } - | NftsCall::mint { .. } - | NftsCall::burn { .. } - | NftsCall::transfer { .. } - | NftsCall::redeposit { .. } - | NftsCall::lock_item_transfer { .. } - | NftsCall::unlock_item_transfer { .. } - | NftsCall::lock_collection { .. } - | NftsCall::transfer_ownership { .. } - | NftsCall::set_team { .. } - | NftsCall::approve_transfer { .. } - | NftsCall::cancel_approval { .. } - | NftsCall::clear_all_transfer_approvals { .. } - | NftsCall::lock_item_properties { .. } - | NftsCall::set_attribute { .. } - | NftsCall::clear_attribute { .. } - | NftsCall::approve_item_attributes { .. } - | NftsCall::cancel_item_attributes_approval { .. } - | NftsCall::set_metadata { .. } - | NftsCall::clear_metadata { .. } - | NftsCall::set_collection_metadata { .. } - | NftsCall::clear_collection_metadata { .. } - | NftsCall::set_accept_ownership { .. } - | NftsCall::set_collection_max_supply { .. } - | NftsCall::update_mint_settings { .. } - | NftsCall::set_price { .. } - | NftsCall::buy_item { .. } - | NftsCall::pay_tips { .. } - | NftsCall::create_swap { .. } - | NftsCall::cancel_swap { .. } - | NftsCall::claim_swap { .. } - ) + | RuntimeCall::Nfts( + NftsCall::create { .. } + | NftsCall::destroy { .. } + | NftsCall::mint { .. } | NftsCall::burn { .. } + | NftsCall::transfer { .. } + | NftsCall::redeposit { .. } + | NftsCall::lock_item_transfer { .. } + | NftsCall::unlock_item_transfer { .. } + | NftsCall::lock_collection { .. } + | NftsCall::transfer_ownership { .. } + | NftsCall::set_team { .. } + | NftsCall::approve_transfer { .. } + | NftsCall::cancel_approval { .. } + | NftsCall::clear_all_transfer_approvals { .. } + | NftsCall::lock_item_properties { .. } + | NftsCall::set_attribute { .. } + | NftsCall::clear_attribute { .. } + | NftsCall::approve_item_attributes { .. } + | NftsCall::cancel_item_attributes_approval { .. } + | NftsCall::set_metadata { .. } + | NftsCall::clear_metadata { .. } + | NftsCall::set_collection_metadata { .. } + | NftsCall::clear_collection_metadata { .. } + | NftsCall::set_accept_ownership { .. } + | NftsCall::set_collection_max_supply { .. } + | NftsCall::update_mint_settings { .. } + | NftsCall::set_price { .. } + | NftsCall::buy_item { .. } + | NftsCall::pay_tips { .. } + | NftsCall::create_swap { .. } + | NftsCall::cancel_swap { .. } + | NftsCall::claim_swap { .. } + ) ) } } @@ -661,7 +630,7 @@ construct_runtime!( // Assets Nfts: pallet_nfts = 50, NftFractionalization: pallet_nft_fractionalization = 51, - TrustBackedAssets: pallet_assets:: = 52, + Assets: pallet_assets:: = 52, } ); From fd46a279073abd855c327df6de32b2e155a74840 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Tue, 4 Jun 2024 15:49:03 +0200 Subject: [PATCH 004/161] fix: add error handling other than ModuleError --- pop-api/examples/fungibles/lib.rs | 36 +-- pop-api/src/lib.rs | 53 +++- pop-api/src/v0/assets/fungibles.rs | 60 +++- pop-api/src/v0/balances.rs | 6 +- pop-api/src/v0/contracts.rs | 286 +++++++++--------- pop-api/src/v0/cross_chain/mod.rs | 4 +- pop-api/src/v0/dispatch_error.rs | 57 ++++ pop-api/src/v0/mod.rs | 3 +- pop-api/src/v0/nfts.rs | 4 +- runtime/devnet/src/extensions/mod.rs | 11 +- .../src/extensions/tests/local_fungibles.rs | 214 ++++++++----- runtime/devnet/src/extensions/tests/mod.rs | 10 +- 12 files changed, 462 insertions(+), 282 deletions(-) create mode 100644 pop-api/src/v0/dispatch_error.rs diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 9c0ae754..e44c4347 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -10,42 +10,42 @@ use pop_api::{ #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum ContractError { - // AssetsError(Error), - // /// The origin of the call doesn't have the right permission. - // BadOrigin, - // /// Custom error type for cases in which an implementation adds its own restrictions. - // Custom(String), - /// Not enough balance to fulfill a request is available. - InsufficientBalance, + /// The amount to mint is less than the existential deposit. + BelowMinimum, + /// Unspecified dispatch error, providing the index and its error index (if none `0`). + DispatchError { index: u8, error: u8 }, /// Not enough allowance to fulfill a request is available. InsufficientAllowance, - /// The asset status is not the expected status. - IncorrectStatus, + /// Not enough balance to fulfill a request is available. + InsufficientBalance, /// The asset ID is already taken. InUse, /// Minimum balance should be non-zero. MinBalanceZero, + /// Unspecified pallet error, providing pallet index and error index. + ModuleError { pallet: u8, error: u16 }, /// The signing account has no permission to do the operation. NoPermission, - // /// Safe transfer check fails (e.g. if the receiving contract does not accept tokens). - // SafeTransferCheckFailed(String), /// The given asset ID is unknown. Unknown, - /// Recipient's address is zero. - ZeroRecipientAddress, - /// Sender's address is zero. - ZeroSenderAddress, - UndefinedError, } impl From for ContractError { fn from(error: FungiblesError) -> Self { match error { - // Error::BalanceLow => Err(InsufficientBalance), + FungiblesError::BelowMinimum => ContractError::BelowMinimum, + FungiblesError::DispatchError { index, error } => { + ContractError::DispatchError { index, error } + }, + FungiblesError::InsufficientAllowance => ContractError::InsufficientAllowance, + FungiblesError::InsufficientBalance => ContractError::InsufficientBalance, FungiblesError::InUse => ContractError::InUse, FungiblesError::MinBalanceZero => ContractError::MinBalanceZero, + FungiblesError::ModuleError { pallet, error } => { + ContractError::ModuleError { pallet, error } + }, + FungiblesError::NoPermission => ContractError::NoPermission, FungiblesError::Unknown => ContractError::Unknown, - _ => ContractError::UndefinedError, } } } diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 0ca4a817..014b5a29 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,14 +1,16 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -pub mod primitives; -pub mod v0; - -use crate::PopApiError::{Assets, Balances, Contracts, Nfts, UnknownStatusCode}; +use core::convert::TryInto; use ink::{prelude::vec::Vec, ChainExtensionInstance}; use primitives::{cross_chain::*, storage_keys::*, AccountId as AccountId32}; pub use sp_runtime::{BoundedVec, MultiAddress, MultiSignature}; use v0::RuntimeCall; -pub use v0::{assets, balances, contracts, cross_chain, nfts, relay_chain_block_number, state}; +pub use v0::{ + assets, balances, contracts, cross_chain, dispatch_error, nfts, relay_chain_block_number, state, +}; + +pub mod primitives; +pub mod v0; // type AccountId = ::AccountId; type AccountId = AccountId32; @@ -19,30 +21,49 @@ type MaxTips = u32; pub type Result = core::result::Result; +struct ModuleError { + pallet: u8, + error: u16, +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum PopApiError { - UnknownStatusCode(u32), - DecodingFailed, - SystemCallFiltered, + Assets(assets::fungibles::AssetsError), Balances(balances::Error), Contracts(contracts::Error), + DecodingFailed, Nfts(nfts::Error), - Assets(assets::fungibles::AssetsError), + SystemCallFiltered, + TokenError(dispatch_error::TokenError), + UnknownModuleStatusCode(u32), + UnknownDispatchStatusCode(u32), Xcm(cross_chain::Error), } impl ink::env::chain_extension::FromStatusCode for PopApiError { fn from_status_code(status_code: u32) -> core::result::Result<(), Self> { + use crate::PopApiError::{ + Assets, Balances, Contracts, Nfts, TokenError, UnknownDispatchStatusCode, + UnknownModuleStatusCode, + }; + match status_code { 0 => Ok(()), - // CallFiltered originates from `frame_system` with pallet-index 0. The CallFiltered error is at index 5 - 5 => Err(PopApiError::SystemCallFiltered), - 10_000..=10_999 => Err(Balances((status_code - 10_000).try_into()?)), - 40_000..=40_999 => Err(Contracts((status_code - 40_000).try_into()?)), - 50_000..=50_999 => Err(Nfts((status_code - 50_000).try_into()?)), - 52_000..=52_999 => Err(Assets((status_code - 52_000).try_into()?)), - _ => Err(UnknownStatusCode(status_code)), + 3_000_000..=3_999_999 => { + let status_code = status_code - 3_000_000; + match status_code { + // CallFiltered originates from `frame_system` with pallet-index 0. The CallFiltered error is at index 5 + 5 => Err(PopApiError::SystemCallFiltered), + 10_000..=10_999 => Err(Balances((status_code - 10_000).try_into()?)), + 40_000..=40_999 => Err(Contracts((status_code - 40_000).try_into()?)), + 50_000..=50_999 => Err(Nfts((status_code - 50_000).try_into()?)), + 52_000..=52_999 => Err(Assets((status_code - 52_000).try_into()?)), + _ => Err(UnknownModuleStatusCode(status_code)), + } + }, + 7_000_000..=7_999_999 => Err(TokenError((status_code - 7_000_000).try_into()?)), + _ => Err(UnknownDispatchStatusCode(status_code)), } } } diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index f2d87a0e..de624938 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,4 +1,8 @@ -use crate::{AccountId, Balance, PopApiError::UnknownStatusCode, RuntimeCall, *}; +use crate::{ + AccountId, Balance, + PopApiError::{UnknownDispatchStatusCode, UnknownModuleStatusCode}, + RuntimeCall, *, +}; use ink::prelude::vec::Vec; use primitives::AssetId; use scale::{Compact, Encode}; @@ -502,7 +506,7 @@ impl TryFrom for AssetsError { 16 => Ok(AssetNotLive), 17 => Ok(IncorrectStatus), 18 => Ok(NotFrozen), - _ => Err(UnknownStatusCode(status_code)), + _ => Err(UnknownModuleStatusCode(status_code)), } } } @@ -510,22 +514,41 @@ impl TryFrom for AssetsError { #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum FungiblesError { - /// The signing account has no permission to do the operation. - NoPermission, - /// The given asset ID is unknown. - Unknown, + /// The amount to mint is less than the existential deposit. + BelowMinimum, + /// Unspecified dispatch error, providing the index and its error index (if none `0`). + DispatchError { index: u8, error: u8 }, + /// Not enough allowance to fulfill a request is available. + InsufficientAllowance, + /// Not enough balance to fulfill a request is available. InsufficientBalance, /// The asset ID is already taken. InUse, /// Minimum balance should be non-zero. MinBalanceZero, + /// Unspecified pallet error, providing pallet index and error index. + ModuleError { pallet: u8, error: u16 }, + /// The signing account has no permission to do the operation. + NoPermission, + /// The given asset ID is unknown. + Unknown, } impl From for FungiblesError { fn from(error: balances::Error) -> Self { match error { balances::Error::InsufficientBalance => FungiblesError::InsufficientBalance, - _ => panic!("Unexpected pallet assets error. This error is unknown to pallet assets"), + _ => FungiblesError::ModuleError { pallet: 40, error: error as u16 }, + } + } +} + +impl From for FungiblesError { + fn from(error: dispatch_error::TokenError) -> Self { + match error { + dispatch_error::TokenError::UnknownAsset => FungiblesError::Unknown, + dispatch_error::TokenError::BelowMinimum => FungiblesError::BelowMinimum, + _ => FungiblesError::DispatchError { index: 7, error: error as u8 }, } } } @@ -533,8 +556,12 @@ impl From for FungiblesError { impl From for FungiblesError { fn from(error: AssetsError) -> Self { match error { + AssetsError::Unapproved => FungiblesError::InsufficientAllowance, AssetsError::InUse => FungiblesError::InUse, - _ => panic!("Unexpected pallet assets error. This error is unknown to pallet assets"), + AssetsError::MinBalanceZero => FungiblesError::MinBalanceZero, + AssetsError::NoPermission => FungiblesError::NoPermission, + AssetsError::Unknown => FungiblesError::Unknown, + _ => FungiblesError::ModuleError { pallet: 40, error: error as u16 }, } } } @@ -543,12 +570,19 @@ impl From for FungiblesError { fn from(error: PopApiError) -> Self { match error { PopApiError::Assets(e) => e.into(), - // PopApiError::Balances(e) => todo!("balances: {:?}", e), PopApiError::Balances(e) => e.into(), - // PopApiError::Contracts(_e) => todo!("contracts"), - // PopApiError::SystemCallFiltered => 100, - // PopApiError::UnknownStatusCode(u) => u, - _ => panic!("Unexpected pallet assets error. This error is unknown to pallet assets"), + PopApiError::TokenError(e) => e.into(), + PopApiError::UnknownModuleStatusCode(e) => { + let pallet = (e / 1_000) as u8; + let error = (e % 1_000) as u16; + FungiblesError::ModuleError { pallet, error } + }, + PopApiError::UnknownDispatchStatusCode(e) => { + let index = (e / 1_000_000) as u8; + let error = (3 % 1_000_000) as u8; + FungiblesError::DispatchError { index, error } + }, + _ => todo!(), } } } diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs index bc48711e..bc422ef4 100644 --- a/pop-api/src/v0/balances.rs +++ b/pop-api/src/v0/balances.rs @@ -1,6 +1,6 @@ use crate::{ dispatch, primitives::MultiAddress, v0::RuntimeCall, AccountId, PopApiError, - PopApiError::UnknownStatusCode, + PopApiError::UnknownModuleStatusCode, }; type Result = core::result::Result; @@ -73,7 +73,7 @@ impl TryFrom for Error { 9 => Ok(TooManyFreezes), 10 => Ok(IssuanceDeactivated), 11 => Ok(DeltaZero), - _ => Err(UnknownStatusCode(status_code)), + _ => Err(UnknownModuleStatusCode(status_code)), } } } @@ -82,7 +82,7 @@ impl From for Error { fn from(error: PopApiError) -> Self { match error { PopApiError::Balances(e) => e, - _ => panic!("expected balances error"), + _ => todo!(), } } } diff --git a/pop-api/src/v0/contracts.rs b/pop-api/src/v0/contracts.rs index d7a1a5dd..5d4a3692 100644 --- a/pop-api/src/v0/contracts.rs +++ b/pop-api/src/v0/contracts.rs @@ -1,156 +1,152 @@ -use crate::{ - PopApiError, - PopApiError::UnknownStatusCode, -}; +use crate::{PopApiError, PopApiError::UnknownModuleStatusCode}; #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum Error { - /// Invalid schedule supplied, e.g. with zero weight of a basic operation. - InvalidSchedule, - /// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`. - InvalidCallFlags, - /// The executed contract exhausted its gas limit. - OutOfGas, - /// The output buffer supplied to a contract API call was too small. - OutputBufferTooSmall, - /// Performing the requested transfer failed. Probably because there isn't enough - /// free balance in the sender's account. - TransferFailed, - /// Performing a call was denied because the calling depth reached the limit - /// of what is specified in the schedule. - MaxCallDepthReached, - /// No contract was found at the specified address. - ContractNotFound, - /// The code supplied to `instantiate_with_code` exceeds the limit specified in the - /// current schedule. - CodeTooLarge, - /// No code could be found at the supplied code hash. - CodeNotFound, - /// No code info could be found at the supplied code hash. - CodeInfoNotFound, - /// A buffer outside of sandbox memory was passed to a contract API function. - OutOfBounds, - /// Input passed to a contract API function failed to decode as expected type. - DecodingFailed, - /// Contract trapped during execution. - ContractTrapped, - /// The size defined in `T::MaxValueSize` was exceeded. - ValueTooLarge, - /// Termination of a contract is not allowed while the contract is already - /// on the call stack. Can be triggered by `seal_terminate`. - TerminatedWhileReentrant, - /// `seal_call` forwarded this contracts input. It therefore is no longer available. - InputForwarded, - /// The subject passed to `seal_random` exceeds the limit. - RandomSubjectTooLong, - /// The amount of topics passed to `seal_deposit_events` exceeds the limit. - TooManyTopics, - /// The chain does not provide a chain extension. Calling the chain extension results - /// in this error. Note that this usually shouldn't happen as deploying such contracts - /// is rejected. - NoChainExtension, - /// Failed to decode the XCM program. - XCMDecodeFailed, - /// A contract with the same AccountId already exists. - DuplicateContract, - /// A contract self destructed in its constructor. - /// - /// This can be triggered by a call to `seal_terminate`. - TerminatedInConstructor, - /// A call tried to invoke a contract that is flagged as non-reentrant. - /// The only other cause is that a call from a contract into the runtime tried to call back - /// into `pallet-contracts`. This would make the whole pallet reentrant with regard to - /// contract code execution which is not supported. - ReentranceDenied, - /// Origin doesn't have enough balance to pay the required storage deposits. - StorageDepositNotEnoughFunds, - /// More storage was created than allowed by the storage deposit limit. - StorageDepositLimitExhausted, - /// Code removal was denied because the code is still in use by at least one contract. - CodeInUse, - /// The contract ran to completion but decided to revert its storage changes. - /// Please note that this error is only returned from extrinsics. When called directly - /// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags - /// to determine whether a reversion has taken place. - ContractReverted, - /// The contract's code was found to be invalid during validation. - /// - /// The most likely cause of this is that an API was used which is not supported by the - /// node. This happens if an older node is used with a new version of ink!. Try updating - /// your node to the newest available version. - /// - /// A more detailed error can be found on the node console if debug messages are enabled - /// by supplying `-lruntime::contracts=debug`. - CodeRejected, - /// An indeterministic code was used in a context where this is not permitted. - Indeterministic, - /// A pending migration needs to complete before the extrinsic can be called. - MigrationInProgress, - /// Migrate dispatch call was attempted but no migration was performed. - NoMigrationPerformed, - /// The contract has reached its maximum number of delegate dependencies. - MaxDelegateDependenciesReached, - /// The dependency was not found in the contract's delegate dependencies. - DelegateDependencyNotFound, - /// The contract already depends on the given delegate dependency. - DelegateDependencyAlreadyExists, - /// Can not add a delegate dependency to the code hash of the contract itself. - CannotAddSelfAsDelegateDependency, + /// Invalid schedule supplied, e.g. with zero weight of a basic operation. + InvalidSchedule, + /// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`. + InvalidCallFlags, + /// The executed contract exhausted its gas limit. + OutOfGas, + /// The output buffer supplied to a contract API call was too small. + OutputBufferTooSmall, + /// Performing the requested transfer failed. Probably because there isn't enough + /// free balance in the sender's account. + TransferFailed, + /// Performing a call was denied because the calling depth reached the limit + /// of what is specified in the schedule. + MaxCallDepthReached, + /// No contract was found at the specified address. + ContractNotFound, + /// The code supplied to `instantiate_with_code` exceeds the limit specified in the + /// current schedule. + CodeTooLarge, + /// No code could be found at the supplied code hash. + CodeNotFound, + /// No code info could be found at the supplied code hash. + CodeInfoNotFound, + /// A buffer outside of sandbox memory was passed to a contract API function. + OutOfBounds, + /// Input passed to a contract API function failed to decode as expected type. + DecodingFailed, + /// Contract trapped during execution. + ContractTrapped, + /// The size defined in `T::MaxValueSize` was exceeded. + ValueTooLarge, + /// Termination of a contract is not allowed while the contract is already + /// on the call stack. Can be triggered by `seal_terminate`. + TerminatedWhileReentrant, + /// `seal_call` forwarded this contracts input. It therefore is no longer available. + InputForwarded, + /// The subject passed to `seal_random` exceeds the limit. + RandomSubjectTooLong, + /// The amount of topics passed to `seal_deposit_events` exceeds the limit. + TooManyTopics, + /// The chain does not provide a chain extension. Calling the chain extension results + /// in this error. Note that this usually shouldn't happen as deploying such contracts + /// is rejected. + NoChainExtension, + /// Failed to decode the XCM program. + XCMDecodeFailed, + /// A contract with the same AccountId already exists. + DuplicateContract, + /// A contract self destructed in its constructor. + /// + /// This can be triggered by a call to `seal_terminate`. + TerminatedInConstructor, + /// A call tried to invoke a contract that is flagged as non-reentrant. + /// The only other cause is that a call from a contract into the runtime tried to call back + /// into `pallet-contracts`. This would make the whole pallet reentrant with regard to + /// contract code execution which is not supported. + ReentranceDenied, + /// Origin doesn't have enough balance to pay the required storage deposits. + StorageDepositNotEnoughFunds, + /// More storage was created than allowed by the storage deposit limit. + StorageDepositLimitExhausted, + /// Code removal was denied because the code is still in use by at least one contract. + CodeInUse, + /// The contract ran to completion but decided to revert its storage changes. + /// Please note that this error is only returned from extrinsics. When called directly + /// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags + /// to determine whether a reversion has taken place. + ContractReverted, + /// The contract's code was found to be invalid during validation. + /// + /// The most likely cause of this is that an API was used which is not supported by the + /// node. This happens if an older node is used with a new version of ink!. Try updating + /// your node to the newest available version. + /// + /// A more detailed error can be found on the node console if debug messages are enabled + /// by supplying `-lruntime::contracts=debug`. + CodeRejected, + /// An indeterministic code was used in a context where this is not permitted. + Indeterministic, + /// A pending migration needs to complete before the extrinsic can be called. + MigrationInProgress, + /// Migrate dispatch call was attempted but no migration was performed. + NoMigrationPerformed, + /// The contract has reached its maximum number of delegate dependencies. + MaxDelegateDependenciesReached, + /// The dependency was not found in the contract's delegate dependencies. + DelegateDependencyNotFound, + /// The contract already depends on the given delegate dependency. + DelegateDependencyAlreadyExists, + /// Can not add a delegate dependency to the code hash of the contract itself. + CannotAddSelfAsDelegateDependency, } - impl TryFrom for Error { - type Error = PopApiError; + type Error = PopApiError; - fn try_from(status_code: u32) -> core::result::Result { - use Error::*; - match status_code { - 0 => Ok(InvalidSchedule), - 1 => Ok(InvalidCallFlags), - 2 => Ok(OutOfGas), - 3 => Ok(OutputBufferTooSmall), - 4 => Ok(TransferFailed), - 5 => Ok(MaxCallDepthReached), - 6 => Ok(ContractNotFound), - 7 => Ok(CodeTooLarge), - 8 => Ok(CodeNotFound), - 9 => Ok(CodeInfoNotFound), - 10 => Ok(OutOfBounds), - 11 => Ok(DecodingFailed), - 12 => Ok(ContractTrapped), - 13 => Ok(ValueTooLarge), - 14 => Ok(TerminatedWhileReentrant), - 15 => Ok(InputForwarded), - 16 => Ok(RandomSubjectTooLong), - 17 => Ok(TooManyTopics), - 18 => Ok(NoChainExtension), - 19 => Ok(XCMDecodeFailed), - 20 => Ok(DuplicateContract), - 21 => Ok(TerminatedInConstructor), - 22 => Ok(ReentranceDenied), - 23 => Ok(StorageDepositNotEnoughFunds), - 24 => Ok(StorageDepositLimitExhausted), - 25 => Ok(CodeInUse), - 26 => Ok(ContractReverted), - 27 => Ok(CodeRejected), - 28 => Ok(Indeterministic), - 29 => Ok(MigrationInProgress), - 30 => Ok(NoMigrationPerformed), - 31 => Ok(MaxDelegateDependenciesReached), - 32 => Ok(DelegateDependencyNotFound), - 33 => Ok(DelegateDependencyAlreadyExists), - 34 => Ok(CannotAddSelfAsDelegateDependency), - _ => Err(UnknownStatusCode(status_code)), - } - } + fn try_from(status_code: u32) -> core::result::Result { + use Error::*; + match status_code { + 0 => Ok(InvalidSchedule), + 1 => Ok(InvalidCallFlags), + 2 => Ok(OutOfGas), + 3 => Ok(OutputBufferTooSmall), + 4 => Ok(TransferFailed), + 5 => Ok(MaxCallDepthReached), + 6 => Ok(ContractNotFound), + 7 => Ok(CodeTooLarge), + 8 => Ok(CodeNotFound), + 9 => Ok(CodeInfoNotFound), + 10 => Ok(OutOfBounds), + 11 => Ok(DecodingFailed), + 12 => Ok(ContractTrapped), + 13 => Ok(ValueTooLarge), + 14 => Ok(TerminatedWhileReentrant), + 15 => Ok(InputForwarded), + 16 => Ok(RandomSubjectTooLong), + 17 => Ok(TooManyTopics), + 18 => Ok(NoChainExtension), + 19 => Ok(XCMDecodeFailed), + 20 => Ok(DuplicateContract), + 21 => Ok(TerminatedInConstructor), + 22 => Ok(ReentranceDenied), + 23 => Ok(StorageDepositNotEnoughFunds), + 24 => Ok(StorageDepositLimitExhausted), + 25 => Ok(CodeInUse), + 26 => Ok(ContractReverted), + 27 => Ok(CodeRejected), + 28 => Ok(Indeterministic), + 29 => Ok(MigrationInProgress), + 30 => Ok(NoMigrationPerformed), + 31 => Ok(MaxDelegateDependenciesReached), + 32 => Ok(DelegateDependencyNotFound), + 33 => Ok(DelegateDependencyAlreadyExists), + 34 => Ok(CannotAddSelfAsDelegateDependency), + _ => Err(UnknownModuleStatusCode(status_code)), + } + } } impl From for Error { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Contracts(e) => e, - _ => panic!("expected balances error"), - } - } -} \ No newline at end of file + fn from(error: PopApiError) -> Self { + match error { + PopApiError::Contracts(e) => e, + _ => panic!("expected balances error"), + } + } +} diff --git a/pop-api/src/v0/cross_chain/mod.rs b/pop-api/src/v0/cross_chain/mod.rs index 6732c119..1e5afbf5 100644 --- a/pop-api/src/v0/cross_chain/mod.rs +++ b/pop-api/src/v0/cross_chain/mod.rs @@ -1,6 +1,6 @@ pub mod coretime; -use crate::{PopApiError::UnknownStatusCode, *}; +use crate::{PopApiError::UnknownModuleStatusCode, *}; type Result = core::result::Result; @@ -92,7 +92,7 @@ impl TryFrom for Error { 21 => Ok(InvalidAssetUnknownReserve), 22 => Ok(InvalidAssetUnsupportedReserve), 23 => Ok(TooManyReserves), - _ => Err(UnknownStatusCode(status_code)), + _ => Err(UnknownModuleStatusCode(status_code)), } } } diff --git a/pop-api/src/v0/dispatch_error.rs b/pop-api/src/v0/dispatch_error.rs new file mode 100644 index 00000000..6ed40ce5 --- /dev/null +++ b/pop-api/src/v0/dispatch_error.rs @@ -0,0 +1,57 @@ +use super::*; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub(crate) enum TokenError { + /// Funds are unavailable. + FundsUnavailable, + /// Some part of the balance gives the only provider reference to the account and thus cannot + /// be (re)moved. + OnlyProvider, + /// Account cannot exist with the funds that would be given. + BelowMinimum, + /// Account cannot be created. + CannotCreate, + /// The asset in question is unknown. + UnknownAsset, + /// Funds exist but are frozen. + Frozen, + /// Operation is not supported by the asset. + Unsupported, + /// Account cannot be created for a held balance. + CannotCreateHold, + /// Withdrawal would cause unwanted loss of account. + NotExpendable, + /// Account cannot receive the assets. + Blocked, +} + +impl TryFrom for TokenError { + type Error = crate::PopApiError; + + fn try_from(status_code: u32) -> core::result::Result { + use TokenError::*; + match status_code { + 0 => Ok(FundsUnavailable), + 1 => Ok(OnlyProvider), + 2 => Ok(BelowMinimum), + 3 => Ok(CannotCreate), + 4 => Ok(UnknownAsset), + 5 => Ok(Frozen), + 6 => Ok(Unsupported), + 7 => Ok(CannotCreateHold), + 8 => Ok(NotExpendable), + 9 => Ok(Blocked), + _ => todo!(), + } + } +} + +impl From for TokenError { + fn from(error: PopApiError) -> Self { + match error { + PopApiError::TokenError(e) => e, + _ => todo!(), + } + } +} diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index def37e55..02169c22 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -3,12 +3,13 @@ use crate::{ BlockNumber, PopApiError, }; +pub mod assets; pub mod balances; pub mod contracts; pub mod cross_chain; +pub mod dispatch_error; pub mod nfts; pub mod state; -pub mod assets; pub fn relay_chain_block_number() -> Result { state::read(RuntimeStateKeys::ParachainSystem(ParachainSystemKeys::LastRelayChainBlockNumber)) diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs index 5a55154f..946a3eca 100644 --- a/pop-api/src/v0/nfts.rs +++ b/pop-api/src/v0/nfts.rs @@ -1,5 +1,5 @@ use super::RuntimeCall; -use crate::{PopApiError::UnknownStatusCode, *}; +use crate::{PopApiError::UnknownModuleStatusCode, *}; use ink::prelude::vec::Vec; use primitives::{ApprovalsLimit, BoundedBTreeMap, KeyLimit, MultiAddress}; pub use primitives::{CollectionId, ItemId}; @@ -660,7 +660,7 @@ impl TryFrom for Error { 42 => Ok(WrongNamespace), 43 => Ok(CollectionNotEmpty), 44 => Ok(WitnessRequired), - _ => Err(UnknownStatusCode(status_code)), + _ => Err(UnknownModuleStatusCode(status_code)), } } } diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index 096f21c9..d2129c4f 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -69,10 +69,19 @@ where Err(DispatchError::Module(error)) => { // encode status code = pallet index in runtime + error index, allowing for // 999 errors + let first = (3u32 * 1_000_000u32) + + (error.index as u32 * 1_000u32) + + u32::from_le_bytes(error.error); Ok(RetVal::Converging( - (error.index as u32 * 1_000) + u32::from_le_bytes(error.error), + // (3u32 * 1_000_000u32) + // + (error.index as u32 * 1_000u32) + // + u32::from_le_bytes(error.error), + first, )) }, + Err(DispatchError::Token(error)) => { + Ok(RetVal::Converging((7u32 * 1_000_000u32) + error as u32)) + }, Err(e) => Err(e), } }, diff --git a/runtime/devnet/src/extensions/tests/local_fungibles.rs b/runtime/devnet/src/extensions/tests/local_fungibles.rs index 2d752361..5bd7dac0 100644 --- a/runtime/devnet/src/extensions/tests/local_fungibles.rs +++ b/runtime/devnet/src/extensions/tests/local_fungibles.rs @@ -5,36 +5,32 @@ use pallet_contracts::debug::ExecResult; #[derive(Decode, Encode, Debug, Eq, PartialEq)] enum FungiblesError { - // AssetsError(Error), - // /// The origin of the call doesn't have the right permission. - // BadOrigin, - // /// Custom error type for cases in which an implementation adds its own restrictions. - // Custom(String), - /// Not enough balance to fulfill a request is available. - InsufficientBalance, + /// The amount to mint is less than the existential deposit. + BelowMinimum, + /// Unspecified dispatch error, providing the index and optionally its error index. + DispatchError { index: u8, error: Option }, /// Not enough allowance to fulfill a request is available. InsufficientAllowance, - /// The asset status is not the expected status. - IncorrectStatus, + /// Not enough balance to fulfill a request is available. + InsufficientBalance, /// The asset ID is already taken. InUse, /// Minimum balance should be non-zero. MinBalanceZero, + /// Unspecified pallet error, providing pallet index and error index. + ModuleError { pallet: u8, error: u16 }, /// The signing account has no permission to do the operation. NoPermission, - // /// Safe transfer check fails (e.g. if the receiving contract does not accept tokens). - // SafeTransferCheckFailed(String), /// The given asset ID is unknown. Unknown, - /// Recipient's address is zero. - ZeroRecipientAddress, - /// Sender's address is zero. - ZeroSenderAddress, - UndefinedError, } const ASSET_ID: u32 = 1; +fn decoded(result: ExecReturnValue) -> T { + ::decode(&mut &result.data[2..]).unwrap() +} + fn allowance( addr: AccountId32, asset_id: u32, @@ -54,10 +50,11 @@ fn balance_of(addr: AccountId32, asset_id: u32, owner: AccountId32) -> ExecRetur } // Call total_supply contract message. -fn total_supply(addr: AccountId32, asset_id: u32) -> ExecReturnValue { +fn total_supply(addr: AccountId32, asset_id: u32) -> Balance { let function = function_selector("total_supply"); let params = [function, asset_id.encode()].concat(); - do_bare_call(addr, params, 0).expect("should work") + let result = do_bare_call(addr, params, 0).expect("should work"); + decoded::(result) } fn asset_exists(addr: AccountId32, asset_id: u32) -> ExecReturnValue { @@ -70,7 +67,7 @@ fn create( addr: AccountId32, asset_id: u32, admin: AccountId32, - min_balance: u128, + min_balance: Balance, ) -> ExecReturnValue { let function = function_selector("create"); let params = [function, asset_id.encode(), admin.encode(), min_balance.encode()].concat(); @@ -95,7 +92,7 @@ fn transfer_from( asset_id: u32, _from: Option, to: Option, - value: u128, + value: Balance, _data: &[u8], ) -> ExecReturnValue { // let function = function_selector("transfer_from"); @@ -109,16 +106,21 @@ fn transfer_from( } // Create an asset and mint to owner. -fn create_asset(asset_id: u32, owner: AccountId32) { +fn create_asset(asset_id: u32, owner: AccountId32, min_balance: Balance) { assert_eq!( - Assets::create(RuntimeOrigin::signed(owner.clone()), asset_id.into(), owner.into(), 1), + Assets::create( + RuntimeOrigin::signed(owner.clone()), + asset_id.into(), + owner.into(), + min_balance + ), Ok(()) ); } // Create an asset and mint to owner. -fn create_asset_and_mint_to(asset_id: u32, owner: AccountId32, to: AccountId32, value: u128) { - create_asset(asset_id, owner.clone()); +fn create_asset_and_mint_to(asset_id: u32, owner: AccountId32, to: AccountId32, value: Balance) { + create_asset(asset_id, owner.clone(), 1); assert_eq!( Assets::mint(RuntimeOrigin::signed(owner.into()), asset_id.into(), to.into(), value,), Ok(()) @@ -130,9 +132,9 @@ fn create_asset_mint_and_approve( asset_id: u32, owner: AccountId32, to: AccountId32, - mint: u128, + mint: Balance, spender: AccountId32, - approve: u128, + approve: Balance, ) { create_asset_and_mint_to(asset_id, owner.clone(), to.clone(), mint); assert_eq!( @@ -151,18 +153,18 @@ fn create_asset_mint_and_approve( fn total_supply_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + let addr = instantiate( + "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", + INIT_VALUE, + vec![], + ); // No tokens in circulation. - assert_eq!( - Assets::total_supply(ASSET_ID).encode(), - total_supply(addr.clone(), ASSET_ID).data[2..] - ); + assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr.clone(), ASSET_ID)); // Tokens in circulation. create_asset_and_mint_to(ASSET_ID, addr.clone(), BOB, 100); - assert_eq!(Assets::total_supply(ASSET_ID).encode(), total_supply(addr, ASSET_ID).data[2..]); + assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr, ASSET_ID)); }); } @@ -171,8 +173,11 @@ fn total_supply_works() { fn balance_of_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + let addr = instantiate( + "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", + INIT_VALUE, + vec![], + ); // No tokens in circulation. assert_eq!( @@ -194,8 +199,11 @@ fn balance_of_works() { fn allowance_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + let addr = instantiate( + "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", + INIT_VALUE, + vec![], + ); // No tokens in circulation. assert_eq!( @@ -217,8 +225,11 @@ fn allowance_works() { fn asset_exists_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + let addr = instantiate( + "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", + INIT_VALUE, + vec![], + ); // No tokens in circulation. assert_eq!( @@ -227,40 +238,45 @@ fn asset_exists_works() { ); // Tokens in circulation. - create_asset(ASSET_ID, addr.clone()); + create_asset(ASSET_ID, addr.clone(), 1); assert_eq!(Assets::asset_exists(ASSET_ID).encode(), asset_exists(addr, ASSET_ID).data[2..]); }); } -fn decode_error(result: ExecReturnValue) -> FungiblesError { - FungiblesError::decode(&mut &result.data[2..]).unwrap() -} - +// Todo - errors: +// - Badorigin: contract is always signed +// - Lookup: is a valid AccountId due to the contract +// - reserve(): Overflow, LiquidityRestrictions; frozen +// - Callback +// - StorageDepositLimitExhausted #[test] #[ignore] fn create_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", 0); let new_asset = 2; + let addr = + instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); assert_eq!( - decode_error(create(addr.clone(), new_asset, BOB, 1)), - FungiblesError::UndefinedError + decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), + FungiblesError::InsufficientBalance ); - // Todo: errors Badorigin, Lookup, reserve(), Callback - // create_asset(ASSET_ID, ALICE); - // // Error `InUse`. - // assert_eq!(decode_error(create(addr.clone(), ASSET_ID, BOB, 1)), FungiblesError::InUse); - // // Error `MinBalanceZero`. - // assert_eq!( - // decode_error(create(addr.clone(), new_asset, BOB, 0)), - // FungiblesError::MinBalanceZero - // ); - // assert!( - // !create(addr.clone(), new_asset, BOB, 1).did_revert(), - // "Contract should have been reverted!" - // ); + let addr = instantiate( + "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", + INIT_VALUE, + vec![1], + ); + create_asset(ASSET_ID, ALICE, 1); + assert_eq!( + decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), + FungiblesError::InUse + ); + assert_eq!( + decoded::(create(addr.clone(), new_asset, BOB, 0)), + FungiblesError::MinBalanceZero + ); + assert!(!create(addr.clone(), new_asset, BOB, 1).did_revert(), "Contract reverted!"); }); } @@ -269,34 +285,78 @@ fn create_works() { fn set_metadata_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); + let addr = instantiate( + "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", + INIT_VALUE, + vec![], + ); - create_asset(ASSET_ID, addr.clone()); + create_asset(ASSET_ID, addr.clone(), 1); let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); - assert!(!result.did_revert(), "Contract should have been reverted!"); + assert!(!result.did_revert(), "Contract reverted!"); }); } +// todo: errors: +// - AssetNotLive: when frozen or being destroyed +// - TokenErrors: https://github.com/paritytech/polkadot-sdk/blob/3977f389cce4a00fd7100f95262e0563622b9aa4/substrate/frame/assets/src/functions.rs#L125 #[test] #[ignore] -fn transfer_from_aka_mint_works() { +fn mint_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE); - - let amount: u128 = 100 * UNIT; - // Create asset with contract as owner. - create_asset(ASSET_ID, addr.clone()); - // Check Bob's asset balance before minting through contract. - let bob_balance_before = Assets::balance(ASSET_ID, &BOB); + let addr = instantiate( + "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", + INIT_VALUE, + vec![], + ); + let amount: Balance = 100 * UNIT; - let result = transfer_from(addr.clone(), ASSET_ID, None, Some(BOB), 100 * UNIT, &[0u8]); + assert_eq!( + decoded::(transfer_from( + addr.clone(), + ASSET_ID, + None, + Some(BOB), + amount, + &[0u8] + )), + FungiblesError::Unknown + ); + create_asset(ASSET_ID, ALICE, 2); + assert_eq!( + decoded::(transfer_from( + addr.clone(), + ASSET_ID, + None, + Some(BOB), + amount, + &[0u8] + )), + FungiblesError::NoPermission + ); + assert_eq!( + decoded::(transfer_from( + addr.clone(), + ASSET_ID, + None, + Some(BOB), + 1, + &[0u8] + )), + FungiblesError::BelowMinimum + ); + let asset = 2; + create_asset(asset, addr.clone(), 2); + let bob_balance_before_mint = Assets::balance(asset, &BOB); + let result = transfer_from(addr.clone(), asset, None, Some(BOB), 100 * UNIT, &[0u8]); assert!(!result.did_revert(), "Contract reverted!"); - - let bob_balance_after = Assets::balance(ASSET_ID, &BOB); - assert_eq!(bob_balance_after, bob_balance_before + amount); + let bob_balance_after_mint = Assets::balance(asset, &BOB); + assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount); }); } + +#[test] +#[ignore] +fn transfer_works() {} diff --git a/runtime/devnet/src/extensions/tests/mod.rs b/runtime/devnet/src/extensions/tests/mod.rs index 30d1a924..03cda2cd 100644 --- a/runtime/devnet/src/extensions/tests/mod.rs +++ b/runtime/devnet/src/extensions/tests/mod.rs @@ -6,11 +6,13 @@ use sp_runtime::{traits::Hash, AccountId32, BuildStorage}; mod local_fungibles; +type Balance = u128; const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); const BOB: AccountId32 = AccountId32::new([2_u8; 32]); -const INIT_VALUE: u128 = 100_000_000 * UNIT; +const INIT_AMOUNT: Balance = 100_000_000 * UNIT; +const INIT_VALUE: Balance = 100 * UNIT; const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); fn new_test_ext() -> sp_io::TestExternalities { @@ -19,7 +21,7 @@ fn new_test_ext() -> sp_io::TestExternalities { .expect("Frame system builds valid default genesis config"); pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INIT_VALUE), (BOB, INIT_VALUE)], + balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT)], } .assimilate_storage(&mut t) .expect("Pallet balances storage can be assimilated"); @@ -65,7 +67,7 @@ fn do_bare_call( } // Deploy, instantiate and return contract address. -fn instantiate(contract: &str, init_value: u128) -> AccountId32 { +fn instantiate(contract: &str, init_value: u128, salt: Vec) -> AccountId32 { let (wasm_binary, _) = load_wasm_module::(contract).expect("could not read .wasm file"); let result = Contracts::bare_instantiate( @@ -75,7 +77,7 @@ fn instantiate(contract: &str, init_value: u128) -> AccountId32 { None, Code::Upload(wasm_binary), function_selector("new"), - vec![], + salt, DEBUG_OUTPUT, CollectEvents::Skip, ) From 1022926e0d35ee56930a0757655df3c7f12b6ec4 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Thu, 6 Jun 2024 11:48:55 +0200 Subject: [PATCH 005/161] test: add transfer --- pop-api/examples/fungibles/lib.rs | 108 +++++---- pop-api/src/lib.rs | 7 +- pop-api/src/v0/assets/fungibles.rs | 206 ++++++++++-------- pop-api/src/v0/balances.rs | 10 +- .../src/extensions/tests/local_fungibles.rs | 205 ++++++++++++----- runtime/devnet/src/extensions/tests/mod.rs | 1 + 6 files changed, 344 insertions(+), 193 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index e44c4347..68e43865 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -1,6 +1,10 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -// Fungibles wrapper contract to allow contracts to interact with local fungibles without the pop api. +/// Local Fungibles: +/// 1. PSP-22 Interface +/// 2. PSP-22 Metadata Interface +/// 3. Asset Management +/// use ink::prelude::vec::Vec; use pop_api::{ assets::fungibles::*, @@ -10,6 +14,8 @@ use pop_api::{ #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum ContractError { + /// The asset is not live; either frozen or being destroyed. + AssetNotLive, /// The amount to mint is less than the existential deposit. BelowMinimum, /// Unspecified dispatch error, providing the index and its error index (if none `0`). @@ -24,6 +30,8 @@ pub enum ContractError { MinBalanceZero, /// Unspecified pallet error, providing pallet index and error index. ModuleError { pallet: u8, error: u16 }, + /// The account to alter does not exist. + NoAccount, /// The signing account has no permission to do the operation. NoPermission, /// The given asset ID is unknown. @@ -33,6 +41,7 @@ pub enum ContractError { impl From for ContractError { fn from(error: FungiblesError) -> Self { match error { + FungiblesError::AssetNotLive => ContractError::AssetNotLive, FungiblesError::BelowMinimum => ContractError::BelowMinimum, FungiblesError::DispatchError { index, error } => { ContractError::DispatchError { index, error } @@ -44,6 +53,7 @@ impl From for ContractError { FungiblesError::ModuleError { pallet, error } => { ContractError::ModuleError { pallet, error } }, + FungiblesError::NoAccount => ContractError::NoAccount, FungiblesError::NoPermission => ContractError::NoPermission, FungiblesError::Unknown => ContractError::Unknown, } @@ -68,6 +78,16 @@ mod fungibles { Default::default() } + /// 1. PSP-22 Interface: + /// - total_supply + /// - balance_of + /// - allowance + /// - transfer + /// - transfer_from + /// - approve + /// - increase_allowance + /// - decrease_allowance + #[ink(message)] pub fn total_supply(&self, id: AssetId) -> Result { total_supply(id).map_err(From::from) @@ -89,13 +109,58 @@ mod fungibles { } #[ink(message)] - pub fn asset_exists(&self, id: AssetId) -> Result { - asset_exists(id).map_err(From::from) + pub fn transfer(&self, id: AssetId, to: AccountId32, value: Balance) -> Result<()> { + ink::env::debug_println!( + "PopApiAssetsExample::transfer: id: {:?}, to: {:?} value: {:?}", + id, + to, + value, + ); + + let result = transfer(id, to, value); + ink::env::debug_println!("Result: {:?}", result); + result.map_err(From::from) + } + + #[ink(message)] + pub fn transfer_from( + &self, + id: AssetId, + from: Option, + to: Option, + value: Balance, + // Size needs to be known at compile time or ink's `Vec` + data: Vec, + ) -> Result<()> { + ink::env::debug_println!( + "PopApiAssetsExample::transfer_from: id: {:?}, from: {:?}, to: {:?} value: {:?}", + id, + from, + to, + value, + ); + + let result = transfer_from(id, from, to, value, &data); + ink::env::debug_println!("Result: {:?}", result); + result.map_err(From::from) } + /// 2. PSP-22 Metadata Interface: + /// - token_name + /// - token_symbol + /// - token_decimals + + /// 3. Asset Management: + /// - create + /// - start_destroy + /// - destroy_accounts + /// - destroy_approvals + /// - finish_destroy + /// - set_metadata + /// - clear_metadata + #[ink(message)] pub fn create(&self, id: AssetId, admin: AccountId32, min_balance: Balance) -> Result<()> { - // create(id, admin, min_balance).map_err(From::from) ink::env::debug_println!( "PopApiAssetsExample::create: id: {:?} admin: {:?} min_balance: {:?}", id, @@ -115,7 +180,6 @@ mod fungibles { symbol: Vec, decimals: u8, ) -> Result<()> { - // set_metadata(id, name, symbol, decimals).map_err(From::from) ink::env::debug_println!( "PopApiAssetsExample::set_metadata: id: {:?} name: {:?} symbol: {:?}, decimals: {:?}", id, @@ -129,39 +193,9 @@ mod fungibles { } #[ink(message)] - pub fn mint(&self, id: AssetId, beneficiary: AccountId32, amount: Balance) -> Result<()> { - ink::env::debug_println!( - "PopApiAssetsExample::mint: id: {:?}, beneficiary: {:?} amount: {:?}", - id, - beneficiary, - amount, - ); - - let result = mint(id, beneficiary, amount); - ink::env::debug_println!("Result: {:?}", result); - result.map_err(From::from) + pub fn asset_exists(&self, id: AssetId) -> Result { + asset_exists(id).map_err(From::from) } - - // #[ink(message)] - // pub fn transfer_from( - // id: AssetId, - // from: Option, - // to: Option, - // value: Balance, - // data: [u8], - // ) -> Result<()> { - // ink::env::debug_println!( - // "PopApiAssetsExample::transfer_from: id: {:?}, from: {:?}, to: {:?} value: {:?}", - // id, - // from, - // to, - // value, - // ); - // - // let result = transfer_from(id, from, to, value)?; - // ink::env::debug_println!("Result: {:?}", result); - // result - // } } #[cfg(test)] diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 014b5a29..be448890 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -21,16 +21,11 @@ type MaxTips = u32; pub type Result = core::result::Result; -struct ModuleError { - pallet: u8, - error: u16, -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum PopApiError { Assets(assets::fungibles::AssetsError), - Balances(balances::Error), + Balances(balances::BalancesError), Contracts(contracts::Error), DecodingFailed, Nfts(nfts::Error), diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index de624938..df9033c7 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,7 +1,6 @@ use crate::{ - AccountId, Balance, - PopApiError::{UnknownDispatchStatusCode, UnknownModuleStatusCode}, - RuntimeCall, *, + balances::BalancesError, AccountId, Balance, PopApiError::UnknownModuleStatusCode, RuntimeCall, + *, }; use ink::prelude::vec::Vec; use primitives::AssetId; @@ -62,28 +61,6 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result>, min_balance: Balance) -> Result<()> { -pub fn create( - id: AssetId, - admin: impl Into>, - min_balance: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::Assets(AssetsCall::Create { - id: id.into(), - admin: admin.into(), - min_balance, - }))?) -} - /// Transfers `value` amount of tokens from the caller's account to account `to`, with additional /// `data` in unspecified format. /// @@ -94,29 +71,27 @@ pub fn create( /// /// # Returns /// Returns `Ok(())` if successful, or an error if the transfer fails. -// #[allow(unused_variables)] -// pub fn transfer( -// id: AssetId, -// to: impl Into>, -// value: Balance, -// ) -> Result<()> { -// todo!() -// // TODO: transfer or transfer_keep_alive -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::Transfer { -// // id: id.into(), -// // target: target.into(), -// // amount: Compact(amount), -// // }))?) -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { -// // id: id.into(), -// // target: target.into(), -// // amount: Compact(amount), -// // }))?) -// } +pub fn transfer( + id: AssetId, + to: impl Into>, + value: Balance, +) -> Result<()> { + // TODO: transfer or transfer_keep_alive + // Ok(dispatch(RuntimeCall::Assets(AssetsCall::Transfer { + // id: id.into(), + // target: target.into(), + // amount: Compact(amount), + // }))?) + Ok(dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { + id: id.into(), + target: to.into(), + amount: Compact(value), + }))?) +} -/// Transfers `value` tokens on the behalf of `from` to the account `to` with additional `data` -/// in unspecified format. This can be used to allow a contract to transfer tokens on ones behalf -/// and/or to charge fees in sub-currencies, for example. +/// Transfers `value` tokens on behalf of `from` to account `to` with additional `data` +/// in unspecified format. If `from` is equal to `None`, tokens will be minted to account `to`. If +/// `to` is equal to `None`, tokens will be burned from account `from`. /// /// # Arguments /// * `id` - The ID of the asset. @@ -126,43 +101,26 @@ pub fn create( /// /// # Returns /// Returns `Ok(())` if successful, or an error if the transfer fails. -// pub fn transfer_from( -// id: AssetId, -// from: impl Into>, -// to: impl Into>, -// value: Balance, -// ) -> Result<()> { -//todo!() -// TODO: depending on `from` and `to`, decide whether to mint, burn or transfer_approved. -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::Mint { -// id: id.into(), -// beneficiary: beneficiary.into(), -// amount: Compact(amount), -// }))?) -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::Burn { -// id: id.into(), -// who: who.into(), -// amount: Compact(amount), -// }))?) -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::TransferApproved { -// id: id.into(), -// owner: from.into(), -// destination: to.into(), -// amount: Compact(value), -// }))?) -// } - -/// Mint assets of a particular class. -pub fn mint( +pub fn transfer_from( id: AssetId, - beneficiary: impl Into>, - amount: Balance, + from: Option>>, + to: Option>>, + value: Balance, + _data: &[u8], ) -> Result<()> { - Ok(dispatch(RuntimeCall::Assets(AssetsCall::Mint { - id: id.into(), - beneficiary: beneficiary.into(), - amount: Compact(amount), - }))?) + match (from, to) { + (None, Some(to)) => mint(id, to, value), + // (Some(from), None) => burn(id, from, value), + (Some(from), Some(to)) => { + Ok(dispatch(RuntimeCall::Assets(AssetsCall::TransferApproved { + id: id.into(), + owner: from.into(), + destination: to.into(), + amount: Compact(value), + }))?) + }, + _ => Ok(()), + } } /// Approves an account to spend a specified number of tokens on behalf of the caller. @@ -277,6 +235,27 @@ pub fn mint( /// - set_metadata /// - clear_metadata +/// Create a new token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `admin` - The account that will administer the asset. +/// * `min_balance` - The minimum balance required for accounts holding this asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the creation fails. +pub fn create( + id: AssetId, + admin: impl Into>, + min_balance: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::Assets(AssetsCall::Create { + id: id.into(), + admin: admin.into(), + min_balance, + }))?) +} + /// Start the process of destroying a token with a given asset ID. /// /// # Arguments @@ -362,10 +341,22 @@ pub fn asset_exists(id: AssetId) -> Result { Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id)))?) } -// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected -// to be compact encoded. The pop api handles that for the developer. -// -// reference: https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development +/// Mint assets of a particular class. +fn mint( + id: AssetId, + beneficiary: impl Into>, + amount: Balance, +) -> Result<()> { + Ok(dispatch(RuntimeCall::Assets(AssetsCall::Mint { + id: id.into(), + beneficiary: beneficiary.into(), + amount: Compact(amount), + }))?) +} + +// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount +// (`Balance`) are expected to be compact encoded. The pop api handles that for the developer. +// https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development // // Asset id that is compact encoded. type AssetIdParameter = Compact; @@ -423,7 +414,6 @@ pub(crate) enum AssetsCall { }, } -// TODO: remove unnecessary errors #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub(crate) enum AssetsError { @@ -514,6 +504,8 @@ impl TryFrom for AssetsError { #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum FungiblesError { + /// The asset is not live; either frozen or being destroyed. + AssetNotLive, /// The amount to mint is less than the existential deposit. BelowMinimum, /// Unspecified dispatch error, providing the index and its error index (if none `0`). @@ -528,16 +520,20 @@ pub enum FungiblesError { MinBalanceZero, /// Unspecified pallet error, providing pallet index and error index. ModuleError { pallet: u8, error: u16 }, + /// The account to alter does not exist. + NoAccount, /// The signing account has no permission to do the operation. NoPermission, /// The given asset ID is unknown. Unknown, } -impl From for FungiblesError { - fn from(error: balances::Error) -> Self { +impl From for FungiblesError { + fn from(error: BalancesError) -> Self { match error { - balances::Error::InsufficientBalance => FungiblesError::InsufficientBalance, + // TODO: this insufficient balance is different than the assets variant. This one is + // for a deposit of creating an asset, the latter is for transfer tokens. + BalancesError::InsufficientBalance => FungiblesError::InsufficientBalance, _ => FungiblesError::ModuleError { pallet: 40, error: error as u16 }, } } @@ -546,8 +542,10 @@ impl From for FungiblesError { impl From for FungiblesError { fn from(error: dispatch_error::TokenError) -> Self { match error { - dispatch_error::TokenError::UnknownAsset => FungiblesError::Unknown, dispatch_error::TokenError::BelowMinimum => FungiblesError::BelowMinimum, + // ED is not respected. + dispatch_error::TokenError::OnlyProvider => FungiblesError::InsufficientBalance, + dispatch_error::TokenError::UnknownAsset => FungiblesError::Unknown, _ => FungiblesError::DispatchError { index: 7, error: error as u8 }, } } @@ -556,12 +554,15 @@ impl From for FungiblesError { impl From for FungiblesError { fn from(error: AssetsError) -> Self { match error { + AssetsError::AssetNotLive => FungiblesError::AssetNotLive, + AssetsError::BalanceLow => FungiblesError::InsufficientBalance, AssetsError::Unapproved => FungiblesError::InsufficientAllowance, AssetsError::InUse => FungiblesError::InUse, AssetsError::MinBalanceZero => FungiblesError::MinBalanceZero, AssetsError::NoPermission => FungiblesError::NoPermission, + AssetsError::NoAccount => FungiblesError::NoAccount, AssetsError::Unknown => FungiblesError::Unknown, - _ => FungiblesError::ModuleError { pallet: 40, error: error as u16 }, + _ => FungiblesError::ModuleError { pallet: 52, error: error as u16 }, } } } @@ -586,3 +587,24 @@ impl From for FungiblesError { } } } + +// macro_rules! impl_error_conversion { +// ($pallet_index:, $pallet_error:ty, $interface_error:ty, $($variant:ident),*) => { +// impl From<$pallet_error> for $interface_error { +// fn from(error: $pallet_error) -> Self { +// match error { +// $( +// <$pallet_error>::$variant => <$interface_error>::$variant, +// )* +// _ => <$interface_error>::ModuleError { pallet: 0, error: [255, 0, 0, 0] }, // Default case +// } +// } +// } +// +// impl FromPalletError<$pallet_error> for $interface_error { +// fn from_pallet_error(error: $pallet_error) -> Self { +// Self::from(error) +// } +// } +// }; +// } diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs index bc422ef4..08db0a75 100644 --- a/pop-api/src/v0/balances.rs +++ b/pop-api/src/v0/balances.rs @@ -3,7 +3,7 @@ use crate::{ PopApiError::UnknownModuleStatusCode, }; -type Result = core::result::Result; +type Result = core::result::Result; pub fn transfer_keep_alive( dest: impl Into>, @@ -28,7 +28,7 @@ pub(crate) enum BalancesCall { #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub(crate) enum Error { +pub(crate) enum BalancesError { /// Vesting balance too high to send value. VestingBalance, /// Account liquidity restrictions prevent withdrawal. @@ -55,11 +55,11 @@ pub(crate) enum Error { DeltaZero, } -impl TryFrom for Error { +impl TryFrom for BalancesError { type Error = PopApiError; fn try_from(status_code: u32) -> core::result::Result { - use Error::*; + use BalancesError::*; match status_code { 0 => Ok(VestingBalance), 1 => Ok(LiquidityRestrictions), @@ -78,7 +78,7 @@ impl TryFrom for Error { } } -impl From for Error { +impl From for BalancesError { fn from(error: PopApiError) -> Self { match error { PopApiError::Balances(e) => e, diff --git a/runtime/devnet/src/extensions/tests/local_fungibles.rs b/runtime/devnet/src/extensions/tests/local_fungibles.rs index 5bd7dac0..5de162c9 100644 --- a/runtime/devnet/src/extensions/tests/local_fungibles.rs +++ b/runtime/devnet/src/extensions/tests/local_fungibles.rs @@ -1,10 +1,11 @@ #![cfg(test)] use super::*; -use pallet_contracts::debug::ExecResult; #[derive(Decode, Encode, Debug, Eq, PartialEq)] enum FungiblesError { + /// The asset is not live; either frozen or being destroyed. + AssetNotLive, /// The amount to mint is less than the existential deposit. BelowMinimum, /// Unspecified dispatch error, providing the index and optionally its error index. @@ -19,13 +20,15 @@ enum FungiblesError { MinBalanceZero, /// Unspecified pallet error, providing pallet index and error index. ModuleError { pallet: u8, error: u16 }, + /// The account to alter does not exist. + NoAccount, /// The signing account has no permission to do the operation. NoPermission, /// The given asset ID is unknown. Unknown, } -const ASSET_ID: u32 = 1; +const ASSET_ID: AssetId = 1; fn decoded(result: ExecReturnValue) -> T { ::decode(&mut &result.data[2..]).unwrap() @@ -33,39 +36,42 @@ fn decoded(result: ExecReturnValue) -> T { fn allowance( addr: AccountId32, - asset_id: u32, + asset_id: AssetId, owner: AccountId32, spender: AccountId32, -) -> ExecReturnValue { +) -> Balance { let function = function_selector("allowance"); let params = [function, asset_id.encode(), owner.encode(), spender.encode()].concat(); - do_bare_call(addr, params, 0).expect("should work") + let result = do_bare_call(addr, params, 0).expect("should work"); + decoded::(result) } // Call balance_of contract message. -fn balance_of(addr: AccountId32, asset_id: u32, owner: AccountId32) -> ExecReturnValue { +fn balance_of(addr: AccountId32, asset_id: AssetId, owner: AccountId32) -> Balance { let function = function_selector("balance_of"); let params = [function, asset_id.encode(), owner.encode()].concat(); - do_bare_call(addr, params, 0).expect("should work") + let result = do_bare_call(addr, params, 0).expect("should work"); + decoded::(result) } // Call total_supply contract message. -fn total_supply(addr: AccountId32, asset_id: u32) -> Balance { +fn total_supply(addr: AccountId32, asset_id: AssetId) -> Balance { let function = function_selector("total_supply"); let params = [function, asset_id.encode()].concat(); let result = do_bare_call(addr, params, 0).expect("should work"); decoded::(result) } -fn asset_exists(addr: AccountId32, asset_id: u32) -> ExecReturnValue { +fn asset_exists(addr: AccountId32, asset_id: AssetId) -> bool { let function = function_selector("asset_exists"); let params = [function, asset_id.encode()].concat(); - do_bare_call(addr, params, 0).expect("should work") + let result = do_bare_call(addr, params, 0).expect("should work"); + decoded::(result) } fn create( addr: AccountId32, - asset_id: u32, + asset_id: AssetId, admin: AccountId32, min_balance: Balance, ) -> ExecReturnValue { @@ -76,7 +82,7 @@ fn create( fn set_metadata( addr: AccountId32, - asset_id: u32, + asset_id: AssetId, name: Vec, symbol: Vec, decimals: u8, @@ -87,26 +93,34 @@ fn set_metadata( do_bare_call(addr, params, 0).expect("should work") } +fn transfer( + addr: AccountId32, + asset_id: AssetId, + to: AccountId32, + value: Balance, +) -> ExecReturnValue { + let function = function_selector("transfer"); + let params = [function, asset_id.encode(), to.encode(), value.encode()].concat(); + do_bare_call(addr, params, 0).expect("should work") +} + fn transfer_from( addr: AccountId32, - asset_id: u32, - _from: Option, + asset_id: AssetId, + from: Option, to: Option, value: Balance, - _data: &[u8], + data: &[u8], ) -> ExecReturnValue { - // let function = function_selector("transfer_from"); - // let params = - // [function, asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()] - // .concat(); - // do_bare_call(addr, params, 0) - let function = function_selector("mint"); - let params = [function, asset_id.encode(), to.unwrap().encode(), value.encode()].concat(); + let function = function_selector("transfer_from"); + let params = + [function, asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()] + .concat(); do_bare_call(addr, params, 0).expect("should work") } // Create an asset and mint to owner. -fn create_asset(asset_id: u32, owner: AccountId32, min_balance: Balance) { +fn create_asset(asset_id: AssetId, owner: AccountId32, min_balance: Balance) -> AssetId { assert_eq!( Assets::create( RuntimeOrigin::signed(owner.clone()), @@ -116,20 +130,27 @@ fn create_asset(asset_id: u32, owner: AccountId32, min_balance: Balance) { ), Ok(()) ); + asset_id } // Create an asset and mint to owner. -fn create_asset_and_mint_to(asset_id: u32, owner: AccountId32, to: AccountId32, value: Balance) { +fn create_asset_and_mint_to( + asset_id: AssetId, + owner: AccountId32, + to: AccountId32, + value: Balance, +) -> AssetId { create_asset(asset_id, owner.clone(), 1); assert_eq!( Assets::mint(RuntimeOrigin::signed(owner.into()), asset_id.into(), to.into(), value,), Ok(()) ); + asset_id } // Create an asset, mints to, and approves spender. fn create_asset_mint_and_approve( - asset_id: u32, + asset_id: AssetId, owner: AccountId32, to: AccountId32, mint: Balance, @@ -148,6 +169,21 @@ fn create_asset_mint_and_approve( ); } +// Freeze an asset. +fn freeze_asset(asset_id: AssetId, owner: AccountId32) { + assert_eq!(Assets::freeze_asset(RuntimeOrigin::signed(owner.into()), asset_id.into()), Ok(())); +} + +// Thaw an asset. +fn thaw_asset(asset_id: AssetId, owner: AccountId32) { + assert_eq!(Assets::thaw_asset(RuntimeOrigin::signed(owner.into()), asset_id.into()), Ok(())); +} + +// Start destroying an asset. +fn start_destroy_asset(asset_id: AssetId, owner: AccountId32) { + assert_eq!(Assets::start_destroy(RuntimeOrigin::signed(owner.into()), asset_id.into()), Ok(())); +} + #[test] #[ignore] fn total_supply_works() { @@ -180,17 +216,11 @@ fn balance_of_works() { ); // No tokens in circulation. - assert_eq!( - Assets::balance(ASSET_ID, BOB).encode(), - balance_of(addr.clone(), ASSET_ID, BOB).data[2..] - ); + assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr.clone(), ASSET_ID, BOB)); // Tokens in circulation. create_asset_and_mint_to(ASSET_ID, addr.clone(), BOB, 100); - assert_eq!( - Assets::balance(ASSET_ID, BOB).encode(), - balance_of(addr, ASSET_ID, BOB).data[2..] - ); + assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr, ASSET_ID, BOB)); }); } @@ -207,15 +237,15 @@ fn allowance_works() { // No tokens in circulation. assert_eq!( - Assets::allowance(ASSET_ID, &BOB, &ALICE).encode(), - allowance(addr.clone(), ASSET_ID, BOB, ALICE).data[2..] + Assets::allowance(ASSET_ID, &BOB, &ALICE), + allowance(addr.clone(), ASSET_ID, BOB, ALICE) ); // Tokens in circulation. create_asset_mint_and_approve(ASSET_ID, addr.clone(), BOB, 100, ALICE, 50); assert_eq!( - Assets::allowance(ASSET_ID, &BOB, &ALICE).encode(), - allowance(addr, ASSET_ID, BOB, ALICE).data[2..] + Assets::allowance(ASSET_ID, &BOB, &ALICE), + allowance(addr, ASSET_ID, BOB, ALICE) ); }); } @@ -232,14 +262,11 @@ fn asset_exists_works() { ); // No tokens in circulation. - assert_eq!( - Assets::asset_exists(ASSET_ID).encode(), - asset_exists(addr.clone(), ASSET_ID).data[2..] - ); + assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr.clone(), ASSET_ID)); // Tokens in circulation. create_asset(ASSET_ID, addr.clone(), 1); - assert_eq!(Assets::asset_exists(ASSET_ID).encode(), asset_exists(addr, ASSET_ID).data[2..]); + assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr, ASSET_ID)); }); } @@ -299,11 +326,12 @@ fn set_metadata_works() { } // todo: errors: -// - AssetNotLive: when frozen or being destroyed -// - TokenErrors: https://github.com/paritytech/polkadot-sdk/blob/3977f389cce4a00fd7100f95262e0563622b9aa4/substrate/frame/assets/src/functions.rs#L125 +// - TokenErrors +// - Arithmetic +// - https://github.com/paritytech/polkadot-sdk/blob/3977f389cce4a00fd7100f95262e0563622b9aa4/substrate/frame/assets/src/functions.rs#L125 #[test] #[ignore] -fn mint_works() { +fn transfer_from_mint_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); let addr = instantiate( @@ -316,7 +344,7 @@ fn mint_works() { assert_eq!( decoded::(transfer_from( addr.clone(), - ASSET_ID, + 1, None, Some(BOB), amount, @@ -324,11 +352,11 @@ fn mint_works() { )), FungiblesError::Unknown ); - create_asset(ASSET_ID, ALICE, 2); + let asset = create_asset(1, ALICE, 2); assert_eq!( decoded::(transfer_from( addr.clone(), - ASSET_ID, + asset, None, Some(BOB), amount, @@ -339,7 +367,7 @@ fn mint_works() { assert_eq!( decoded::(transfer_from( addr.clone(), - ASSET_ID, + asset, None, Some(BOB), 1, @@ -347,16 +375,87 @@ fn mint_works() { )), FungiblesError::BelowMinimum ); - let asset = 2; - create_asset(asset, addr.clone(), 2); + let asset = create_asset(2, addr.clone(), 2); + freeze_asset(asset, addr.clone()); + assert_eq!( + decoded::(transfer_from( + addr.clone(), + asset, + None, + Some(BOB), + amount, + &[0u8] + )), + FungiblesError::AssetNotLive + ); + thaw_asset(asset, addr.clone()); let bob_balance_before_mint = Assets::balance(asset, &BOB); - let result = transfer_from(addr.clone(), asset, None, Some(BOB), 100 * UNIT, &[0u8]); + let result = transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8]); assert!(!result.did_revert(), "Contract reverted!"); let bob_balance_after_mint = Assets::balance(asset, &BOB); assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount); + start_destroy_asset(asset, addr.clone()); + assert_eq!( + decoded::(transfer_from( + addr.clone(), + asset, + None, + Some(BOB), + amount, + &[0u8] + )), + FungiblesError::AssetNotLive + ); }); } +// Todo: error: +// - Frozen: account is frozen, who do you freeze an account? +// - https://github.com/paritytech/polkadot-sdk/blob/2460cddf57660a88844d201f769eb17a7accce5a/substrate/frame/assets/src/functions.rs#L161 +// - ArithmeticError: Underflow, Overflow +// - https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/functions.rs#L125 +// - #[test] #[ignore] -fn transfer_works() {} +fn transfer_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate( + "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", + INIT_VALUE, + vec![], + ); + let amount: Balance = 100 * UNIT; + + assert_eq!( + decoded::(transfer(addr.clone(), 1, BOB, amount,)), + FungiblesError::Unknown + ); + let asset = create_asset_and_mint_to(1, ALICE, addr.clone(), amount); + freeze_asset(asset, ALICE); + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount,)), + FungiblesError::AssetNotLive + ); + thaw_asset(asset, ALICE); + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), + FungiblesError::InsufficientBalance + ); + // Errors due to ED. Could be Belowminimum + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount)), + FungiblesError::InsufficientBalance + ); + let bob_balance_before_mint = Assets::balance(asset, &BOB); + let result = transfer(addr.clone(), asset, BOB, amount / 2); + assert!(!result.did_revert(), "Contract reverted!"); + let bob_balance_after_mint = Assets::balance(asset, &BOB); + assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); + start_destroy_asset(asset, ALICE); + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), + FungiblesError::AssetNotLive + ); + }); +} diff --git a/runtime/devnet/src/extensions/tests/mod.rs b/runtime/devnet/src/extensions/tests/mod.rs index 03cda2cd..cbd13d62 100644 --- a/runtime/devnet/src/extensions/tests/mod.rs +++ b/runtime/devnet/src/extensions/tests/mod.rs @@ -7,6 +7,7 @@ use sp_runtime::{traits::Hash, AccountId32, BuildStorage}; mod local_fungibles; type Balance = u128; +type AssetId = u32; const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); From ecc82e266d772bbe6d57b3feb9049e3228152f8a Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Thu, 6 Jun 2024 11:51:10 +0200 Subject: [PATCH 006/161] chore: remove polkadot launch --- polkadot-launch/config.json | 39 ------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 polkadot-launch/config.json diff --git a/polkadot-launch/config.json b/polkadot-launch/config.json deleted file mode 100644 index f03f983a..00000000 --- a/polkadot-launch/config.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "relaychain": { - "bin": "../../polkadot/target/release/polkadot", - "chain": "rococo-local", - "nodes": [ - { - "name": "alice", - "wsPort": 9944, - "port": 30444 - }, - { - "name": "bob", - "wsPort": 9955, - "port": 30555 - } - ] - }, - "parachains": [ - { - "bin": "../target/release/polkadot-parachain", - "id": "200", - "balance": "1000000000000000000000", - "nodes": [ - { - "wsPort": 9988, - "name": "alice", - "port": 31200, - "flags": [ - "--force-authoring", - "--", - "--execution=wasm" - ] - } - ] - } - ], - "types": { - } -} From e81f78a957ff3773bc45e93a61f8bf3c17538bc0 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Thu, 6 Jun 2024 14:04:31 +0200 Subject: [PATCH 007/161] # This is a combination of 8 commits. # This is the 1st commit message: refactor: general # This is the commit message #2: init # This is the commit message #3: begin refactor # This is the commit message #4: refactor: error handling # This is the commit message #5: tests: add error handling tests # This is the commit message #6: WIP # This is the commit message #7: finalise error handling # This is the commit message #8: refactor: easier review --- Cargo.lock | 2723 ++++++++++------ pop-api/examples/fungibles/expanded.rs | 2766 ----------------- pop-api/examples/fungibles/lib.rs | 94 +- pop-api/src/error.rs | 255 ++ pop-api/src/lib.rs | 58 +- pop-api/src/v0/assets/fungibles.rs | 610 ---- pop-api/src/v0/assets/mod.rs | 3 +- pop-api/src/v0/assets/pallets/assets.rs | 491 +++ pop-api/src/v0/assets/pallets/mod.rs | 1 + pop-api/src/v0/assets/use_cases/fungibles.rs | 372 +++ pop-api/src/v0/assets/use_cases/mod.rs | 1 + pop-api/src/v0/balances.rs | 21 +- pop-api/src/v0/contracts.rs | 152 - pop-api/src/v0/cross_chain/mod.rs | 15 +- pop-api/src/v0/dispatch_error.rs | 57 - pop-api/src/v0/mod.rs | 4 +- pop-api/src/v0/nfts.rs | 15 +- primitives/src/storage_keys.rs | 3 - runtime/devnet/Cargo.toml | 2 + .../src/{extensions/mod.rs => extensions.rs} | 45 +- runtime/devnet/src/extensions/tests/mod.rs | 89 - runtime/devnet/src/lib.rs | 2 + .../{extensions => }/tests/local_fungibles.rs | 199 +- runtime/devnet/src/tests/mod.rs | 262 ++ 24 files changed, 3335 insertions(+), 4905 deletions(-) delete mode 100644 pop-api/examples/fungibles/expanded.rs create mode 100644 pop-api/src/error.rs delete mode 100644 pop-api/src/v0/assets/fungibles.rs create mode 100644 pop-api/src/v0/assets/pallets/assets.rs create mode 100644 pop-api/src/v0/assets/pallets/mod.rs create mode 100644 pop-api/src/v0/assets/use_cases/fungibles.rs create mode 100644 pop-api/src/v0/assets/use_cases/mod.rs delete mode 100644 pop-api/src/v0/contracts.rs delete mode 100644 pop-api/src/v0/dispatch_error.rs rename runtime/devnet/src/{extensions/mod.rs => extensions.rs} (97%) delete mode 100644 runtime/devnet/src/extensions/tests/mod.rs rename runtime/devnet/src/{extensions => }/tests/local_fungibles.rs (70%) create mode 100644 runtime/devnet/src/tests/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 17cc70e5..77c563fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -343,7 +343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -358,6 +358,12 @@ version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f840fb7195bcfc5e17ea40c26e5ce6d5b9ce5d584466e17703209657e459ae0" +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + [[package]] name = "arrayref" version = "0.3.7" @@ -373,6 +379,12 @@ dependencies = [ "nodrop", ] +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "arrayvec" version = "0.7.4" @@ -404,7 +416,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -486,17 +498,17 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-consensus-aura", - "sp-core", + "sp-core 29.0.0", "sp-genesis-builder", "sp-inherents", "sp-offchain", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", - "sp-std", - "sp-storage", + "sp-std 14.0.0", + "sp-storage 20.0.0", "sp-transaction-pool", "sp-version", - "sp-weights", + "sp-weights 28.0.0", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", @@ -525,9 +537,9 @@ dependencies = [ "parachains-common", "parachains-runtimes-test-utils", "parity-scale-codec", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", @@ -551,8 +563,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -909,7 +921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ "bitcoin_hashes", - "rand", + "rand 0.8.5", "rand_core 0.6.4", "serde", "unicode-normalization", @@ -1012,6 +1024,18 @@ dependencies = [ "constant_time_eq 0.3.0", ] +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -1030,6 +1054,15 @@ dependencies = [ "generic-array 0.14.7", ] +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + [[package]] name = "blocking" version = "1.5.1" @@ -1116,7 +1149,7 @@ dependencies = [ "frame-system", "polkadot-primitives", "sp-api", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -1130,8 +1163,8 @@ dependencies = [ "bp-runtime", "frame-support", "sp-api", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -1145,8 +1178,8 @@ dependencies = [ "bp-runtime", "frame-support", "sp-api", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -1162,9 +1195,9 @@ dependencies = [ "scale-info", "serde", "sp-consensus-grandpa", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -1179,8 +1212,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-std", + "sp-core 29.0.0", + "sp-std 14.0.0", ] [[package]] @@ -1196,9 +1229,9 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -1215,9 +1248,9 @@ dependencies = [ "parity-util-mem", "scale-info", "serde", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -1231,8 +1264,8 @@ dependencies = [ "frame-support", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -1250,13 +1283,13 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-state-machine", - "sp-std", - "sp-trie", - "trie-db", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", + "trie-db 0.28.0", ] [[package]] @@ -1269,15 +1302,15 @@ dependencies = [ "bp-parachains", "bp-polkadot-core", "bp-runtime", - "ed25519-dalek", + "ed25519-dalek 2.1.1", "finality-grandpa", "parity-scale-codec", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-consensus-grandpa", - "sp-core", - "sp-runtime", - "sp-std", - "sp-trie", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", ] [[package]] @@ -1286,7 +1319,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6663e0179d475e30cfcf28cf597cdc8f4bb1c2c39a557b4cbe0057db0657fb67" dependencies = [ - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -1297,8 +1330,8 @@ checksum = "86ff4abe93be7bc1663adc41817b1aa3476fbec953ce361537419924310d5dd4" dependencies = [ "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", ] [[package]] @@ -1328,11 +1361,11 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-trie", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", "staging-xcm", "staging-xcm-builder", ] @@ -1745,6 +1778,26 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "const_env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9e4f72c6e3398ca6da372abd9affd8f89781fe728869bbf986206e9af9627e" +dependencies = [ + "const_env_impl", +] + +[[package]] +name = "const_env_impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f51209740b5e1589e702b3044cdd4562cef41b6da404904192ffffb852d62" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -2044,8 +2097,8 @@ dependencies = [ "sc-client-api", "sc-service", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "url", ] @@ -2068,8 +2121,8 @@ dependencies = [ "sc-client-api", "sp-api", "sp-consensus", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "tracing", ] @@ -2101,16 +2154,16 @@ dependencies = [ "sc-telemetry", "schnellru", "sp-api", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-aura", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-keystore", - "sp-runtime", - "sp-state-machine", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", "sp-timestamp", "substrate-prometheus-endpoint", "tracing", @@ -2138,10 +2191,10 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-slots", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "sp-timestamp", - "sp-trie", + "sp-trie 30.0.0", "substrate-prometheus-endpoint", "tracing", ] @@ -2157,8 +2210,8 @@ dependencies = [ "cumulus-primitives-parachain-inherent", "sp-consensus", "sp-inherents", - "sp-runtime", - "sp-state-machine", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", "thiserror", ] @@ -2180,9 +2233,9 @@ dependencies = [ "sc-client-api", "sp-blockchain", "sp-consensus", - "sp-core", - "sp-runtime", - "sp-state-machine", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", "tracing", ] @@ -2203,11 +2256,11 @@ dependencies = [ "sp-api", "sp-crypto-hashing", "sp-inherents", - "sp-runtime", - "sp-state-machine", - "sp-std", - "sp-storage", - "sp-trie", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-std 14.0.0", + "sp-storage 20.0.0", + "sp-trie 30.0.0", "tracing", ] @@ -2227,12 +2280,12 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-overseer", "polkadot-primitives", - "rand", + "rand 0.8.5", "sc-client-api", "sc-consensus", "sp-consensus", "sp-maybe-compressed-blob", - "sp-runtime", + "sp-runtime 32.0.0", "tracing", ] @@ -2268,8 +2321,8 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "sp-transaction-pool", ] @@ -2286,10 +2339,10 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-consensus-aura", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -2315,17 +2368,17 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-parachains", "scale-info", - "sp-core", - "sp-externalities", + "sp-core 29.0.0", + "sp-externalities 0.26.0", "sp-inherents", - "sp-io", - "sp-runtime", - "sp-state-machine", - "sp-std", - "sp-trie", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", "sp-version", "staging-xcm", - "trie-db", + "trie-db 0.28.0", ] [[package]] @@ -2351,8 +2404,8 @@ dependencies = [ "frame-system", "pallet-session", "parity-scale-codec", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -2366,9 +2419,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", ] @@ -2390,10 +2443,10 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-parachains", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-executor", ] @@ -2409,8 +2462,8 @@ dependencies = [ "polkadot-primitives", "sp-api", "sp-consensus-aura", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -2425,9 +2478,9 @@ dependencies = [ "polkadot-primitives", "scale-info", "sp-api", - "sp-runtime", - "sp-std", - "sp-trie", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", "staging-xcm", ] @@ -2441,10 +2494,10 @@ dependencies = [ "cumulus-primitives-core", "parity-scale-codec", "scale-info", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-std", - "sp-trie", + "sp-std 14.0.0", + "sp-trie 30.0.0", ] [[package]] @@ -2453,9 +2506,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b74f9141190b9f4bf96a947ade46da64097b77f1ebfa8d611c81724250e119" dependencies = [ - "sp-externalities", - "sp-runtime-interface", - "sp-trie", + "sp-externalities 0.26.0", + "sp-runtime-interface 25.0.0", + "sp-trie 30.0.0", ] [[package]] @@ -2471,9 +2524,9 @@ dependencies = [ "parity-scale-codec", "polkadot-runtime-common", "polkadot-runtime-parachains", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -2499,9 +2552,9 @@ dependencies = [ "sc-tracing", "sp-api", "sp-consensus", - "sp-core", - "sp-runtime", - "sp-state-machine", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", ] [[package]] @@ -2519,7 +2572,7 @@ dependencies = [ "sc-client-api", "sp-api", "sp-blockchain", - "sp-state-machine", + "sp-state-machine 0.36.0", "thiserror", ] @@ -2559,7 +2612,7 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-runtime", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "tokio", "tracing", @@ -2581,7 +2634,7 @@ dependencies = [ "parity-scale-codec", "pin-project", "polkadot-overseer", - "rand", + "rand 0.8.5", "sc-client-api", "sc-rpc-api", "sc-service", @@ -2593,10 +2646,10 @@ dependencies = [ "sp-api", "sp-authority-discovery", "sp-consensus-babe", - "sp-core", - "sp-runtime", - "sp-state-machine", - "sp-storage", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-storage 20.0.0", "sp-version", "thiserror", "tokio", @@ -2614,10 +2667,23 @@ dependencies = [ "cumulus-primitives-core", "parity-scale-codec", "polkadot-primitives", - "sp-runtime", - "sp-state-machine", - "sp-std", - "sp-trie", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", +] + +[[package]] +name = "curve25519-dalek" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" +dependencies = [ + "byteorder", + "digest 0.8.1", + "rand_core 0.5.1", + "subtle 2.5.0", + "zeroize", ] [[package]] @@ -3064,10 +3130,19 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", - "signature", + "signature 2.2.0", "spki", ] +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature 1.6.4", +] + [[package]] name = "ed25519" version = "2.2.3" @@ -3075,7 +3150,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", - "signature", + "signature 2.2.0", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.0", + "ed25519 1.5.3", + "sha2 0.9.9", + "zeroize", ] [[package]] @@ -3085,7 +3172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek 4.1.2", - "ed25519", + "ed25519 2.2.3", "rand_core 0.6.4", "serde", "sha2 0.10.8", @@ -3114,7 +3201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ "curve25519-dalek 4.1.2", - "ed25519", + "ed25519 2.2.3", "hashbrown 0.14.3", "hex", "rand_core 0.6.4", @@ -3174,8 +3261,8 @@ dependencies = [ "sc-consensus-grandpa", "sp-authority-discovery", "sp-consensus-babe", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "staging-xcm", "xcm-emulator", ] @@ -3422,6 +3509,12 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -3539,7 +3632,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -3616,13 +3709,13 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-core", - "sp-io", - "sp-runtime", - "sp-runtime-interface", - "sp-std", - "sp-storage", + "sp-application-crypto 31.0.0", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-runtime-interface 25.0.0", + "sp-std 14.0.0", + "sp-storage 20.0.0", "static_assertions", ] @@ -3647,7 +3740,7 @@ dependencies = [ "linked-hash-map", "log", "parity-scale-codec", - "rand", + "rand 0.8.5", "rand_pcg", "sc-block-builder", "sc-cli", @@ -3660,17 +3753,17 @@ dependencies = [ "serde_json", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-database", - "sp-externalities", + "sp-externalities 0.26.0", "sp-inherents", - "sp-io", - "sp-keystore", - "sp-runtime", - "sp-state-machine", - "sp-storage", - "sp-trie", - "sp-wasm-interface", + "sp-io 31.0.0", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-storage 20.0.0", + "sp-trie 30.0.0", + "sp-wasm-interface 20.0.0", "thiserror", "thousands", ] @@ -3698,11 +3791,11 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", "sp-npos-elections", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -3717,11 +3810,11 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-tracing", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-tracing 16.0.0", ] [[package]] @@ -3759,11 +3852,11 @@ dependencies = [ "log", "parity-scale-codec", "serde", - "sp-core", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-io", - "sp-runtime", - "sp-state-machine", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", "spinners", "substrate-rpc-client", "tokio", @@ -3794,20 +3887,20 @@ dependencies = [ "serde_json", "smallvec", "sp-api", - "sp-arithmetic", - "sp-core", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", "sp-crypto-hashing-proc-macro", - "sp-debug-derive", + "sp-debug-derive 14.0.0", "sp-genesis-builder", "sp-inherents", - "sp-io", + "sp-io 31.0.0", "sp-metadata-ir", - "sp-runtime", + "sp-runtime 32.0.0", "sp-staking", - "sp-state-machine", - "sp-std", - "sp-tracing", - "sp-weights", + "sp-state-machine 0.36.0", + "sp-std 14.0.0", + "sp-tracing 16.0.0", + "sp-weights 28.0.0", "static_assertions", "tt-call", ] @@ -3869,12 +3962,12 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "sp-version", - "sp-weights", + "sp-weights 28.0.0", ] [[package]] @@ -3888,9 +3981,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -3912,8 +4005,8 @@ dependencies = [ "frame-support", "parity-scale-codec", "sp-api", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -4163,7 +4256,7 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" dependencies = [ - "rand", + "rand 0.8.5", "rand_core 0.6.4", ] @@ -4669,6 +4762,206 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "ink" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4a862aedbfda93175ddf75c9aaa2ae4c4b39ee5cee06c16d50bccce05bf5c7" +dependencies = [ + "derive_more", + "ink_env", + "ink_macro", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage", + "pallet-contracts-uapi-next", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_allocator" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cee56055bac6d928d425e944c5f3b69baa33c9635822fd1c00cd4afc70fde3e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_codegen" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a1f8473fa09e0f9b6f3cb3f8d18c07c14ebf9ea1f7cdfee270f009d45ee8e9" +dependencies = [ + "blake2 0.10.6", + "derive_more", + "either", + "heck 0.4.1", + "impl-serde", + "ink_ir", + "ink_primitives", + "itertools 0.12.1", + "parity-scale-codec", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.58", +] + +[[package]] +name = "ink_engine" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f357e2e867f4e222ffc4015a6e61d1073548de89f70a4e36a8b0385562777fa" +dependencies = [ + "blake2 0.10.6", + "derive_more", + "ink_primitives", + "pallet-contracts-uapi-next", + "parity-scale-codec", + "secp256k1 0.28.2", + "sha2 0.10.8", + "sha3", +] + +[[package]] +name = "ink_env" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42cec50b7e4f8406aab25801b015d3802a52d76cfbe48ce11cfb4200fa88e296" +dependencies = [ + "blake2 0.10.6", + "cfg-if", + "const_env", + "derive_more", + "ink_allocator", + "ink_engine", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "num-traits", + "pallet-contracts-uapi-next", + "parity-scale-codec", + "paste", + "rlibc", + "scale-decode", + "scale-encode", + "scale-info", + "schnorrkel 0.11.4", + "secp256k1 0.28.2", + "sha2 0.10.8", + "sha3", + "static_assertions", +] + +[[package]] +name = "ink_ir" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b1ad2975551c4ed800af971289ed6d2c68ac41ffc03a42010b3e01d7360dfb2" +dependencies = [ + "blake2 0.10.6", + "either", + "impl-serde", + "ink_prelude", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "ink_macro" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aee1a546f37eae3b3cd223832d31702033c5369dcfa3405899587c110a7908d3" +dependencies = [ + "ink_codegen", + "ink_ir", + "ink_primitives", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.58", + "synstructure 0.13.1", +] + +[[package]] +name = "ink_metadata" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a98fcc0ff9292ff68c7ee7b84c93533c9ff13859ec3b148faa822e2da9954fe6" +dependencies = [ + "derive_more", + "impl-serde", + "ink_prelude", + "ink_primitives", + "linkme", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea1734d058c80aa72e59c8ae75624fd8a51791efba21469f273156c0f4cad5c9" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec35ef7f45e67a53b6142d7e7f18e6d9292d76c3a2a1da14cf8423e481813d" +dependencies = [ + "derive_more", + "ink_prelude", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "xxhash-rust", +] + +[[package]] +name = "ink_storage" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbdb04cad74df858c05bc9cb6f30bbf12da33c3e2cb7ca211749c001fa761aa9" +dependencies = [ + "array-init", + "cfg-if", + "derive_more", + "ink_env", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "pallet-contracts-uapi-next", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage_traits" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83ce49e3d2935fc1ec3e73117119712b187d3123339f6a31624e92f75fa2293d" +dependencies = [ + "ink_metadata", + "ink_prelude", + "ink_primitives", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "inout" version = "0.1.3" @@ -4726,8 +5019,8 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "staging-xcm", "staging-xcm-executor", "tracing-subscriber 0.3.18", @@ -4923,7 +5216,7 @@ dependencies = [ "hyper", "jsonrpsee-types 0.20.3", "parking_lot 0.12.1", - "rand", + "rand 0.8.5", "rustc-hash", "serde", "serde_json", @@ -5256,7 +5549,7 @@ dependencies = [ "parking_lot 0.12.1", "pin-project", "quick-protobuf", - "rand", + "rand 0.8.5", "rw-stream-sink", "smallvec", "thiserror", @@ -5307,12 +5600,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" dependencies = [ "bs58 0.4.0", - "ed25519-dalek", + "ed25519-dalek 2.1.1", "log", "multiaddr", "multihash 0.17.0", "quick-protobuf", - "rand", + "rand 0.8.5", "sha2 0.10.8", "thiserror", "zeroize", @@ -5337,7 +5630,7 @@ dependencies = [ "libp2p-swarm", "log", "quick-protobuf", - "rand", + "rand 0.8.5", "sha2 0.10.8", "smallvec", "thiserror", @@ -5359,7 +5652,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "log", - "rand", + "rand 0.8.5", "smallvec", "socket2 0.4.10", "tokio", @@ -5395,7 +5688,7 @@ dependencies = [ "log", "once_cell", "quick-protobuf", - "rand", + "rand 0.8.5", "sha2 0.10.8", "snow", "static_assertions", @@ -5417,7 +5710,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "rand", + "rand 0.8.5", "void", ] @@ -5437,7 +5730,7 @@ dependencies = [ "log", "parking_lot 0.12.1", "quinn-proto", - "rand", + "rand 0.8.5", "rustls 0.20.9", "thiserror", "tokio", @@ -5455,7 +5748,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm", - "rand", + "rand 0.8.5", "smallvec", ] @@ -5474,7 +5767,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm-derive", "log", - "rand", + "rand 0.8.5", "smallvec", "tokio", "void", @@ -5610,7 +5903,7 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand", + "rand 0.8.5", "serde", "sha2 0.9.9", "typenum", @@ -5680,6 +5973,26 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "linkme" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccb76662d78edc9f9bf56360d6919bdacc8b7761227727e5082f128eeb90bbf5" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dccda732e04fa3baf2e17cf835bfe2601c7c2edafd64417c627dabae3a8cda" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "linregress" version = "0.5.3" @@ -5951,6 +6264,18 @@ dependencies = [ "hash-db", ] +[[package]] +name = "merlin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.5.1", + "zeroize", +] + [[package]] name = "merlin" version = "3.0.0" @@ -5970,7 +6295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69672161530e8aeca1d1400fbf3f1a1747ff60ea604265a4e906c2442df20532" dependencies = [ "futures", - "rand", + "rand 0.8.5", "thrift", ] @@ -6017,7 +6342,7 @@ dependencies = [ "lioness", "log", "parking_lot 0.12.1", - "rand", + "rand 0.8.5", "rand_chacha 0.3.1", "rand_distr", "subtle 2.5.0", @@ -6040,9 +6365,9 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-beefy", - "sp-core", + "sp-core 29.0.0", "sp-mmr-primitives", - "sp-runtime", + "sp-runtime 32.0.0", ] [[package]] @@ -6056,9 +6381,9 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-mmr-primitives", - "sp-runtime", + "sp-runtime 32.0.0", ] [[package]] @@ -6189,7 +6514,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -6214,7 +6539,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -6270,7 +6595,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bddcd3bf5144b6392de80e04c347cd7fab2508f6df16a85fc496ecd5cec39bc" dependencies = [ - "rand", + "rand 0.8.5", ] [[package]] @@ -6598,11 +6923,11 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6617,8 +6942,8 @@ dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6632,9 +6957,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6650,10 +6975,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6668,9 +6993,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6685,10 +7010,10 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-consensus-aura", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6702,10 +7027,10 @@ dependencies = [ "pallet-session", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-authority-discovery", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6719,8 +7044,8 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6738,14 +7063,14 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-consensus-babe", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", "sp-session", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -6764,11 +7089,11 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-tracing", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-tracing 16.0.0", ] [[package]] @@ -6784,8 +7109,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6803,10 +7128,10 @@ dependencies = [ "scale-info", "serde", "sp-consensus-beefy", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -6828,11 +7153,11 @@ dependencies = [ "serde", "sp-api", "sp-consensus-beefy", - "sp-core", - "sp-io", - "sp-runtime", - "sp-state-machine", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-std 14.0.0", ] [[package]] @@ -6848,10 +7173,10 @@ dependencies = [ "pallet-treasury", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6871,9 +7196,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-consensus-grandpa", - "sp-runtime", - "sp-std", - "sp-trie", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", ] [[package]] @@ -6891,8 +7216,8 @@ dependencies = [ "num-traits", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6912,9 +7237,9 @@ dependencies = [ "pallet-bridge-grandpa", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", - "sp-trie", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", ] [[package]] @@ -6933,9 +7258,9 @@ dependencies = [ "pallet-bridge-messages", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-runtime", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6950,10 +7275,10 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-runtime", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6970,10 +7295,10 @@ dependencies = [ "pallet-treasury", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -6989,11 +7314,11 @@ dependencies = [ "pallet-authorship", "pallet-session", "parity-scale-codec", - "rand", + "rand 0.8.5", "scale-info", - "sp-runtime", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7008,10 +7333,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7031,16 +7356,16 @@ dependencies = [ "pallet-contracts-proc-macro", "pallet-contracts-uapi", "parity-scale-codec", - "rand", + "rand 0.8.5", "rand_pcg", "scale-info", "serde", "smallvec", "sp-api", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", "wasm-instrument", @@ -7071,6 +7396,17 @@ dependencies = [ "scale-info", ] +[[package]] +name = "pallet-contracts-uapi-next" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd549c16296ea5b2eb7c65c56aba548b286c1be4d7675b424ff6ccb8319c97a9" +dependencies = [ + "bitflags 1.3.2", + "paste", + "polkavm-derive", +] + [[package]] name = "pallet-conviction-voting" version = "29.0.0" @@ -7084,9 +7420,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7102,10 +7438,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7121,14 +7457,14 @@ dependencies = [ "log", "pallet-election-provider-support-benchmarking", "parity-scale-codec", - "rand", + "rand 0.8.5", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-io 31.0.0", "sp-npos-elections", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "strum 0.24.1", ] @@ -7143,8 +7479,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "sp-npos-elections", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7159,12 +7495,12 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", + "sp-core 29.0.0", + "sp-io 31.0.0", "sp-npos-elections", - "sp-runtime", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7181,10 +7517,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 31.0.0", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7201,14 +7537,14 @@ dependencies = [ "pallet-session", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-consensus-grandpa", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", "sp-session", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7224,9 +7560,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7242,12 +7578,12 @@ dependencies = [ "pallet-authorship", "parity-scale-codec", "scale-info", - "sp-application-crypto", - "sp-core", - "sp-io", - "sp-runtime", + "sp-application-crypto 31.0.0", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7261,11 +7597,11 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", + "sp-core 29.0.0", + "sp-io 31.0.0", "sp-keyring", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7280,10 +7616,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7299,12 +7635,12 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-weights", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-weights 28.0.0", ] [[package]] @@ -7319,11 +7655,11 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", + "sp-core 29.0.0", + "sp-io 31.0.0", "sp-mmr-primitives", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7338,9 +7674,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7357,8 +7693,8 @@ dependencies = [ "pallet-nfts", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7374,10 +7710,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7389,7 +7725,7 @@ dependencies = [ "pallet-nfts", "parity-scale-codec", "sp-api", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7403,10 +7739,10 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-runtime", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7421,12 +7757,12 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", - "sp-tracing", + "sp-std 14.0.0", + "sp-tracing 16.0.0", ] [[package]] @@ -7444,10 +7780,10 @@ dependencies = [ "pallet-staking", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-runtime-interface", + "sp-runtime 32.0.0", + "sp-runtime-interface 25.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7459,7 +7795,7 @@ dependencies = [ "pallet-nomination-pools", "parity-scale-codec", "sp-api", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7475,9 +7811,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-runtime", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7500,9 +7836,9 @@ dependencies = [ "pallet-staking", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7517,10 +7853,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7534,9 +7870,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7552,11 +7888,11 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7570,9 +7906,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7589,10 +7925,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-arithmetic", - "sp-io", - "sp-runtime", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7605,10 +7941,10 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7624,10 +7960,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", - "sp-std", - "sp-weights", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-weights 28.0.0", ] [[package]] @@ -7643,14 +7979,14 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", "sp-session", "sp-staking", - "sp-state-machine", - "sp-std", - "sp-trie", + "sp-state-machine 0.36.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", ] [[package]] @@ -7665,10 +8001,10 @@ dependencies = [ "pallet-session", "pallet-staking", "parity-scale-codec", - "rand", - "sp-runtime", + "rand 0.8.5", + "sp-runtime 32.0.0", "sp-session", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7684,10 +8020,10 @@ dependencies = [ "parity-scale-codec", "rand_chacha 0.2.2", "scale-info", - "sp-arithmetic", - "sp-io", - "sp-runtime", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7707,11 +8043,11 @@ dependencies = [ "rand_chacha 0.2.2", "scale-info", "serde", - "sp-application-crypto", - "sp-io", - "sp-runtime", + "sp-application-crypto 31.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -7733,7 +8069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "505d45e08bad052f55fb51f00a6b6244d23ee46ffdc8091f6cddf4e3a880319d" dependencies = [ "log", - "sp-arithmetic", + "sp-arithmetic 24.0.0", ] [[package]] @@ -7759,10 +8095,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7777,9 +8113,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7796,10 +8132,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-inherents", - "sp-io", - "sp-runtime", - "sp-std", - "sp-storage", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-storage 20.0.0", "sp-timestamp", ] @@ -7817,10 +8153,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7834,10 +8170,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7851,10 +8187,10 @@ dependencies = [ "parity-scale-codec", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-rpc", - "sp-runtime", - "sp-weights", + "sp-runtime 32.0.0", + "sp-weights 28.0.0", ] [[package]] @@ -7866,8 +8202,8 @@ dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "sp-api", - "sp-runtime", - "sp-weights", + "sp-runtime 32.0.0", + "sp-weights 28.0.0", ] [[package]] @@ -7885,9 +8221,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7902,8 +8238,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7917,10 +8253,10 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7935,8 +8271,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7951,8 +8287,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -7970,10 +8306,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -7991,9 +8327,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", - "sp-std", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -8012,9 +8348,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", ] @@ -8041,10 +8377,10 @@ dependencies = [ "polkadot-primitives", "scale-info", "sp-consensus-aura", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-parachain-info", "staging-xcm", "staging-xcm-executor", @@ -8071,11 +8407,11 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "sp-consensus-aura", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-tracing", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-tracing 16.0.0", "staging-parachain-info", "staging-xcm", "staging-xcm-executor", @@ -8103,7 +8439,7 @@ dependencies = [ "lz4", "memmap2 0.5.10", "parking_lot 0.12.1", - "rand", + "rand 0.8.5", "siphasher 0.3.11", "snap", "winapi", @@ -8168,7 +8504,7 @@ checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -8252,6 +8588,15 @@ dependencies = [ "crypto-mac 0.11.0", ] +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "pbkdf2" version = "0.12.2" @@ -8425,7 +8770,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", + "rand 0.8.5", "tracing-gum", ] @@ -8442,7 +8787,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", + "rand 0.8.5", "tracing-gum", ] @@ -8462,10 +8807,10 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", + "rand 0.8.5", "schnellru", - "sp-core", - "sp-keystore", + "sp-core 29.0.0", + "sp-keystore 0.35.0", "thiserror", "tracing-gum", ] @@ -8486,7 +8831,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", + "rand 0.8.5", "sc-network", "schnellru", "thiserror", @@ -8514,8 +8859,8 @@ dependencies = [ "sc-storage-monitor", "sc-sysinfo", "sc-tracing", - "sp-core", - "sp-io", + "sp-core 29.0.0", + "sp-io 31.0.0", "sp-keyring", "sp-maybe-compressed-blob", "substrate-build-script-utils", @@ -8538,9 +8883,9 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-core", - "sp-keystore", - "sp-runtime", + "sp-core 29.0.0", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "thiserror", "tokio-util", "tracing-gum", @@ -8554,9 +8899,9 @@ checksum = "b6a08e4e014c853b252ecbbe3ccd67b2d33d78e46988d309b8cccf4ac06e25ef" dependencies = [ "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -8579,8 +8924,8 @@ dependencies = [ "polkadot-primitives", "sc-network", "schnellru", - "sp-application-crypto", - "sp-keystore", + "sp-application-crypto 31.0.0", + "sp-keystore 0.35.0", "thiserror", "tracing-gum", ] @@ -8595,8 +8940,8 @@ dependencies = [ "polkadot-node-primitives", "polkadot-primitives", "reed-solomon-novelpoly", - "sp-core", - "sp-trie", + "sp-core 29.0.0", + "sp-trie 30.0.0", "thiserror", ] @@ -8612,14 +8957,14 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", + "rand 0.8.5", "rand_chacha 0.3.1", "sc-network", "sc-network-common", - "sp-application-crypto", - "sp-core", + "sp-application-crypto 31.0.0", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-keystore", + "sp-keystore 0.35.0", "tracing-gum", ] @@ -8660,7 +9005,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-core", + "sp-core 29.0.0", "sp-maybe-compressed-blob", "thiserror", "tracing-gum", @@ -8678,7 +9023,7 @@ dependencies = [ "futures-timer", "itertools 0.10.5", "kvdb", - "merlin", + "merlin 3.0.0", "parity-scale-codec", "polkadot-node-jaeger", "polkadot-node-primitives", @@ -8686,16 +9031,16 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", - "rand", + "rand 0.8.5", "rand_chacha 0.3.1", "rand_core 0.6.4", "sc-keystore", "schnellru", "schnorrkel 0.11.4", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-consensus", "sp-consensus-slots", - "sp-runtime", + "sp-runtime 32.0.0", "thiserror", "tracing-gum", ] @@ -8739,7 +9084,7 @@ dependencies = [ "polkadot-primitives", "polkadot-statement-table", "schnellru", - "sp-keystore", + "sp-keystore 0.35.0", "thiserror", "tracing-gum", ] @@ -8754,7 +9099,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-keystore", + "sp-keystore 0.35.0", "thiserror", "tracing-gum", "wasm-timer", @@ -8912,11 +9257,11 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-parachain-primitives", "polkadot-primitives", - "rand", + "rand 0.8.5", "slotmap", - "sp-core", + "sp-core 29.0.0", "sp-maybe-compressed-blob", - "sp-wasm-interface", + "sp-wasm-interface 20.0.0", "tempfile", "thiserror", "tokio", @@ -8935,7 +9280,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", - "sp-keystore", + "sp-keystore 0.35.0", "thiserror", "tracing-gum", ] @@ -8959,11 +9304,11 @@ dependencies = [ "sc-executor-common", "sc-executor-wasmtime", "seccompiler", - "sp-core", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-externalities", - "sp-io", - "sp-tracing", + "sp-externalities 0.26.0", + "sp-io 31.0.0", + "sp-tracing 16.0.0", "thiserror", "tracing-gum", ] @@ -8998,7 +9343,7 @@ dependencies = [ "polkadot-node-primitives", "polkadot-primitives", "sc-network", - "sp-core", + "sp-core 29.0.0", "thiserror", "tokio", ] @@ -9040,7 +9385,7 @@ dependencies = [ "polkadot-node-jaeger", "polkadot-node-primitives", "polkadot-primitives", - "rand", + "rand 0.8.5", "sc-authority-discovery", "sc-network", "strum 0.24.1", @@ -9062,12 +9407,12 @@ dependencies = [ "polkadot-primitives", "schnorrkel 0.11.4", "serde", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-consensus-babe", - "sp-core", - "sp-keystore", + "sp-core 29.0.0", + "sp-keystore 0.35.0", "sp-maybe-compressed-blob", - "sp-runtime", + "sp-runtime 32.0.0", "thiserror", "zstd 0.12.4", ] @@ -9107,7 +9452,7 @@ dependencies = [ "sp-authority-discovery", "sp-blockchain", "sp-consensus-babe", - "sp-runtime", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "thiserror", ] @@ -9138,12 +9483,12 @@ dependencies = [ "polkadot-overseer", "polkadot-primitives", "prioritized-metered-channel", - "rand", + "rand 0.8.5", "sc-client-api", "schnellru", - "sp-application-crypto", - "sp-core", - "sp-keystore", + "sp-application-crypto 31.0.0", + "sp-core 29.0.0", + "sp-keystore 0.35.0", "thiserror", "tracing-gum", ] @@ -9166,7 +9511,7 @@ dependencies = [ "polkadot-primitives", "sc-client-api", "sp-api", - "sp-core", + "sp-core 29.0.0", "tikv-jemalloc-ctl", "tracing-gum", ] @@ -9183,10 +9528,10 @@ dependencies = [ "polkadot-core-primitives", "scale-info", "serde", - "sp-core", - "sp-runtime", - "sp-std", - "sp-weights", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-weights 28.0.0", ] [[package]] @@ -9204,17 +9549,17 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-arithmetic", + "sp-application-crypto 31.0.0", + "sp-arithmetic 24.0.0", "sp-authority-discovery", "sp-consensus-slots", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-io", - "sp-keystore", - "sp-runtime", + "sp-io 31.0.0", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -9245,8 +9590,8 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "substrate-frame-rpc-system", "substrate-state-trie-migration-rpc", ] @@ -9289,14 +9634,14 @@ dependencies = [ "serde_derive", "slot-range-helper", "sp-api", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-io", + "sp-io 31.0.0", "sp-npos-elections", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", "sp-staking", - "sp-std", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -9313,8 +9658,8 @@ dependencies = [ "frame-benchmarking", "parity-scale-codec", "polkadot-primitives", - "sp-std", - "sp-tracing", + "sp-std 14.0.0", + "sp-tracing 16.0.0", ] [[package]] @@ -9346,22 +9691,22 @@ dependencies = [ "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-metrics", - "rand", + "rand 0.8.5", "rand_chacha 0.3.1", "rustc-hex", "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-arithmetic", - "sp-core", + "sp-application-crypto 31.0.0", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", "sp-inherents", - "sp-io", - "sp-keystore", - "sp-runtime", + "sp-io 31.0.0", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "sp-session", "sp-staking", - "sp-std", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-executor", "static_assertions", @@ -9464,21 +9809,21 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-io", + "sp-io 31.0.0", "sp-keyring", - "sp-keystore", + "sp-keystore 0.35.0", "sp-mmr-primitives", "sp-offchain", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", - "sp-state-machine", - "sp-storage", + "sp-state-machine 0.36.0", + "sp-storage 20.0.0", "sp-timestamp", "sp-transaction-pool", "sp-version", - "sp-weights", + "sp-weights 28.0.0", "substrate-prometheus-endpoint", "thiserror", "tracing-gum", @@ -9503,7 +9848,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-keystore", + "sp-keystore 0.35.0", "sp-staking", "thiserror", "tracing-gum", @@ -9517,7 +9862,7 @@ checksum = "de5e010da3c6a65d8f263d0f825a04d995ffc8a37f886f674fcbbc73bf158d01" dependencies = [ "parity-scale-codec", "polkadot-primitives", - "sp-core", + "sp-core 29.0.0", "tracing-gum", ] @@ -9603,6 +9948,19 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "pop-api" +version = "0.0.0" +dependencies = [ + "enumflags2", + "ink", + "parity-scale-codec", + "pop-primitives", + "scale-info", + "sp-io 23.0.0", + "sp-runtime 24.0.0", +] + [[package]] name = "pop-node" version = "0.1.0-alpha" @@ -9653,11 +10011,11 @@ dependencies = [ "sp-block-builder", "sp-blockchain", "sp-consensus-aura", - "sp-core", - "sp-io", - "sp-keystore", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-keystore 0.35.0", "sp-offchain", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", "sp-timestamp", "sp-transaction-pool", @@ -9687,8 +10045,8 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -9740,6 +10098,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-runtime-common", + "pop-api", "pop-primitives", "pop-runtime-common", "scale-info", @@ -9747,14 +10106,14 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-consensus-aura", - "sp-core", + "sp-core 29.0.0", "sp-genesis-builder", "sp-inherents", - "sp-io", + "sp-io 31.0.0", "sp-offchain", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", - "sp-std", + "sp-std 14.0.0", "sp-transaction-pool", "sp-version", "staging-parachain-info", @@ -9820,14 +10179,14 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-consensus-aura", - "sp-core", + "sp-core 29.0.0", "sp-genesis-builder", "sp-inherents", - "sp-io", + "sp-io 31.0.0", "sp-offchain", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", - "sp-std", + "sp-std 14.0.0", "sp-transaction-pool", "sp-version", "staging-parachain-info", @@ -10187,7 +10546,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" dependencies = [ "bytes", - "rand", + "rand 0.8.5", "ring 0.16.20", "rustc-hash", "rustls 0.20.9", @@ -10215,7 +10574,20 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.5" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ @@ -10269,7 +10641,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -10495,6 +10876,12 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + [[package]] name = "rlp" version = "0.5.2" @@ -10587,22 +10974,22 @@ dependencies = [ "serde_derive", "smallvec", "sp-api", - "sp-arithmetic", + "sp-arithmetic 24.0.0", "sp-authority-discovery", "sp-block-builder", "sp-consensus-babe", "sp-consensus-beefy", - "sp-core", + "sp-core 29.0.0", "sp-genesis-builder", "sp-inherents", - "sp-io", + "sp-io 31.0.0", "sp-mmr-primitives", "sp-offchain", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", "sp-staking", - "sp-std", - "sp-storage", + "sp-std 14.0.0", + "sp-storage 20.0.0", "sp-transaction-pool", "sp-version", "staging-xcm", @@ -10622,9 +11009,9 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "smallvec", - "sp-core", - "sp-runtime", - "sp-weights", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-weights 28.0.0", "staging-xcm", "staging-xcm-builder", ] @@ -10927,8 +11314,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357127c91373ed6d1ae582f6e3300ab5b13bcde43bbf270a891f44194ef48b70" dependencies = [ "log", - "sp-core", - "sp-wasm-interface", + "sp-core 29.0.0", + "sp-wasm-interface 20.0.0", "thiserror", ] @@ -10949,15 +11336,15 @@ dependencies = [ "parity-scale-codec", "prost 0.12.3", "prost-build", - "rand", + "rand 0.8.5", "sc-client-api", "sc-network", "sp-api", "sp-authority-discovery", "sp-blockchain", - "sp-core", - "sp-keystore", - "sp-runtime", + "sp-core 29.0.0", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "thiserror", ] @@ -10979,9 +11366,9 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-runtime", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", ] @@ -10995,10 +11382,10 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-runtime", - "sp-trie", + "sp-runtime 32.0.0", + "sp-trie 30.0.0", ] [[package]] @@ -11020,12 +11407,12 @@ dependencies = [ "serde", "serde_json", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-crypto-hashing", "sp-genesis-builder", - "sp-io", - "sp-runtime", - "sp-state-machine", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", ] [[package]] @@ -11057,7 +11444,7 @@ dependencies = [ "log", "names", "parity-scale-codec", - "rand", + "rand 0.8.5", "regex", "rpassword", "sc-client-api", @@ -11072,11 +11459,11 @@ dependencies = [ "serde", "serde_json", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-keyring", - "sp-keystore", - "sp-panic-handler", - "sp-runtime", + "sp-keystore 0.35.0", + "sp-panic-handler 13.0.0", + "sp-runtime 32.0.0", "sp-version", "thiserror", "tokio", @@ -11099,14 +11486,14 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", + "sp-core 29.0.0", "sp-database", - "sp-externalities", - "sp-runtime", - "sp-state-machine", + "sp-externalities 0.26.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", "sp-statement-store", - "sp-storage", - "sp-trie", + "sp-storage 20.0.0", + "sp-trie 30.0.0", "substrate-prometheus-endpoint", ] @@ -11128,13 +11515,13 @@ dependencies = [ "sc-client-api", "sc-state-db", "schnellru", - "sp-arithmetic", + "sp-arithmetic 24.0.0", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-database", - "sp-runtime", - "sp-state-machine", - "sp-trie", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-trie 30.0.0", ] [[package]] @@ -11156,9 +11543,9 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", - "sp-runtime", - "sp-state-machine", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", "substrate-prometheus-endpoint", "thiserror", ] @@ -11179,16 +11566,16 @@ dependencies = [ "sc-consensus-slots", "sc-telemetry", "sp-api", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-aura", "sp-consensus-slots", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "thiserror", ] @@ -11215,17 +11602,17 @@ dependencies = [ "sc-telemetry", "sc-transaction-pool-api", "sp-api", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", "sp-consensus-slots", - "sp-core", + "sp-core 29.0.0", "sp-crypto-hashing", "sp-inherents", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "thiserror", ] @@ -11243,13 +11630,13 @@ dependencies = [ "sc-rpc-api", "serde", "sp-api", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-core", - "sp-keystore", - "sp-runtime", + "sp-core 29.0.0", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "thiserror", ] @@ -11274,16 +11661,16 @@ dependencies = [ "sc-network-sync", "sc-utils", "sp-api", - "sp-application-crypto", - "sp-arithmetic", + "sp-application-crypto 31.0.0", + "sp-arithmetic 24.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-beefy", - "sp-core", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-keystore", + "sp-keystore 0.35.0", "sp-mmr-primitives", - "sp-runtime", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "thiserror", "tokio", @@ -11305,8 +11692,8 @@ dependencies = [ "sc-rpc", "serde", "sp-consensus-beefy", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "thiserror", ] @@ -11321,7 +11708,7 @@ dependencies = [ "sc-client-api", "sc-consensus", "sp-blockchain", - "sp-runtime", + "sp-runtime 32.0.0", ] [[package]] @@ -11341,7 +11728,7 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot 0.12.1", - "rand", + "rand 0.8.5", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -11355,15 +11742,15 @@ dependencies = [ "sc-utils", "serde_json", "sp-api", - "sp-application-crypto", - "sp-arithmetic", + "sp-application-crypto 31.0.0", + "sp-arithmetic 24.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-grandpa", - "sp-core", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "thiserror", ] @@ -11384,8 +11771,8 @@ dependencies = [ "sc-rpc", "serde", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "thiserror", ] @@ -11403,14 +11790,14 @@ dependencies = [ "sc-client-api", "sc-consensus", "sc-telemetry", - "sp-arithmetic", + "sp-arithmetic 24.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-slots", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-runtime", - "sp-state-machine", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", ] [[package]] @@ -11425,14 +11812,14 @@ dependencies = [ "sc-executor-wasmtime", "schnellru", "sp-api", - "sp-core", - "sp-externalities", - "sp-io", - "sp-panic-handler", - "sp-runtime-interface", - "sp-trie", + "sp-core 29.0.0", + "sp-externalities 0.26.0", + "sp-io 31.0.0", + "sp-panic-handler 13.0.0", + "sp-runtime-interface 25.0.0", + "sp-trie 30.0.0", "sp-version", - "sp-wasm-interface", + "sp-wasm-interface 20.0.0", "tracing", ] @@ -11444,7 +11831,7 @@ checksum = "07498138dee3ddf2c71299ca372d8449880bb3a8a8a299a483094e9c26b0823e" dependencies = [ "sc-allocator", "sp-maybe-compressed-blob", - "sp-wasm-interface", + "sp-wasm-interface 20.0.0", "thiserror", "wasm-instrument", ] @@ -11463,8 +11850,8 @@ dependencies = [ "rustix 0.36.17", "sc-allocator", "sc-executor-common", - "sp-runtime-interface", - "sp-wasm-interface", + "sp-runtime-interface 25.0.0", + "sp-wasm-interface 20.0.0", "wasmtime", ] @@ -11483,7 +11870,7 @@ dependencies = [ "sc-network-common", "sc-network-sync", "sp-blockchain", - "sp-runtime", + "sp-runtime 32.0.0", ] [[package]] @@ -11495,9 +11882,9 @@ dependencies = [ "array-bytes 6.2.2", "parking_lot 0.12.1", "serde_json", - "sp-application-crypto", - "sp-core", - "sp-keystore", + "sp-application-crypto 31.0.0", + "sp-core 29.0.0", + "sp-keystore 0.35.0", "thiserror", ] @@ -11524,10 +11911,10 @@ dependencies = [ "sc-transaction-pool-api", "sp-api", "sp-consensus", - "sp-core", - "sp-keystore", + "sp-core 29.0.0", + "sp-keystore 0.35.0", "sp-mixnet", - "sp-runtime", + "sp-runtime 32.0.0", "thiserror", ] @@ -11555,17 +11942,17 @@ dependencies = [ "parking_lot 0.12.1", "partial_sort", "pin-project", - "rand", + "rand 0.8.5", "sc-client-api", "sc-network-common", "sc-utils", "serde", "serde_json", "smallvec", - "sp-arithmetic", + "sp-arithmetic 24.0.0", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "thiserror", "tokio", @@ -11591,7 +11978,7 @@ dependencies = [ "sc-client-api", "sc-network", "sp-blockchain", - "sp-runtime", + "sp-runtime 32.0.0", "thiserror", "unsigned-varint", ] @@ -11611,7 +11998,7 @@ dependencies = [ "sc-consensus", "sp-consensus", "sp-consensus-grandpa", - "sp-runtime", + "sp-runtime 32.0.0", ] [[package]] @@ -11629,7 +12016,7 @@ dependencies = [ "sc-network-common", "sc-network-sync", "schnellru", - "sp-runtime", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "tracing", ] @@ -11651,8 +12038,8 @@ dependencies = [ "sc-client-api", "sc-network", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "thiserror", ] @@ -11681,12 +12068,12 @@ dependencies = [ "sc-utils", "schnellru", "smallvec", - "sp-arithmetic", + "sp-arithmetic 24.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-grandpa", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", "thiserror", "tokio", @@ -11709,7 +12096,7 @@ dependencies = [ "sc-network-sync", "sc-utils", "sp-consensus", - "sp-runtime", + "sp-runtime 32.0.0", "substrate-prometheus-endpoint", ] @@ -11732,18 +12119,18 @@ dependencies = [ "once_cell", "parity-scale-codec", "parking_lot 0.12.1", - "rand", + "rand 0.8.5", "sc-client-api", "sc-network", "sc-network-common", "sc-transaction-pool-api", "sc-utils", "sp-api", - "sp-core", - "sp-externalities", - "sp-keystore", + "sp-core 29.0.0", + "sp-externalities 0.26.0", + "sp-keystore 0.35.0", "sp-offchain", - "sp-runtime", + "sp-runtime 32.0.0", "threadpool", "tracing", ] @@ -11780,11 +12167,11 @@ dependencies = [ "serde_json", "sp-api", "sp-blockchain", - "sp-core", - "sp-keystore", + "sp-core 29.0.0", + "sp-keystore 0.35.0", "sp-offchain", "sp-rpc", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", "sp-statement-store", "sp-version", @@ -11805,9 +12192,9 @@ dependencies = [ "scale-info", "serde", "serde_json", - "sp-core", + "sp-core 29.0.0", "sp-rpc", - "sp-runtime", + "sp-runtime 32.0.0", "sp-version", "thiserror", ] @@ -11850,9 +12237,9 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-rpc", - "sp-runtime", + "sp-runtime 32.0.0", "sp-version", "thiserror", "tokio", @@ -11875,7 +12262,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.1", "pin-project", - "rand", + "rand 0.8.5", "sc-chain-spec", "sc-client-api", "sc-client-db", @@ -11903,16 +12290,16 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", - "sp-externalities", - "sp-keystore", - "sp-runtime", + "sp-core 29.0.0", + "sp-externalities 0.26.0", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "sp-session", - "sp-state-machine", - "sp-storage", + "sp-state-machine 0.36.0", + "sp-storage 20.0.0", "sp-transaction-pool", "sp-transaction-storage-proof", - "sp-trie", + "sp-trie 30.0.0", "sp-version", "static_init", "substrate-prometheus-endpoint", @@ -11932,7 +12319,7 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot 0.12.1", - "sp-core", + "sp-core 29.0.0", ] [[package]] @@ -11944,7 +12331,7 @@ dependencies = [ "clap", "fs4", "log", - "sp-core", + "sp-core 29.0.0", "thiserror", "tokio", ] @@ -11965,7 +12352,7 @@ dependencies = [ "serde", "serde_json", "sp-blockchain", - "sp-runtime", + "sp-runtime 32.0.0", "thiserror", ] @@ -11979,16 +12366,16 @@ dependencies = [ "futures", "libc", "log", - "rand", + "rand 0.8.5", "rand_pcg", "regex", "sc-telemetry", "serde", "serde_json", - "sp-core", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-io", - "sp-std", + "sp-io 31.0.0", + "sp-std 14.0.0", ] [[package]] @@ -12003,7 +12390,7 @@ dependencies = [ "log", "parking_lot 0.12.1", "pin-project", - "rand", + "rand 0.8.5", "sc-utils", "serde", "serde_json", @@ -12032,10 +12419,10 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-rpc", - "sp-runtime", - "sp-tracing", + "sp-runtime 32.0.0", + "sp-tracing 16.0.0", "thiserror", "tracing", "tracing-log 0.1.4", @@ -12073,10 +12460,10 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-runtime", - "sp-tracing", + "sp-runtime 32.0.0", + "sp-tracing 16.0.0", "sp-transaction-pool", "substrate-prometheus-endpoint", "thiserror", @@ -12094,8 +12481,8 @@ dependencies = [ "parity-scale-codec", "serde", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "thiserror", ] @@ -12112,7 +12499,7 @@ dependencies = [ "log", "parking_lot 0.12.1", "prometheus", - "sp-arithmetic", + "sp-arithmetic 24.0.0", ] [[package]] @@ -12193,6 +12580,7 @@ dependencies = [ "derive_more", "parity-scale-codec", "scale-info-derive", + "schemars", "serde", ] @@ -12250,6 +12638,30 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.58", +] + [[package]] name = "schnellru" version = "0.2.1" @@ -12261,6 +12673,24 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "schnorrkel" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "curve25519-dalek 2.1.3", + "getrandom 0.1.16", + "merlin 2.0.1", + "rand 0.7.3", + "rand_core 0.5.1", + "sha2 0.8.2", + "subtle 2.5.0", + "zeroize", +] + [[package]] name = "schnorrkel" version = "0.10.2" @@ -12270,7 +12700,7 @@ dependencies = [ "arrayref", "arrayvec 0.7.4", "curve25519-dalek-ng", - "merlin", + "merlin 3.0.0", "rand_core 0.6.4", "sha2 0.9.9", "subtle-ng", @@ -12288,7 +12718,7 @@ dependencies = [ "arrayvec 0.7.4", "curve25519-dalek 4.1.2", "getrandom_or_panic", - "merlin", + "merlin 3.0.0", "rand_core 0.6.4", "serde_bytes", "sha2 0.10.8", @@ -12341,13 +12771,31 @@ dependencies = [ "libc", ] +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "secp256k1-sys 0.6.1", +] + [[package]] name = "secp256k1" version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ - "secp256k1-sys", + "secp256k1-sys 0.9.2", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", ] [[package]] @@ -12453,6 +12901,17 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "serde_json" version = "1.0.115" @@ -12497,6 +12956,18 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha2" version = "0.9.9" @@ -12555,6 +13026,12 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + [[package]] name = "signature" version = "2.2.0" @@ -12620,8 +13097,8 @@ dependencies = [ "enumn", "parity-scale-codec", "paste", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -12700,7 +13177,7 @@ dependencies = [ "hmac 0.12.1", "itertools 0.11.0", "libsecp256k1", - "merlin", + "merlin 3.0.0", "no-std-net", "nom", "num-bigint", @@ -12709,7 +13186,7 @@ dependencies = [ "pbkdf2 0.12.2", "pin-project", "poly1305", - "rand", + "rand 0.8.5", "rand_chacha 0.3.1", "ruzstd 0.4.0", "schnorrkel 0.10.2", @@ -12755,7 +13232,7 @@ dependencies = [ "itertools 0.12.1", "libm", "libsecp256k1", - "merlin", + "merlin 3.0.0", "no-std-net", "nom", "num-bigint", @@ -12764,7 +13241,7 @@ dependencies = [ "pbkdf2 0.12.2", "pin-project", "poly1305", - "rand", + "rand 0.8.5", "rand_chacha 0.3.1", "ruzstd 0.5.0", "schnorrkel 0.11.4", @@ -12807,7 +13284,7 @@ dependencies = [ "no-std-net", "parking_lot 0.12.1", "pin-project", - "rand", + "rand 0.8.5", "rand_chacha 0.3.1", "serde", "serde_json", @@ -12843,7 +13320,7 @@ dependencies = [ "no-std-net", "parking_lot 0.12.1", "pin-project", - "rand", + "rand 0.8.5", "rand_chacha 0.3.1", "serde", "serde_json", @@ -12903,10 +13380,10 @@ dependencies = [ "serde", "snowbridge-ethereum", "snowbridge-milagro-bls", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "ssz_rs", "ssz_rs_derive", "static_assertions", @@ -12927,11 +13404,11 @@ dependencies = [ "scale-info", "serde", "snowbridge-beacon-primitives", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", ] @@ -12953,10 +13430,10 @@ dependencies = [ "scale-info", "serde", "serde-big-array", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -12968,7 +13445,7 @@ dependencies = [ "hex", "lazy_static", "parity-scale-codec", - "rand", + "rand 0.8.5", "scale-info", "snowbridge-amcl", "zeroize", @@ -12989,10 +13466,10 @@ dependencies = [ "scale-info", "serde", "snowbridge-core", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -13031,7 +13508,7 @@ dependencies = [ "http", "httparse", "log", - "rand", + "rand 0.8.5", "sha-1", ] @@ -13046,13 +13523,13 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api-proc-macro", - "sp-core", - "sp-externalities", + "sp-core 29.0.0", + "sp-externalities 0.26.0", "sp-metadata-ir", - "sp-runtime", - "sp-state-machine", - "sp-std", - "sp-trie", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", "sp-version", "thiserror", ] @@ -13072,6 +13549,20 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "sp-application-crypto" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899492ea547816d5dfe9a5a2ecc32f65a7110805af6da3380aa4902371b31dc2" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 21.0.0", + "sp-io 23.0.0", + "sp-std 8.0.0", +] + [[package]] name = "sp-application-crypto" version = "31.0.0" @@ -13081,9 +13572,24 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-std", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-std 14.0.0", +] + +[[package]] +name = "sp-arithmetic" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6020576e544c6824a51d651bc8df8e6ab67cd59f1c9ac09868bb81a5199ded" +dependencies = [ + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std 8.0.0", + "static_assertions", ] [[package]] @@ -13097,7 +13603,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std", + "sp-std 14.0.0", "static_assertions", ] @@ -13110,9 +13616,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-application-crypto", - "sp-runtime", - "sp-std", + "sp-application-crypto 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -13123,8 +13629,8 @@ checksum = "1b36ce171caa7eb2bbe682c089f755fdefa71d3702e4fb1ba30d10146aef99d5" dependencies = [ "sp-api", "sp-inherents", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -13141,8 +13647,8 @@ dependencies = [ "sp-api", "sp-consensus", "sp-database", - "sp-runtime", - "sp-state-machine", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", "thiserror", ] @@ -13155,10 +13661,10 @@ dependencies = [ "async-trait", "futures", "log", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-runtime", - "sp-state-machine", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", "thiserror", ] @@ -13172,11 +13678,11 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-consensus-slots", "sp-inherents", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "sp-timestamp", ] @@ -13191,12 +13697,12 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", + "sp-application-crypto 31.0.0", "sp-consensus-slots", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "sp-timestamp", ] @@ -13211,13 +13717,13 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-core", + "sp-application-crypto 31.0.0", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-io", + "sp-io 31.0.0", "sp-mmr-primitives", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "strum 0.24.1", ] @@ -13233,11 +13739,11 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-core", - "sp-keystore", - "sp-runtime", - "sp-std", + "sp-application-crypto 31.0.0", + "sp-core 29.0.0", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -13249,10 +13755,55 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std", + "sp-std 14.0.0", "sp-timestamp", ] +[[package]] +name = "sp-core" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f18d9e2f67d8661f9729f35347069ac29d92758b59135176799db966947a7336" +dependencies = [ + "array-bytes 4.2.0", + "bitflags 1.3.2", + "blake2 0.10.6", + "bounded-collections 0.1.9", + "bs58 0.4.0", + "dyn-clonable", + "ed25519-zebra 3.1.0", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "lazy_static", + "libsecp256k1", + "log", + "merlin 2.0.1", + "parity-scale-codec", + "parking_lot 0.12.1", + "paste", + "primitive-types", + "rand 0.8.5", + "regex", + "scale-info", + "schnorrkel 0.9.1", + "secp256k1 0.24.3", + "secrecy", + "serde", + "sp-core-hashing 9.0.0", + "sp-debug-derive 8.0.0", + "sp-externalities 0.19.0", + "sp-runtime-interface 17.0.0", + "sp-std 8.0.0", + "sp-storage 13.0.0", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tiny-bip39", + "zeroize", +] + [[package]] name = "sp-core" version = "29.0.0" @@ -13274,23 +13825,23 @@ dependencies = [ "itertools 0.10.5", "libsecp256k1", "log", - "merlin", + "merlin 3.0.0", "parity-scale-codec", "parking_lot 0.12.1", "paste", "primitive-types", - "rand", + "rand 0.8.5", "scale-info", "schnorrkel 0.11.4", - "secp256k1", + "secp256k1 0.28.2", "secrecy", "serde", "sp-crypto-hashing", - "sp-debug-derive", - "sp-externalities", - "sp-runtime-interface", - "sp-std", - "sp-storage", + "sp-debug-derive 14.0.0", + "sp-externalities 0.26.0", + "sp-runtime-interface 25.0.0", + "sp-std 14.0.0", + "sp-storage 20.0.0", "ss58-registry", "substrate-bip39", "thiserror", @@ -13299,6 +13850,21 @@ dependencies = [ "zeroize", ] +[[package]] +name = "sp-core-hashing" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee599a8399448e65197f9a6cee338ad192e9023e35e31f22382964c3c174c68" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "sp-std 8.0.0", + "twox-hash", +] + [[package]] name = "sp-core-hashing" version = "15.0.0" @@ -13348,6 +13914,17 @@ dependencies = [ "parking_lot 0.12.1", ] +[[package]] +name = "sp-debug-derive" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f531814d2f16995144c74428830ccf7d94ff4a7749632b83ad8199b181140c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "sp-debug-derive" version = "14.0.0" @@ -13359,6 +13936,18 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "sp-externalities" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0f71c671e01a8ca60da925d43a1b351b69626e268b8837f8371e320cf1dd100" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-std 8.0.0", + "sp-storage 13.0.0", +] + [[package]] name = "sp-externalities" version = "0.26.0" @@ -13367,8 +13956,8 @@ checksum = "e7096ed024cec397804864898b093b51e14c7299f1d00c67dd5800330e02bb82" dependencies = [ "environmental", "parity-scale-codec", - "sp-std", - "sp-storage", + "sp-std 14.0.0", + "sp-storage 20.0.0", ] [[package]] @@ -13379,8 +13968,8 @@ checksum = "fd865540ec19479c7349b584ccd78cc34c3f3a628a2a69dbb6365ceec36295ee" dependencies = [ "serde_json", "sp-api", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -13393,11 +13982,38 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "thiserror", ] +[[package]] +name = "sp-io" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d597e35a9628fe7454b08965b2442e3ec0f264b0a90d41328e87422cec02e99" +dependencies = [ + "bytes", + "ed25519 1.5.3", + "ed25519-dalek 1.0.1", + "futures", + "libsecp256k1", + "log", + "parity-scale-codec", + "rustversion", + "secp256k1 0.24.3", + "sp-core 21.0.0", + "sp-externalities 0.19.0", + "sp-keystore 0.27.0", + "sp-runtime-interface 17.0.0", + "sp-state-machine 0.28.0", + "sp-std 8.0.0", + "sp-tracing 10.0.0", + "sp-trie 22.0.0", + "tracing", + "tracing-core", +] + [[package]] name = "sp-io" version = "31.0.0" @@ -13405,21 +14021,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec43aa073eab35fcb920d7592474d5427ea3be2bf938706a3ad955d7ba54fd8d" dependencies = [ "bytes", - "ed25519-dalek", + "ed25519-dalek 2.1.1", "libsecp256k1", "log", "parity-scale-codec", "rustversion", - "secp256k1", - "sp-core", + "secp256k1 0.28.2", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-externalities", - "sp-keystore", - "sp-runtime-interface", - "sp-state-machine", - "sp-std", - "sp-tracing", - "sp-trie", + "sp-externalities 0.26.0", + "sp-keystore 0.35.0", + "sp-runtime-interface 25.0.0", + "sp-state-machine 0.36.0", + "sp-std 14.0.0", + "sp-tracing 16.0.0", + "sp-trie 30.0.0", "tracing", "tracing-core", ] @@ -13430,11 +14046,25 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cf0a2f881958466fc92bc9b39bbc2c0d815ded4a21f8f953372b0ac2e11b02" dependencies = [ - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", "strum 0.24.1", ] +[[package]] +name = "sp-keystore" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be3cdd67cc1d9c1db17c5cbc4ec4924054a8437009d167f21f6590797e4aa45" +dependencies = [ + "futures", + "parity-scale-codec", + "parking_lot 0.12.1", + "sp-core 21.0.0", + "sp-externalities 0.19.0", + "thiserror", +] + [[package]] name = "sp-keystore" version = "0.35.0" @@ -13443,8 +14073,8 @@ checksum = "444f2d53968b1ce5e908882710ff1f3873fcf3e95f59d57432daf685bbacb959" dependencies = [ "parity-scale-codec", "parking_lot 0.12.1", - "sp-core", - "sp-externalities", + "sp-core 29.0.0", + "sp-externalities 0.26.0", "thiserror", ] @@ -13467,7 +14097,7 @@ dependencies = [ "frame-metadata 16.0.0", "parity-scale-codec", "scale-info", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -13479,8 +14109,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-application-crypto", - "sp-std", + "sp-application-crypto 31.0.0", + "sp-std 14.0.0", ] [[package]] @@ -13495,10 +14125,10 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-core", - "sp-debug-derive", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-debug-derive 14.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "thiserror", ] @@ -13511,10 +14141,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-arithmetic", - "sp-core", - "sp-runtime", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -13524,8 +14154,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d83b955dce0b6d143bec3f60571311168f362b1c16cf044da7037a407b66c19" dependencies = [ "sp-api", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", +] + +[[package]] +name = "sp-panic-handler" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd2de46003fa8212426838ca71cd42ee36a26480ba9ffea983506ce03131033" +dependencies = [ + "backtrace", + "lazy_static", + "regex", ] [[package]] @@ -13547,7 +14188,30 @@ checksum = "9af4b73fe7ddd88b1641cca90048c4e525e721763199e6fd29c4f590884f4d16" dependencies = [ "rustc-hash", "serde", - "sp-core", + "sp-core 29.0.0", +] + +[[package]] +name = "sp-runtime" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21c5bfc764a1a8259d7e8f7cfd22c84006275a512c958d3ff966c92151e134d5" +dependencies = [ + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "scale-info", + "serde", + "sp-application-crypto 23.0.0", + "sp-arithmetic 16.0.0", + "sp-core 21.0.0", + "sp-io 23.0.0", + "sp-std 8.0.0", + "sp-weights 20.0.0", ] [[package]] @@ -13563,16 +14227,35 @@ dependencies = [ "log", "parity-scale-codec", "paste", - "rand", + "rand 0.8.5", "scale-info", "serde", "simple-mermaid", - "sp-application-crypto", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-std", - "sp-weights", + "sp-application-crypto 31.0.0", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-std 14.0.0", + "sp-weights 28.0.0", +] + +[[package]] +name = "sp-runtime-interface" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e676128182f90015e916f806cba635c8141e341e7abbc45d25525472e1bbce8" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities 0.19.0", + "sp-runtime-interface-proc-macro 11.0.0", + "sp-std 8.0.0", + "sp-storage 13.0.0", + "sp-tracing 10.0.0", + "sp-wasm-interface 14.0.0", + "static_assertions", ] [[package]] @@ -13585,15 +14268,28 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "primitive-types", - "sp-externalities", - "sp-runtime-interface-proc-macro", - "sp-std", - "sp-storage", - "sp-tracing", - "sp-wasm-interface", + "sp-externalities 0.26.0", + "sp-runtime-interface-proc-macro 17.0.0", + "sp-std 14.0.0", + "sp-storage 20.0.0", + "sp-tracing 16.0.0", + "sp-wasm-interface 20.0.0", "static_assertions", ] +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d5bd5566fe5633ec48dfa35ab152fd29f8a577c21971e1c6db9f28afb9bbb9" +dependencies = [ + "Inflector", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" @@ -13617,11 +14313,11 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-core", - "sp-keystore", - "sp-runtime", + "sp-core 29.0.0", + "sp-keystore 0.35.0", + "sp-runtime 32.0.0", "sp-staking", - "sp-std", + "sp-std 14.0.0", ] [[package]] @@ -13634,9 +14330,30 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-runtime", - "sp-std", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", +] + +[[package]] +name = "sp-state-machine" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ef45d31f9e7ac648f8899a0cd038a3608f8499028bff55b6c799702592325b6" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "rand 0.8.5", + "smallvec", + "sp-core 21.0.0", + "sp-externalities 0.19.0", + "sp-panic-handler 8.0.0", + "sp-std 8.0.0", + "sp-trie 22.0.0", + "thiserror", + "tracing", ] [[package]] @@ -13649,16 +14366,16 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot 0.12.1", - "rand", + "rand 0.8.5", "smallvec", - "sp-core", - "sp-externalities", - "sp-panic-handler", - "sp-std", - "sp-trie", + "sp-core 29.0.0", + "sp-externalities 0.26.0", + "sp-panic-handler 13.0.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", "thiserror", "tracing", - "trie-db", + "trie-db 0.28.0", ] [[package]] @@ -13669,30 +14386,50 @@ checksum = "309a9ae4e8134bbed8ffc510cf4d461a4a651f9250b556de782cedd876abe1ff" dependencies = [ "aes-gcm", "curve25519-dalek 4.1.2", - "ed25519-dalek", + "ed25519-dalek 2.1.1", "hkdf", "parity-scale-codec", - "rand", + "rand 0.8.5", "scale-info", "sha2 0.10.8", "sp-api", - "sp-application-crypto", - "sp-core", + "sp-application-crypto 31.0.0", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-externalities", - "sp-runtime", - "sp-runtime-interface", - "sp-std", + "sp-externalities 0.26.0", + "sp-runtime 32.0.0", + "sp-runtime-interface 25.0.0", + "sp-std 14.0.0", "thiserror", "x25519-dalek 2.0.1", ] +[[package]] +name = "sp-std" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53458e3c57df53698b3401ec0934bea8e8cfce034816873c0b0abbd83d7bac0d" + [[package]] name = "sp-std" version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" +[[package]] +name = "sp-storage" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94294be83f11d4958cfea89ed5798f0b6605f5defc3a996948848458abbcc18e" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive 8.0.0", + "sp-std 8.0.0", +] + [[package]] name = "sp-storage" version = "20.0.0" @@ -13703,8 +14440,8 @@ dependencies = [ "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive", - "sp-std", + "sp-debug-derive 14.0.0", + "sp-std 14.0.0", ] [[package]] @@ -13716,11 +14453,24 @@ dependencies = [ "async-trait", "parity-scale-codec", "sp-inherents", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "thiserror", ] +[[package]] +name = "sp-tracing" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357f7591980dd58305956d32f8f6646d0a8ea9ea0e7e868e46f53b68ddf00cec" +dependencies = [ + "parity-scale-codec", + "sp-std 8.0.0", + "tracing", + "tracing-core", + "tracing-subscriber 0.2.25", +] + [[package]] name = "sp-tracing" version = "16.0.0" @@ -13728,7 +14478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0351810b9d074df71c4514c5228ed05c250607cba131c1c9d1526760ab69c05c" dependencies = [ "parity-scale-codec", - "sp-std", + "sp-std 14.0.0", "tracing", "tracing-core", "tracing-subscriber 0.2.25", @@ -13741,7 +14491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9742861c5330bdcb42856a6eed3d3745b58ee1c92ca4c9260032ff4e6c387165" dependencies = [ "sp-api", - "sp-runtime", + "sp-runtime 32.0.0", ] [[package]] @@ -13753,11 +14503,35 @@ dependencies = [ "async-trait", "parity-scale-codec", "scale-info", - "sp-core", + "sp-core 29.0.0", "sp-inherents", - "sp-runtime", - "sp-std", - "sp-trie", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-trie 30.0.0", +] + +[[package]] +name = "sp-trie" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4eeb7ef23f79eba8609db79ef9cef242f994f1f87a3c0387b4b5f177fda74" +dependencies = [ + "ahash 0.8.11", + "hash-db", + "hashbrown 0.13.2", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot 0.12.1", + "scale-info", + "schnellru", + "sp-core 21.0.0", + "sp-std 8.0.0", + "thiserror", + "tracing", + "trie-db 0.27.1", + "trie-root", ] [[package]] @@ -13773,15 +14547,15 @@ dependencies = [ "nohash-hasher", "parity-scale-codec", "parking_lot 0.12.1", - "rand", + "rand 0.8.5", "scale-info", "schnellru", - "sp-core", - "sp-externalities", - "sp-std", + "sp-core 29.0.0", + "sp-externalities 0.26.0", + "sp-std 14.0.0", "thiserror", "tracing", - "trie-db", + "trie-db 0.28.0", "trie-root", ] @@ -13797,8 +14571,8 @@ dependencies = [ "scale-info", "serde", "sp-crypto-hashing-proc-macro", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", "sp-version-proc-macro", "thiserror", ] @@ -13815,6 +14589,20 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "sp-wasm-interface" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19c122609ca5d8246be6386888596320d03c7bc880959eaa2c36bcd5acd6846" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-std 8.0.0", + "wasmtime", +] + [[package]] name = "sp-wasm-interface" version = "20.0.0" @@ -13825,10 +14613,26 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", - "sp-std", + "sp-std 14.0.0", "wasmtime", ] +[[package]] +name = "sp-weights" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45d084c735544f70625b821c3acdbc7a2fc1893ca98b85f1942631284692c75b" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic 16.0.0", + "sp-core 21.0.0", + "sp-debug-derive 8.0.0", + "sp-std 8.0.0", +] + [[package]] name = "sp-weights" version = "28.0.0" @@ -13840,9 +14644,9 @@ dependencies = [ "scale-info", "serde", "smallvec", - "sp-arithmetic", - "sp-debug-derive", - "sp-std", + "sp-arithmetic 24.0.0", + "sp-debug-derive 14.0.0", + "sp-std 14.0.0", ] [[package]] @@ -13933,8 +14737,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-runtime", - "sp-std", + "sp-runtime 32.0.0", + "sp-std 14.0.0", ] [[package]] @@ -13952,7 +14756,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-weights", + "sp-weights 28.0.0", "xcm-procedural", ] @@ -13970,11 +14774,11 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "scale-info", - "sp-arithmetic", - "sp-io", - "sp-runtime", - "sp-std", - "sp-weights", + "sp-arithmetic 24.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-weights 28.0.0", "staging-xcm", "staging-xcm-executor", ] @@ -13992,12 +14796,12 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-weights", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-weights 28.0.0", "staging-xcm", ] @@ -14136,8 +14940,8 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 29.0.0", + "sp-runtime 32.0.0", ] [[package]] @@ -14164,7 +14968,7 @@ dependencies = [ "log", "sc-rpc-api", "serde", - "sp-runtime", + "sp-runtime 32.0.0", ] [[package]] @@ -14178,11 +14982,11 @@ dependencies = [ "sc-client-api", "sc-rpc-api", "serde", - "sp-core", - "sp-runtime", - "sp-state-machine", - "sp-trie", - "trie-db", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", + "sp-trie 30.0.0", + "trie-db 0.28.0", ] [[package]] @@ -14248,7 +15052,7 @@ dependencies = [ "scale-value", "serde", "serde_json", - "sp-core-hashing", + "sp-core-hashing 15.0.0", "subxt-lightclient", "subxt-macro", "subxt-metadata", @@ -14320,7 +15124,7 @@ dependencies = [ "frame-metadata 16.0.0", "parity-scale-codec", "scale-info", - "sp-core-hashing", + "sp-core-hashing 15.0.0", "thiserror", ] @@ -14337,10 +15141,10 @@ dependencies = [ "pbkdf2 0.12.2", "regex", "schnorrkel 0.11.4", - "secp256k1", + "secp256k1 0.28.2", "secrecy", "sha2 0.10.8", - "sp-core-hashing", + "sp-core-hashing 15.0.0", "subxt", "thiserror", "zeroize", @@ -14380,6 +15184,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -14460,7 +15275,7 @@ dependencies = [ "polkadot-core-primitives", "rococo-runtime-constants", "smallvec", - "sp-runtime", + "sp-runtime 32.0.0", "staging-xcm", "westend-runtime-constants", ] @@ -14595,6 +15410,25 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac 0.12.1", + "once_cell", + "pbkdf2 0.11.0", + "rand 0.8.5", + "rustc-hash", + "sha2 0.10.8", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -14656,7 +15490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" dependencies = [ "pin-project", - "rand", + "rand 0.8.5", "tokio", ] @@ -14968,6 +15802,19 @@ dependencies = [ "tracing-log 0.2.0", ] +[[package]] +name = "trie-db" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" +dependencies = [ + "hash-db", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec", +] + [[package]] name = "trie-db" version = "0.28.0" @@ -15006,7 +15853,7 @@ dependencies = [ "idna 0.2.3", "ipnet", "lazy_static", - "rand", + "rand 0.8.5", "smallvec", "socket2 0.4.10", "thiserror", @@ -15062,19 +15909,19 @@ dependencies = [ "sp-api", "sp-consensus-aura", "sp-consensus-babe", - "sp-core", - "sp-debug-derive", - "sp-externalities", + "sp-core 29.0.0", + "sp-debug-derive 14.0.0", + "sp-externalities 0.26.0", "sp-inherents", - "sp-io", - "sp-keystore", + "sp-io 31.0.0", + "sp-keystore 0.35.0", "sp-rpc", - "sp-runtime", - "sp-state-machine", + "sp-runtime 32.0.0", + "sp-state-machine 0.36.0", "sp-timestamp", "sp-transaction-storage-proof", "sp-version", - "sp-weights", + "sp-weights 28.0.0", "substrate-rpc-client", "zstd 0.12.4", ] @@ -15093,7 +15940,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand", + "rand 0.8.5", "static_assertions", ] @@ -15244,7 +16091,7 @@ dependencies = [ "arrayref", "constcat", "digest 0.10.7", - "rand", + "rand 0.8.5", "rand_chacha 0.3.1", "rand_core 0.6.4", "sha2 0.10.8", @@ -15654,7 +16501,7 @@ dependencies = [ "memfd", "memoffset", "paste", - "rand", + "rand 0.8.5", "rustix 0.36.17", "wasmtime-asm-macros", "wasmtime-environ", @@ -15783,24 +16630,24 @@ dependencies = [ "serde_derive", "smallvec", "sp-api", - "sp-application-crypto", - "sp-arithmetic", + "sp-application-crypto 31.0.0", + "sp-arithmetic 24.0.0", "sp-authority-discovery", "sp-block-builder", "sp-consensus-babe", "sp-consensus-beefy", - "sp-core", + "sp-core 29.0.0", "sp-genesis-builder", "sp-inherents", - "sp-io", + "sp-io 31.0.0", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", - "sp-runtime", + "sp-runtime 32.0.0", "sp-session", "sp-staking", - "sp-std", - "sp-storage", + "sp-std 14.0.0", + "sp-storage 20.0.0", "sp-transaction-pool", "sp-version", "staging-xcm", @@ -15820,9 +16667,9 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "smallvec", - "sp-core", - "sp-runtime", - "sp-weights", + "sp-core 29.0.0", + "sp-runtime 32.0.0", + "sp-weights 28.0.0", "staging-xcm", "staging-xcm-builder", ] @@ -16214,13 +17061,13 @@ dependencies = [ "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-parachains", - "sp-arithmetic", - "sp-core", + "sp-arithmetic 24.0.0", + "sp-core 29.0.0", "sp-crypto-hashing", - "sp-io", - "sp-runtime", - "sp-std", - "sp-tracing", + "sp-io 31.0.0", + "sp-runtime 32.0.0", + "sp-std 14.0.0", + "sp-tracing 16.0.0", "staging-xcm", "staging-xcm-executor", ] @@ -16237,6 +17084,12 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "xxhash-rust" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" + [[package]] name = "yamux" version = "0.10.2" @@ -16247,7 +17100,7 @@ dependencies = [ "log", "nohash-hasher", "parking_lot 0.12.1", - "rand", + "rand 0.8.5", "static_assertions", ] diff --git a/pop-api/examples/fungibles/expanded.rs b/pop-api/examples/fungibles/expanded.rs deleted file mode 100644 index c73cdeb7..00000000 --- a/pop-api/examples/fungibles/expanded.rs +++ /dev/null @@ -1,2766 +0,0 @@ -#![feature(prelude_import)] -#[prelude_import] -use std::prelude::rust_2021::*; -#[macro_use] -extern crate std; -use pop_api::{ - primitives::{AccountId as AccountId32, AssetId}, - assets::fungibles::*, -}; -pub enum FungiblesError { - /// Not enough balance to fulfill a request is available. - InsufficientBalance, - /// Not enough allowance to fulfill a request is available. - InsufficientAllowance, - /// The asset status is not the expected status. - IncorrectStatus, - /// The asset ID is already taken. - InUse, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given asset ID is unknown. - Unknown, - /// Recipient's address is zero. - ZeroRecipientAddress, - /// Sender's address is zero. - ZeroSenderAddress, -} -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - impl ::scale_info::TypeInfo for FungiblesError { - type Identity = Self; - fn type_info() -> ::scale_info::Type { - ::scale_info::Type::builder() - .path( - ::scale_info::Path::new_with_replace( - "FungiblesError", - "fungibles", - &[], - ), - ) - .type_params(::alloc::vec::Vec::new()) - .variant( - ::scale_info::build::Variants::new() - .variant( - "InsufficientBalance", - |v| { - v - .index(0usize as ::core::primitive::u8) - .docs( - &["Not enough balance to fulfill a request is available."], - ) - }, - ) - .variant( - "InsufficientAllowance", - |v| { - v - .index(1usize as ::core::primitive::u8) - .docs( - &["Not enough allowance to fulfill a request is available."], - ) - }, - ) - .variant( - "IncorrectStatus", - |v| { - v - .index(2usize as ::core::primitive::u8) - .docs(&["The asset status is not the expected status."]) - }, - ) - .variant( - "InUse", - |v| { - v - .index(3usize as ::core::primitive::u8) - .docs(&["The asset ID is already taken."]) - }, - ) - .variant( - "MinBalanceZero", - |v| { - v - .index(4usize as ::core::primitive::u8) - .docs(&["Minimum balance should be non-zero."]) - }, - ) - .variant( - "NoPermission", - |v| { - v - .index(5usize as ::core::primitive::u8) - .docs( - &[ - "The signing account has no permission to do the operation.", - ], - ) - }, - ) - .variant( - "Unknown", - |v| { - v - .index(6usize as ::core::primitive::u8) - .docs(&["The given asset ID is unknown."]) - }, - ) - .variant( - "ZeroRecipientAddress", - |v| { - v - .index(7usize as ::core::primitive::u8) - .docs(&["Recipient's address is zero."]) - }, - ) - .variant( - "ZeroSenderAddress", - |v| { - v - .index(8usize as ::core::primitive::u8) - .docs(&["Sender's address is zero."]) - }, - ), - ) - } - } -}; -#[automatically_derived] -impl ::core::fmt::Debug for FungiblesError { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - ::core::fmt::Formatter::write_str( - f, - match self { - FungiblesError::InsufficientBalance => "InsufficientBalance", - FungiblesError::InsufficientAllowance => "InsufficientAllowance", - FungiblesError::IncorrectStatus => "IncorrectStatus", - FungiblesError::InUse => "InUse", - FungiblesError::MinBalanceZero => "MinBalanceZero", - FungiblesError::NoPermission => "NoPermission", - FungiblesError::Unknown => "Unknown", - FungiblesError::ZeroRecipientAddress => "ZeroRecipientAddress", - FungiblesError::ZeroSenderAddress => "ZeroSenderAddress", - }, - ) - } -} -#[automatically_derived] -impl ::core::marker::Copy for FungiblesError {} -#[automatically_derived] -impl ::core::clone::Clone for FungiblesError { - #[inline] - fn clone(&self) -> FungiblesError { - *self - } -} -#[automatically_derived] -impl ::core::marker::StructuralPartialEq for FungiblesError {} -#[automatically_derived] -impl ::core::cmp::PartialEq for FungiblesError { - #[inline] - fn eq(&self, other: &FungiblesError) -> bool { - let __self_tag = ::core::intrinsics::discriminant_value(self); - let __arg1_tag = ::core::intrinsics::discriminant_value(other); - __self_tag == __arg1_tag - } -} -#[automatically_derived] -impl ::core::cmp::Eq for FungiblesError { - #[inline] - #[doc(hidden)] - #[coverage(off)] - fn assert_receiver_is_total_eq(&self) -> () {} -} -#[allow(deprecated)] -const _: () = { - #[automatically_derived] - impl ::scale::Encode for FungiblesError { - fn size_hint(&self) -> usize { - 1_usize - + match *self { - FungiblesError::InsufficientBalance => 0_usize, - FungiblesError::InsufficientAllowance => 0_usize, - FungiblesError::IncorrectStatus => 0_usize, - FungiblesError::InUse => 0_usize, - FungiblesError::MinBalanceZero => 0_usize, - FungiblesError::NoPermission => 0_usize, - FungiblesError::Unknown => 0_usize, - FungiblesError::ZeroRecipientAddress => 0_usize, - FungiblesError::ZeroSenderAddress => 0_usize, - _ => 0_usize, - } - } - fn encode_to<__CodecOutputEdqy: ::scale::Output + ?::core::marker::Sized>( - &self, - __codec_dest_edqy: &mut __CodecOutputEdqy, - ) { - match *self { - FungiblesError::InsufficientBalance => { - #[allow(clippy::unnecessary_cast)] - __codec_dest_edqy.push_byte(0usize as ::core::primitive::u8); - } - FungiblesError::InsufficientAllowance => { - #[allow(clippy::unnecessary_cast)] - __codec_dest_edqy.push_byte(1usize as ::core::primitive::u8); - } - FungiblesError::IncorrectStatus => { - #[allow(clippy::unnecessary_cast)] - __codec_dest_edqy.push_byte(2usize as ::core::primitive::u8); - } - FungiblesError::InUse => { - #[allow(clippy::unnecessary_cast)] - __codec_dest_edqy.push_byte(3usize as ::core::primitive::u8); - } - FungiblesError::MinBalanceZero => { - #[allow(clippy::unnecessary_cast)] - __codec_dest_edqy.push_byte(4usize as ::core::primitive::u8); - } - FungiblesError::NoPermission => { - #[allow(clippy::unnecessary_cast)] - __codec_dest_edqy.push_byte(5usize as ::core::primitive::u8); - } - FungiblesError::Unknown => { - #[allow(clippy::unnecessary_cast)] - __codec_dest_edqy.push_byte(6usize as ::core::primitive::u8); - } - FungiblesError::ZeroRecipientAddress => { - #[allow(clippy::unnecessary_cast)] - __codec_dest_edqy.push_byte(7usize as ::core::primitive::u8); - } - FungiblesError::ZeroSenderAddress => { - #[allow(clippy::unnecessary_cast)] - __codec_dest_edqy.push_byte(8usize as ::core::primitive::u8); - } - _ => {} - } - } - } - #[automatically_derived] - impl ::scale::EncodeLike for FungiblesError {} -}; -#[allow(deprecated)] -const _: () = { - #[automatically_derived] - impl ::scale::Decode for FungiblesError { - fn decode<__CodecInputEdqy: ::scale::Input>( - __codec_input_edqy: &mut __CodecInputEdqy, - ) -> ::core::result::Result { - match __codec_input_edqy - .read_byte() - .map_err(|e| { - e - .chain( - "Could not decode `FungiblesError`, failed to read variant byte", - ) - })? - { - #[allow(clippy::unnecessary_cast)] - __codec_x_edqy if __codec_x_edqy == 0usize as ::core::primitive::u8 => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Ok(FungiblesError::InsufficientBalance) - })(); - } - #[allow(clippy::unnecessary_cast)] - __codec_x_edqy if __codec_x_edqy == 1usize as ::core::primitive::u8 => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Ok(FungiblesError::InsufficientAllowance) - })(); - } - #[allow(clippy::unnecessary_cast)] - __codec_x_edqy if __codec_x_edqy == 2usize as ::core::primitive::u8 => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Ok(FungiblesError::IncorrectStatus) - })(); - } - #[allow(clippy::unnecessary_cast)] - __codec_x_edqy if __codec_x_edqy == 3usize as ::core::primitive::u8 => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Ok(FungiblesError::InUse) - })(); - } - #[allow(clippy::unnecessary_cast)] - __codec_x_edqy if __codec_x_edqy == 4usize as ::core::primitive::u8 => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Ok(FungiblesError::MinBalanceZero) - })(); - } - #[allow(clippy::unnecessary_cast)] - __codec_x_edqy if __codec_x_edqy == 5usize as ::core::primitive::u8 => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Ok(FungiblesError::NoPermission) - })(); - } - #[allow(clippy::unnecessary_cast)] - __codec_x_edqy if __codec_x_edqy == 6usize as ::core::primitive::u8 => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Ok(FungiblesError::Unknown) - })(); - } - #[allow(clippy::unnecessary_cast)] - __codec_x_edqy if __codec_x_edqy == 7usize as ::core::primitive::u8 => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Ok(FungiblesError::ZeroRecipientAddress) - })(); - } - #[allow(clippy::unnecessary_cast)] - __codec_x_edqy if __codec_x_edqy == 8usize as ::core::primitive::u8 => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Ok(FungiblesError::ZeroSenderAddress) - })(); - } - _ => { - #[allow(clippy::redundant_closure_call)] - return (move || { - ::core::result::Result::Err( - <_ as ::core::convert::Into< - _, - >>::into( - "Could not decode `FungiblesError`, variant doesn't exist", - ), - ) - })(); - } - } - } - } -}; -impl From for FungiblesError { - fn from(error: Error) -> Self { - match error { - Error::InUse => FungiblesError::InUse, - Error::MinBalanceZero => FungiblesError::MinBalanceZero, - Error::Unknown => FungiblesError::Unknown, - _ => ::core::panicking::panic("not yet implemented"), - } - } -} -/// The fungibles result type. -pub type Result = core::result::Result; -mod fungibles { - impl ::ink::env::ContractEnv for Fungibles { - type Env = pop_api::Environment; - } - type Environment = ::Env; - type AccountId = <::Env as ::ink::env::Environment>::AccountId; - type Balance = <::Env as ::ink::env::Environment>::Balance; - type Hash = <::Env as ::ink::env::Environment>::Hash; - type Timestamp = <::Env as ::ink::env::Environment>::Timestamp; - type BlockNumber = <::Env as ::ink::env::Environment>::BlockNumber; - type ChainExtension = <::Env as ::ink::env::Environment>::ChainExtension; - const MAX_EVENT_TOPICS: usize = <::Env as ::ink::env::Environment>::MAX_EVENT_TOPICS; - const _: () = { - struct Check { - salt: (), - } - }; - #[scale_info(crate = ::ink::scale_info)] - #[cfg(not(feature = "__ink_dylint_Storage"))] - pub struct Fungibles {} - const _: () = { - impl< - __ink_generic_salt: ::ink::storage::traits::StorageKey, - > ::ink::storage::traits::StorableHint<__ink_generic_salt> for Fungibles { - type Type = Fungibles; - type PreferredKey = ::ink::storage::traits::AutoKey; - } - }; - const _: () = { - impl ::ink::storage::traits::StorageKey for Fungibles { - const KEY: ::ink::primitives::Key = <() as ::ink::storage::traits::StorageKey>::KEY; - } - }; - const _: () = { - impl ::ink::storage::traits::Storable for Fungibles { - #[inline(always)] - #[allow(non_camel_case_types)] - fn decode<__ink_I: ::ink::scale::Input>( - __input: &mut __ink_I, - ) -> ::core::result::Result { - ::core::result::Result::Ok(Fungibles {}) - } - #[inline(always)] - #[allow(non_camel_case_types)] - fn encode<__ink_O: ::ink::scale::Output + ?::core::marker::Sized>( - &self, - __dest: &mut __ink_O, - ) { - match self { - Fungibles {} => {} - } - } - #[inline(always)] - #[allow(non_camel_case_types)] - fn encoded_size(&self) -> ::core::primitive::usize { - match self { - Fungibles {} => ::core::primitive::usize::MIN, - } - } - } - }; - #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const _: () = { - impl ::ink::scale_info::TypeInfo for Fungibles { - type Identity = Self; - fn type_info() -> ::ink::scale_info::Type { - ::ink::scale_info::Type::builder() - .path( - ::ink::scale_info::Path::new_with_replace( - "Fungibles", - "fungibles::fungibles", - &[], - ), - ) - .type_params(::alloc::vec::Vec::new()) - .composite(::ink::scale_info::build::Fields::named()) - } - } - }; - const _: () = { - impl ::ink::storage::traits::StorageLayout for Fungibles { - fn layout( - __key: &::ink::primitives::Key, - ) -> ::ink::metadata::layout::Layout { - ::ink::metadata::layout::Layout::Struct( - ::ink::metadata::layout::StructLayout::new("Fungibles", []), - ) - } - } - }; - #[automatically_derived] - impl ::core::default::Default for Fungibles { - #[inline] - fn default() -> Fungibles { - Fungibles {} - } - } - const _: () = { - impl ::ink::reflect::ContractName for Fungibles { - const NAME: &'static str = "Fungibles"; - } - }; - const _: () = { - impl<'a> ::ink::codegen::Env for &'a Fungibles { - type EnvAccess = ::ink::EnvAccess< - 'a, - ::Env, - >; - fn env(self) -> Self::EnvAccess { - <::EnvAccess as ::core::default::Default>::default() - } - } - impl<'a> ::ink::codegen::StaticEnv for Fungibles { - type EnvAccess = ::ink::EnvAccess< - 'static, - ::Env, - >; - fn env() -> Self::EnvAccess { - <::EnvAccess as ::core::default::Default>::default() - } - } - }; - const _: () = { - #[allow(unused_imports)] - use ::ink::codegen::{Env as _, StaticEnv as _}; - }; - impl ::ink::reflect::DispatchableConstructorInfo<0x9BAE9D5E_u32> for Fungibles { - type Input = (); - type Output = Self; - type Storage = Fungibles; - type Error = <::ink::reflect::ConstructorOutputValue< - Self, - > as ::ink::reflect::ConstructorOutput>::Error; - const IS_RESULT: ::core::primitive::bool = <::ink::reflect::ConstructorOutputValue< - Self, - > as ::ink::reflect::ConstructorOutput>::IS_RESULT; - const CALLABLE: fn(Self::Input) -> Self::Output = |_| { Fungibles::new() }; - const PAYABLE: ::core::primitive::bool = true; - const SELECTOR: [::core::primitive::u8; 4usize] = [ - 0x9B_u8, - 0xAE_u8, - 0x9D_u8, - 0x5E_u8, - ]; - const LABEL: &'static ::core::primitive::str = "new"; - } - impl ::ink::reflect::DispatchableMessageInfo<0xDB6375A8_u32> for Fungibles { - type Input = AssetId; - type Output = Result; - type Storage = Fungibles; - const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | - storage, - __ink_binding_0| - { Fungibles::total_supply(storage, __ink_binding_0) }; - const SELECTOR: [::core::primitive::u8; 4usize] = [ - 0xDB_u8, - 0x63_u8, - 0x75_u8, - 0xA8_u8, - ]; - const PAYABLE: ::core::primitive::bool = false; - const MUTATES: ::core::primitive::bool = false; - const LABEL: &'static ::core::primitive::str = "total_supply"; - } - impl ::ink::reflect::DispatchableMessageInfo<0x0F755A56_u32> for Fungibles { - type Input = (AssetId, AccountId32); - type Output = Result; - type Storage = Fungibles; - const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | - storage, - (__ink_binding_0, __ink_binding_1)| - { Fungibles::balance_of(storage, __ink_binding_0, __ink_binding_1) }; - const SELECTOR: [::core::primitive::u8; 4usize] = [ - 0x0F_u8, - 0x75_u8, - 0x5A_u8, - 0x56_u8, - ]; - const PAYABLE: ::core::primitive::bool = false; - const MUTATES: ::core::primitive::bool = false; - const LABEL: &'static ::core::primitive::str = "balance_of"; - } - impl ::ink::reflect::DispatchableMessageInfo<0x6A00165E_u32> for Fungibles { - type Input = (AssetId, AccountId32, AccountId32); - type Output = Result; - type Storage = Fungibles; - const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | - storage, - (__ink_binding_0, __ink_binding_1, __ink_binding_2)| - { - Fungibles::allowance( - storage, - __ink_binding_0, - __ink_binding_1, - __ink_binding_2, - ) - }; - const SELECTOR: [::core::primitive::u8; 4usize] = [ - 0x6A_u8, - 0x00_u8, - 0x16_u8, - 0x5E_u8, - ]; - const PAYABLE: ::core::primitive::bool = false; - const MUTATES: ::core::primitive::bool = false; - const LABEL: &'static ::core::primitive::str = "allowance"; - } - impl ::ink::reflect::DispatchableMessageInfo<0xAA6B65DB_u32> for Fungibles { - type Input = AssetId; - type Output = Result; - type Storage = Fungibles; - const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | - storage, - __ink_binding_0| - { Fungibles::asset_exists(storage, __ink_binding_0) }; - const SELECTOR: [::core::primitive::u8; 4usize] = [ - 0xAA_u8, - 0x6B_u8, - 0x65_u8, - 0xDB_u8, - ]; - const PAYABLE: ::core::primitive::bool = false; - const MUTATES: ::core::primitive::bool = false; - const LABEL: &'static ::core::primitive::str = "asset_exists"; - } - impl ::ink::reflect::DispatchableMessageInfo<0x1F8E8E22_u32> for Fungibles { - type Input = (u32, AccountId32, Balance); - type Output = Result<()>; - type Storage = Fungibles; - const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = | - storage, - (__ink_binding_0, __ink_binding_1, __ink_binding_2)| - { - Fungibles::mint_asset( - storage, - __ink_binding_0, - __ink_binding_1, - __ink_binding_2, - ) - }; - const SELECTOR: [::core::primitive::u8; 4usize] = [ - 0x1F_u8, - 0x8E_u8, - 0x8E_u8, - 0x22_u8, - ]; - const PAYABLE: ::core::primitive::bool = false; - const MUTATES: ::core::primitive::bool = false; - const LABEL: &'static ::core::primitive::str = "mint_asset"; - } - const _: () = { - #[allow(non_camel_case_types)] - pub enum __ink_ConstructorDecoder { - Constructor0( - >::Input, - ), - } - impl ::ink::reflect::DecodeDispatch for __ink_ConstructorDecoder { - fn decode_dispatch( - input: &mut I, - ) -> ::core::result::Result - where - I: ::ink::scale::Input, - { - const CONSTRUCTOR_0: [::core::primitive::u8; 4usize] = >::SELECTOR; - match <[::core::primitive::u8; 4usize] as ::ink::scale::Decode>::decode( - input, - ) - .map_err(|_| ::ink::reflect::DispatchError::InvalidSelector)? - { - CONSTRUCTOR_0 => { - ::core::result::Result::Ok( - Self::Constructor0( - <>::Input as ::ink::scale::Decode>::decode(input) - .map_err(|_| { - ::ink::reflect::DispatchError::InvalidParameters - })?, - ), - ) - } - _invalid => { - ::core::result::Result::Err( - ::ink::reflect::DispatchError::UnknownSelector, - ) - } - } - } - } - impl ::ink::scale::Decode for __ink_ConstructorDecoder { - fn decode( - input: &mut I, - ) -> ::core::result::Result - where - I: ::ink::scale::Input, - { - ::decode_dispatch(input) - .map_err(::core::convert::Into::into) - } - } - impl ::ink::reflect::ExecuteDispatchable for __ink_ConstructorDecoder { - #[allow(clippy::nonminimal_bool)] - fn execute_dispatchable( - self, - ) -> ::core::result::Result<(), ::ink::reflect::DispatchError> { - match self { - Self::Constructor0(input) => { - if { - false - || { - let constructor_0 = false; - let constructor_0 = >::PAYABLE; - constructor_0 - } - } - && !>::PAYABLE - { - ::ink::codegen::deny_payment::< - ::Env, - >()?; - } - let result: >::Output = >::CALLABLE(input); - let output_value = ::ink::reflect::ConstructorOutputValue::new( - result, - ); - let output_result = <::ink::reflect::ConstructorOutputValue< - >::Output, - > as ::ink::reflect::ConstructorOutput< - Fungibles, - >>::as_result(&output_value); - if let ::core::result::Result::Ok(contract) = output_result - .as_ref() - { - ::ink::env::set_contract_storage::< - ::ink::primitives::Key, - Fungibles, - >( - &::KEY, - contract, - ); - } - let mut flag = ::ink::env::ReturnFlags::empty(); - if output_result.is_err() { - flag = ::ink::env::ReturnFlags::REVERT; - } - ::ink::env::return_value::< - ::ink::ConstructorResult< - ::core::result::Result< - (), - &<::ink::reflect::ConstructorOutputValue< - >::Output, - > as ::ink::reflect::ConstructorOutput>::Error, - >, - >, - >( - flag, - &::ink::ConstructorResult::Ok(output_result.map(|_| ())), - ); - } - } - } - } - impl ::ink::reflect::ContractConstructorDecoder for Fungibles { - type Type = __ink_ConstructorDecoder; - } - }; - const _: () = { - #[allow(non_camel_case_types)] - pub enum __ink_MessageDecoder { - Message0( - >::Input, - ), - Message1( - >::Input, - ), - Message2( - >::Input, - ), - Message3( - >::Input, - ), - Message4( - >::Input, - ), - } - impl ::ink::reflect::DecodeDispatch for __ink_MessageDecoder { - fn decode_dispatch( - input: &mut I, - ) -> ::core::result::Result - where - I: ::ink::scale::Input, - { - const MESSAGE_0: [::core::primitive::u8; 4usize] = >::SELECTOR; - const MESSAGE_1: [::core::primitive::u8; 4usize] = >::SELECTOR; - const MESSAGE_2: [::core::primitive::u8; 4usize] = >::SELECTOR; - const MESSAGE_3: [::core::primitive::u8; 4usize] = >::SELECTOR; - const MESSAGE_4: [::core::primitive::u8; 4usize] = >::SELECTOR; - match <[::core::primitive::u8; 4usize] as ::ink::scale::Decode>::decode( - input, - ) - .map_err(|_| ::ink::reflect::DispatchError::InvalidSelector)? - { - MESSAGE_0 => { - ::core::result::Result::Ok( - Self::Message0( - <>::Input as ::ink::scale::Decode>::decode(input) - .map_err(|_| { - ::ink::reflect::DispatchError::InvalidParameters - })?, - ), - ) - } - MESSAGE_1 => { - ::core::result::Result::Ok( - Self::Message1( - <>::Input as ::ink::scale::Decode>::decode(input) - .map_err(|_| { - ::ink::reflect::DispatchError::InvalidParameters - })?, - ), - ) - } - MESSAGE_2 => { - ::core::result::Result::Ok( - Self::Message2( - <>::Input as ::ink::scale::Decode>::decode(input) - .map_err(|_| { - ::ink::reflect::DispatchError::InvalidParameters - })?, - ), - ) - } - MESSAGE_3 => { - ::core::result::Result::Ok( - Self::Message3( - <>::Input as ::ink::scale::Decode>::decode(input) - .map_err(|_| { - ::ink::reflect::DispatchError::InvalidParameters - })?, - ), - ) - } - MESSAGE_4 => { - ::core::result::Result::Ok( - Self::Message4( - <>::Input as ::ink::scale::Decode>::decode(input) - .map_err(|_| { - ::ink::reflect::DispatchError::InvalidParameters - })?, - ), - ) - } - _invalid => { - ::core::result::Result::Err( - ::ink::reflect::DispatchError::UnknownSelector, - ) - } - } - } - } - impl ::ink::scale::Decode for __ink_MessageDecoder { - fn decode( - input: &mut I, - ) -> ::core::result::Result - where - I: ::ink::scale::Input, - { - ::decode_dispatch(input) - .map_err(::core::convert::Into::into) - } - } - fn push_contract(contract: ::core::mem::ManuallyDrop, mutates: bool) { - if mutates { - ::ink::env::set_contract_storage::< - ::ink::primitives::Key, - Fungibles, - >(&::KEY, &contract); - } - } - impl ::ink::reflect::ExecuteDispatchable for __ink_MessageDecoder { - #[allow(clippy::nonminimal_bool, clippy::let_unit_value)] - fn execute_dispatchable( - self, - ) -> ::core::result::Result<(), ::ink::reflect::DispatchError> { - let key = ::KEY; - let mut contract: ::core::mem::ManuallyDrop = ::core::mem::ManuallyDrop::new( - match ::ink::env::get_contract_storage(&key) { - ::core::result::Result::Ok( - ::core::option::Option::Some(value), - ) => value, - ::core::result::Result::Ok(::core::option::Option::None) => { - ::core::panicking::panic_fmt( - format_args!("storage entry was empty"), - ); - } - ::core::result::Result::Err(_) => { - ::core::panicking::panic_fmt( - format_args!("could not properly decode storage entry"), - ); - } - }, - ); - match self { - Self::Message0(input) => { - if { - false - || { - let message_0 = false; - let message_0 = >::PAYABLE; - message_0 - } - || { - let message_1 = false; - let message_1 = >::PAYABLE; - message_1 - } - || { - let message_2 = false; - let message_2 = >::PAYABLE; - message_2 - } - || { - let message_3 = false; - let message_3 = >::PAYABLE; - message_3 - } - || { - let message_4 = false; - let message_4 = >::PAYABLE; - message_4 - } - } - && !>::PAYABLE - { - ::ink::codegen::deny_payment::< - ::Env, - >()?; - } - let result: >::Output = >::CALLABLE(&mut contract, input); - let is_reverted = { - #[allow(unused_imports)] - use ::ink::result_info::IsResultTypeFallback as _; - ::ink::result_info::IsResultType::< - >::Output, - >::VALUE - } - && { - #[allow(unused_imports)] - use ::ink::result_info::IsResultErrFallback as _; - ::ink::result_info::IsResultErr(&result).value() - }; - let mut flag = ::ink::env::ReturnFlags::REVERT; - if !is_reverted { - flag = ::ink::env::ReturnFlags::empty(); - push_contract( - contract, - >::MUTATES, - ); - } - ::ink::env::return_value::< - ::ink::MessageResult< - >::Output, - >, - >(flag, &::ink::MessageResult::Ok(result)) - } - Self::Message1(input) => { - if { - false - || { - let message_0 = false; - let message_0 = >::PAYABLE; - message_0 - } - || { - let message_1 = false; - let message_1 = >::PAYABLE; - message_1 - } - || { - let message_2 = false; - let message_2 = >::PAYABLE; - message_2 - } - || { - let message_3 = false; - let message_3 = >::PAYABLE; - message_3 - } - || { - let message_4 = false; - let message_4 = >::PAYABLE; - message_4 - } - } - && !>::PAYABLE - { - ::ink::codegen::deny_payment::< - ::Env, - >()?; - } - let result: >::Output = >::CALLABLE(&mut contract, input); - let is_reverted = { - #[allow(unused_imports)] - use ::ink::result_info::IsResultTypeFallback as _; - ::ink::result_info::IsResultType::< - >::Output, - >::VALUE - } - && { - #[allow(unused_imports)] - use ::ink::result_info::IsResultErrFallback as _; - ::ink::result_info::IsResultErr(&result).value() - }; - let mut flag = ::ink::env::ReturnFlags::REVERT; - if !is_reverted { - flag = ::ink::env::ReturnFlags::empty(); - push_contract( - contract, - >::MUTATES, - ); - } - ::ink::env::return_value::< - ::ink::MessageResult< - >::Output, - >, - >(flag, &::ink::MessageResult::Ok(result)) - } - Self::Message2(input) => { - if { - false - || { - let message_0 = false; - let message_0 = >::PAYABLE; - message_0 - } - || { - let message_1 = false; - let message_1 = >::PAYABLE; - message_1 - } - || { - let message_2 = false; - let message_2 = >::PAYABLE; - message_2 - } - || { - let message_3 = false; - let message_3 = >::PAYABLE; - message_3 - } - || { - let message_4 = false; - let message_4 = >::PAYABLE; - message_4 - } - } - && !>::PAYABLE - { - ::ink::codegen::deny_payment::< - ::Env, - >()?; - } - let result: >::Output = >::CALLABLE(&mut contract, input); - let is_reverted = { - #[allow(unused_imports)] - use ::ink::result_info::IsResultTypeFallback as _; - ::ink::result_info::IsResultType::< - >::Output, - >::VALUE - } - && { - #[allow(unused_imports)] - use ::ink::result_info::IsResultErrFallback as _; - ::ink::result_info::IsResultErr(&result).value() - }; - let mut flag = ::ink::env::ReturnFlags::REVERT; - if !is_reverted { - flag = ::ink::env::ReturnFlags::empty(); - push_contract( - contract, - >::MUTATES, - ); - } - ::ink::env::return_value::< - ::ink::MessageResult< - >::Output, - >, - >(flag, &::ink::MessageResult::Ok(result)) - } - Self::Message3(input) => { - if { - false - || { - let message_0 = false; - let message_0 = >::PAYABLE; - message_0 - } - || { - let message_1 = false; - let message_1 = >::PAYABLE; - message_1 - } - || { - let message_2 = false; - let message_2 = >::PAYABLE; - message_2 - } - || { - let message_3 = false; - let message_3 = >::PAYABLE; - message_3 - } - || { - let message_4 = false; - let message_4 = >::PAYABLE; - message_4 - } - } - && !>::PAYABLE - { - ::ink::codegen::deny_payment::< - ::Env, - >()?; - } - let result: >::Output = >::CALLABLE(&mut contract, input); - let is_reverted = { - #[allow(unused_imports)] - use ::ink::result_info::IsResultTypeFallback as _; - ::ink::result_info::IsResultType::< - >::Output, - >::VALUE - } - && { - #[allow(unused_imports)] - use ::ink::result_info::IsResultErrFallback as _; - ::ink::result_info::IsResultErr(&result).value() - }; - let mut flag = ::ink::env::ReturnFlags::REVERT; - if !is_reverted { - flag = ::ink::env::ReturnFlags::empty(); - push_contract( - contract, - >::MUTATES, - ); - } - ::ink::env::return_value::< - ::ink::MessageResult< - >::Output, - >, - >(flag, &::ink::MessageResult::Ok(result)) - } - Self::Message4(input) => { - if { - false - || { - let message_0 = false; - let message_0 = >::PAYABLE; - message_0 - } - || { - let message_1 = false; - let message_1 = >::PAYABLE; - message_1 - } - || { - let message_2 = false; - let message_2 = >::PAYABLE; - message_2 - } - || { - let message_3 = false; - let message_3 = >::PAYABLE; - message_3 - } - || { - let message_4 = false; - let message_4 = >::PAYABLE; - message_4 - } - } - && !>::PAYABLE - { - ::ink::codegen::deny_payment::< - ::Env, - >()?; - } - let result: >::Output = >::CALLABLE(&mut contract, input); - let is_reverted = { - #[allow(unused_imports)] - use ::ink::result_info::IsResultTypeFallback as _; - ::ink::result_info::IsResultType::< - >::Output, - >::VALUE - } - && { - #[allow(unused_imports)] - use ::ink::result_info::IsResultErrFallback as _; - ::ink::result_info::IsResultErr(&result).value() - }; - let mut flag = ::ink::env::ReturnFlags::REVERT; - if !is_reverted { - flag = ::ink::env::ReturnFlags::empty(); - push_contract( - contract, - >::MUTATES, - ); - } - ::ink::env::return_value::< - ::ink::MessageResult< - >::Output, - >, - >(flag, &::ink::MessageResult::Ok(result)) - } - }; - } - } - impl ::ink::reflect::ContractMessageDecoder for Fungibles { - type Type = __ink_MessageDecoder; - } - }; - const _: () = { - use ::ink::codegen::{Env as _, StaticEnv as _}; - const _: ::ink::codegen::utils::IsSameType = ::ink::codegen::utils::IsSameType::< - Fungibles, - >::new(); - impl Fungibles { - #[cfg(not(feature = "__ink_dylint_Constructor"))] - pub fn new() -> Self { - ::ink_env::debug_message( - &{ - let res = ::alloc::fmt::format( - format_args!( - "{0}\n", - { - let res = ::alloc::fmt::format( - format_args!("PopApiAssetsExample::new"), - ); - res - }, - ), - ); - res - }, - ); - Default::default() - } - pub fn total_supply(&self, id: AssetId) -> Result { - total_supply(id).map_err(From::from) - } - pub fn balance_of( - &self, - id: AssetId, - owner: AccountId32, - ) -> Result { - balance_of(id, owner).map_err(From::from) - } - pub fn allowance( - &self, - id: AssetId, - owner: AccountId32, - spender: AccountId32, - ) -> Result { - allowance(id, owner, spender).map_err(From::from) - } - pub fn asset_exists(&self, id: AssetId) -> Result { - asset_exists(id).map_err(From::from) - } - pub fn mint_asset( - &self, - id: u32, - beneficiary: AccountId32, - amount: Balance, - ) -> Result<()> { - ::ink_env::debug_message( - &{ - let res = ::alloc::fmt::format( - format_args!( - "{0}\n", - { - let res = ::alloc::fmt::format( - format_args!( - "PopApiAssetsExample::mint_asset_through_runtime: id: {0:?} beneficiary: {1:?} amount: {2:?}", - id, - beneficiary, - amount, - ), - ); - res - }, - ), - ); - res - }, - ); - let result = mint(id, beneficiary, amount)?; - ::ink_env::debug_message( - &{ - let res = ::alloc::fmt::format( - format_args!( - "{0}\n", - { - let res = ::alloc::fmt::format( - format_args!("Result: {0:?}", result), - ); - res - }, - ), - ); - res - }, - ); - Ok(()) - } - } - const _: () = { - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchInput, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchOutput>, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchInput, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchInput, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchOutput>, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchInput, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchInput, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchInput, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchOutput>, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchInput, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchOutput>, - >(); - ::ink::codegen::utils::consume_type::<::ink::codegen::DispatchInput>(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchInput, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchInput, - >(); - ::ink::codegen::utils::consume_type::< - ::ink::codegen::DispatchOutput>, - >(); - }; - }; - const _: () = { - #[codec(crate = ::ink::scale)] - #[scale_info(crate = ::ink::scale_info)] - /// The ink! smart contract's call builder. - /// - /// Implements the underlying on-chain calling of the ink! smart contract - /// messages and trait implementations in a type safe way. - #[repr(transparent)] - pub struct CallBuilder { - account_id: AccountId, - } - #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const _: () = { - impl ::ink::scale_info::TypeInfo for CallBuilder { - type Identity = Self; - fn type_info() -> ::ink::scale_info::Type { - ::ink::scale_info::Type::builder() - .path( - ::ink::scale_info::Path::new_with_replace( - "CallBuilder", - "fungibles::fungibles", - &[], - ), - ) - .type_params(::alloc::vec::Vec::new()) - .docs( - &[ - "The ink! smart contract's call builder.", - "", - "Implements the underlying on-chain calling of the ink! smart contract", - "messages and trait implementations in a type safe way.", - ], - ) - .composite( - ::ink::scale_info::build::Fields::named() - .field(|f| { - f - .ty::() - .name("account_id") - .type_name("AccountId") - }), - ) - } - } - }; - #[allow(deprecated)] - const _: () = { - #[automatically_derived] - impl ::ink::scale::Decode for CallBuilder { - fn decode<__CodecInputEdqy: ::ink::scale::Input>( - __codec_input_edqy: &mut __CodecInputEdqy, - ) -> ::core::result::Result { - ::core::result::Result::Ok(CallBuilder { - account_id: { - let __codec_res_edqy = ::decode( - __codec_input_edqy, - ); - match __codec_res_edqy { - ::core::result::Result::Err(e) => { - return ::core::result::Result::Err( - e.chain("Could not decode `CallBuilder::account_id`"), - ); - } - ::core::result::Result::Ok(__codec_res_edqy) => { - __codec_res_edqy - } - } - }, - }) - } - fn decode_into<__CodecInputEdqy: ::ink::scale::Input>( - __codec_input_edqy: &mut __CodecInputEdqy, - dst_: &mut ::core::mem::MaybeUninit, - ) -> ::core::result::Result< - ::ink::scale::DecodeFinished, - ::ink::scale::Error, - > { - match ( - &::core::mem::size_of::(), - &::core::mem::size_of::(), - ) { - (left_val, right_val) => { - if !(*left_val == *right_val) { - let kind = ::core::panicking::AssertKind::Eq; - ::core::panicking::assert_failed( - kind, - &*left_val, - &*right_val, - ::core::option::Option::None, - ); - } - } - }; - if !(if ::core::mem::size_of::() > 0 { 1 } else { 0 } - <= 1) - { - ::core::panicking::panic( - "assertion failed: if ::core::mem::size_of::() > 0 { 1 } else { 0 } <= 1", - ) - } - { - let dst_: &mut ::core::mem::MaybeUninit = dst_; - let dst_: &mut ::core::mem::MaybeUninit = unsafe { - &mut *dst_ - .as_mut_ptr() - .cast::<::core::mem::MaybeUninit>() - }; - ::decode_into( - __codec_input_edqy, - dst_, - )?; - } - unsafe { - ::core::result::Result::Ok( - ::ink::scale::DecodeFinished::assert_decoding_finished(), - ) - } - } - } - }; - #[allow(deprecated)] - const _: () = { - #[automatically_derived] - impl ::ink::scale::Encode for CallBuilder { - fn size_hint(&self) -> usize { - ::ink::scale::Encode::size_hint(&&self.account_id) - } - fn encode_to< - __CodecOutputEdqy: ::ink::scale::Output + ?::core::marker::Sized, - >(&self, __codec_dest_edqy: &mut __CodecOutputEdqy) { - ::ink::scale::Encode::encode_to(&&self.account_id, __codec_dest_edqy) - } - fn encode( - &self, - ) -> ::ink::scale::alloc::vec::Vec<::core::primitive::u8> { - ::ink::scale::Encode::encode(&&self.account_id) - } - fn using_encoded< - __CodecOutputReturn, - __CodecUsingEncodedCallback: ::core::ops::FnOnce( - &[::core::primitive::u8], - ) -> __CodecOutputReturn, - >(&self, f: __CodecUsingEncodedCallback) -> __CodecOutputReturn { - ::ink::scale::Encode::using_encoded(&&self.account_id, f) - } - } - #[automatically_derived] - impl ::ink::scale::EncodeLike for CallBuilder {} - }; - #[automatically_derived] - impl ::core::fmt::Debug for CallBuilder { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - ::core::fmt::Formatter::debug_struct_field1_finish( - f, - "CallBuilder", - "account_id", - &&self.account_id, - ) - } - } - #[automatically_derived] - impl ::core::hash::Hash for CallBuilder { - #[inline] - fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { - ::core::hash::Hash::hash(&self.account_id, state) - } - } - #[automatically_derived] - impl ::core::marker::StructuralPartialEq for CallBuilder {} - #[automatically_derived] - impl ::core::cmp::PartialEq for CallBuilder { - #[inline] - fn eq(&self, other: &CallBuilder) -> bool { - self.account_id == other.account_id - } - } - #[automatically_derived] - impl ::core::cmp::Eq for CallBuilder { - #[inline] - #[doc(hidden)] - #[coverage(off)] - fn assert_receiver_is_total_eq(&self) -> () { - let _: ::core::cmp::AssertParamIsEq; - } - } - #[automatically_derived] - impl ::core::clone::Clone for CallBuilder { - #[inline] - fn clone(&self) -> CallBuilder { - CallBuilder { - account_id: ::core::clone::Clone::clone(&self.account_id), - } - } - } - const _: () = { - impl ::ink::storage::traits::StorageLayout for CallBuilder { - fn layout( - __key: &::ink::primitives::Key, - ) -> ::ink::metadata::layout::Layout { - ::ink::metadata::layout::Layout::Struct( - ::ink::metadata::layout::StructLayout::new( - "CallBuilder", - [ - ::ink::metadata::layout::FieldLayout::new( - "account_id", - ::layout( - __key, - ), - ), - ], - ), - ) - } - } - }; - const _: () = { - impl ::ink::codegen::ContractCallBuilder for Fungibles { - type Type = CallBuilder; - } - impl ::ink::env::ContractEnv for CallBuilder { - type Env = ::Env; - } - }; - impl ::ink::env::call::FromAccountId for CallBuilder { - #[inline] - fn from_account_id(account_id: AccountId) -> Self { - Self { account_id } - } - } - impl ::ink::ToAccountId for CallBuilder { - #[inline] - fn to_account_id(&self) -> AccountId { - ::clone(&self.account_id) - } - } - impl ::core::convert::AsRef for CallBuilder { - fn as_ref(&self) -> &AccountId { - &self.account_id - } - } - impl ::core::convert::AsMut for CallBuilder { - fn as_mut(&mut self) -> &mut AccountId { - &mut self.account_id - } - } - impl CallBuilder { - #[allow(clippy::type_complexity)] - #[inline] - pub fn total_supply( - &self, - __ink_binding_0: AssetId, - ) -> ::ink::env::call::CallBuilder< - Environment, - ::ink::env::call::utils::Set<::ink::env::call::Call>, - ::ink::env::call::utils::Set< - ::ink::env::call::ExecutionInput< - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::EmptyArgumentList, - >, - >, - >, - ::ink::env::call::utils::Set< - ::ink::env::call::utils::ReturnType>, - >, - > { - ::ink::env::call::build_call::() - .call(::ink::ToAccountId::to_account_id(self)) - .exec_input( - ::ink::env::call::ExecutionInput::new( - ::ink::env::call::Selector::new([ - 0xDB_u8, - 0x63_u8, - 0x75_u8, - 0xA8_u8, - ]), - ) - .push_arg(__ink_binding_0), - ) - .returns::>() - } - #[allow(clippy::type_complexity)] - #[inline] - pub fn balance_of( - &self, - __ink_binding_0: AssetId, - __ink_binding_1: AccountId32, - ) -> ::ink::env::call::CallBuilder< - Environment, - ::ink::env::call::utils::Set<::ink::env::call::Call>, - ::ink::env::call::utils::Set< - ::ink::env::call::ExecutionInput< - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::EmptyArgumentList, - >, - >, - >, - >, - ::ink::env::call::utils::Set< - ::ink::env::call::utils::ReturnType>, - >, - > { - ::ink::env::call::build_call::() - .call(::ink::ToAccountId::to_account_id(self)) - .exec_input( - ::ink::env::call::ExecutionInput::new( - ::ink::env::call::Selector::new([ - 0x0F_u8, - 0x75_u8, - 0x5A_u8, - 0x56_u8, - ]), - ) - .push_arg(__ink_binding_0) - .push_arg(__ink_binding_1), - ) - .returns::>() - } - #[allow(clippy::type_complexity)] - #[inline] - pub fn allowance( - &self, - __ink_binding_0: AssetId, - __ink_binding_1: AccountId32, - __ink_binding_2: AccountId32, - ) -> ::ink::env::call::CallBuilder< - Environment, - ::ink::env::call::utils::Set<::ink::env::call::Call>, - ::ink::env::call::utils::Set< - ::ink::env::call::ExecutionInput< - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::EmptyArgumentList, - >, - >, - >, - >, - >, - ::ink::env::call::utils::Set< - ::ink::env::call::utils::ReturnType>, - >, - > { - ::ink::env::call::build_call::() - .call(::ink::ToAccountId::to_account_id(self)) - .exec_input( - ::ink::env::call::ExecutionInput::new( - ::ink::env::call::Selector::new([ - 0x6A_u8, - 0x00_u8, - 0x16_u8, - 0x5E_u8, - ]), - ) - .push_arg(__ink_binding_0) - .push_arg(__ink_binding_1) - .push_arg(__ink_binding_2), - ) - .returns::>() - } - #[allow(clippy::type_complexity)] - #[inline] - pub fn asset_exists( - &self, - __ink_binding_0: AssetId, - ) -> ::ink::env::call::CallBuilder< - Environment, - ::ink::env::call::utils::Set<::ink::env::call::Call>, - ::ink::env::call::utils::Set< - ::ink::env::call::ExecutionInput< - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::EmptyArgumentList, - >, - >, - >, - ::ink::env::call::utils::Set< - ::ink::env::call::utils::ReturnType>, - >, - > { - ::ink::env::call::build_call::() - .call(::ink::ToAccountId::to_account_id(self)) - .exec_input( - ::ink::env::call::ExecutionInput::new( - ::ink::env::call::Selector::new([ - 0xAA_u8, - 0x6B_u8, - 0x65_u8, - 0xDB_u8, - ]), - ) - .push_arg(__ink_binding_0), - ) - .returns::>() - } - #[allow(clippy::type_complexity)] - #[inline] - pub fn mint_asset( - &self, - __ink_binding_0: u32, - __ink_binding_1: AccountId32, - __ink_binding_2: Balance, - ) -> ::ink::env::call::CallBuilder< - Environment, - ::ink::env::call::utils::Set<::ink::env::call::Call>, - ::ink::env::call::utils::Set< - ::ink::env::call::ExecutionInput< - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::ArgumentList< - ::ink::env::call::utils::Argument, - ::ink::env::call::utils::EmptyArgumentList, - >, - >, - >, - >, - >, - ::ink::env::call::utils::Set< - ::ink::env::call::utils::ReturnType>, - >, - > { - ::ink::env::call::build_call::() - .call(::ink::ToAccountId::to_account_id(self)) - .exec_input( - ::ink::env::call::ExecutionInput::new( - ::ink::env::call::Selector::new([ - 0x1F_u8, - 0x8E_u8, - 0x8E_u8, - 0x22_u8, - ]), - ) - .push_arg(__ink_binding_0) - .push_arg(__ink_binding_1) - .push_arg(__ink_binding_2), - ) - .returns::>() - } - } - }; - #[codec(crate = ::ink::scale)] - #[scale_info(crate = ::ink::scale_info)] - pub struct FungiblesRef { - inner: ::Type, - } - #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const _: () = { - impl ::ink::scale_info::TypeInfo for FungiblesRef { - type Identity = Self; - fn type_info() -> ::ink::scale_info::Type { - ::ink::scale_info::Type::builder() - .path( - ::ink::scale_info::Path::new_with_replace( - "FungiblesRef", - "fungibles::fungibles", - &[], - ), - ) - .type_params(::alloc::vec::Vec::new()) - .composite( - ::ink::scale_info::build::Fields::named() - .field(|f| { - f - .ty::< - ::Type, - >() - .name("inner") - .type_name( - "::Type", - ) - }), - ) - } - } - }; - #[allow(deprecated)] - const _: () = { - #[automatically_derived] - impl ::ink::scale::Decode for FungiblesRef { - fn decode<__CodecInputEdqy: ::ink::scale::Input>( - __codec_input_edqy: &mut __CodecInputEdqy, - ) -> ::core::result::Result { - ::core::result::Result::Ok(FungiblesRef { - inner: { - let __codec_res_edqy = <::Type as ::ink::scale::Decode>::decode( - __codec_input_edqy, - ); - match __codec_res_edqy { - ::core::result::Result::Err(e) => { - return ::core::result::Result::Err( - e.chain("Could not decode `FungiblesRef::inner`"), - ); - } - ::core::result::Result::Ok(__codec_res_edqy) => { - __codec_res_edqy - } - } - }, - }) - } - } - }; - #[allow(deprecated)] - const _: () = { - #[automatically_derived] - impl ::ink::scale::Encode for FungiblesRef { - fn size_hint(&self) -> usize { - ::ink::scale::Encode::size_hint(&&self.inner) - } - fn encode_to< - __CodecOutputEdqy: ::ink::scale::Output + ?::core::marker::Sized, - >(&self, __codec_dest_edqy: &mut __CodecOutputEdqy) { - ::ink::scale::Encode::encode_to(&&self.inner, __codec_dest_edqy) - } - fn encode(&self) -> ::ink::scale::alloc::vec::Vec<::core::primitive::u8> { - ::ink::scale::Encode::encode(&&self.inner) - } - fn using_encoded< - __CodecOutputReturn, - __CodecUsingEncodedCallback: ::core::ops::FnOnce( - &[::core::primitive::u8], - ) -> __CodecOutputReturn, - >(&self, f: __CodecUsingEncodedCallback) -> __CodecOutputReturn { - ::ink::scale::Encode::using_encoded(&&self.inner, f) - } - } - #[automatically_derived] - impl ::ink::scale::EncodeLike for FungiblesRef {} - }; - #[automatically_derived] - impl ::core::fmt::Debug for FungiblesRef { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - ::core::fmt::Formatter::debug_struct_field1_finish( - f, - "FungiblesRef", - "inner", - &&self.inner, - ) - } - } - #[automatically_derived] - impl ::core::hash::Hash for FungiblesRef { - #[inline] - fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { - ::core::hash::Hash::hash(&self.inner, state) - } - } - #[automatically_derived] - impl ::core::marker::StructuralPartialEq for FungiblesRef {} - #[automatically_derived] - impl ::core::cmp::PartialEq for FungiblesRef { - #[inline] - fn eq(&self, other: &FungiblesRef) -> bool { - self.inner == other.inner - } - } - #[automatically_derived] - impl ::core::cmp::Eq for FungiblesRef { - #[inline] - #[doc(hidden)] - #[coverage(off)] - fn assert_receiver_is_total_eq(&self) -> () { - let _: ::core::cmp::AssertParamIsEq< - ::Type, - >; - } - } - #[automatically_derived] - impl ::core::clone::Clone for FungiblesRef { - #[inline] - fn clone(&self) -> FungiblesRef { - FungiblesRef { - inner: ::core::clone::Clone::clone(&self.inner), - } - } - } - const _: () = { - impl ::ink::storage::traits::StorageLayout for FungiblesRef { - fn layout( - __key: &::ink::primitives::Key, - ) -> ::ink::metadata::layout::Layout { - ::ink::metadata::layout::Layout::Struct( - ::ink::metadata::layout::StructLayout::new( - "FungiblesRef", - [ - ::ink::metadata::layout::FieldLayout::new( - "inner", - <::Type as ::ink::storage::traits::StorageLayout>::layout( - __key, - ), - ), - ], - ), - ) - } - } - }; - const _: () = { - impl ::ink::env::ContractReference for Fungibles { - type Type = FungiblesRef; - } - impl ::ink::env::call::ConstructorReturnType for Fungibles { - type Output = FungiblesRef; - type Error = (); - fn ok(value: FungiblesRef) -> Self::Output { - value - } - } - impl ::ink::env::call::ConstructorReturnType - for ::core::result::Result - where - E: ::ink::scale::Decode, - { - const IS_RESULT: bool = true; - type Output = ::core::result::Result; - type Error = E; - fn ok(value: FungiblesRef) -> Self::Output { - ::core::result::Result::Ok(value) - } - fn err(err: Self::Error) -> ::core::option::Option { - ::core::option::Option::Some(::core::result::Result::Err(err)) - } - } - impl ::ink::env::ContractEnv for FungiblesRef { - type Env = ::Env; - } - }; - impl FungiblesRef { - #[inline] - #[allow(clippy::type_complexity)] - pub fn new() -> ::ink::env::call::CreateBuilder< - Environment, - Self, - ::ink::env::call::utils::Unset, - ::ink::env::call::utils::Set< - ::ink::env::call::LimitParamsV2< - ::Env, - >, - >, - ::ink::env::call::utils::Unset, - ::ink::env::call::utils::Set< - ::ink::env::call::ExecutionInput< - ::ink::env::call::utils::EmptyArgumentList, - >, - >, - ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, - ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType>, - > { - ::ink::env::call::build_create::() - .exec_input( - ::ink::env::call::ExecutionInput::new( - ::ink::env::call::Selector::new([ - 0x9B_u8, - 0xAE_u8, - 0x9D_u8, - 0x5E_u8, - ]), - ), - ) - .returns::() - } - #[inline] - pub fn total_supply(&self, id: AssetId) -> Result { - self.try_total_supply(id) - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "total_supply", - error, - ), - ); - }) - } - #[inline] - pub fn try_total_supply( - &self, - id: AssetId, - ) -> ::ink::MessageResult> { - ::call(self) - .total_supply(id) - .try_invoke() - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "total_supply", - error, - ), - ); - }) - } - #[inline] - pub fn balance_of(&self, id: AssetId, owner: AccountId32) -> Result { - self.try_balance_of(id, owner) - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "balance_of", - error, - ), - ); - }) - } - #[inline] - pub fn try_balance_of( - &self, - id: AssetId, - owner: AccountId32, - ) -> ::ink::MessageResult> { - ::call(self) - .balance_of(id, owner) - .try_invoke() - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "balance_of", - error, - ), - ); - }) - } - #[inline] - pub fn allowance( - &self, - id: AssetId, - owner: AccountId32, - spender: AccountId32, - ) -> Result { - self.try_allowance(id, owner, spender) - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "allowance", - error, - ), - ); - }) - } - #[inline] - pub fn try_allowance( - &self, - id: AssetId, - owner: AccountId32, - spender: AccountId32, - ) -> ::ink::MessageResult> { - ::call(self) - .allowance(id, owner, spender) - .try_invoke() - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "allowance", - error, - ), - ); - }) - } - #[inline] - pub fn asset_exists(&self, id: AssetId) -> Result { - self.try_asset_exists(id) - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "asset_exists", - error, - ), - ); - }) - } - #[inline] - pub fn try_asset_exists( - &self, - id: AssetId, - ) -> ::ink::MessageResult> { - ::call(self) - .asset_exists(id) - .try_invoke() - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "asset_exists", - error, - ), - ); - }) - } - #[inline] - pub fn mint_asset( - &self, - id: u32, - beneficiary: AccountId32, - amount: Balance, - ) -> Result<()> { - self.try_mint_asset(id, beneficiary, amount) - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "mint_asset", - error, - ), - ); - }) - } - #[inline] - pub fn try_mint_asset( - &self, - id: u32, - beneficiary: AccountId32, - amount: Balance, - ) -> ::ink::MessageResult> { - ::call(self) - .mint_asset(id, beneficiary, amount) - .try_invoke() - .unwrap_or_else(|error| { - ::core::panicking::panic_fmt( - format_args!( - "encountered error while calling {0}::{1}: {2:?}", - "Fungibles", - "mint_asset", - error, - ), - ); - }) - } - } - const _: () = { - impl ::ink::codegen::TraitCallBuilder for FungiblesRef { - type Builder = ::Type; - #[inline] - fn call(&self) -> &Self::Builder { - &self.inner - } - #[inline] - fn call_mut(&mut self) -> &mut Self::Builder { - &mut self.inner - } - } - }; - impl ::ink::env::call::FromAccountId for FungiblesRef { - #[inline] - fn from_account_id(account_id: AccountId) -> Self { - Self { - inner: <::Type as ::ink::env::call::FromAccountId< - Environment, - >>::from_account_id(account_id), - } - } - } - impl ::ink::ToAccountId for FungiblesRef { - #[inline] - fn to_account_id(&self) -> AccountId { - <::Type as ::ink::ToAccountId< - Environment, - >>::to_account_id(&self.inner) - } - } - impl ::core::convert::AsRef for FungiblesRef { - fn as_ref(&self) -> &AccountId { - <_ as ::core::convert::AsRef>::as_ref(&self.inner) - } - } - impl ::core::convert::AsMut for FungiblesRef { - fn as_mut(&mut self) -> &mut AccountId { - <_ as ::core::convert::AsMut>::as_mut(&mut self.inner) - } - } - #[cfg(feature = "std")] - #[cfg(not(feature = "ink-as-dependency"))] - const _: () = { - #[no_mangle] - pub fn __ink_generate_metadata() -> ::ink::metadata::InkProject { - let layout = ::ink::metadata::layout::Layout::Root( - ::ink::metadata::layout::RootLayout::new( - <::ink::metadata::layout::LayoutKey as ::core::convert::From< - ::ink::primitives::Key, - >>::from(::KEY), - ::layout( - &::KEY, - ), - ::ink::scale_info::meta_type::(), - ), - ); - ::ink::metadata::layout::ValidateLayout::validate(&layout) - .unwrap_or_else(|error| { - { - ::core::panicking::panic_fmt( - format_args!("metadata ink! generation failed: {0}", error), - ); - } - }); - ::ink::metadata::InkProject::new( - layout, - ::ink::metadata::ContractSpec::new() - .constructors([ - ::ink::metadata::ConstructorSpec::from_label("new") - .selector([0x9B_u8, 0xAE_u8, 0x9D_u8, 0x5E_u8]) - .args([]) - .payable(true) - .default(false) - .returns( - ::ink::metadata::ReturnTypeSpec::new( - if >::IS_RESULT { - ::ink::metadata::TypeSpec::with_name_str::< - ::ink::ConstructorResult< - ::core::result::Result< - (), - >::Error, - >, - >, - >("ink_primitives::ConstructorResult") - } else { - ::ink::metadata::TypeSpec::with_name_str::< - ::ink::ConstructorResult<()>, - >("ink_primitives::ConstructorResult") - }, - ), - ) - .docs([]) - .done(), - ]) - .messages([ - ::ink::metadata::MessageSpec::from_label("total_supply") - .selector([0xDB_u8, 0x63_u8, 0x75_u8, 0xA8_u8]) - .args([ - ::ink::metadata::MessageParamSpec::new("id") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - AssetId, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["AssetId"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ]) - .returns( - ::ink::metadata::ReturnTypeSpec::new( - ::ink::metadata::TypeSpec::with_name_segs::< - ::ink::MessageResult>, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter([ - "ink", - "MessageResult", - ]), - ::core::convert::AsRef::as_ref, - ), - ), - ), - ) - .mutates(false) - .payable(false) - .default(false) - .docs([]) - .done(), - ::ink::metadata::MessageSpec::from_label("balance_of") - .selector([0x0F_u8, 0x75_u8, 0x5A_u8, 0x56_u8]) - .args([ - ::ink::metadata::MessageParamSpec::new("id") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - AssetId, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["AssetId"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ::ink::metadata::MessageParamSpec::new("owner") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - AccountId32, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["AccountId32"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ]) - .returns( - ::ink::metadata::ReturnTypeSpec::new( - ::ink::metadata::TypeSpec::with_name_segs::< - ::ink::MessageResult>, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter([ - "ink", - "MessageResult", - ]), - ::core::convert::AsRef::as_ref, - ), - ), - ), - ) - .mutates(false) - .payable(false) - .default(false) - .docs([]) - .done(), - ::ink::metadata::MessageSpec::from_label("allowance") - .selector([0x6A_u8, 0x00_u8, 0x16_u8, 0x5E_u8]) - .args([ - ::ink::metadata::MessageParamSpec::new("id") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - AssetId, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["AssetId"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ::ink::metadata::MessageParamSpec::new("owner") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - AccountId32, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["AccountId32"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ::ink::metadata::MessageParamSpec::new("spender") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - AccountId32, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["AccountId32"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ]) - .returns( - ::ink::metadata::ReturnTypeSpec::new( - ::ink::metadata::TypeSpec::with_name_segs::< - ::ink::MessageResult>, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter([ - "ink", - "MessageResult", - ]), - ::core::convert::AsRef::as_ref, - ), - ), - ), - ) - .mutates(false) - .payable(false) - .default(false) - .docs([]) - .done(), - ::ink::metadata::MessageSpec::from_label("asset_exists") - .selector([0xAA_u8, 0x6B_u8, 0x65_u8, 0xDB_u8]) - .args([ - ::ink::metadata::MessageParamSpec::new("id") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - AssetId, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["AssetId"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ]) - .returns( - ::ink::metadata::ReturnTypeSpec::new( - ::ink::metadata::TypeSpec::with_name_segs::< - ::ink::MessageResult>, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter([ - "ink", - "MessageResult", - ]), - ::core::convert::AsRef::as_ref, - ), - ), - ), - ) - .mutates(false) - .payable(false) - .default(false) - .docs([]) - .done(), - ::ink::metadata::MessageSpec::from_label("mint_asset") - .selector([0x1F_u8, 0x8E_u8, 0x8E_u8, 0x22_u8]) - .args([ - ::ink::metadata::MessageParamSpec::new("id") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - u32, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["u32"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ::ink::metadata::MessageParamSpec::new("beneficiary") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - AccountId32, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["AccountId32"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ::ink::metadata::MessageParamSpec::new("amount") - .of_type( - ::ink::metadata::TypeSpec::with_name_segs::< - Balance, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["Balance"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .done(), - ]) - .returns( - ::ink::metadata::ReturnTypeSpec::new( - ::ink::metadata::TypeSpec::with_name_segs::< - ::ink::MessageResult>, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter([ - "ink", - "MessageResult", - ]), - ::core::convert::AsRef::as_ref, - ), - ), - ), - ) - .mutates(false) - .payable(false) - .default(false) - .docs([]) - .done(), - ]) - .collect_events() - .docs([]) - .lang_error( - ::ink::metadata::TypeSpec::with_name_segs::< - ::ink::LangError, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["ink", "LangError"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .environment( - ::ink::metadata::EnvironmentSpec::new() - .account_id( - ::ink::metadata::TypeSpec::with_name_segs::< - AccountId, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["AccountId"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .balance( - ::ink::metadata::TypeSpec::with_name_segs::< - Balance, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["Balance"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .hash( - ::ink::metadata::TypeSpec::with_name_segs::< - Hash, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["Hash"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .timestamp( - ::ink::metadata::TypeSpec::with_name_segs::< - Timestamp, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["Timestamp"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .block_number( - ::ink::metadata::TypeSpec::with_name_segs::< - BlockNumber, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["BlockNumber"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .chain_extension( - ::ink::metadata::TypeSpec::with_name_segs::< - ChainExtension, - _, - >( - ::core::iter::Iterator::map( - ::core::iter::IntoIterator::into_iter(["ChainExtension"]), - ::core::convert::AsRef::as_ref, - ), - ), - ) - .max_event_topics(MAX_EVENT_TOPICS) - .static_buffer_size(::ink::env::BUFFER_SIZE) - .done(), - ) - .done(), - ) - } - }; - use super::*; -} diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 68e43865..59040590 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -7,61 +7,12 @@ /// use ink::prelude::vec::Vec; use pop_api::{ - assets::fungibles::*, + assets::use_cases::fungibles as api, + error::PopApiError, primitives::{AccountId as AccountId32, AssetId}, }; -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum ContractError { - /// The asset is not live; either frozen or being destroyed. - AssetNotLive, - /// The amount to mint is less than the existential deposit. - BelowMinimum, - /// Unspecified dispatch error, providing the index and its error index (if none `0`). - DispatchError { index: u8, error: u8 }, - /// Not enough allowance to fulfill a request is available. - InsufficientAllowance, - /// Not enough balance to fulfill a request is available. - InsufficientBalance, - /// The asset ID is already taken. - InUse, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// Unspecified pallet error, providing pallet index and error index. - ModuleError { pallet: u8, error: u16 }, - /// The account to alter does not exist. - NoAccount, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given asset ID is unknown. - Unknown, -} - -impl From for ContractError { - fn from(error: FungiblesError) -> Self { - match error { - FungiblesError::AssetNotLive => ContractError::AssetNotLive, - FungiblesError::BelowMinimum => ContractError::BelowMinimum, - FungiblesError::DispatchError { index, error } => { - ContractError::DispatchError { index, error } - }, - FungiblesError::InsufficientAllowance => ContractError::InsufficientAllowance, - FungiblesError::InsufficientBalance => ContractError::InsufficientBalance, - FungiblesError::InUse => ContractError::InUse, - FungiblesError::MinBalanceZero => ContractError::MinBalanceZero, - FungiblesError::ModuleError { pallet, error } => { - ContractError::ModuleError { pallet, error } - }, - FungiblesError::NoAccount => ContractError::NoAccount, - FungiblesError::NoPermission => ContractError::NoPermission, - FungiblesError::Unknown => ContractError::Unknown, - } - } -} - -/// The fungibles result type. -pub type Result = core::result::Result; +pub type Result = core::result::Result; #[ink::contract(env = pop_api::Environment)] mod fungibles { @@ -74,7 +25,7 @@ mod fungibles { impl Fungibles { #[ink(constructor, payable)] pub fn new() -> Self { - ink::env::debug_println!("PopApiAssetsExample::new"); + ink::env::debug_println!("PopApiFungiblesExample::new"); Default::default() } @@ -90,12 +41,12 @@ mod fungibles { #[ink(message)] pub fn total_supply(&self, id: AssetId) -> Result { - total_supply(id).map_err(From::from) + api::total_supply(id) } #[ink(message)] pub fn balance_of(&self, id: AssetId, owner: AccountId32) -> Result { - balance_of(id, owner).map_err(From::from) + api::balance_of(id, owner) } #[ink(message)] @@ -105,21 +56,21 @@ mod fungibles { owner: AccountId32, spender: AccountId32, ) -> Result { - allowance(id, owner, spender).map_err(From::from) + api::allowance(id, owner, spender) } #[ink(message)] pub fn transfer(&self, id: AssetId, to: AccountId32, value: Balance) -> Result<()> { ink::env::debug_println!( - "PopApiAssetsExample::transfer: id: {:?}, to: {:?} value: {:?}", + "PopApiFungiblesExample::transfer: id: {:?}, to: {:?} value: {:?}", id, to, value, ); - let result = transfer(id, to, value); + let result = api::transfer(id, to, value); ink::env::debug_println!("Result: {:?}", result); - result.map_err(From::from) + result } #[ink(message)] @@ -129,20 +80,21 @@ mod fungibles { from: Option, to: Option, value: Balance, - // Size needs to be known at compile time or ink's `Vec` + // In the standard a `[u8]`, but the size needs to be known at compile time ink's `Vec` + // has to be used. data: Vec, ) -> Result<()> { ink::env::debug_println!( - "PopApiAssetsExample::transfer_from: id: {:?}, from: {:?}, to: {:?} value: {:?}", + "PopApiFungiblesExample::transfer_from: id: {:?}, from: {:?}, to: {:?} value: {:?}", id, from, to, value, ); - let result = transfer_from(id, from, to, value, &data); + let result = api::transfer_from(id, from, to, value, &data); ink::env::debug_println!("Result: {:?}", result); - result.map_err(From::from) + result } /// 2. PSP-22 Metadata Interface: @@ -162,14 +114,14 @@ mod fungibles { #[ink(message)] pub fn create(&self, id: AssetId, admin: AccountId32, min_balance: Balance) -> Result<()> { ink::env::debug_println!( - "PopApiAssetsExample::create: id: {:?} admin: {:?} min_balance: {:?}", + "PopApiFungiblesExample::create: id: {:?} admin: {:?} min_balance: {:?}", id, admin, min_balance, ); - let result = create(id, admin, min_balance); + let result = api::create(id, admin, min_balance); ink::env::debug_println!("Result: {:?}", result); - result.map_err(From::from) + result } #[ink(message)] @@ -181,20 +133,20 @@ mod fungibles { decimals: u8, ) -> Result<()> { ink::env::debug_println!( - "PopApiAssetsExample::set_metadata: id: {:?} name: {:?} symbol: {:?}, decimals: {:?}", + "PopApiFungiblesExample::set_metadata: id: {:?} name: {:?} symbol: {:?}, decimals: {:?}", id, name, symbol, decimals, ); - let result = set_metadata(id, name, symbol, decimals); + let result = api::set_metadata(id, name, symbol, decimals); ink::env::debug_println!("Result: {:?}", result); - result.map_err(From::from) + result } #[ink(message)] pub fn asset_exists(&self, id: AssetId) -> Result { - asset_exists(id).map_err(From::from) + api::asset_exists(id) } } @@ -204,7 +156,7 @@ mod fungibles { #[ink::test] fn default_works() { - PopApiAssetsExample::new(); + PopApiFungiblesExample::new(); } } } diff --git a/pop-api/src/error.rs b/pop-api/src/error.rs new file mode 100644 index 00000000..92da4045 --- /dev/null +++ b/pop-api/src/error.rs @@ -0,0 +1,255 @@ +use crate::assets::use_cases::fungibles::{convert_to_fungibles_error, FungiblesError}; +use ink::env::chain_extension::FromStatusCode; +use scale::{Decode, Encode}; +use PopApiError::*; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +#[repr(u8)] +pub enum PopApiError { + /// Some unknown error occurred. Go to the Pop API docs section `Pop API error`. + Other { + // Index within the `DispatchError` + dispatch_error_index: u8, + // Index within the `DispatchError` variant. + error_index: u8, + // Index for further nesting, e.g. pallet error. + error: u8, + } = 0, + /// Failed to lookup some data. + CannotLookup = 1, + /// A bad origin. + BadOrigin = 2, + /// A custom error in a module. + Module { + index: u8, + error: u8, + } = 3, + /// At least one consumer is remaining so the account cannot be destroyed. + ConsumerRemaining = 4, + /// There are no providers so the account cannot be created. + NoProviders = 5, + /// There are too many consumers so the account cannot be created. + TooManyConsumers = 6, + /// An error to do with tokens. + Token(TokenError) = 7, + /// An arithmetic error. + Arithmetic(ArithmeticError) = 8, + /// The number of transactional layers has been reached, or we are not in a transactional + /// layer. + Transactional(TransactionalError) = 9, + /// Resources exhausted, e.g. attempt to read/write data which is too large to manipulate. + Exhausted = 10, + /// The state is corrupt; this is generally not going to fix itself. + Corruption = 11, + /// Some resource (e.g. a preimage) is unavailable right now. This might fix itself later. + Unavailable = 12, + /// Root origin is not allowed. + RootNotAllowed = 13, + // TODO: make generic and add docs. + UseCaseError(FungiblesError) = 254, + DecodingFailed = 255, +} + +impl FromStatusCode for PopApiError { + fn from_status_code(status_code: u32) -> core::result::Result<(), Self> { + match status_code { + 0 => Ok(()), + _ => Err(convert_to_pop_api_error(status_code)), + } + } +} + +// `pub` because it is used in `runtime/devnet/src/extensions/tests/mod.rs`'s test: +// `dispatch_error_to_status_code_to_pop_api_error_works` +// +// This function converts a given `status_code` (u32) into a `PopApiError`. First it encodes the +// status code into a 4-byte array and checks for unknown nested errors. If decoding into +// `PopApiError` fails (e.g. a breaking change in the `DispatchError`), it handles the error by +// converting it to the `Other` variant by shifting each byte one position forward (the last byte is +// not used for anything)and setting the first byte to 0. If decoding succeeds, it checks if the +// error is of the `Module` variant and performs any necessary conversion based on the use case. +pub fn convert_to_pop_api_error(status_code: u32) -> PopApiError { + let mut encoded: [u8; 4] = + status_code.encode().try_into().expect("qid u32 always encodes to 4 bytes"); + encoded = check_for_unknown_nesting(encoded); + let error = match PopApiError::decode(&mut &encoded[..]) { + Err(_) => { + encoded[3] = encoded[2]; + encoded[2] = encoded[1]; + encoded[1] = encoded[0]; + encoded[0] = 0; + PopApiError::decode(&mut &encoded[..]).unwrap().into() + }, + Ok(error) => { + if let crate::PopApiError::Module { index, error } = error { + // TODO: make generic. + convert_to_fungibles_error(index, error) + } else { + error + } + }, + }; + ink::env::debug_println!("PopApiError: {:?}", error); + error +} + +// If a unknown nested variant of the `DispatchError` is detected meaning any of the subsequent +// bytes are non-zero (e.g. breaking change in the DispatchError), the error needs to be converted +// into `PopApiError::Other`'s encoded value. This conversion is done by shifting the bytes one +// position forward (the last byte is discarded as it is not being used) and replacing the first +// byte with the `Other` encoded value (0u8). This ensures that the error is correctly categorized +// as an `Other` variant. +fn check_for_unknown_nesting(encoded_error: [u8; 4]) -> [u8; 4] { + if non_nested_pop_api_errors().contains(&encoded_error[0]) + && encoded_error[1..].iter().any(|x| *x != 0u8) + { + [0u8, encoded_error[0], encoded_error[1], encoded_error[2]] + } else if singular_nested_pop_api_errors().contains(&encoded_error[0]) + && encoded_error[2..].iter().any(|x| *x != 0u8) + { + [0u8, encoded_error[0], encoded_error[1], encoded_error[2]] + } else { + encoded_error + } +} + +impl From for PopApiError { + fn from(_: scale::Error) -> Self { + DecodingFailed + } +} +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum TokenError { + /// Funds are unavailable. + FundsUnavailable, + /// Some part of the balance gives the only provider reference to the account and thus cannot + /// be (re)moved. + OnlyProvider, + /// Account cannot exist with the funds that would be given. + BelowMinimum, + /// Account cannot be created. + CannotCreate, + /// The asset in question is unknown. + UnknownAsset, + /// Funds exist but are frozen. + Frozen, + /// Operation is not supported by the asset. + Unsupported, + /// Account cannot be created for a held balance. + CannotCreateHold, + /// Withdrawal would cause unwanted loss of account. + NotExpendable, + /// Account cannot receive the assets. + Blocked, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum ArithmeticError { + /// Underflow. + Underflow, + /// Overflow. + Overflow, + /// Division by zero. + DivisionByZero, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum TransactionalError { + /// Too many transactional layers have been spawned. + LimitReached, + /// A transactional layer was expected, but does not exist. + NoLayer, +} + +fn singular_nested_pop_api_errors() -> [u8; 3] { + const TOKEN_ERROR: u8 = 7; + const ARITHMETIC_ERROR: u8 = 8; + const TRANSACTION_ERROR: u8 = 9; + [TOKEN_ERROR, ARITHMETIC_ERROR, TRANSACTION_ERROR] +} + +fn non_nested_pop_api_errors() -> [u8; 9] { + const CANNOT_LOOKUP: u8 = 1; + const BAD_ORIGIN: u8 = 2; + const CONSUMER_REMAINING: u8 = 4; + const NO_PROVIDERS: u8 = 5; + const TOO_MANY_CONSUMERS: u8 = 6; + const EXHAUSTED: u8 = 10; + const CORRUPTION: u8 = 11; + const UNAVAILABLE: u8 = 12; + const ROOT_NOT_ALLOWED: u8 = 13; + [ + CANNOT_LOOKUP, + BAD_ORIGIN, + CONSUMER_REMAINING, + NO_PROVIDERS, + TOO_MANY_CONSUMERS, + EXHAUSTED, + CORRUPTION, + UNAVAILABLE, + ROOT_NOT_ALLOWED, + ] +} + +#[test] +fn u32_always_encodes_to_4_bytes() { + assert_eq!(0u32.encode().len(), 4); + assert_eq!(u32::MAX.encode().len(), 4); +} + +// If decoding failed the encoded value is converted to the `PopApiError::Other`. This handles +// unknown errors coming from the runtime. This could happen if a contract is not upgraded to the +// latest Pop API version. +#[test] +fn test_non_existing_pop_api_errors() { + let encoded_error = [7u8, 100u8, 0u8, 0u8]; + let status_code = u32::decode(&mut &encoded_error[..]).unwrap(); + let pop_api_error = ::from_status_code(status_code); + assert_eq!(Err(Other { dispatch_error_index: 7, error_index: 100, error: 0 }), pop_api_error); +} + +// If the encoded value indicates a nested PopApiError which is not handled by the Pop API version, +// the encoded value is converted into `PopApiError::Other`. +#[test] +fn check_for_unknown_nested_pop_api_errors_works() { + for &error_code in &non_nested_pop_api_errors() { + let encoded_error = [error_code, 1, 2, 3]; + let result = check_for_unknown_nesting(encoded_error); + let decoded = PopApiError::decode(&mut &result[..]).unwrap(); + + assert_eq!( + decoded, + Other { dispatch_error_index: error_code, error_index: 1, error: 2 }, + "Failed for error code: {}", + error_code + ); + } + for &error_code in &singular_nested_pop_api_errors() { + let encoded_error = [error_code, 1, 2, 3]; + let result = check_for_unknown_nesting(encoded_error); + let decoded = PopApiError::decode(&mut &result[..]).unwrap(); + + assert_eq!( + decoded, + Other { dispatch_error_index: error_code, error_index: 1, error: 2 }, + "Failed for error code: {}", + error_code + ); + } +} + +// This test ensures that a non-zero value for unused bytes does not interfere with the correct +// decoding of the error. It verifies that even with an additional byte, the errors are correctly +// decoded and represented in its correct variant. +#[test] +fn extra_byte_does_not_mess_up_decoding() { + // Module error + let encoded_error = [3u8, 4u8, 5u8, 6u8]; + let status_code = u32::decode(&mut &encoded_error[..]).unwrap(); + let pop_api_error = ::from_status_code(status_code); + assert_eq!(Err(Module { index: 4, error: 5 }), pop_api_error); +} diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index be448890..a785aebe 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,19 +1,19 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use core::convert::TryInto; +use crate::error::PopApiError; use ink::{prelude::vec::Vec, ChainExtensionInstance}; use primitives::{cross_chain::*, storage_keys::*, AccountId as AccountId32}; +use scale::Encode; pub use sp_runtime::{BoundedVec, MultiAddress, MultiSignature}; use v0::RuntimeCall; -pub use v0::{ - assets, balances, contracts, cross_chain, dispatch_error, nfts, relay_chain_block_number, state, -}; +pub use v0::{assets, balances, cross_chain, nfts, relay_chain_block_number, state}; +pub mod error; pub mod primitives; pub mod v0; -// type AccountId = ::AccountId; type AccountId = AccountId32; +// TODO: do the same as above and check expanded code. type Balance = ::Balance; type BlockNumber = ::BlockNumber; type StringLimit = u32; @@ -21,54 +21,6 @@ type MaxTips = u32; pub type Result = core::result::Result; -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum PopApiError { - Assets(assets::fungibles::AssetsError), - Balances(balances::BalancesError), - Contracts(contracts::Error), - DecodingFailed, - Nfts(nfts::Error), - SystemCallFiltered, - TokenError(dispatch_error::TokenError), - UnknownModuleStatusCode(u32), - UnknownDispatchStatusCode(u32), - Xcm(cross_chain::Error), -} - -impl ink::env::chain_extension::FromStatusCode for PopApiError { - fn from_status_code(status_code: u32) -> core::result::Result<(), Self> { - use crate::PopApiError::{ - Assets, Balances, Contracts, Nfts, TokenError, UnknownDispatchStatusCode, - UnknownModuleStatusCode, - }; - - match status_code { - 0 => Ok(()), - 3_000_000..=3_999_999 => { - let status_code = status_code - 3_000_000; - match status_code { - // CallFiltered originates from `frame_system` with pallet-index 0. The CallFiltered error is at index 5 - 5 => Err(PopApiError::SystemCallFiltered), - 10_000..=10_999 => Err(Balances((status_code - 10_000).try_into()?)), - 40_000..=40_999 => Err(Contracts((status_code - 40_000).try_into()?)), - 50_000..=50_999 => Err(Nfts((status_code - 50_000).try_into()?)), - 52_000..=52_999 => Err(Assets((status_code - 52_000).try_into()?)), - _ => Err(UnknownModuleStatusCode(status_code)), - } - }, - 7_000_000..=7_999_999 => Err(TokenError((status_code - 7_000_000).try_into()?)), - _ => Err(UnknownDispatchStatusCode(status_code)), - } - } -} - -impl From for PopApiError { - fn from(_: scale::Error) -> Self { - panic!("encountered unexpected invalid SCALE encoding") - } -} - #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum Environment {} diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs deleted file mode 100644 index df9033c7..00000000 --- a/pop-api/src/v0/assets/fungibles.rs +++ /dev/null @@ -1,610 +0,0 @@ -use crate::{ - balances::BalancesError, AccountId, Balance, PopApiError::UnknownModuleStatusCode, RuntimeCall, - *, -}; -use ink::prelude::vec::Vec; -use primitives::AssetId; -use scale::{Compact, Encode}; - -type Result = core::result::Result; - -/// Local Fungibles: -/// 1. PSP-22 Interface -/// 2. PSP-22 Metadata Interface -/// 3. Asset Management - -/// 1. PSP-22 Interface: -/// - total_supply -/// - balance_of -/// - allowance -/// - transfer -/// - transfer_from -/// - approve -/// - increase_allowance -/// - decrease_allowance - -/// Returns the total token supply for a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// The total supply of the token, or an error if the operation fails. -pub fn total_supply(id: AssetId) -> Result { - Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id)))?) -} - -/// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if -/// the account is non-existent. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `owner` - The account whose balance is being queried. -/// -/// # Returns -/// The balance of the specified account, or an error if the operation fails. -pub fn balance_of(id: AssetId, owner: AccountId) -> Result { - Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner)))?) -} - -/// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given -/// asset ID. Returns `0` if no allowance has been set. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `owner` - The account that owns the tokens. -/// * `spender` - The account that is allowed to spend the tokens. -/// -/// # Returns -/// The remaining allowance, or an error if the operation fails. -pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender)))?) -} - -/// Transfers `value` amount of tokens from the caller's account to account `to`, with additional -/// `data` in unspecified format. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `to` - The recipient account. -/// * `value` - The number of tokens to transfer. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the transfer fails. -pub fn transfer( - id: AssetId, - to: impl Into>, - value: Balance, -) -> Result<()> { - // TODO: transfer or transfer_keep_alive - // Ok(dispatch(RuntimeCall::Assets(AssetsCall::Transfer { - // id: id.into(), - // target: target.into(), - // amount: Compact(amount), - // }))?) - Ok(dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { - id: id.into(), - target: to.into(), - amount: Compact(value), - }))?) -} - -/// Transfers `value` tokens on behalf of `from` to account `to` with additional `data` -/// in unspecified format. If `from` is equal to `None`, tokens will be minted to account `to`. If -/// `to` is equal to `None`, tokens will be burned from account `from`. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `from` - The account from which the tokens are transferred. -/// * `to` - The recipient account. -/// * `value` - The number of tokens to transfer. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the transfer fails. -pub fn transfer_from( - id: AssetId, - from: Option>>, - to: Option>>, - value: Balance, - _data: &[u8], -) -> Result<()> { - match (from, to) { - (None, Some(to)) => mint(id, to, value), - // (Some(from), None) => burn(id, from, value), - (Some(from), Some(to)) => { - Ok(dispatch(RuntimeCall::Assets(AssetsCall::TransferApproved { - id: id.into(), - owner: from.into(), - destination: to.into(), - amount: Compact(value), - }))?) - }, - _ => Ok(()), - } -} - -/// Approves an account to spend a specified number of tokens on behalf of the caller. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `spender` - The account that is allowed to spend the tokens. -/// * `value` - The number of tokens to approve. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the approval fails. -// #[allow(unused_variables)] -// fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { -// todo!() -// // TODO: read allowance and increase or decrease. -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { -// // id: id.into(), -// // delegate: spender.into(), -// // amount: Compact(value), -// // }))?) -// } - -/// Increases the allowance of a spender. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `spender` - The account that is allowed to spend the tokens. -/// * `value` - The number of tokens to increase the allowance by. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { -// id: id.into(), -// delegate: spender.into(), -// amount: Compact(value), -// }))?) -// } - -/// Decreases the allowance of a spender. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `spender` - The account that is allowed to spend the tokens. -/// * `value` - The number of tokens to decrease the allowance by. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// #[allow(unused_variables)] -// fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { -// todo!() -// // TODO: cancel_approval + approve_transfer -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::CancelApproval { -// // id: id.into(), -// // delegate: delegate.into(), -// // }))?) -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { -// // id: id.into(), -// // delegate: spender.into(), -// // amount: Compact(value), -// // }))?) -// } - -/// 2. PSP-22 Metadata Interface: -/// - token_name -/// - token_symbol -/// - token_decimals - -/// Returns the token name for a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// The name of the token as a byte vector, or an error if the operation fails. -// #[allow(unused_variables)] -// pub fn token_name(id: AssetId) -> Result>> { -// todo!() -// // Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenName(id)))?) -// } - -/// Returns the token symbol for a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// The symbol of the token as a byte vector, or an error if the operation fails. -// #[allow(unused_variables)] -// fn token_symbol(id: AssetId) -> Result>> { -// todo!() -// } - -/// Returns the token decimals for a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// The number of decimals of the token as a byte vector, or an error if the operation fails. -// #[allow(unused_variables)] -// fn token_decimals(id: AssetId) -> Result>> { -// todo!() -// } - -/// 3. Asset Management: -/// - create -/// - start_destroy -/// - destroy_accounts -/// - destroy_approvals -/// - finish_destroy -/// - set_metadata -/// - clear_metadata - -/// Create a new token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `admin` - The account that will administer the asset. -/// * `min_balance` - The minimum balance required for accounts holding this asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the creation fails. -pub fn create( - id: AssetId, - admin: impl Into>, - min_balance: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::Assets(AssetsCall::Create { - id: id.into(), - admin: admin.into(), - min_balance, - }))?) -} - -/// Start the process of destroying a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn start_destroy(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { -// id: id.into(), -// }))?) -// } - -/// Destroy all accounts associated with a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn destroy_accounts(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { -// id: id.into(), -// }))?) -// } - -/// Destroy all approvals associated with a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn destroy_approvals(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { -// id: id.into(), -// }))?) -// } - -/// Complete the process of destroying a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn finish_destroy(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { -// id: id.into(), -// }))?) -// } - -/// Set the metadata for a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { - Ok(dispatch(RuntimeCall::Assets(AssetsCall::SetMetadata { - id: id.into(), - name, - symbol, - decimals, - }))?) -} - -/// Clear the metadata for a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn clear_metadata(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { -// id: id.into(), -// }))?) -// } - -pub fn asset_exists(id: AssetId) -> Result { - Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id)))?) -} - -/// Mint assets of a particular class. -fn mint( - id: AssetId, - beneficiary: impl Into>, - amount: Balance, -) -> Result<()> { - Ok(dispatch(RuntimeCall::Assets(AssetsCall::Mint { - id: id.into(), - beneficiary: beneficiary.into(), - amount: Compact(amount), - }))?) -} - -// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount -// (`Balance`) are expected to be compact encoded. The pop api handles that for the developer. -// https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development -// -// Asset id that is compact encoded. -type AssetIdParameter = Compact; -// Balance amount that is compact encoded. -type BalanceParameter = Compact; - -#[allow(warnings, unused)] -#[derive(Encode)] -pub(crate) enum AssetsCall { - #[codec(index = 0)] - Create { id: AssetIdParameter, admin: MultiAddress, min_balance: Balance }, - #[codec(index = 2)] - StartDestroy { id: AssetIdParameter }, - #[codec(index = 3)] - DestroyAccounts { id: AssetIdParameter }, - #[codec(index = 4)] - DestroyApprovals { id: AssetIdParameter }, - #[codec(index = 5)] - FinishDestroy { id: AssetIdParameter }, - #[codec(index = 6)] - Mint { - id: AssetIdParameter, - beneficiary: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 7)] - Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, - // TODO: ED or not - // #[codec(index = 8)] - // Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, - #[codec(index = 9)] - TransferKeepAlive { - id: AssetIdParameter, - target: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 17)] - SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, - #[codec(index = 18)] - ClearMetadata { id: AssetIdParameter }, - #[codec(index = 22)] - ApproveTransfer { - id: AssetIdParameter, - delegate: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 23)] - CancelApproval { id: AssetIdParameter, delegate: MultiAddress }, - #[codec(index = 25)] - TransferApproved { - id: AssetIdParameter, - owner: MultiAddress, - destination: MultiAddress, - amount: BalanceParameter, - }, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub(crate) enum AssetsError { - /// Account balance must be greater than or equal to the transfer amount. - BalanceLow, - /// The account to alter does not exist. - NoAccount, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given asset ID is unknown. - Unknown, - /// The origin account is frozen. - Frozen, - /// The asset ID is already taken. - InUse, - /// Invalid witness data given. - BadWitness, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// Unable to increment the consumer reference counters on the account. Either no provider - /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one - /// fewer then the maximum number of consumers has been reached. - UnavailableConsumer, - /// Invalid metadata given. - BadMetadata, - /// No approval exists that would allow the transfer. - Unapproved, - /// The source account would not survive the transfer and it needs to stay alive. - WouldDie, - /// The asset-account already exists. - AlreadyExists, - /// The asset-account doesn't have an associated deposit. - NoDeposit, - /// The operation would result in funds being burned. - WouldBurn, - /// The asset is a live asset and is actively being used. Usually emit for operations such - /// as `start_destroy` which require the asset to be in a destroying state. - LiveAsset, - /// The asset is not live, and likely being destroyed. - AssetNotLive, - /// The asset status is not the expected status. - IncorrectStatus, - /// The asset should be frozen before the given operation. - NotFrozen, - /// Callback action resulted in error - CallbackFailed, -} - -impl From for AssetsError { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Assets(e) => e, - _ => panic!("Expected AssetsError"), - } - } -} - -impl TryFrom for AssetsError { - type Error = PopApiError; - - fn try_from(status_code: u32) -> core::result::Result { - use AssetsError::*; - match status_code { - 0 => Ok(BalanceLow), - 1 => Ok(NoAccount), - 2 => Ok(NoPermission), - 3 => Ok(Unknown), - 4 => Ok(Frozen), - 5 => Ok(InUse), - 6 => Ok(BadWitness), - 7 => Ok(MinBalanceZero), - 8 => Ok(UnavailableConsumer), - 9 => Ok(BadMetadata), - 10 => Ok(Unapproved), - 11 => Ok(WouldDie), - 12 => Ok(AlreadyExists), - 13 => Ok(NoDeposit), - 14 => Ok(WouldBurn), - 15 => Ok(LiveAsset), - 16 => Ok(AssetNotLive), - 17 => Ok(IncorrectStatus), - 18 => Ok(NotFrozen), - _ => Err(UnknownModuleStatusCode(status_code)), - } - } -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum FungiblesError { - /// The asset is not live; either frozen or being destroyed. - AssetNotLive, - /// The amount to mint is less than the existential deposit. - BelowMinimum, - /// Unspecified dispatch error, providing the index and its error index (if none `0`). - DispatchError { index: u8, error: u8 }, - /// Not enough allowance to fulfill a request is available. - InsufficientAllowance, - /// Not enough balance to fulfill a request is available. - InsufficientBalance, - /// The asset ID is already taken. - InUse, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// Unspecified pallet error, providing pallet index and error index. - ModuleError { pallet: u8, error: u16 }, - /// The account to alter does not exist. - NoAccount, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given asset ID is unknown. - Unknown, -} - -impl From for FungiblesError { - fn from(error: BalancesError) -> Self { - match error { - // TODO: this insufficient balance is different than the assets variant. This one is - // for a deposit of creating an asset, the latter is for transfer tokens. - BalancesError::InsufficientBalance => FungiblesError::InsufficientBalance, - _ => FungiblesError::ModuleError { pallet: 40, error: error as u16 }, - } - } -} - -impl From for FungiblesError { - fn from(error: dispatch_error::TokenError) -> Self { - match error { - dispatch_error::TokenError::BelowMinimum => FungiblesError::BelowMinimum, - // ED is not respected. - dispatch_error::TokenError::OnlyProvider => FungiblesError::InsufficientBalance, - dispatch_error::TokenError::UnknownAsset => FungiblesError::Unknown, - _ => FungiblesError::DispatchError { index: 7, error: error as u8 }, - } - } -} - -impl From for FungiblesError { - fn from(error: AssetsError) -> Self { - match error { - AssetsError::AssetNotLive => FungiblesError::AssetNotLive, - AssetsError::BalanceLow => FungiblesError::InsufficientBalance, - AssetsError::Unapproved => FungiblesError::InsufficientAllowance, - AssetsError::InUse => FungiblesError::InUse, - AssetsError::MinBalanceZero => FungiblesError::MinBalanceZero, - AssetsError::NoPermission => FungiblesError::NoPermission, - AssetsError::NoAccount => FungiblesError::NoAccount, - AssetsError::Unknown => FungiblesError::Unknown, - _ => FungiblesError::ModuleError { pallet: 52, error: error as u16 }, - } - } -} - -impl From for FungiblesError { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Assets(e) => e.into(), - PopApiError::Balances(e) => e.into(), - PopApiError::TokenError(e) => e.into(), - PopApiError::UnknownModuleStatusCode(e) => { - let pallet = (e / 1_000) as u8; - let error = (e % 1_000) as u16; - FungiblesError::ModuleError { pallet, error } - }, - PopApiError::UnknownDispatchStatusCode(e) => { - let index = (e / 1_000_000) as u8; - let error = (3 % 1_000_000) as u8; - FungiblesError::DispatchError { index, error } - }, - _ => todo!(), - } - } -} - -// macro_rules! impl_error_conversion { -// ($pallet_index:, $pallet_error:ty, $interface_error:ty, $($variant:ident),*) => { -// impl From<$pallet_error> for $interface_error { -// fn from(error: $pallet_error) -> Self { -// match error { -// $( -// <$pallet_error>::$variant => <$interface_error>::$variant, -// )* -// _ => <$interface_error>::ModuleError { pallet: 0, error: [255, 0, 0, 0] }, // Default case -// } -// } -// } -// -// impl FromPalletError<$pallet_error> for $interface_error { -// fn from_pallet_error(error: $pallet_error) -> Self { -// Self::from(error) -// } -// } -// }; -// } diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index d6b0261c..736ccc0e 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1 +1,2 @@ -pub mod fungibles; \ No newline at end of file +pub(crate) mod pallets; +pub mod use_cases; diff --git a/pop-api/src/v0/assets/pallets/assets.rs b/pop-api/src/v0/assets/pallets/assets.rs new file mode 100644 index 00000000..7a575e08 --- /dev/null +++ b/pop-api/src/v0/assets/pallets/assets.rs @@ -0,0 +1,491 @@ +// TODO: what to put in this file? +#![allow(dead_code)] + +use crate::{Balance, RuntimeCall, *}; +use ink::prelude::vec::Vec; +use primitives::{AssetId, MultiAddress}; +use scale::{Compact, Encode}; + +type Result = core::result::Result; + +/// [Pallet Assets](https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/lib.rs): +/// 1. Dispatchables +/// 2. Read state functions +/// +/// 1. Dispatchables within pallet assets (TrustBackedAssets instance) that can be used via the pop api on Pop Network: +/// - create +/// - start_destroy +/// - destroy_accounts +/// - destroy_approvals +/// - finish_destroy +/// - mint +/// - burn +/// - transfer +/// - transfer_keep_alive +/// - force_transfer +/// - freeze +/// - thaw +/// - freeze_asset +/// - thaw_asset +/// - transfer_ownership +/// - set_team +/// - set_metadata +/// - clear_metadata +/// - approve_transfer +/// - cancel_approval +/// - force_cancel_approval +/// - transfer_approved +/// - touch +/// - refund +/// - set_min_balance +/// - touch_other +/// - refund_other +/// - block + +/// Issue a new class of fungible assets from a public origin. +pub(crate) fn create( + id: AssetId, + admin: impl Into>, + min_balance: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Create { + id: id.into(), + admin: admin.into(), + min_balance, + })) +} + +/// Start the process of destroying a fungible asset class. +pub(crate) fn start_destroy(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { id: id.into() })) +} + +/// Destroy all accounts associated with a given asset. +pub(crate) fn destroy_accounts(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { id: id.into() })) +} + +/// Destroy all approvals associated with a given asset up to the max (see runtime configuration Assets `RemoveItemsLimit`). +pub(crate) fn destroy_approvals(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { id: id.into() })) +} + +/// Complete destroying asset and unreserve currency. +pub(crate) fn finish_destroy(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { id: id.into() })) +} + +/// Mint assets of a particular class. +pub(crate) fn mint( + id: AssetId, + beneficiary: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Mint { + id: id.into(), + beneficiary: beneficiary.into(), + amount: Compact(amount), + })) +} + +/// Reduce the balance of `who` by as much as possible up to `amount` assets of `id`. +pub(crate) fn burn( + id: AssetId, + who: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Burn { + id: id.into(), + who: who.into(), + amount: Compact(amount), + })) +} + +/// Move some assets from the sender account to another. +pub(crate) fn transfer( + id: AssetId, + target: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { + id: id.into(), + target: target.into(), + amount: Compact(amount), + })) +} + +/// Move some assets from the sender account to another, keeping the sender account alive. +pub(crate) fn transfer_keep_alive( + id: AssetId, + target: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { + id: id.into(), + target: target.into(), + amount: Compact(amount), + })) +} + +/// Move some assets from one account to another. Sender should be the Admin of the asset `id`. +pub(crate) fn force_transfer( + id: AssetId, + source: impl Into>, + dest: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ForceTransfer { + id: id.into(), + source: source.into(), + dest: dest.into(), + amount: Compact(amount), + })) +} + +/// Disallow further unprivileged transfers of an asset `id` from an account `who`. `who` +/// must already exist as an entry in `Account`s of the asset. If you want to freeze an +/// account that does not have an entry, use `touch_other` first. +pub(crate) fn freeze(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Freeze { id: id.into(), who: who.into() })) +} + +/// Allow unprivileged transfers to and from an account again. +pub(crate) fn thaw(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Thaw { id: id.into(), who: who.into() })) +} + +/// Disallow further unprivileged transfers for the asset class. +pub(crate) fn freeze_asset(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::FreezeAsset { id: id.into() })) +} + +/// Allow unprivileged transfers for the asset again. +pub(crate) fn thaw_asset(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ThawAsset { id: id.into() })) +} + +/// Change the Owner of an asset. +pub(crate) fn transfer_ownership( + id: AssetId, + owner: impl Into>, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TransferOwnership { + id: id.into(), + owner: owner.into(), + })) +} + +/// Change the Issuer, Admin and Freezer of an asset. +pub(crate) fn set_team( + id: AssetId, + issuer: impl Into>, + admin: impl Into>, + freezer: impl Into>, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::SetTeam { + id: id.into(), + issuer: issuer.into(), + admin: admin.into(), + freezer: freezer.into(), + })) +} + +/// Set the metadata for an asset. +pub(crate) fn set_metadata( + id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::SetMetadata { id: id.into(), name, symbol, decimals })) +} + +/// Clear the metadata for an asset. +pub(crate) fn clear_metadata(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { id: id.into() })) +} + +/// Approve an amount of asset for transfer by a delegated third-party account. +pub(crate) fn approve_transfer( + id: AssetId, + delegate: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { + id: id.into(), + delegate: delegate.into(), + amount: Compact(amount), + })) +} + +/// Cancel all of some asset approved for delegated transfer by a third-party account. +pub(crate) fn cancel_approval( + id: AssetId, + delegate: impl Into>, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::CancelApproval { + id: id.into(), + delegate: delegate.into(), + })) +} + +/// Cancel all of some asset approved for delegated transfer by a third-party account. +pub(crate) fn force_cancel_approval( + id: AssetId, + owner: impl Into>, + delegate: impl Into>, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ForceCancelApproval { + id: id.into(), + owner: owner.into(), + delegate: delegate.into(), + })) +} + +/// Transfer some asset balance from a previously delegated account to some third-party +/// account. +pub(crate) fn transfer_approved( + id: AssetId, + owner: impl Into>, + destination: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TransferApproved { + id: id.into(), + owner: owner.into(), + destination: destination.into(), + amount: Compact(amount), + })) +} + +/// Create an asset account for non-provider assets. +pub(crate) fn touch(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Touch { id: id.into() })) +} + +/// Return the deposit (if any) of an asset account or a consumer reference (if any) of an +/// account. +pub(crate) fn refund(id: AssetId, allow_burn: bool) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Refund { id: id.into(), allow_burn })) +} + +/// Sets the minimum balance of an asset. +pub(crate) fn set_min_balance(id: AssetId, min_balance: Balance) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::SetMinBalance { + id: id.into(), + min_balance: Compact(min_balance), + })) +} + +/// Create an asset account for `who`. +pub(crate) fn touch_other(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TouchOther { id: id.into(), who: who.into() })) +} + +/// Return the deposit (if any) of a target asset account. Useful if you are the depositor. +pub(crate) fn refund_other(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::RefundOther { id: id.into(), who: who.into() })) +} + +/// Disallow further unprivileged transfers of an asset `id` to and from an account `who`. +pub(crate) fn block(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Block { id: id.into(), who: who.into() })) +} + +/// 2. Read state functions +/// - total_supply +/// - + +pub(crate) fn total_supply(id: AssetId) -> Result { + state::read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id))).into() +} + +pub(crate) fn balance_of(id: AssetId, owner: AccountId) -> Result { + state::read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner))).into() +} + +pub(crate) fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { + state::read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender))).into() +} +pub(crate) fn asset_exists(id: AssetId) -> Result { + state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))).into() +} + +// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected +// to be compact encoded. The pop api handles that for the developer. +// +// reference: https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development +// +// Asset id that is compact encoded. +type AssetIdParameter = Compact; +// Balance amount that is compact encoded. +type BalanceParameter = Compact; + +#[derive(Encode)] +pub(crate) enum AssetsCall { + #[codec(index = 0)] + Create { id: AssetIdParameter, admin: MultiAddress, min_balance: Balance }, + #[codec(index = 2)] + StartDestroy { id: AssetIdParameter }, + #[codec(index = 3)] + DestroyAccounts { id: AssetIdParameter }, + #[codec(index = 4)] + DestroyApprovals { id: AssetIdParameter }, + #[codec(index = 5)] + FinishDestroy { id: AssetIdParameter }, + #[codec(index = 6)] + Mint { + id: AssetIdParameter, + beneficiary: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 7)] + Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, + #[codec(index = 8)] + Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, + #[codec(index = 9)] + TransferKeepAlive { + id: AssetIdParameter, + target: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 10)] + ForceTransfer { + id: AssetIdParameter, + source: MultiAddress, + dest: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 11)] + Freeze { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 12)] + Thaw { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 13)] + FreezeAsset { id: AssetIdParameter }, + #[codec(index = 14)] + ThawAsset { id: AssetIdParameter }, + #[codec(index = 15)] + TransferOwnership { id: AssetIdParameter, owner: MultiAddress }, + #[codec(index = 16)] + SetTeam { + id: AssetIdParameter, + issuer: MultiAddress, + admin: MultiAddress, + freezer: MultiAddress, + }, + #[codec(index = 17)] + SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, + #[codec(index = 18)] + ClearMetadata { id: AssetIdParameter }, + #[codec(index = 22)] + ApproveTransfer { + id: AssetIdParameter, + delegate: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 23)] + CancelApproval { id: AssetIdParameter, delegate: MultiAddress }, + #[codec(index = 24)] + ForceCancelApproval { + id: AssetIdParameter, + owner: MultiAddress, + delegate: MultiAddress, + }, + #[codec(index = 25)] + TransferApproved { + id: AssetIdParameter, + owner: MultiAddress, + destination: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 26)] + Touch { id: AssetIdParameter }, + #[codec(index = 27)] + Refund { id: AssetIdParameter, allow_burn: bool }, + #[codec(index = 28)] + SetMinBalance { id: AssetIdParameter, min_balance: BalanceParameter }, + #[codec(index = 29)] + TouchOther { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 30)] + RefundOther { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 31)] + Block { id: AssetIdParameter, who: MultiAddress }, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum AssetsError { + /// Account balance must be greater than or equal to the transfer amount. + BalanceLow, + /// The account to alter does not exist. + NoAccount, + /// The signing account has no permission to do the operation. + NoPermission, + /// The given asset ID is unknown. + Unknown, + /// The origin account is frozen. + Frozen, + /// The asset ID is already taken. + InUse, + /// Invalid witness data given. + BadWitness, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// Unable to increment the consumer reference counters on the account. Either no provider + /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one + /// fewer then the maximum number of consumers has been reached. + UnavailableConsumer, + /// Invalid metadata given. + BadMetadata, + /// No approval exists that would allow the transfer. + Unapproved, + /// The source account would not survive the transfer and it needs to stay alive. + WouldDie, + /// The asset-account already exists. + AlreadyExists, + /// The asset-account doesn't have an associated deposit. + NoDeposit, + /// The operation would result in funds being burned. + WouldBurn, + /// The asset is a live asset and is actively being used. Usually emit for operations such + /// as `start_destroy` which require the asset to be in a destroying state. + LiveAsset, + /// The asset is not live, and likely being destroyed. + AssetNotLive, + /// The asset status is not the expected status. + IncorrectStatus, + /// The asset should be frozen before the given operation. + NotFrozen, + /// Callback action resulted in error. + CallbackFailed, +} + +impl TryFrom for AssetsError { + type Error = PopApiError; + + fn try_from(status_code: u32) -> core::result::Result { + use AssetsError::*; + match status_code { + 0 => Ok(BalanceLow), + 1 => Ok(NoAccount), + 2 => Ok(NoPermission), + 3 => Ok(Unknown), + 4 => Ok(Frozen), + 5 => Ok(InUse), + 6 => Ok(BadWitness), + 7 => Ok(MinBalanceZero), + 8 => Ok(UnavailableConsumer), + 9 => Ok(BadMetadata), + 10 => Ok(Unapproved), + 11 => Ok(WouldDie), + 12 => Ok(AlreadyExists), + 13 => Ok(NoDeposit), + 14 => Ok(WouldBurn), + 15 => Ok(LiveAsset), + 16 => Ok(AssetNotLive), + 17 => Ok(IncorrectStatus), + 18 => Ok(NotFrozen), + _ => todo!(), + } + } +} diff --git a/pop-api/src/v0/assets/pallets/mod.rs b/pop-api/src/v0/assets/pallets/mod.rs new file mode 100644 index 00000000..0b8a53a0 --- /dev/null +++ b/pop-api/src/v0/assets/pallets/mod.rs @@ -0,0 +1 @@ +pub(crate) mod assets; diff --git a/pop-api/src/v0/assets/use_cases/fungibles.rs b/pop-api/src/v0/assets/use_cases/fungibles.rs new file mode 100644 index 00000000..4af5d97e --- /dev/null +++ b/pop-api/src/v0/assets/use_cases/fungibles.rs @@ -0,0 +1,372 @@ +use crate::{ + assets::pallets, + error::PopApiError::{self, *}, + AccountId, Balance, *, +}; +use ink::prelude::vec::Vec; +use primitives::AssetId; + +type Result = core::result::Result; + +/// Local Fungibles: +/// 1. PSP-22 Interface +/// 2. PSP-22 Metadata Interface +/// 3. Asset Management + +/// 1. PSP-22 Interface: +/// - total_supply +/// - balance_of +/// - allowance +/// - transfer +/// - transfer_from +/// - approve +/// - increase_allowance +/// - decrease_allowance + +/// Returns the total token supply for a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// The total supply of the token, or an error if the operation fails. +pub fn total_supply(id: AssetId) -> Result { + pallets::assets::total_supply(id) +} + +/// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if +/// the account is non-existent. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `owner` - The account whose balance is being queried. +/// +/// # Returns +/// The balance of the specified account, or an error if the operation fails. +pub fn balance_of(id: AssetId, owner: AccountId) -> Result { + pallets::assets::balance_of(id, owner) +} + +/// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given +/// asset ID. Returns `0` if no allowance has been set. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `owner` - The account that owns the tokens. +/// * `spender` - The account that is allowed to spend the tokens. +/// +/// # Returns +/// The remaining allowance, or an error if the operation fails. +pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { + pallets::assets::allowance(id, owner, spender) +} + +/// Transfers `value` amount of tokens from the caller's account to account `to`, with additional +/// `data` in unspecified format. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `to` - The recipient account. +/// * `value` - The number of tokens to transfer. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the transfer fails. +pub fn transfer( + id: AssetId, + to: impl Into>, + value: Balance, +) -> Result<()> { + pallets::assets::transfer(id, to, value) +} + +/// Transfers `value` tokens on behalf of `from` to account `to` with additional `data` +/// in unspecified format. If `from` is equal to `None`, tokens will be minted to account `to`. If +/// `to` is equal to `None`, tokens will be burned from account `from`. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `from` - The account from which the tokens are transferred. +/// * `to` - The recipient account. +/// * `value` - The number of tokens to transfer. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the transfer fails. +pub fn transfer_from( + id: AssetId, + from: Option>>, + to: Option>>, + value: Balance, + _data: &[u8], +) -> Result<()> { + match (from, to) { + (None, Some(to)) => pallets::assets::mint(id, to, value), + (Some(from), None) => pallets::assets::burn(id, from, value), + (Some(from), Some(to)) => pallets::assets::transfer_approved(id, from, to, value), + _ => Ok(()), + } +} + +/// Approves an account to spend a specified number of tokens on behalf of the caller. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `spender` - The account that is allowed to spend the tokens. +/// * `value` - The number of tokens to approve. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the approval fails. +// #[allow(unused_variables)] +// fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { +// todo!() +// // TODO: read allowance and increase or decrease. +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { +// // id: id.into(), +// // delegate: spender.into(), +// // amount: Compact(value), +// // }))?) +// } + +/// Increases the allowance of a spender. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `spender` - The account that is allowed to spend the tokens. +/// * `value` - The number of tokens to increase the allowance by. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { +// id: id.into(), +// delegate: spender.into(), +// amount: Compact(value), +// }))?) +// } + +/// Decreases the allowance of a spender. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `spender` - The account that is allowed to spend the tokens. +/// * `value` - The number of tokens to decrease the allowance by. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// #[allow(unused_variables)] +// fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { +// todo!() +// // TODO: cancel_approval + approve_transfer +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::CancelApproval { +// // id: id.into(), +// // delegate: delegate.into(), +// // }))?) +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { +// // id: id.into(), +// // delegate: spender.into(), +// // amount: Compact(value), +// // }))?) +// } + +/// 2. PSP-22 Metadata Interface: +/// - token_name +/// - token_symbol +/// - token_decimals + +/// Returns the token name for a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// The name of the token as a byte vector, or an error if the operation fails. +// #[allow(unused_variables)] +// pub fn token_name(id: AssetId) -> Result>> { +// todo!() +// // Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenName(id)))?) +// } + +/// Returns the token symbol for a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// The symbol of the token as a byte vector, or an error if the operation fails. +// #[allow(unused_variables)] +// fn token_symbol(id: AssetId) -> Result>> { +// todo!() +// } + +/// Returns the token decimals for a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// The number of decimals of the token as a byte vector, or an error if the operation fails. +// #[allow(unused_variables)] +// fn token_decimals(id: AssetId) -> Result>> { +// todo!() +// } + +/// 3. Asset Management: +/// - create +/// - start_destroy +/// - destroy_accounts +/// - destroy_approvals +/// - finish_destroy +/// - set_metadata +/// - clear_metadata + +/// Create a new token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// * `admin` - The account that will administer the asset. +/// * `min_balance` - The minimum balance required for accounts holding this asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the creation fails. +pub fn create( + id: AssetId, + admin: impl Into>, + min_balance: Balance, +) -> Result<()> { + pallets::assets::create(id, admin, min_balance) +} + +/// Start the process of destroying a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn start_destroy(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { +// id: id.into(), +// }))?) +// } + +/// Destroy all accounts associated with a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn destroy_accounts(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { +// id: id.into(), +// }))?) +// } + +/// Destroy all approvals associated with a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn destroy_approvals(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { +// id: id.into(), +// }))?) +// } + +/// Complete the process of destroying a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn finish_destroy(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { +// id: id.into(), +// }))?) +// } + +/// Set the metadata for a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { + pallets::assets::set_metadata(id, name, symbol, decimals) +} + +/// Clear the metadata for a token with a given asset ID. +/// +/// # Arguments +/// * `id` - The ID of the asset. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +// fn clear_metadata(id: AssetId) -> Result<()> { +// Ok(dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { +// id: id.into(), +// }))?) +// } + +pub fn asset_exists(id: AssetId) -> Result { + pallets::assets::asset_exists(id) +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum FungiblesError { + /// The asset is not live; either frozen or being destroyed. + AssetNotLive, + /// Not enough allowance to fulfill a request is available. + InsufficientAllowance, + /// Not enough balance to fulfill a request is available. + InsufficientBalance, + /// The asset ID is already taken. + InUse, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// The account to alter does not exist. + NoAccount, + /// The signing account has no permission to do the operation. + NoPermission, + /// The given asset ID is unknown. + Unknown, + // // TODO: + // // - Originally `InsufficientBalance` for the deposit but this would result in the same error + // // as the error when there is insufficient balance for transferring an asset. + /// No balance for creation of assets or fees. + NoBalance, +} + +// TODO: make generic. +pub(crate) fn convert_to_fungibles_error(index: u8, error: u8) -> PopApiError { + match index { + 10 => balance_into(error), + 52 => assets_into(error), + _ => Module { index, error }, + } +} + +fn balance_into(error: u8) -> PopApiError { + match error { + 2 => UseCaseError(FungiblesError::NoBalance), + _ => Module { index: 10, error }, + } +} + +fn assets_into(error: u8) -> PopApiError { + match error { + 0 => UseCaseError(FungiblesError::InsufficientBalance), + 1 => UseCaseError(FungiblesError::NoAccount), + 2 => UseCaseError(FungiblesError::NoPermission), + 3 => UseCaseError(FungiblesError::Unknown), + 5 => UseCaseError(FungiblesError::InUse), + 7 => UseCaseError(FungiblesError::MinBalanceZero), + 10 => UseCaseError(FungiblesError::InsufficientAllowance), + 16 => UseCaseError(FungiblesError::AssetNotLive), + _ => Module { index: 52, error }, + } +} diff --git a/pop-api/src/v0/assets/use_cases/mod.rs b/pop-api/src/v0/assets/use_cases/mod.rs new file mode 100644 index 00000000..182590df --- /dev/null +++ b/pop-api/src/v0/assets/use_cases/mod.rs @@ -0,0 +1 @@ +pub mod fungibles; diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs index 08db0a75..5d38d851 100644 --- a/pop-api/src/v0/balances.rs +++ b/pop-api/src/v0/balances.rs @@ -1,9 +1,7 @@ -use crate::{ - dispatch, primitives::MultiAddress, v0::RuntimeCall, AccountId, PopApiError, - PopApiError::UnknownModuleStatusCode, -}; +// TODO: what to put in this file? +use crate::{dispatch, error::PopApiError, primitives::MultiAddress, v0::RuntimeCall, AccountId}; -type Result = core::result::Result; +type Result = core::result::Result; pub fn transfer_keep_alive( dest: impl Into>, @@ -17,7 +15,7 @@ pub fn transfer_keep_alive( #[derive(scale::Encode)] #[allow(dead_code)] -pub(crate) enum BalancesCall { +pub enum BalancesCall { #[codec(index = 3)] TransferKeepAlive { dest: MultiAddress, @@ -28,7 +26,7 @@ pub(crate) enum BalancesCall { #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub(crate) enum BalancesError { +pub enum BalancesError { /// Vesting balance too high to send value. VestingBalance, /// Account liquidity restrictions prevent withdrawal. @@ -73,15 +71,6 @@ impl TryFrom for BalancesError { 9 => Ok(TooManyFreezes), 10 => Ok(IssuanceDeactivated), 11 => Ok(DeltaZero), - _ => Err(UnknownModuleStatusCode(status_code)), - } - } -} - -impl From for BalancesError { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Balances(e) => e, _ => todo!(), } } diff --git a/pop-api/src/v0/contracts.rs b/pop-api/src/v0/contracts.rs deleted file mode 100644 index 5d4a3692..00000000 --- a/pop-api/src/v0/contracts.rs +++ /dev/null @@ -1,152 +0,0 @@ -use crate::{PopApiError, PopApiError::UnknownModuleStatusCode}; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum Error { - /// Invalid schedule supplied, e.g. with zero weight of a basic operation. - InvalidSchedule, - /// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`. - InvalidCallFlags, - /// The executed contract exhausted its gas limit. - OutOfGas, - /// The output buffer supplied to a contract API call was too small. - OutputBufferTooSmall, - /// Performing the requested transfer failed. Probably because there isn't enough - /// free balance in the sender's account. - TransferFailed, - /// Performing a call was denied because the calling depth reached the limit - /// of what is specified in the schedule. - MaxCallDepthReached, - /// No contract was found at the specified address. - ContractNotFound, - /// The code supplied to `instantiate_with_code` exceeds the limit specified in the - /// current schedule. - CodeTooLarge, - /// No code could be found at the supplied code hash. - CodeNotFound, - /// No code info could be found at the supplied code hash. - CodeInfoNotFound, - /// A buffer outside of sandbox memory was passed to a contract API function. - OutOfBounds, - /// Input passed to a contract API function failed to decode as expected type. - DecodingFailed, - /// Contract trapped during execution. - ContractTrapped, - /// The size defined in `T::MaxValueSize` was exceeded. - ValueTooLarge, - /// Termination of a contract is not allowed while the contract is already - /// on the call stack. Can be triggered by `seal_terminate`. - TerminatedWhileReentrant, - /// `seal_call` forwarded this contracts input. It therefore is no longer available. - InputForwarded, - /// The subject passed to `seal_random` exceeds the limit. - RandomSubjectTooLong, - /// The amount of topics passed to `seal_deposit_events` exceeds the limit. - TooManyTopics, - /// The chain does not provide a chain extension. Calling the chain extension results - /// in this error. Note that this usually shouldn't happen as deploying such contracts - /// is rejected. - NoChainExtension, - /// Failed to decode the XCM program. - XCMDecodeFailed, - /// A contract with the same AccountId already exists. - DuplicateContract, - /// A contract self destructed in its constructor. - /// - /// This can be triggered by a call to `seal_terminate`. - TerminatedInConstructor, - /// A call tried to invoke a contract that is flagged as non-reentrant. - /// The only other cause is that a call from a contract into the runtime tried to call back - /// into `pallet-contracts`. This would make the whole pallet reentrant with regard to - /// contract code execution which is not supported. - ReentranceDenied, - /// Origin doesn't have enough balance to pay the required storage deposits. - StorageDepositNotEnoughFunds, - /// More storage was created than allowed by the storage deposit limit. - StorageDepositLimitExhausted, - /// Code removal was denied because the code is still in use by at least one contract. - CodeInUse, - /// The contract ran to completion but decided to revert its storage changes. - /// Please note that this error is only returned from extrinsics. When called directly - /// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags - /// to determine whether a reversion has taken place. - ContractReverted, - /// The contract's code was found to be invalid during validation. - /// - /// The most likely cause of this is that an API was used which is not supported by the - /// node. This happens if an older node is used with a new version of ink!. Try updating - /// your node to the newest available version. - /// - /// A more detailed error can be found on the node console if debug messages are enabled - /// by supplying `-lruntime::contracts=debug`. - CodeRejected, - /// An indeterministic code was used in a context where this is not permitted. - Indeterministic, - /// A pending migration needs to complete before the extrinsic can be called. - MigrationInProgress, - /// Migrate dispatch call was attempted but no migration was performed. - NoMigrationPerformed, - /// The contract has reached its maximum number of delegate dependencies. - MaxDelegateDependenciesReached, - /// The dependency was not found in the contract's delegate dependencies. - DelegateDependencyNotFound, - /// The contract already depends on the given delegate dependency. - DelegateDependencyAlreadyExists, - /// Can not add a delegate dependency to the code hash of the contract itself. - CannotAddSelfAsDelegateDependency, -} - -impl TryFrom for Error { - type Error = PopApiError; - - fn try_from(status_code: u32) -> core::result::Result { - use Error::*; - match status_code { - 0 => Ok(InvalidSchedule), - 1 => Ok(InvalidCallFlags), - 2 => Ok(OutOfGas), - 3 => Ok(OutputBufferTooSmall), - 4 => Ok(TransferFailed), - 5 => Ok(MaxCallDepthReached), - 6 => Ok(ContractNotFound), - 7 => Ok(CodeTooLarge), - 8 => Ok(CodeNotFound), - 9 => Ok(CodeInfoNotFound), - 10 => Ok(OutOfBounds), - 11 => Ok(DecodingFailed), - 12 => Ok(ContractTrapped), - 13 => Ok(ValueTooLarge), - 14 => Ok(TerminatedWhileReentrant), - 15 => Ok(InputForwarded), - 16 => Ok(RandomSubjectTooLong), - 17 => Ok(TooManyTopics), - 18 => Ok(NoChainExtension), - 19 => Ok(XCMDecodeFailed), - 20 => Ok(DuplicateContract), - 21 => Ok(TerminatedInConstructor), - 22 => Ok(ReentranceDenied), - 23 => Ok(StorageDepositNotEnoughFunds), - 24 => Ok(StorageDepositLimitExhausted), - 25 => Ok(CodeInUse), - 26 => Ok(ContractReverted), - 27 => Ok(CodeRejected), - 28 => Ok(Indeterministic), - 29 => Ok(MigrationInProgress), - 30 => Ok(NoMigrationPerformed), - 31 => Ok(MaxDelegateDependenciesReached), - 32 => Ok(DelegateDependencyNotFound), - 33 => Ok(DelegateDependencyAlreadyExists), - 34 => Ok(CannotAddSelfAsDelegateDependency), - _ => Err(UnknownModuleStatusCode(status_code)), - } - } -} - -impl From for Error { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Contracts(e) => e, - _ => panic!("expected balances error"), - } - } -} diff --git a/pop-api/src/v0/cross_chain/mod.rs b/pop-api/src/v0/cross_chain/mod.rs index 1e5afbf5..1d3c5b7d 100644 --- a/pop-api/src/v0/cross_chain/mod.rs +++ b/pop-api/src/v0/cross_chain/mod.rs @@ -1,8 +1,8 @@ pub mod coretime; -use crate::{PopApiError::UnknownModuleStatusCode, *}; +use crate::error::PopApiError; -type Result = core::result::Result; +type Result = core::result::Result; #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] @@ -92,16 +92,7 @@ impl TryFrom for Error { 21 => Ok(InvalidAssetUnknownReserve), 22 => Ok(InvalidAssetUnsupportedReserve), 23 => Ok(TooManyReserves), - _ => Err(UnknownModuleStatusCode(status_code)), - } - } -} - -impl From for Error { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Xcm(e) => e, - _ => panic!("expected xcm error"), + _ => todo!(), } } } diff --git a/pop-api/src/v0/dispatch_error.rs b/pop-api/src/v0/dispatch_error.rs deleted file mode 100644 index 6ed40ce5..00000000 --- a/pop-api/src/v0/dispatch_error.rs +++ /dev/null @@ -1,57 +0,0 @@ -use super::*; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub(crate) enum TokenError { - /// Funds are unavailable. - FundsUnavailable, - /// Some part of the balance gives the only provider reference to the account and thus cannot - /// be (re)moved. - OnlyProvider, - /// Account cannot exist with the funds that would be given. - BelowMinimum, - /// Account cannot be created. - CannotCreate, - /// The asset in question is unknown. - UnknownAsset, - /// Funds exist but are frozen. - Frozen, - /// Operation is not supported by the asset. - Unsupported, - /// Account cannot be created for a held balance. - CannotCreateHold, - /// Withdrawal would cause unwanted loss of account. - NotExpendable, - /// Account cannot receive the assets. - Blocked, -} - -impl TryFrom for TokenError { - type Error = crate::PopApiError; - - fn try_from(status_code: u32) -> core::result::Result { - use TokenError::*; - match status_code { - 0 => Ok(FundsUnavailable), - 1 => Ok(OnlyProvider), - 2 => Ok(BelowMinimum), - 3 => Ok(CannotCreate), - 4 => Ok(UnknownAsset), - 5 => Ok(Frozen), - 6 => Ok(Unsupported), - 7 => Ok(CannotCreateHold), - 8 => Ok(NotExpendable), - 9 => Ok(Blocked), - _ => todo!(), - } - } -} - -impl From for TokenError { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::TokenError(e) => e, - _ => todo!(), - } - } -} diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 02169c22..75bcb878 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -5,9 +5,7 @@ use crate::{ pub mod assets; pub mod balances; -pub mod contracts; pub mod cross_chain; -pub mod dispatch_error; pub mod nfts; pub mod state; @@ -22,5 +20,5 @@ pub(crate) enum RuntimeCall { #[codec(index = 50)] Nfts(nfts::NftCalls), #[codec(index = 52)] - Assets(assets::fungibles::AssetsCall), + Assets(assets::pallets::assets::AssetsCall), } diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs index 946a3eca..2de306a9 100644 --- a/pop-api/src/v0/nfts.rs +++ b/pop-api/src/v0/nfts.rs @@ -1,12 +1,12 @@ use super::RuntimeCall; -use crate::{PopApiError::UnknownModuleStatusCode, *}; +use crate::{PopApiError, *}; use ink::prelude::vec::Vec; use primitives::{ApprovalsLimit, BoundedBTreeMap, KeyLimit, MultiAddress}; pub use primitives::{CollectionId, ItemId}; use scale::Encode; pub use types::*; -type Result = core::result::Result; +type Result = core::result::Result; /// Issue a new collection of non-fungible items pub fn create( @@ -660,16 +660,7 @@ impl TryFrom for Error { 42 => Ok(WrongNamespace), 43 => Ok(CollectionNotEmpty), 44 => Ok(WitnessRequired), - _ => Err(UnknownModuleStatusCode(status_code)), - } - } -} - -impl From for Error { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Nfts(e) => e, - _ => panic!("unexpected pallet nfts error. This error is unknown to pallet nfts"), + _ => todo!(), } } } diff --git a/primitives/src/storage_keys.rs b/primitives/src/storage_keys.rs index 67448842..fc7234aa 100644 --- a/primitives/src/storage_keys.rs +++ b/primitives/src/storage_keys.rs @@ -1,5 +1,4 @@ use super::*; -// use scale::{Decode, Encode, MaxEncodedLen}; #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum RuntimeStateKeys { @@ -28,8 +27,6 @@ pub enum NftsKeys { Owner(CollectionId, ItemId), /// Get the attribute value of `item` of `collection` corresponding to `key`. Attribute(CollectionId, ItemId, BoundedVec), - // /// Get the custom attribute value of `item` of `collection` corresponding to `key`. - // CustomAttribute(AccountId, CollectionId, ItemId, BoundedVec), /// Get the system attribute value of `item` of `collection` corresponding to `key` SystemAttribute(CollectionId, Option, BoundedVec), /// Get the attribute value of `item` of `collection` corresponding to `key`. diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index d4fe2923..46208d8f 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -91,6 +91,7 @@ parachain-info.workspace = true env_logger = "0.11.2" hex = "0.4.3" enumflags2 = "0.7.9" +pop-api = { path = "../../pop-api", default-features = false } [features] default = ["std"] @@ -138,6 +139,7 @@ std = [ "polkadot-parachain-primitives/std", "polkadot-runtime-common/std", "pop-primitives/std", + "pop-api/std", "scale-info/std", "sp-api/std", "sp-io/std", diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions.rs similarity index 97% rename from runtime/devnet/src/extensions/mod.rs rename to runtime/devnet/src/extensions.rs index d2129c4f..014893f9 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions.rs @@ -17,10 +17,7 @@ use pop_primitives::{ AssetId, CollectionId, ItemId, }; use sp_core::crypto::UncheckedFrom; -use sp_runtime::{ - traits::{BlockNumberProvider, Dispatchable}, - DispatchError, -}; +use sp_runtime::traits::{BlockNumberProvider, Dispatchable}; use sp_std::{boxed::Box, vec::Vec}; use xcm::{ latest::{prelude::*, OriginKind::SovereignAccount}, @@ -32,9 +29,6 @@ use crate::{ RuntimeOrigin, UNIT, }; -#[cfg(test)] -mod tests; - const LOG_TARGET: &str = "pop-api::extension"; type ContractSchedule = ::Schedule; @@ -42,6 +36,7 @@ type ContractSchedule = ::Schedule; #[derive(Default)] pub struct PopApiExtension; +// TODO: check removal or simplification of trait bounds. impl ChainExtension for PopApiExtension where T: pallet_contracts::Config @@ -59,31 +54,12 @@ where fn call(&mut self, env: Environment) -> Result where E: Ext, - // T::AccountId: UncheckedFrom + AsRef<[u8]>, { log::debug!(target:LOG_TARGET, " extension called "); match v0::FuncId::try_from(env.func_id())? { - v0::FuncId::Dispatch => { - match dispatch::(env) { - Ok(()) => Ok(RetVal::Converging(0)), - Err(DispatchError::Module(error)) => { - // encode status code = pallet index in runtime + error index, allowing for - // 999 errors - let first = (3u32 * 1_000_000u32) - + (error.index as u32 * 1_000u32) - + u32::from_le_bytes(error.error); - Ok(RetVal::Converging( - // (3u32 * 1_000_000u32) - // + (error.index as u32 * 1_000u32) - // + u32::from_le_bytes(error.error), - first, - )) - }, - Err(DispatchError::Token(error)) => { - Ok(RetVal::Converging((7u32 * 1_000_000u32) + error as u32)) - }, - Err(e) => Err(e), - } + v0::FuncId::Dispatch => match dispatch::(env) { + Ok(()) => Ok(RetVal::Converging(0)), + Err(e) => Ok(RetVal::Converging(convert_to_status_code(e))), }, v0::FuncId::ReadState => { read_state::(env)?; @@ -97,6 +73,17 @@ where } } +pub(crate) fn convert_to_status_code(error: DispatchError) -> u32 { + match error { + _ => { + let mut encoded_error = error.encode(); + // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). + encoded_error.resize(4, 0); + u32::decode(&mut &encoded_error[..]).unwrap() + }, + } +} + pub mod v0 { #[derive(Debug)] pub enum FuncId { diff --git a/runtime/devnet/src/extensions/tests/mod.rs b/runtime/devnet/src/extensions/tests/mod.rs deleted file mode 100644 index cbd13d62..00000000 --- a/runtime/devnet/src/extensions/tests/mod.rs +++ /dev/null @@ -1,89 +0,0 @@ -#![cfg(test)] -use super::*; -use crate::{Assets, Balances, Contracts, Runtime, System}; -use pallet_contracts::{Code, CollectEvents, Determinism, ExecReturnValue}; -use sp_runtime::{traits::Hash, AccountId32, BuildStorage}; - -mod local_fungibles; - -type Balance = u128; -type AssetId = u32; -const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; - -const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); -const BOB: AccountId32 = AccountId32::new([2_u8; 32]); -const INIT_AMOUNT: Balance = 100_000_000 * UNIT; -const INIT_VALUE: Balance = 100 * UNIT; -const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); - -fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default() - .build_storage() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT)], - } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext -} - -fn load_wasm_module(path: &str) -> std::io::Result<(Vec, ::Output)> -where - T: frame_system::Config, -{ - let wasm_binary = std::fs::read(path)?; - let code_hash = T::Hashing::hash(&wasm_binary); - Ok((wasm_binary, code_hash)) -} - -fn function_selector(name: &str) -> Vec { - let hash = sp_io::hashing::blake2_256(name.as_bytes()); - [hash[0..4].to_vec()].concat() -} - -fn do_bare_call( - addr: AccountId32, - input: Vec, - value: u128, -) -> Result { - let result = Contracts::bare_call( - ALICE, - addr.into(), - value.into(), - GAS_LIMIT, - None, - input, - DEBUG_OUTPUT, - CollectEvents::Skip, - Determinism::Enforced, - ); - log::debug!("Contract debug buffer - {:?}", String::from_utf8(result.debug_message.clone())); - log::debug!("result: {:?}", result); - result.result -} - -// Deploy, instantiate and return contract address. -fn instantiate(contract: &str, init_value: u128, salt: Vec) -> AccountId32 { - let (wasm_binary, _) = - load_wasm_module::(contract).expect("could not read .wasm file"); - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - salt, - DEBUG_OUTPUT, - CollectEvents::Skip, - ) - .result - .unwrap(); - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - result.account_id -} diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index a82be804..416a3298 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -10,6 +10,8 @@ mod extensions; mod weights; // Public due to integration tests crate. pub mod config; +#[cfg(test)] +mod tests; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; diff --git a/runtime/devnet/src/extensions/tests/local_fungibles.rs b/runtime/devnet/src/tests/local_fungibles.rs similarity index 70% rename from runtime/devnet/src/extensions/tests/local_fungibles.rs rename to runtime/devnet/src/tests/local_fungibles.rs index 5de162c9..bc13fbde 100644 --- a/runtime/devnet/src/extensions/tests/local_fungibles.rs +++ b/runtime/devnet/src/tests/local_fungibles.rs @@ -2,31 +2,10 @@ use super::*; -#[derive(Decode, Encode, Debug, Eq, PartialEq)] -enum FungiblesError { - /// The asset is not live; either frozen or being destroyed. - AssetNotLive, - /// The amount to mint is less than the existential deposit. - BelowMinimum, - /// Unspecified dispatch error, providing the index and optionally its error index. - DispatchError { index: u8, error: Option }, - /// Not enough allowance to fulfill a request is available. - InsufficientAllowance, - /// Not enough balance to fulfill a request is available. - InsufficientBalance, - /// The asset ID is already taken. - InUse, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// Unspecified pallet error, providing pallet index and error index. - ModuleError { pallet: u8, error: u16 }, - /// The account to alter does not exist. - NoAccount, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given asset ID is unknown. - Unknown, -} +use pop_api::{ + error::{ArithmeticError::*, PopApiError::*, TokenError::*}, + v0::assets::use_cases::fungibles::FungiblesError::*, +}; const ASSET_ID: AssetId = 1; @@ -119,8 +98,7 @@ fn transfer_from( do_bare_call(addr, params, 0).expect("should work") } -// Create an asset and mint to owner. -fn create_asset(asset_id: AssetId, owner: AccountId32, min_balance: Balance) -> AssetId { +fn create_asset(owner: AccountId32, asset_id: AssetId, min_balance: Balance) -> AssetId { assert_eq!( Assets::create( RuntimeOrigin::signed(owner.clone()), @@ -133,31 +111,34 @@ fn create_asset(asset_id: AssetId, owner: AccountId32, min_balance: Balance) -> asset_id } -// Create an asset and mint to owner. +fn mint_asset(owner: AccountId32, asset_id: AssetId, to: AccountId32, value: Balance) -> AssetId { + assert_eq!( + Assets::mint(RuntimeOrigin::signed(owner.clone()), asset_id.into(), to.into(), value), + Ok(()) + ); + asset_id +} + fn create_asset_and_mint_to( - asset_id: AssetId, owner: AccountId32, + asset_id: AssetId, to: AccountId32, value: Balance, ) -> AssetId { - create_asset(asset_id, owner.clone(), 1); - assert_eq!( - Assets::mint(RuntimeOrigin::signed(owner.into()), asset_id.into(), to.into(), value,), - Ok(()) - ); - asset_id + create_asset(owner.clone(), asset_id, 1); + mint_asset(owner, asset_id, to, value) } // Create an asset, mints to, and approves spender. fn create_asset_mint_and_approve( - asset_id: AssetId, owner: AccountId32, + asset_id: AssetId, to: AccountId32, mint: Balance, spender: AccountId32, approve: Balance, ) { - create_asset_and_mint_to(asset_id, owner.clone(), to.clone(), mint); + create_asset_and_mint_to(owner.clone(), asset_id, to.clone(), mint); assert_eq!( Assets::approve_transfer( RuntimeOrigin::signed(to.into()), @@ -199,7 +180,7 @@ fn total_supply_works() { assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr.clone(), ASSET_ID)); // Tokens in circulation. - create_asset_and_mint_to(ASSET_ID, addr.clone(), BOB, 100); + create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr, ASSET_ID)); }); } @@ -219,7 +200,7 @@ fn balance_of_works() { assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr.clone(), ASSET_ID, BOB)); // Tokens in circulation. - create_asset_and_mint_to(ASSET_ID, addr.clone(), BOB, 100); + create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr, ASSET_ID, BOB)); }); } @@ -242,7 +223,7 @@ fn allowance_works() { ); // Tokens in circulation. - create_asset_mint_and_approve(ASSET_ID, addr.clone(), BOB, 100, ALICE, 50); + create_asset_mint_and_approve(addr.clone(), ASSET_ID, BOB, 100, ALICE, 50); assert_eq!( Assets::allowance(ASSET_ID, &BOB, &ALICE), allowance(addr, ASSET_ID, BOB, ALICE) @@ -265,7 +246,7 @@ fn asset_exists_works() { assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr.clone(), ASSET_ID)); // Tokens in circulation. - create_asset(ASSET_ID, addr.clone(), 1); + create_asset(addr.clone(), ASSET_ID, 1); assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr, ASSET_ID)); }); } @@ -276,34 +257,52 @@ fn asset_exists_works() { // - reserve(): Overflow, LiquidityRestrictions; frozen // - Callback // - StorageDepositLimitExhausted +// todo: errors: +// - TokenErrors +// - Arithmetic +// - https://github.com/paritytech/polkadot-sdk/blob/3977f389cce4a00fd7100f95262e0563622b9aa4/substrate/frame/assets/src/functions.rs#L125 #[test] #[ignore] fn create_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); let new_asset = 2; + // Instantiate a contract without balance (relay token). let addr = instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); - + // No balance to pay for fees. assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), - FungiblesError::InsufficientBalance + decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), + UseCaseError(NoBalance) ); + // Instantiate a contract without balance (relay token). + let addr = + instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", 100, vec![2]); + // TODO: make sure it has enough for the fees but not for the deposit. + // No balance to pay fe deposit. + assert_eq!( + decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), + UseCaseError(NoBalance) + ); + // Instantiate a contract with balance. let addr = instantiate( "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1], ); - create_asset(ASSET_ID, ALICE, 1); + create_asset(ALICE, ASSET_ID, 1); + // Asset ID is already taken. assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), - FungiblesError::InUse + decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), + UseCaseError(InUse) ); + // The minimal balance for an asset must be non zero. assert_eq!( - decoded::(create(addr.clone(), new_asset, BOB, 0)), - FungiblesError::MinBalanceZero + decoded::(create(addr.clone(), new_asset, BOB, 0)), + UseCaseError(MinBalanceZero) ); - assert!(!create(addr.clone(), new_asset, BOB, 1).did_revert(), "Contract reverted!"); + let result = create(addr.clone(), new_asset, BOB, 1); + assert!(!result.did_revert(), "Contract reverted!"); }); } @@ -318,17 +317,12 @@ fn set_metadata_works() { vec![], ); - create_asset(ASSET_ID, addr.clone(), 1); - + create_asset(addr.clone(), ASSET_ID, 1); let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); assert!(!result.did_revert(), "Contract reverted!"); }); } -// todo: errors: -// - TokenErrors -// - Arithmetic -// - https://github.com/paritytech/polkadot-sdk/blob/3977f389cce4a00fd7100f95262e0563622b9aa4/substrate/frame/assets/src/functions.rs#L125 #[test] #[ignore] fn transfer_from_mint_works() { @@ -341,20 +335,15 @@ fn transfer_from_mint_works() { ); let amount: Balance = 100 * UNIT; + // Asset does not exist. assert_eq!( - decoded::(transfer_from( - addr.clone(), - 1, - None, - Some(BOB), - amount, - &[0u8] - )), - FungiblesError::Unknown + decoded::(transfer_from(addr.clone(), 1, None, Some(BOB), amount, &[0u8])), + Token(UnknownAsset) ); - let asset = create_asset(1, ALICE, 2); + let asset = create_asset(ALICE, 1, 2); + // Minting can only be done by the owner. assert_eq!( - decoded::(transfer_from( + decoded::(transfer_from( addr.clone(), asset, None, @@ -362,23 +351,18 @@ fn transfer_from_mint_works() { amount, &[0u8] )), - FungiblesError::NoPermission + UseCaseError(NoPermission) ); + // Minimum balance of an asset can not be zero. assert_eq!( - decoded::(transfer_from( - addr.clone(), - asset, - None, - Some(BOB), - 1, - &[0u8] - )), - FungiblesError::BelowMinimum + decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), 1, &[0u8])), + Token(BelowMinimum) ); - let asset = create_asset(2, addr.clone(), 2); + let asset = create_asset(addr.clone(), 2, 2); + // Asset is not live, i.e. frozen or being destroyed. freeze_asset(asset, addr.clone()); assert_eq!( - decoded::(transfer_from( + decoded::(transfer_from( addr.clone(), asset, None, @@ -386,17 +370,31 @@ fn transfer_from_mint_works() { amount, &[0u8] )), - FungiblesError::AssetNotLive + UseCaseError(AssetNotLive) ); thaw_asset(asset, addr.clone()); + // Successful mint. let bob_balance_before_mint = Assets::balance(asset, &BOB); let result = transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8]); assert!(!result.did_revert(), "Contract reverted!"); let bob_balance_after_mint = Assets::balance(asset, &BOB); assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount); + // Can not mint more tokens than Balance::MAX. + assert_eq!( + decoded::(transfer_from( + addr.clone(), + asset, + None, + Some(BOB), + Balance::MAX, + &[0u8] + )), + Arithmetic(Overflow) + ); + // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(asset, addr.clone()); assert_eq!( - decoded::(transfer_from( + decoded::(transfer_from( addr.clone(), asset, None, @@ -404,17 +402,15 @@ fn transfer_from_mint_works() { amount, &[0u8] )), - FungiblesError::AssetNotLive + UseCaseError(AssetNotLive) ); }); } // Todo: error: -// - Frozen: account is frozen, who do you freeze an account? // - https://github.com/paritytech/polkadot-sdk/blob/2460cddf57660a88844d201f769eb17a7accce5a/substrate/frame/assets/src/functions.rs#L161 // - ArithmeticError: Underflow, Overflow // - https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/functions.rs#L125 -// - #[test] #[ignore] fn transfer_works() { @@ -427,35 +423,46 @@ fn transfer_works() { ); let amount: Balance = 100 * UNIT; + // Asset does not exist. assert_eq!( - decoded::(transfer(addr.clone(), 1, BOB, amount,)), - FungiblesError::Unknown + decoded::(transfer(addr.clone(), 1, BOB, amount,)), + UseCaseError(Unknown) ); - let asset = create_asset_and_mint_to(1, ALICE, addr.clone(), amount); + // Create asset with Alice as owner and mint `amount` to contract address. + let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); + // Asset is not live, i.e. frozen or being destroyed. freeze_asset(asset, ALICE); assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount,)), - FungiblesError::AssetNotLive + decoded::(transfer(addr.clone(), asset, BOB, amount,)), + UseCaseError(AssetNotLive) ); thaw_asset(asset, ALICE); + // Not enough balance. assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), - FungiblesError::InsufficientBalance + decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), + UseCaseError(InsufficientBalance) ); - // Errors due to ED. Could be Belowminimum + // Not enough balance due to ED. assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount)), - FungiblesError::InsufficientBalance + decoded::(transfer(addr.clone(), asset, BOB, amount)), + UseCaseError(InsufficientBalance) ); + // Successful transfer. let bob_balance_before_mint = Assets::balance(asset, &BOB); let result = transfer(addr.clone(), asset, BOB, amount / 2); assert!(!result.did_revert(), "Contract reverted!"); let bob_balance_after_mint = Assets::balance(asset, &BOB); assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); + // Transfer asset to account that does not exist. + assert_eq!( + decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), + Token(CannotCreate) + ); + // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(asset, ALICE); assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), - FungiblesError::AssetNotLive + decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), + UseCaseError(AssetNotLive) ); }); } diff --git a/runtime/devnet/src/tests/mod.rs b/runtime/devnet/src/tests/mod.rs new file mode 100644 index 00000000..c13030a3 --- /dev/null +++ b/runtime/devnet/src/tests/mod.rs @@ -0,0 +1,262 @@ +#![cfg(test)] + +use crate::{ + config::assets::TrustBackedAssetsInstance, Assets, Contracts, Runtime, RuntimeOrigin, System, + Weight, UNIT, +}; +use codec::{Decode, Encode}; +use frame_support::traits::fungibles::{approvals::Inspect as ApprovalInspect, Inspect}; +use frame_system::Config; +use pallet_contracts::{Code, CollectEvents, Determinism, ExecReturnValue}; +use pop_api::error::{ArithmeticError, PopApiError, TokenError, TransactionalError}; +use sp_runtime::{traits::Hash, AccountId32, BuildStorage, DispatchError}; + +mod local_fungibles; + +type Balance = u128; +type AssetId = u32; +const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; + +const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); +const BOB: AccountId32 = AccountId32::new([2_u8; 32]); +// FERDIE has no initial balance. +const FERDIE: AccountId32 = AccountId32::new([3_u8; 32]); +const INIT_AMOUNT: Balance = 100_000_000 * UNIT; +const INIT_VALUE: Balance = 100 * UNIT; +const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); + +fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { + balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT)], + } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +fn load_wasm_module(path: &str) -> std::io::Result<(Vec, ::Output)> +where + T: frame_system::Config, +{ + let wasm_binary = std::fs::read(path)?; + let code_hash = T::Hashing::hash(&wasm_binary); + Ok((wasm_binary, code_hash)) +} + +fn function_selector(name: &str) -> Vec { + let hash = sp_io::hashing::blake2_256(name.as_bytes()); + [hash[0..4].to_vec()].concat() +} + +fn do_bare_call( + addr: AccountId32, + input: Vec, + value: u128, +) -> Result { + let result = Contracts::bare_call( + ALICE, + addr.into(), + value.into(), + GAS_LIMIT, + None, + input, + DEBUG_OUTPUT, + CollectEvents::Skip, + Determinism::Enforced, + ); + log::debug!("Contract debug buffer - {:?}", String::from_utf8(result.debug_message.clone())); + log::debug!("result: {:?}", result); + result.result +} + +// Deploy, instantiate and return contract address. +fn instantiate(contract: &str, init_value: u128, salt: Vec) -> AccountId32 { + let (wasm_binary, _) = + load_wasm_module::(contract).expect("could not read .wasm file"); + let result = Contracts::bare_instantiate( + ALICE, + init_value, + GAS_LIMIT, + None, + Code::Upload(wasm_binary), + function_selector("new"), + salt, + DEBUG_OUTPUT, + CollectEvents::Skip, + ) + .result + .unwrap(); + assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); + result.account_id +} + +pub fn get_pallet_index() -> u8 { + // Get the index of the pallet (module) + <::PalletInfo as frame_support::traits::PalletInfo>::index::() + .expect("Every active module has an index in the runtime; qed") as u8 +} + +#[test] +fn encoding_decoding_dispatch_error() { + use codec::{Decode, Encode}; + use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; + + new_test_ext().execute_with(|| { + let error = DispatchError::Module(ModuleError { + index: 255, + error: [2, 0, 0, 0], + message: Some("error message"), + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); + assert_eq!( + decoded, + // `message` is skipped for encoding. + DispatchError::Module(ModuleError { index: 255, error: [2, 0, 0, 0], message: None }) + ); + println!("Encoded Module Error: {:?}", encoded); + + // Example pallet assets Error into ModuleError + let index = get_pallet_index::(); + let mut error = + pallet_assets::Error::NotFrozen::.encode(); + error.resize(sp_runtime::MAX_MODULE_ERROR_ENCODED_SIZE, 0); + let message = None; + let error = DispatchError::Module(ModuleError { + index, + error: TryInto::try_into(error).expect("should work"), + message, + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 52, 18, 0, 0, 0]); + assert_eq!( + decoded, + DispatchError::Module(ModuleError { index: 52, error: [18, 0, 0, 0], message: None }) + ); + println!("Encoded Module Error: {:?}", encoded); + + // Example DispatchError::Token + let error = DispatchError::Token(TokenError::UnknownAsset); + let encoded = error.encode(); + assert_eq!(encoded, vec![7, 4]); + println!("Encoded Token Error: {:?}", encoded); + + // Example DispatchError::Arithmetic + let error = DispatchError::Arithmetic(ArithmeticError::Overflow); + let encoded = error.encode(); + assert_eq!(encoded, vec![8, 1]); + println!("Encoded Arithmetic Error: {:?}", encoded); + }); +} + +#[test] +fn encoding_of_enum() { + use codec::{Decode, Encode}; + + // Comprehensive enum with all different type of variants. + #[derive(Debug, PartialEq, Encode, Decode)] + enum ComprehensiveEnum { + SimpleVariant, + DataVariant(u8), + NamedFields { w: u8 }, + NestedEnum(InnerEnum), + OptionVariant(Option), + VecVariant(Vec), + TupleVariant(u8, u8), + NestedStructVariant(NestedStruct), + NestedEnumStructVariant(NestedEnumStruct), + } + + #[derive(Debug, PartialEq, Encode, Decode)] + enum InnerEnum { + A, + B { inner_data: u8 }, + C(u8), + } + + #[derive(Debug, PartialEq, Encode, Decode)] + struct NestedStruct { + x: u8, + y: u8, + } + + #[derive(Debug, PartialEq, Encode, Decode)] + struct NestedEnumStruct { + inner_enum: InnerEnum, + } + + // Creating each possible variant for an enum. + let enum_simple = ComprehensiveEnum::SimpleVariant; + let enum_data = ComprehensiveEnum::DataVariant(42); + let enum_named = ComprehensiveEnum::NamedFields { w: 42 }; + let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 }); + let enum_option = ComprehensiveEnum::OptionVariant(Some(42)); + let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]); + let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42); + let enum_nested_struct = ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 }); + let enum_nested_enum_struct = ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { + inner_enum: InnerEnum::C(42), + }); + + // Encode and print each variant individually to see their encoded values. + println!("{:?} -> {:?}", enum_simple, enum_simple.encode()); + println!("{:?} -> {:?}", enum_data, enum_data.encode()); + println!("{:?} -> {:?}", enum_named, enum_named.encode()); + println!("{:?} -> {:?}", enum_nested, enum_nested.encode()); + println!("{:?} -> {:?}", enum_option, enum_option.encode()); + println!("{:?} -> {:?}", enum_vec, enum_vec.encode()); + println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode()); + println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode()); + println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); +} + +#[test] +fn dispatch_error_to_status_code_to_pop_api_error_works() { + // Create all the different `DispatchError` variants with its respective `PopApiError`. + let test_cases = vec![ + (DispatchError::CannotLookup, PopApiError::CannotLookup), + (DispatchError::BadOrigin, PopApiError::BadOrigin), + ( + DispatchError::Module(sp_runtime::ModuleError { + index: 1, + error: [2, 0, 0, 0], + message: Some("hallo"), + }), + PopApiError::Module { index: 1, error: 2 }, + ), + (DispatchError::ConsumerRemaining, PopApiError::ConsumerRemaining), + (DispatchError::NoProviders, PopApiError::NoProviders), + (DispatchError::TooManyConsumers, PopApiError::TooManyConsumers), + ( + DispatchError::Token(sp_runtime::TokenError::FundsUnavailable), + PopApiError::Token(TokenError::FundsUnavailable), + ), + ( + DispatchError::Arithmetic(sp_runtime::ArithmeticError::Overflow), + PopApiError::Arithmetic(ArithmeticError::Overflow), + ), + ( + DispatchError::Transactional(sp_runtime::TransactionalError::LimitReached), + PopApiError::Transactional(TransactionalError::LimitReached), + ), + (DispatchError::Exhausted, PopApiError::Exhausted), + (DispatchError::Corruption, PopApiError::Corruption), + (DispatchError::Unavailable, PopApiError::Unavailable), + (DispatchError::RootNotAllowed, PopApiError::RootNotAllowed), + ]; + for (error, pop_api_error) in test_cases { + // Show that the encoding and decoding of the PopApiError <> u32 (status code) works. + let status_code = crate::extensions::convert_to_status_code(error); + let error = pop_api::error::convert_to_pop_api_error(status_code); + assert_eq!(pop_api_error, error,); + } +} From f824801e092ac5a6224779bbf06f93ec3b04402b Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Thu, 20 Jun 2024 15:50:00 +0200 Subject: [PATCH 008/161] refactor: error handling --- pop-api/src/lib.rs | 2 +- pop-api/src/v0/assets/pallets/assets.rs | 3 ++- pop-api/src/v0/balances.rs | 3 ++- primitives/Cargo.toml | 5 ----- primitives/src/lib.rs | 7 +------ runtime/devnet/src/tests/local_fungibles.rs | 22 ++++++++------------- runtime/testnet/src/extensions.rs | 5 ++++- 7 files changed, 18 insertions(+), 29 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index a785aebe..e78aff9e 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -13,7 +13,7 @@ pub mod primitives; pub mod v0; type AccountId = AccountId32; -// TODO: do the same as above and check expanded code. +// TODO: do the same as above and check expanded macro code. type Balance = ::Balance; type BlockNumber = ::BlockNumber; type StringLimit = u32; diff --git a/pop-api/src/v0/assets/pallets/assets.rs b/pop-api/src/v0/assets/pallets/assets.rs index 7a575e08..b28d3086 100644 --- a/pop-api/src/v0/assets/pallets/assets.rs +++ b/pop-api/src/v0/assets/pallets/assets.rs @@ -1,4 +1,3 @@ -// TODO: what to put in this file? #![allow(dead_code)] use crate::{Balance, RuntimeCall, *}; @@ -412,6 +411,8 @@ pub(crate) enum AssetsCall { Block { id: AssetIdParameter, who: MultiAddress }, } +// TODO: do we want add this. Not being used atm but necessary if we want to provide access to the +// rest of the pallet. #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum AssetsError { diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs index 5d38d851..c9759a45 100644 --- a/pop-api/src/v0/balances.rs +++ b/pop-api/src/v0/balances.rs @@ -1,4 +1,3 @@ -// TODO: what to put in this file? use crate::{dispatch, error::PopApiError, primitives::MultiAddress, v0::RuntimeCall, AccountId}; type Result = core::result::Result; @@ -24,6 +23,8 @@ pub enum BalancesCall { }, } +// TODO: do we want add this. Not being used atm but necessary if we want to provide access to the +// rest of the pallet. #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum BalancesError { diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 1098b557..e7237b51 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -12,11 +12,6 @@ scale-decode = { version = "0.10.0", default-features = false, features = ["deri scale-encode = { version = "0.5.0", default-features = false, features = ["derive"], optional = true } scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } -#scale = { workspace = true, features = ["max-encoded-len"] } -#scale-decode = { workspace = true, features = ["derive"], optional = true } -#scale-encode = { workspace = true, features = ["derive"], optional = true } -#scale-info = { workspace = true, features = ["derive"], optional = true } - [features] default = ["std"] std = [ diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 7c1672b8..1e008c31 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -3,12 +3,7 @@ pub use bounded_collections::{BoundedBTreeMap, BoundedBTreeSet, BoundedVec, ConstU32}; use scale::{Decode, Encode, MaxEncodedLen}; #[cfg(feature = "std")] -use { - scale_decode::DecodeAsType, - scale_encode::EncodeAsType, - scale_info::TypeInfo, -}; - +use {scale_decode::DecodeAsType, scale_encode::EncodeAsType, scale_info::TypeInfo}; pub mod cross_chain; pub mod storage_keys; diff --git a/runtime/devnet/src/tests/local_fungibles.rs b/runtime/devnet/src/tests/local_fungibles.rs index bc13fbde..b1ddda2e 100644 --- a/runtime/devnet/src/tests/local_fungibles.rs +++ b/runtime/devnet/src/tests/local_fungibles.rs @@ -1,3 +1,11 @@ +// Todo - errors: +// - Badorigin: contract is always signed +// - Lookup: is a valid AccountId due to the contract +// - Many errors can occur from calling a dispatchable. As of now, most of the DispatchErrors are +// handled by the pop api but not all of them are tested. How should I approach this? I.e.: +// - Arithmetic errors +// - Token errors +// - others (besides Module errors) that I might haven't found yet. #![cfg(test)] use super::*; @@ -251,16 +259,6 @@ fn asset_exists_works() { }); } -// Todo - errors: -// - Badorigin: contract is always signed -// - Lookup: is a valid AccountId due to the contract -// - reserve(): Overflow, LiquidityRestrictions; frozen -// - Callback -// - StorageDepositLimitExhausted -// todo: errors: -// - TokenErrors -// - Arithmetic -// - https://github.com/paritytech/polkadot-sdk/blob/3977f389cce4a00fd7100f95262e0563622b9aa4/substrate/frame/assets/src/functions.rs#L125 #[test] #[ignore] fn create_works() { @@ -407,10 +405,6 @@ fn transfer_from_mint_works() { }); } -// Todo: error: -// - https://github.com/paritytech/polkadot-sdk/blob/2460cddf57660a88844d201f769eb17a7accce5a/substrate/frame/assets/src/functions.rs#L161 -// - ArithmeticError: Underflow, Overflow -// - https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/functions.rs#L125 #[test] #[ignore] fn transfer_works() { diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index 6bbfaa36..4e7402a7 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -86,6 +86,7 @@ impl TryFrom for v0::FuncId { 0x1 => Self::ReadState, _ => { log::error!("called an unregistered `func_id`: {:}", func_id); + // TODO: Other error. return Err(DispatchError::Other("unimplemented func_id")); }, }; @@ -206,6 +207,7 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, + _ => Err(DispatchError::Other("Unknown state keys")), }? .encode(); @@ -215,7 +217,8 @@ where ); env.write(&result, false, None).map_err(|e| { log::trace!(target: LOG_TARGET, "{:?}", e); - DispatchError::Other("unable to write results to contract memory") + // TODO: Other error. + DispatchError::Other("Unable to write results to contract memory") }) } From 467050307884c6692bcbbbfa6b704f0c42f4ab16 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Thu, 20 Jun 2024 18:49:18 +0200 Subject: [PATCH 009/161] refactor: clarify todos --- pop-api/src/lib.rs | 2 +- pop-api/src/v0/assets/pallets/assets.rs | 4 ++-- pop-api/src/v0/balances.rs | 4 ++-- runtime/devnet/src/extensions.rs | 2 ++ runtime/devnet/src/tests/local_fungibles.rs | 8 +++----- runtime/testnet/src/extensions.rs | 1 + 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index e78aff9e..d00f1e9a 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -13,7 +13,7 @@ pub mod primitives; pub mod v0; type AccountId = AccountId32; -// TODO: do the same as above and check expanded macro code. +// TODO: do the same as the AccountId above and check expanded macro code. type Balance = ::Balance; type BlockNumber = ::BlockNumber; type StringLimit = u32; diff --git a/pop-api/src/v0/assets/pallets/assets.rs b/pop-api/src/v0/assets/pallets/assets.rs index b28d3086..87695b81 100644 --- a/pop-api/src/v0/assets/pallets/assets.rs +++ b/pop-api/src/v0/assets/pallets/assets.rs @@ -411,8 +411,8 @@ pub(crate) enum AssetsCall { Block { id: AssetIdParameter, who: MultiAddress }, } -// TODO: do we want add this. Not being used atm but necessary if we want to provide access to the -// rest of the pallet. +// TODO: Not being used atm but necessary if we want to provide access to the +// rest of the pallet, outside of the use cases. #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum AssetsError { diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs index c9759a45..56c3ca72 100644 --- a/pop-api/src/v0/balances.rs +++ b/pop-api/src/v0/balances.rs @@ -23,8 +23,8 @@ pub enum BalancesCall { }, } -// TODO: do we want add this. Not being used atm but necessary if we want to provide access to the -// rest of the pallet. +// TODO: Not being used atm but necessary if we want to provide access to the +// rest of the pallet, outside of the use cases. #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum BalancesError { diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions.rs index 014893f9..32667d16 100644 --- a/runtime/devnet/src/extensions.rs +++ b/runtime/devnet/src/extensions.rs @@ -103,6 +103,7 @@ impl TryFrom for v0::FuncId { 0x2 => Self::SendXcm, _ => { log::error!("called an unregistered `func_id`: {:}", func_id); + // TODO: Other error. return Err(DispatchError::Other("unimplemented func_id")); }, }; @@ -236,6 +237,7 @@ where ); env.write(&result, false, None).map_err(|e| { log::trace!(target: LOG_TARGET, "{:?}", e); + // TODO: Other error. DispatchError::Other("unable to write results to contract memory") }) } diff --git a/runtime/devnet/src/tests/local_fungibles.rs b/runtime/devnet/src/tests/local_fungibles.rs index b1ddda2e..9f208b15 100644 --- a/runtime/devnet/src/tests/local_fungibles.rs +++ b/runtime/devnet/src/tests/local_fungibles.rs @@ -1,11 +1,9 @@ // Todo - errors: // - Badorigin: contract is always signed // - Lookup: is a valid AccountId due to the contract -// - Many errors can occur from calling a dispatchable. As of now, most of the DispatchErrors are -// handled by the pop api but not all of them are tested. How should I approach this? I.e.: -// - Arithmetic errors -// - Token errors -// - others (besides Module errors) that I might haven't found yet. +// - Many errors can occur from calling a dispatchable. All the DispatchErrors are handled by the +// pop api but not all the possible errors for each dipatchable are tested. How should I approach +// this? #![cfg(test)] use super::*; diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index 4e7402a7..a3284ad4 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -207,6 +207,7 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, + // TODO: devnet / testnet feature. _ => Err(DispatchError::Other("Unknown state keys")), }? .encode(); From 2283161fdf9334697cbc84b9437767b189b9ce06 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Mon, 24 Jun 2024 17:38:28 +0200 Subject: [PATCH 010/161] refactor: error handling comments part 1 --- pop-api/Cargo.toml | 4 + pop-api/examples/fungibles/Cargo.toml | 2 +- pop-api/examples/fungibles/lib.rs | 25 +- pop-api/src/error.rs | 341 +++++++----- pop-api/src/lib.rs | 27 +- .../v0/assets/{use_cases => }/fungibles.rs | 74 ++- pop-api/src/v0/assets/mod.rs | 496 +++++++++++++++++- pop-api/src/v0/assets/pallets/assets.rs | 492 ----------------- pop-api/src/v0/assets/pallets/mod.rs | 1 - pop-api/src/v0/assets/use_cases/mod.rs | 1 - pop-api/src/v0/balances.rs | 6 +- pop-api/src/v0/cross_chain/mod.rs | 13 +- pop-api/src/v0/mod.rs | 26 +- pop-api/src/v0/nfts.rs | 8 +- pop-api/src/v0/state.rs | 3 +- runtime/devnet/Cargo.toml | 2 +- runtime/devnet/src/extensions.rs | 13 +- runtime/devnet/src/tests/local_fungibles.rs | 24 +- runtime/devnet/src/tests/mod.rs | 4 +- 19 files changed, 816 insertions(+), 746 deletions(-) rename pop-api/src/v0/assets/{use_cases => }/fungibles.rs (86%) delete mode 100644 pop-api/src/v0/assets/pallets/assets.rs delete mode 100644 pop-api/src/v0/assets/pallets/mod.rs delete mode 100644 pop-api/src/v0/assets/use_cases/mod.rs diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 80818235..b80cb3b0 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -31,3 +31,7 @@ std = [ "sp-io/std", "sp-runtime/std", ] +assets = [] +balances = [] +nfts = [] +cross-chain = [] diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 1fe32d6d..514f000f 100755 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false } +pop-api = { path = "../../../pop-api", default-features = false, features = ["assets"] } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 59040590..161c7fdd 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -7,12 +7,12 @@ /// use ink::prelude::vec::Vec; use pop_api::{ - assets::use_cases::fungibles as api, - error::PopApiError, + assets::fungibles::{self as api, FungiblesError}, + error::{PopApiError, StatusCode}, primitives::{AccountId as AccountId32, AssetId}, }; -pub type Result = core::result::Result; +pub type Result = core::result::Result; #[ink::contract(env = pop_api::Environment)] mod fungibles { @@ -41,12 +41,12 @@ mod fungibles { #[ink(message)] pub fn total_supply(&self, id: AssetId) -> Result { - api::total_supply(id) + api::total_supply(id).map_err(|e| e.into()) } #[ink(message)] pub fn balance_of(&self, id: AssetId, owner: AccountId32) -> Result { - api::balance_of(id, owner) + api::balance_of(id, owner).map_err(|e| e.into()) } #[ink(message)] @@ -56,7 +56,7 @@ mod fungibles { owner: AccountId32, spender: AccountId32, ) -> Result { - api::allowance(id, owner, spender) + api::allowance(id, owner, spender).map_err(|e| e.into()) } #[ink(message)] @@ -68,7 +68,7 @@ mod fungibles { value, ); - let result = api::transfer(id, to, value); + let result = api::transfer(id, to, value).map_err(|e| e.into()); ink::env::debug_println!("Result: {:?}", result); result } @@ -80,8 +80,7 @@ mod fungibles { from: Option, to: Option, value: Balance, - // In the standard a `[u8]`, but the size needs to be known at compile time ink's `Vec` - // has to be used. + // In the standard a `[u8]`, but the size needs to be known at compile time. data: Vec, ) -> Result<()> { ink::env::debug_println!( @@ -92,7 +91,7 @@ mod fungibles { value, ); - let result = api::transfer_from(id, from, to, value, &data); + let result = api::transfer_from(id, from, to, value, &data).map_err(|e| e.into()); ink::env::debug_println!("Result: {:?}", result); result } @@ -119,7 +118,7 @@ mod fungibles { admin, min_balance, ); - let result = api::create(id, admin, min_balance); + let result = api::create(id, admin, min_balance).map_err(|e| e.into()); ink::env::debug_println!("Result: {:?}", result); result } @@ -139,14 +138,14 @@ mod fungibles { symbol, decimals, ); - let result = api::set_metadata(id, name, symbol, decimals); + let result = api::set_metadata(id, name, symbol, decimals).map_err(|e| e.into()); ink::env::debug_println!("Result: {:?}", result); result } #[ink(message)] pub fn asset_exists(&self, id: AssetId) -> Result { - api::asset_exists(id) + api::asset_exists(id).map_err(|e| e.into()) } } diff --git a/pop-api/src/error.rs b/pop-api/src/error.rs index 92da4045..4d5a8fb9 100644 --- a/pop-api/src/error.rs +++ b/pop-api/src/error.rs @@ -1,8 +1,35 @@ -use crate::assets::use_cases::fungibles::{convert_to_fungibles_error, FungiblesError}; use ink::env::chain_extension::FromStatusCode; use scale::{Decode, Encode}; use PopApiError::*; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub struct StatusCode(pub u32); + +impl From for StatusCode { + fn from(value: u32) -> Self { + StatusCode(value) + } +} +impl FromStatusCode for StatusCode { + fn from_status_code(status_code: u32) -> Result<(), Self> { + match status_code { + 0 => Ok(()), + _ => { + let mut encoded = status_code.to_le_bytes(); + convert_unknown_errors(&mut encoded); + Err(StatusCode::from(u32::from_le_bytes(encoded))) + }, + } + } +} + +impl From for StatusCode { + fn from(_: scale::Error) -> Self { + DecodingFailed.into() + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] #[repr(u8)] @@ -46,79 +73,87 @@ pub enum PopApiError { Unavailable = 12, /// Root origin is not allowed. RootNotAllowed = 13, - // TODO: make generic and add docs. - UseCaseError(FungiblesError) = 254, DecodingFailed = 255, } -impl FromStatusCode for PopApiError { - fn from_status_code(status_code: u32) -> core::result::Result<(), Self> { - match status_code { - 0 => Ok(()), - _ => Err(convert_to_pop_api_error(status_code)), - } +impl From for StatusCode { + fn from(value: PopApiError) -> Self { + let mut encoded_error = value.encode(); + // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). + encoded_error.resize(4, 0); + StatusCode::from( + u32::decode(&mut &encoded_error[..]).expect("qid, resized to 4 bytes line above"), + ) } } -// `pub` because it is used in `runtime/devnet/src/extensions/tests/mod.rs`'s test: -// `dispatch_error_to_status_code_to_pop_api_error_works` -// -// This function converts a given `status_code` (u32) into a `PopApiError`. First it encodes the -// status code into a 4-byte array and checks for unknown nested errors. If decoding into -// `PopApiError` fails (e.g. a breaking change in the `DispatchError`), it handles the error by -// converting it to the `Other` variant by shifting each byte one position forward (the last byte is -// not used for anything)and setting the first byte to 0. If decoding succeeds, it checks if the -// error is of the `Module` variant and performs any necessary conversion based on the use case. -pub fn convert_to_pop_api_error(status_code: u32) -> PopApiError { - let mut encoded: [u8; 4] = - status_code.encode().try_into().expect("qid u32 always encodes to 4 bytes"); - encoded = check_for_unknown_nesting(encoded); - let error = match PopApiError::decode(&mut &encoded[..]) { - Err(_) => { - encoded[3] = encoded[2]; - encoded[2] = encoded[1]; - encoded[1] = encoded[0]; - encoded[0] = 0; - PopApiError::decode(&mut &encoded[..]).unwrap().into() - }, - Ok(error) => { - if let crate::PopApiError::Module { index, error } = error { - // TODO: make generic. - convert_to_fungibles_error(index, error) - } else { - error - } - }, - }; - ink::env::debug_println!("PopApiError: {:?}", error); - error +impl From for PopApiError { + // `pub` because it is used in `runtime/devnet/src/extensions/tests/mod.rs`'s test: + // `dispatch_error_to_status_code_to_pop_api_error_works` + // + // This function converts a given `status_code` (u32) into a `PopApiError`. + fn from(value: StatusCode) -> Self { + let encoded: [u8; 4] = value.0.to_le_bytes(); + PopApiError::decode(&mut &encoded[..]).unwrap_or(DecodingFailed) + } } -// If a unknown nested variant of the `DispatchError` is detected meaning any of the subsequent -// bytes are non-zero (e.g. breaking change in the DispatchError), the error needs to be converted -// into `PopApiError::Other`'s encoded value. This conversion is done by shifting the bytes one -// position forward (the last byte is discarded as it is not being used) and replacing the first -// byte with the `Other` encoded value (0u8). This ensures that the error is correctly categorized -// as an `Other` variant. -fn check_for_unknown_nesting(encoded_error: [u8; 4]) -> [u8; 4] { - if non_nested_pop_api_errors().contains(&encoded_error[0]) - && encoded_error[1..].iter().any(|x| *x != 0u8) - { - [0u8, encoded_error[0], encoded_error[1], encoded_error[2]] - } else if singular_nested_pop_api_errors().contains(&encoded_error[0]) +// If an unknown nested variant of the `DispatchError` is detected (i.e., any of the subsequent +// bytes are non-zero, indicating a breaking change in the `DispatchError`), the error needs to be +// converted into the encoded value of `PopApiError::Other`. This conversion is performed by +// shifting the bytes one position forward (discarding the last byte as it is not used) and setting +// the first byte to the encoded value of `Other` (0u8). This ensures the error is correctly +// categorized as an `Other` variant. +// +// Byte layout explanation: +// - Byte 0: PopApiError +// - Byte 1: +// - Must be zero for `UNIT_ERRORS`. +// - Represents the nested error in `SINGLE_NESTED_ERRORS`. +// - Represents the first level of nesting in `DOUBLE_NESTED_ERRORS`. +// - Byte 2: +// - Represents the second level of nesting in `DOUBLE_NESTED_ERRORS`. +// - Byte 3: +// - Unused or represents further nested information. +// +// This mechanism ensures backward compatibility by correctly categorizing any unknown nested errors +// into the `Other` variant, thus preventing issues caused by new or unexpected error formats. +pub(crate) fn convert_unknown_nested_errors(encoded_error: &mut [u8; 4]) { + // Converts single nested errors that are known to the Pop API as unit errors into `Other`. + if UNIT_ERRORS.contains(&encoded_error[0]) && encoded_error[1..].iter().any(|x| *x != 0u8) { + encoded_error[..].rotate_right(1); + encoded_error[0] = 0u8; + // Converts double nested errors that are known to the Pop API as single nested errors into + // `Other`. + } else if SINGLE_NESTED_ERRORS.contains(&encoded_error[0]) && encoded_error[2..].iter().any(|x| *x != 0u8) { - [0u8, encoded_error[0], encoded_error[1], encoded_error[2]] - } else { - encoded_error + encoded_error[..].rotate_right(1); + encoded_error[0] = 0u8; + } else if DOUBLE_NESTED_ERRORS.contains(&encoded_error[0]) + && encoded_error[3..].iter().any(|x| *x != 0u8) + { + encoded_error[..].rotate_right(1); + encoded_error[0] = 0u8; } } -impl From for PopApiError { - fn from(_: scale::Error) -> Self { - DecodingFailed +pub(crate) fn convert_unknown_errors(encoded_error: &mut [u8; 4]) { + let all_errors = [ + UNIT_ERRORS.as_slice(), + SINGLE_NESTED_ERRORS.as_slice(), + DOUBLE_NESTED_ERRORS.as_slice(), + // `DecodingFailed`. + &[255u8], + ] + .concat(); + if !all_errors.contains(&encoded_error[0]) { + encoded_error[..].rotate_right(1); + encoded_error[0] = 0u8; } + convert_unknown_nested_errors(encoded_error); } + #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum TokenError { @@ -165,91 +200,129 @@ pub enum TransactionalError { NoLayer, } -fn singular_nested_pop_api_errors() -> [u8; 3] { - const TOKEN_ERROR: u8 = 7; - const ARITHMETIC_ERROR: u8 = 8; - const TRANSACTION_ERROR: u8 = 9; - [TOKEN_ERROR, ARITHMETIC_ERROR, TRANSACTION_ERROR] -} +// Unit `DispatchError` variants (variant: index): +// - CannotLookup: 1, +// - BadOrigin: 2, +// - ConsumerRemaining: 4, +// - NoProviders: 5, +// - TooManyConsumers: 6, +// - Exhausted: 10, +// - Corruption: 11, +// - Unavailable: 12, +// - RootNotAllowed: 13, +const UNIT_ERRORS: [u8; 9] = [1, 2, 4, 5, 6, 10, 11, 12, 13]; -fn non_nested_pop_api_errors() -> [u8; 9] { - const CANNOT_LOOKUP: u8 = 1; - const BAD_ORIGIN: u8 = 2; - const CONSUMER_REMAINING: u8 = 4; - const NO_PROVIDERS: u8 = 5; - const TOO_MANY_CONSUMERS: u8 = 6; - const EXHAUSTED: u8 = 10; - const CORRUPTION: u8 = 11; - const UNAVAILABLE: u8 = 12; - const ROOT_NOT_ALLOWED: u8 = 13; - [ - CANNOT_LOOKUP, - BAD_ORIGIN, - CONSUMER_REMAINING, - NO_PROVIDERS, - TOO_MANY_CONSUMERS, - EXHAUSTED, - CORRUPTION, - UNAVAILABLE, - ROOT_NOT_ALLOWED, - ] -} +// Single nested `DispatchError` variants (variant: index): +// - Token: 3, +// - Arithmetic: 8, +// - Transaction: 9, +const SINGLE_NESTED_ERRORS: [u8; 3] = [7, 8, 9]; -#[test] -fn u32_always_encodes_to_4_bytes() { - assert_eq!(0u32.encode().len(), 4); - assert_eq!(u32::MAX.encode().len(), 4); -} +const DOUBLE_NESTED_ERRORS: [u8; 1] = [3]; -// If decoding failed the encoded value is converted to the `PopApiError::Other`. This handles -// unknown errors coming from the runtime. This could happen if a contract is not upgraded to the -// latest Pop API version. -#[test] -fn test_non_existing_pop_api_errors() { - let encoded_error = [7u8, 100u8, 0u8, 0u8]; - let status_code = u32::decode(&mut &encoded_error[..]).unwrap(); - let pop_api_error = ::from_status_code(status_code); - assert_eq!(Err(Other { dispatch_error_index: 7, error_index: 100, error: 0 }), pop_api_error); -} +#[cfg(test)] +mod tests { + use super::*; + use crate::error::{ArithmeticError::*, TokenError::*, TransactionalError::*}; + + #[test] + fn u32_always_encodes_to_4_bytes() { + assert_eq!(0u32.encode().len(), 4); + assert_eq!(u32::MAX.encode().len(), 4); + } -// If the encoded value indicates a nested PopApiError which is not handled by the Pop API version, -// the encoded value is converted into `PopApiError::Other`. -#[test] -fn check_for_unknown_nested_pop_api_errors_works() { - for &error_code in &non_nested_pop_api_errors() { - let encoded_error = [error_code, 1, 2, 3]; - let result = check_for_unknown_nesting(encoded_error); - let decoded = PopApiError::decode(&mut &result[..]).unwrap(); + // Decodes into `StatusCode(u32)` and converts it into the `PopApiError`. + fn into_pop_api_error(encoded_error: [u8; 4]) -> PopApiError { + let status_code = + StatusCode::from_status_code(u32::decode(&mut &encoded_error[..]).unwrap()) + .unwrap_err(); + status_code.into() + } + // Tests for the `From` implementation for `PopApiError`. + // + // If the encoded value indicates a nested `PopApiError` which is not handled by the Pop API + // version, the encoded value is converted into `PopApiError::Other`. + #[test] + fn test_unit_pop_api_error_variants() { + let errors = vec![ + CannotLookup, + BadOrigin, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + ]; + for (i, &error_code) in UNIT_ERRORS.iter().enumerate() { + assert_eq!(into_pop_api_error([error_code, 0, 0, 0]), errors[i]); + assert_eq!( + into_pop_api_error([error_code, 1, 0, 0]), + Other { dispatch_error_index: error_code, error_index: 1, error: 0 }, + ); + assert_eq!( + into_pop_api_error([error_code, 1, 1, 0]), + Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, + ); + assert_eq!( + into_pop_api_error([error_code, 1, 1, 1]), + Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, + ); + } + } + + #[test] + fn test_single_nested_pop_api_error_variants() { + let errors = vec![ + [Token(FundsUnavailable), Token(OnlyProvider)], + [Arithmetic(Underflow), Arithmetic(Overflow)], + [Transactional(LimitReached), Transactional(NoLayer)], + ]; + for (i, &error_code) in SINGLE_NESTED_ERRORS.iter().enumerate() { + assert_eq!(into_pop_api_error([error_code, 0, 0, 0]), errors[i][0]); + assert_eq!(into_pop_api_error([error_code, 1, 0, 0]), errors[i][1]); + assert_eq!( + into_pop_api_error([error_code, 1, 1, 0]), + Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, + ); + assert_eq!( + into_pop_api_error([error_code, 1, 1, 1]), + Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, + ); + } + } + + #[test] + fn test_double_nested_pop_api_error_variants() { + assert_eq!(into_pop_api_error([3, 0, 0, 0]), Module { index: 0, error: 0 }); + assert_eq!(into_pop_api_error([3, 1, 0, 0]), Module { index: 1, error: 0 }); + assert_eq!(into_pop_api_error([3, 1, 1, 0]), Module { index: 1, error: 1 }); + // TODO: doesn't make sense. assert_eq!( - decoded, - Other { dispatch_error_index: error_code, error_index: 1, error: 2 }, - "Failed for error code: {}", - error_code + into_pop_api_error([3, 1, 1, 1]), + Other { dispatch_error_index: 3, error_index: 1, error: 1 }, ); } - for &error_code in &singular_nested_pop_api_errors() { - let encoded_error = [error_code, 1, 2, 3]; - let result = check_for_unknown_nesting(encoded_error); - let decoded = PopApiError::decode(&mut &result[..]).unwrap(); + #[test] + fn test_decoding_failed() { + assert_eq!(into_pop_api_error([255, 0, 0, 0]), DecodingFailed); + assert_eq!(into_pop_api_error([255, 255, 0, 0]), DecodingFailed); + assert_eq!(into_pop_api_error([255, 255, 255, 0]), DecodingFailed); + assert_eq!(into_pop_api_error([255, 255, 255, 255]), DecodingFailed); + } + + #[test] + fn test_random_encoded_values() { + assert_eq!( + into_pop_api_error([100, 100, 100, 100]), + Other { dispatch_error_index: 100, error_index: 100, error: 100 } + ); assert_eq!( - decoded, - Other { dispatch_error_index: error_code, error_index: 1, error: 2 }, - "Failed for error code: {}", - error_code + into_pop_api_error([200, 200, 200, 200]), + Other { dispatch_error_index: 200, error_index: 200, error: 200 } ); } } - -// This test ensures that a non-zero value for unused bytes does not interfere with the correct -// decoding of the error. It verifies that even with an additional byte, the errors are correctly -// decoded and represented in its correct variant. -#[test] -fn extra_byte_does_not_mess_up_decoding() { - // Module error - let encoded_error = [3u8, 4u8, 5u8, 6u8]; - let status_code = u32::decode(&mut &encoded_error[..]).unwrap(); - let pop_api_error = ::from_status_code(status_code); - assert_eq!(Err(Module { index: 4, error: 5 }), pop_api_error); -} diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index d00f1e9a..90c81998 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,12 +1,19 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use crate::error::PopApiError; use ink::{prelude::vec::Vec, ChainExtensionInstance}; -use primitives::{cross_chain::*, storage_keys::*, AccountId as AccountId32}; -use scale::Encode; pub use sp_runtime::{BoundedVec, MultiAddress, MultiSignature}; -use v0::RuntimeCall; -pub use v0::{assets, balances, cross_chain, nfts, relay_chain_block_number, state}; + +use crate::error::{PopApiError, StatusCode}; +use primitives::{storage_keys::*, AccountId as AccountId32}; +#[cfg(feature = "assets")] +pub use v0::assets; +#[cfg(feature = "balances")] +pub use v0::balances; +#[cfg(feature = "cross-chain")] +pub use v0::cross_chain; +#[cfg(feature = "nfts")] +pub use v0::nfts; +use v0::{state, RuntimeCall}; pub mod error; pub mod primitives; @@ -15,11 +22,7 @@ pub mod v0; type AccountId = AccountId32; // TODO: do the same as the AccountId above and check expanded macro code. type Balance = ::Balance; -type BlockNumber = ::BlockNumber; -type StringLimit = u32; -type MaxTips = u32; - -pub type Result = core::result::Result; +pub type Result = core::result::Result; #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] @@ -40,7 +43,7 @@ impl ink::env::Environment for Environment { #[ink::chain_extension(extension = 909)] pub trait PopApi { - type ErrorCode = PopApiError; + type ErrorCode = StatusCode; #[ink(function = 0)] #[allow(private_interfaces)] @@ -50,6 +53,7 @@ pub trait PopApi { #[allow(private_interfaces)] fn read_state(key: RuntimeStateKeys) -> Result>; + #[cfg(feature = "cross-chain")] #[ink(function = 2)] #[allow(private_interfaces)] fn send_xcm(xcm: CrossChainMessage) -> Result<()>; @@ -67,6 +71,7 @@ fn read_state(key: RuntimeStateKeys) -> Result> { .read_state(key) } +#[cfg(feature = "cross-chain")] fn send_xcm(xcm: CrossChainMessage) -> Result<()> { <::ChainExtension as ChainExtensionInstance>::instantiate( ) diff --git a/pop-api/src/v0/assets/use_cases/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs similarity index 86% rename from pop-api/src/v0/assets/use_cases/fungibles.rs rename to pop-api/src/v0/assets/fungibles.rs index 4af5d97e..b1bb86a7 100644 --- a/pop-api/src/v0/assets/use_cases/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,12 +1,8 @@ -use crate::{ - assets::pallets, - error::PopApiError::{self, *}, - AccountId, Balance, *, -}; +use crate::{assets, primitives::AssetId, AccountId, Balance, MultiAddress, StatusCode}; use ink::prelude::vec::Vec; -use primitives::AssetId; +use scale::Encode; -type Result = core::result::Result; +type Result = core::result::Result; /// Local Fungibles: /// 1. PSP-22 Interface @@ -31,7 +27,7 @@ type Result = core::result::Result; /// # Returns /// The total supply of the token, or an error if the operation fails. pub fn total_supply(id: AssetId) -> Result { - pallets::assets::total_supply(id) + assets::total_supply(id) } /// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if @@ -44,7 +40,7 @@ pub fn total_supply(id: AssetId) -> Result { /// # Returns /// The balance of the specified account, or an error if the operation fails. pub fn balance_of(id: AssetId, owner: AccountId) -> Result { - pallets::assets::balance_of(id, owner) + assets::balance_of(id, owner) } /// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given @@ -58,7 +54,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { /// # Returns /// The remaining allowance, or an error if the operation fails. pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - pallets::assets::allowance(id, owner, spender) + assets::allowance(id, owner, spender) } /// Transfers `value` amount of tokens from the caller's account to account `to`, with additional @@ -76,7 +72,7 @@ pub fn transfer( to: impl Into>, value: Balance, ) -> Result<()> { - pallets::assets::transfer(id, to, value) + assets::transfer(id, to, value) } /// Transfers `value` tokens on behalf of `from` to account `to` with additional `data` @@ -99,9 +95,9 @@ pub fn transfer_from( _data: &[u8], ) -> Result<()> { match (from, to) { - (None, Some(to)) => pallets::assets::mint(id, to, value), - (Some(from), None) => pallets::assets::burn(id, from, value), - (Some(from), Some(to)) => pallets::assets::transfer_approved(id, from, to, value), + (None, Some(to)) => assets::mint(id, to, value), + (Some(from), None) => assets::burn(id, from, value), + (Some(from), Some(to)) => assets::transfer_approved(id, from, to, value), _ => Ok(()), } } @@ -232,7 +228,7 @@ pub fn create( admin: impl Into>, min_balance: Balance, ) -> Result<()> { - pallets::assets::create(id, admin, min_balance) + assets::create(id, admin, min_balance) } /// Start the process of destroying a token with a given asset ID. @@ -295,7 +291,7 @@ pub fn create( /// # Returns /// Returns `Ok(())` if successful, or an error if the operation fails. pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { - pallets::assets::set_metadata(id, name, symbol, decimals) + assets::set_metadata(id, name, symbol, decimals) } /// Clear the metadata for a token with a given asset ID. @@ -312,12 +308,13 @@ pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) - // } pub fn asset_exists(id: AssetId) -> Result { - pallets::assets::asset_exists(id) + assets::asset_exists(id) } #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum FungiblesError { + Other(StatusCode), /// The asset is not live; either frozen or being destroyed. AssetNotLive, /// Not enough allowance to fulfill a request is available. @@ -341,32 +338,21 @@ pub enum FungiblesError { NoBalance, } -// TODO: make generic. -pub(crate) fn convert_to_fungibles_error(index: u8, error: u8) -> PopApiError { - match index { - 10 => balance_into(error), - 52 => assets_into(error), - _ => Module { index, error }, - } -} - -fn balance_into(error: u8) -> PopApiError { - match error { - 2 => UseCaseError(FungiblesError::NoBalance), - _ => Module { index: 10, error }, - } -} - -fn assets_into(error: u8) -> PopApiError { - match error { - 0 => UseCaseError(FungiblesError::InsufficientBalance), - 1 => UseCaseError(FungiblesError::NoAccount), - 2 => UseCaseError(FungiblesError::NoPermission), - 3 => UseCaseError(FungiblesError::Unknown), - 5 => UseCaseError(FungiblesError::InUse), - 7 => UseCaseError(FungiblesError::MinBalanceZero), - 10 => UseCaseError(FungiblesError::InsufficientAllowance), - 16 => UseCaseError(FungiblesError::AssetNotLive), - _ => Module { index: 52, error }, +impl From for FungiblesError { + fn from(value: StatusCode) -> Self { + let encoded = value.0.to_le_bytes(); + match encoded { + // Balances. + [3, 10, 2, _] => FungiblesError::NoBalance, + // Assets. + [3, 52, 0, _] => FungiblesError::NoAccount, + [3, 52, 1, _] => FungiblesError::NoPermission, + [3, 52, 2, _] => FungiblesError::Unknown, + [3, 52, 3, _] => FungiblesError::InUse, + [3, 52, 5, _] => FungiblesError::MinBalanceZero, + [3, 52, 7, _] => FungiblesError::InsufficientAllowance, + [3, 52, 10, _] => FungiblesError::AssetNotLive, + _ => FungiblesError::Other(value), + } } } diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 736ccc0e..4ce68219 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,2 +1,494 @@ -pub(crate) mod pallets; -pub mod use_cases; +#![allow(dead_code)] + +use crate::{Balance, RuntimeCall, *}; +use ink::prelude::vec::Vec; +use primitives::{AssetId, MultiAddress}; +use scale::{Compact, Encode}; + +pub mod fungibles; + +type Result = core::result::Result; + +/// [Pallet Assets](https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/lib.rs): +/// 1. Dispatchables +/// 2. Read state functions +/// +/// 1. Dispatchables within pallet assets (TrustBackedAssets instance) that can be used via the pop api on Pop Network: +/// - create +/// - start_destroy +/// - destroy_accounts +/// - destroy_approvals +/// - finish_destroy +/// - mint +/// - burn +/// - transfer +/// - transfer_keep_alive +/// - force_transfer +/// - freeze +/// - thaw +/// - freeze_asset +/// - thaw_asset +/// - transfer_ownership +/// - set_team +/// - set_metadata +/// - clear_metadata +/// - approve_transfer +/// - cancel_approval +/// - force_cancel_approval +/// - transfer_approved +/// - touch +/// - refund +/// - set_min_balance +/// - touch_other +/// - refund_other +/// - block + +/// Issue a new class of fungible assets from a public origin. +pub(crate) fn create( + id: AssetId, + admin: impl Into>, + min_balance: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Create { + id: id.into(), + admin: admin.into(), + min_balance, + })) +} + +/// Start the process of destroying a fungible asset class. +pub(crate) fn start_destroy(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { id: id.into() })) +} + +/// Destroy all accounts associated with a given asset. +pub(crate) fn destroy_accounts(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { id: id.into() })) +} + +/// Destroy all approvals associated with a given asset up to the max (see runtime configuration Assets `RemoveItemsLimit`). +pub(crate) fn destroy_approvals(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { id: id.into() })) +} + +/// Complete destroying asset and unreserve currency. +pub(crate) fn finish_destroy(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { id: id.into() })) +} + +/// Mint assets of a particular class. +pub(crate) fn mint( + id: AssetId, + beneficiary: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Mint { + id: id.into(), + beneficiary: beneficiary.into(), + amount: Compact(amount), + })) +} + +/// Reduce the balance of `who` by as much as possible up to `amount` assets of `id`. +pub(crate) fn burn( + id: AssetId, + who: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Burn { + id: id.into(), + who: who.into(), + amount: Compact(amount), + })) +} + +/// Move some assets from the sender account to another. +pub(crate) fn transfer( + id: AssetId, + target: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { + id: id.into(), + target: target.into(), + amount: Compact(amount), + })) +} + +/// Move some assets from the sender account to another, keeping the sender account alive. +pub(crate) fn transfer_keep_alive( + id: AssetId, + target: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { + id: id.into(), + target: target.into(), + amount: Compact(amount), + })) +} + +/// Move some assets from one account to another. Sender should be the Admin of the asset `id`. +pub(crate) fn force_transfer( + id: AssetId, + source: impl Into>, + dest: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ForceTransfer { + id: id.into(), + source: source.into(), + dest: dest.into(), + amount: Compact(amount), + })) +} + +/// Disallow further unprivileged transfers of an asset `id` from an account `who`. `who` +/// must already exist as an entry in `Account`s of the asset. If you want to freeze an +/// account that does not have an entry, use `touch_other` first. +pub(crate) fn freeze(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Freeze { id: id.into(), who: who.into() })) +} + +/// Allow unprivileged transfers to and from an account again. +pub(crate) fn thaw(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Thaw { id: id.into(), who: who.into() })) +} + +/// Disallow further unprivileged transfers for the asset class. +pub(crate) fn freeze_asset(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::FreezeAsset { id: id.into() })) +} + +/// Allow unprivileged transfers for the asset again. +pub(crate) fn thaw_asset(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ThawAsset { id: id.into() })) +} + +/// Change the Owner of an asset. +pub(crate) fn transfer_ownership( + id: AssetId, + owner: impl Into>, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TransferOwnership { + id: id.into(), + owner: owner.into(), + })) +} + +/// Change the Issuer, Admin and Freezer of an asset. +pub(crate) fn set_team( + id: AssetId, + issuer: impl Into>, + admin: impl Into>, + freezer: impl Into>, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::SetTeam { + id: id.into(), + issuer: issuer.into(), + admin: admin.into(), + freezer: freezer.into(), + })) +} + +/// Set the metadata for an asset. +pub(crate) fn set_metadata( + id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::SetMetadata { id: id.into(), name, symbol, decimals })) +} + +/// Clear the metadata for an asset. +pub(crate) fn clear_metadata(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { id: id.into() })) +} + +/// Approve an amount of asset for transfer by a delegated third-party account. +pub(crate) fn approve_transfer( + id: AssetId, + delegate: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { + id: id.into(), + delegate: delegate.into(), + amount: Compact(amount), + })) +} + +/// Cancel all of some asset approved for delegated transfer by a third-party account. +pub(crate) fn cancel_approval( + id: AssetId, + delegate: impl Into>, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::CancelApproval { + id: id.into(), + delegate: delegate.into(), + })) +} + +/// Cancel all of some asset approved for delegated transfer by a third-party account. +pub(crate) fn force_cancel_approval( + id: AssetId, + owner: impl Into>, + delegate: impl Into>, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::ForceCancelApproval { + id: id.into(), + owner: owner.into(), + delegate: delegate.into(), + })) +} + +/// Transfer some asset balance from a previously delegated account to some third-party +/// account. +pub(crate) fn transfer_approved( + id: AssetId, + owner: impl Into>, + destination: impl Into>, + amount: Balance, +) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TransferApproved { + id: id.into(), + owner: owner.into(), + destination: destination.into(), + amount: Compact(amount), + })) +} + +/// Create an asset account for non-provider assets. +pub(crate) fn touch(id: AssetId) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Touch { id: id.into() })) +} + +/// Return the deposit (if any) of an asset account or a consumer reference (if any) of an +/// account. +pub(crate) fn refund(id: AssetId, allow_burn: bool) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Refund { id: id.into(), allow_burn })) +} + +/// Sets the minimum balance of an asset. +pub(crate) fn set_min_balance(id: AssetId, min_balance: Balance) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::SetMinBalance { + id: id.into(), + min_balance: Compact(min_balance), + })) +} + +/// Create an asset account for `who`. +pub(crate) fn touch_other(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::TouchOther { id: id.into(), who: who.into() })) +} + +/// Return the deposit (if any) of a target asset account. Useful if you are the depositor. +pub(crate) fn refund_other(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::RefundOther { id: id.into(), who: who.into() })) +} + +/// Disallow further unprivileged transfers of an asset `id` to and from an account `who`. +pub(crate) fn block(id: AssetId, who: impl Into>) -> Result<()> { + dispatch(RuntimeCall::Assets(AssetsCall::Block { id: id.into(), who: who.into() })) +} + +/// 2. Read state functions +/// - total_supply +/// - + +pub(crate) fn total_supply(id: AssetId) -> Result { + state::read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id))).into() +} + +pub(crate) fn balance_of(id: AssetId, owner: AccountId) -> Result { + state::read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner))).into() +} + +pub(crate) fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { + state::read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender))).into() +} +pub(crate) fn asset_exists(id: AssetId) -> Result { + state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))).into() +} + +// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected +// to be compact encoded. The pop api handles that for the developer. +// +// reference: https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development +// +// Asset id that is compact encoded. +type AssetIdParameter = Compact; +// Balance amount that is compact encoded. +type BalanceParameter = Compact; + +#[derive(Encode)] +pub(crate) enum AssetsCall { + #[codec(index = 0)] + Create { id: AssetIdParameter, admin: MultiAddress, min_balance: Balance }, + #[codec(index = 2)] + StartDestroy { id: AssetIdParameter }, + #[codec(index = 3)] + DestroyAccounts { id: AssetIdParameter }, + #[codec(index = 4)] + DestroyApprovals { id: AssetIdParameter }, + #[codec(index = 5)] + FinishDestroy { id: AssetIdParameter }, + #[codec(index = 6)] + Mint { + id: AssetIdParameter, + beneficiary: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 7)] + Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, + #[codec(index = 8)] + Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, + #[codec(index = 9)] + TransferKeepAlive { + id: AssetIdParameter, + target: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 10)] + ForceTransfer { + id: AssetIdParameter, + source: MultiAddress, + dest: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 11)] + Freeze { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 12)] + Thaw { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 13)] + FreezeAsset { id: AssetIdParameter }, + #[codec(index = 14)] + ThawAsset { id: AssetIdParameter }, + #[codec(index = 15)] + TransferOwnership { id: AssetIdParameter, owner: MultiAddress }, + #[codec(index = 16)] + SetTeam { + id: AssetIdParameter, + issuer: MultiAddress, + admin: MultiAddress, + freezer: MultiAddress, + }, + #[codec(index = 17)] + SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, + #[codec(index = 18)] + ClearMetadata { id: AssetIdParameter }, + #[codec(index = 22)] + ApproveTransfer { + id: AssetIdParameter, + delegate: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 23)] + CancelApproval { id: AssetIdParameter, delegate: MultiAddress }, + #[codec(index = 24)] + ForceCancelApproval { + id: AssetIdParameter, + owner: MultiAddress, + delegate: MultiAddress, + }, + #[codec(index = 25)] + TransferApproved { + id: AssetIdParameter, + owner: MultiAddress, + destination: MultiAddress, + amount: BalanceParameter, + }, + #[codec(index = 26)] + Touch { id: AssetIdParameter }, + #[codec(index = 27)] + Refund { id: AssetIdParameter, allow_burn: bool }, + #[codec(index = 28)] + SetMinBalance { id: AssetIdParameter, min_balance: BalanceParameter }, + #[codec(index = 29)] + TouchOther { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 30)] + RefundOther { id: AssetIdParameter, who: MultiAddress }, + #[codec(index = 31)] + Block { id: AssetIdParameter, who: MultiAddress }, +} + +// TODO: Not being used atm but necessary if we want to provide access to the +// rest of the pallet, outside of the use cases. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum AssetsError { + /// Account balance must be greater than or equal to the transfer amount. + BalanceLow, + /// The account to alter does not exist. + NoAccount, + /// The signing account has no permission to do the operation. + NoPermission, + /// The given asset ID is unknown. + Unknown, + /// The origin account is frozen. + Frozen, + /// The asset ID is already taken. + InUse, + /// Invalid witness data given. + BadWitness, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// Unable to increment the consumer reference counters on the account. Either no provider + /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one + /// fewer then the maximum number of consumers has been reached. + UnavailableConsumer, + /// Invalid metadata given. + BadMetadata, + /// No approval exists that would allow the transfer. + Unapproved, + /// The source account would not survive the transfer and it needs to stay alive. + WouldDie, + /// The asset-account already exists. + AlreadyExists, + /// The asset-account doesn't have an associated deposit. + NoDeposit, + /// The operation would result in funds being burned. + WouldBurn, + /// The asset is a live asset and is actively being used. Usually emit for operations such + /// as `start_destroy` which require the asset to be in a destroying state. + LiveAsset, + /// The asset is not live, and likely being destroyed. + AssetNotLive, + /// The asset status is not the expected status. + IncorrectStatus, + /// The asset should be frozen before the given operation. + NotFrozen, + /// Callback action resulted in error. + CallbackFailed, +} + +impl TryFrom for AssetsError { + type Error = PopApiError; + + fn try_from(status_code: u32) -> core::result::Result { + use AssetsError::*; + match status_code { + 0 => Ok(BalanceLow), + 1 => Ok(NoAccount), + 2 => Ok(NoPermission), + 3 => Ok(Unknown), + 4 => Ok(Frozen), + 5 => Ok(InUse), + 6 => Ok(BadWitness), + 7 => Ok(MinBalanceZero), + 8 => Ok(UnavailableConsumer), + 9 => Ok(BadMetadata), + 10 => Ok(Unapproved), + 11 => Ok(WouldDie), + 12 => Ok(AlreadyExists), + 13 => Ok(NoDeposit), + 14 => Ok(WouldBurn), + 15 => Ok(LiveAsset), + 16 => Ok(AssetNotLive), + 17 => Ok(IncorrectStatus), + 18 => Ok(NotFrozen), + _ => todo!(), + } + } +} diff --git a/pop-api/src/v0/assets/pallets/assets.rs b/pop-api/src/v0/assets/pallets/assets.rs deleted file mode 100644 index 87695b81..00000000 --- a/pop-api/src/v0/assets/pallets/assets.rs +++ /dev/null @@ -1,492 +0,0 @@ -#![allow(dead_code)] - -use crate::{Balance, RuntimeCall, *}; -use ink::prelude::vec::Vec; -use primitives::{AssetId, MultiAddress}; -use scale::{Compact, Encode}; - -type Result = core::result::Result; - -/// [Pallet Assets](https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/lib.rs): -/// 1. Dispatchables -/// 2. Read state functions -/// -/// 1. Dispatchables within pallet assets (TrustBackedAssets instance) that can be used via the pop api on Pop Network: -/// - create -/// - start_destroy -/// - destroy_accounts -/// - destroy_approvals -/// - finish_destroy -/// - mint -/// - burn -/// - transfer -/// - transfer_keep_alive -/// - force_transfer -/// - freeze -/// - thaw -/// - freeze_asset -/// - thaw_asset -/// - transfer_ownership -/// - set_team -/// - set_metadata -/// - clear_metadata -/// - approve_transfer -/// - cancel_approval -/// - force_cancel_approval -/// - transfer_approved -/// - touch -/// - refund -/// - set_min_balance -/// - touch_other -/// - refund_other -/// - block - -/// Issue a new class of fungible assets from a public origin. -pub(crate) fn create( - id: AssetId, - admin: impl Into>, - min_balance: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Create { - id: id.into(), - admin: admin.into(), - min_balance, - })) -} - -/// Start the process of destroying a fungible asset class. -pub(crate) fn start_destroy(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { id: id.into() })) -} - -/// Destroy all accounts associated with a given asset. -pub(crate) fn destroy_accounts(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { id: id.into() })) -} - -/// Destroy all approvals associated with a given asset up to the max (see runtime configuration Assets `RemoveItemsLimit`). -pub(crate) fn destroy_approvals(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { id: id.into() })) -} - -/// Complete destroying asset and unreserve currency. -pub(crate) fn finish_destroy(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { id: id.into() })) -} - -/// Mint assets of a particular class. -pub(crate) fn mint( - id: AssetId, - beneficiary: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Mint { - id: id.into(), - beneficiary: beneficiary.into(), - amount: Compact(amount), - })) -} - -/// Reduce the balance of `who` by as much as possible up to `amount` assets of `id`. -pub(crate) fn burn( - id: AssetId, - who: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Burn { - id: id.into(), - who: who.into(), - amount: Compact(amount), - })) -} - -/// Move some assets from the sender account to another. -pub(crate) fn transfer( - id: AssetId, - target: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { - id: id.into(), - target: target.into(), - amount: Compact(amount), - })) -} - -/// Move some assets from the sender account to another, keeping the sender account alive. -pub(crate) fn transfer_keep_alive( - id: AssetId, - target: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { - id: id.into(), - target: target.into(), - amount: Compact(amount), - })) -} - -/// Move some assets from one account to another. Sender should be the Admin of the asset `id`. -pub(crate) fn force_transfer( - id: AssetId, - source: impl Into>, - dest: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ForceTransfer { - id: id.into(), - source: source.into(), - dest: dest.into(), - amount: Compact(amount), - })) -} - -/// Disallow further unprivileged transfers of an asset `id` from an account `who`. `who` -/// must already exist as an entry in `Account`s of the asset. If you want to freeze an -/// account that does not have an entry, use `touch_other` first. -pub(crate) fn freeze(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Freeze { id: id.into(), who: who.into() })) -} - -/// Allow unprivileged transfers to and from an account again. -pub(crate) fn thaw(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Thaw { id: id.into(), who: who.into() })) -} - -/// Disallow further unprivileged transfers for the asset class. -pub(crate) fn freeze_asset(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::FreezeAsset { id: id.into() })) -} - -/// Allow unprivileged transfers for the asset again. -pub(crate) fn thaw_asset(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ThawAsset { id: id.into() })) -} - -/// Change the Owner of an asset. -pub(crate) fn transfer_ownership( - id: AssetId, - owner: impl Into>, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TransferOwnership { - id: id.into(), - owner: owner.into(), - })) -} - -/// Change the Issuer, Admin and Freezer of an asset. -pub(crate) fn set_team( - id: AssetId, - issuer: impl Into>, - admin: impl Into>, - freezer: impl Into>, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::SetTeam { - id: id.into(), - issuer: issuer.into(), - admin: admin.into(), - freezer: freezer.into(), - })) -} - -/// Set the metadata for an asset. -pub(crate) fn set_metadata( - id: AssetId, - name: Vec, - symbol: Vec, - decimals: u8, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::SetMetadata { id: id.into(), name, symbol, decimals })) -} - -/// Clear the metadata for an asset. -pub(crate) fn clear_metadata(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { id: id.into() })) -} - -/// Approve an amount of asset for transfer by a delegated third-party account. -pub(crate) fn approve_transfer( - id: AssetId, - delegate: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { - id: id.into(), - delegate: delegate.into(), - amount: Compact(amount), - })) -} - -/// Cancel all of some asset approved for delegated transfer by a third-party account. -pub(crate) fn cancel_approval( - id: AssetId, - delegate: impl Into>, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::CancelApproval { - id: id.into(), - delegate: delegate.into(), - })) -} - -/// Cancel all of some asset approved for delegated transfer by a third-party account. -pub(crate) fn force_cancel_approval( - id: AssetId, - owner: impl Into>, - delegate: impl Into>, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ForceCancelApproval { - id: id.into(), - owner: owner.into(), - delegate: delegate.into(), - })) -} - -/// Transfer some asset balance from a previously delegated account to some third-party -/// account. -pub(crate) fn transfer_approved( - id: AssetId, - owner: impl Into>, - destination: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TransferApproved { - id: id.into(), - owner: owner.into(), - destination: destination.into(), - amount: Compact(amount), - })) -} - -/// Create an asset account for non-provider assets. -pub(crate) fn touch(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Touch { id: id.into() })) -} - -/// Return the deposit (if any) of an asset account or a consumer reference (if any) of an -/// account. -pub(crate) fn refund(id: AssetId, allow_burn: bool) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Refund { id: id.into(), allow_burn })) -} - -/// Sets the minimum balance of an asset. -pub(crate) fn set_min_balance(id: AssetId, min_balance: Balance) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::SetMinBalance { - id: id.into(), - min_balance: Compact(min_balance), - })) -} - -/// Create an asset account for `who`. -pub(crate) fn touch_other(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TouchOther { id: id.into(), who: who.into() })) -} - -/// Return the deposit (if any) of a target asset account. Useful if you are the depositor. -pub(crate) fn refund_other(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::RefundOther { id: id.into(), who: who.into() })) -} - -/// Disallow further unprivileged transfers of an asset `id` to and from an account `who`. -pub(crate) fn block(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Block { id: id.into(), who: who.into() })) -} - -/// 2. Read state functions -/// - total_supply -/// - - -pub(crate) fn total_supply(id: AssetId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id))).into() -} - -pub(crate) fn balance_of(id: AssetId, owner: AccountId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner))).into() -} - -pub(crate) fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender))).into() -} -pub(crate) fn asset_exists(id: AssetId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))).into() -} - -// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected -// to be compact encoded. The pop api handles that for the developer. -// -// reference: https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development -// -// Asset id that is compact encoded. -type AssetIdParameter = Compact; -// Balance amount that is compact encoded. -type BalanceParameter = Compact; - -#[derive(Encode)] -pub(crate) enum AssetsCall { - #[codec(index = 0)] - Create { id: AssetIdParameter, admin: MultiAddress, min_balance: Balance }, - #[codec(index = 2)] - StartDestroy { id: AssetIdParameter }, - #[codec(index = 3)] - DestroyAccounts { id: AssetIdParameter }, - #[codec(index = 4)] - DestroyApprovals { id: AssetIdParameter }, - #[codec(index = 5)] - FinishDestroy { id: AssetIdParameter }, - #[codec(index = 6)] - Mint { - id: AssetIdParameter, - beneficiary: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 7)] - Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, - #[codec(index = 8)] - Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, - #[codec(index = 9)] - TransferKeepAlive { - id: AssetIdParameter, - target: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 10)] - ForceTransfer { - id: AssetIdParameter, - source: MultiAddress, - dest: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 11)] - Freeze { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 12)] - Thaw { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 13)] - FreezeAsset { id: AssetIdParameter }, - #[codec(index = 14)] - ThawAsset { id: AssetIdParameter }, - #[codec(index = 15)] - TransferOwnership { id: AssetIdParameter, owner: MultiAddress }, - #[codec(index = 16)] - SetTeam { - id: AssetIdParameter, - issuer: MultiAddress, - admin: MultiAddress, - freezer: MultiAddress, - }, - #[codec(index = 17)] - SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, - #[codec(index = 18)] - ClearMetadata { id: AssetIdParameter }, - #[codec(index = 22)] - ApproveTransfer { - id: AssetIdParameter, - delegate: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 23)] - CancelApproval { id: AssetIdParameter, delegate: MultiAddress }, - #[codec(index = 24)] - ForceCancelApproval { - id: AssetIdParameter, - owner: MultiAddress, - delegate: MultiAddress, - }, - #[codec(index = 25)] - TransferApproved { - id: AssetIdParameter, - owner: MultiAddress, - destination: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 26)] - Touch { id: AssetIdParameter }, - #[codec(index = 27)] - Refund { id: AssetIdParameter, allow_burn: bool }, - #[codec(index = 28)] - SetMinBalance { id: AssetIdParameter, min_balance: BalanceParameter }, - #[codec(index = 29)] - TouchOther { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 30)] - RefundOther { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 31)] - Block { id: AssetIdParameter, who: MultiAddress }, -} - -// TODO: Not being used atm but necessary if we want to provide access to the -// rest of the pallet, outside of the use cases. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum AssetsError { - /// Account balance must be greater than or equal to the transfer amount. - BalanceLow, - /// The account to alter does not exist. - NoAccount, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given asset ID is unknown. - Unknown, - /// The origin account is frozen. - Frozen, - /// The asset ID is already taken. - InUse, - /// Invalid witness data given. - BadWitness, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// Unable to increment the consumer reference counters on the account. Either no provider - /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one - /// fewer then the maximum number of consumers has been reached. - UnavailableConsumer, - /// Invalid metadata given. - BadMetadata, - /// No approval exists that would allow the transfer. - Unapproved, - /// The source account would not survive the transfer and it needs to stay alive. - WouldDie, - /// The asset-account already exists. - AlreadyExists, - /// The asset-account doesn't have an associated deposit. - NoDeposit, - /// The operation would result in funds being burned. - WouldBurn, - /// The asset is a live asset and is actively being used. Usually emit for operations such - /// as `start_destroy` which require the asset to be in a destroying state. - LiveAsset, - /// The asset is not live, and likely being destroyed. - AssetNotLive, - /// The asset status is not the expected status. - IncorrectStatus, - /// The asset should be frozen before the given operation. - NotFrozen, - /// Callback action resulted in error. - CallbackFailed, -} - -impl TryFrom for AssetsError { - type Error = PopApiError; - - fn try_from(status_code: u32) -> core::result::Result { - use AssetsError::*; - match status_code { - 0 => Ok(BalanceLow), - 1 => Ok(NoAccount), - 2 => Ok(NoPermission), - 3 => Ok(Unknown), - 4 => Ok(Frozen), - 5 => Ok(InUse), - 6 => Ok(BadWitness), - 7 => Ok(MinBalanceZero), - 8 => Ok(UnavailableConsumer), - 9 => Ok(BadMetadata), - 10 => Ok(Unapproved), - 11 => Ok(WouldDie), - 12 => Ok(AlreadyExists), - 13 => Ok(NoDeposit), - 14 => Ok(WouldBurn), - 15 => Ok(LiveAsset), - 16 => Ok(AssetNotLive), - 17 => Ok(IncorrectStatus), - 18 => Ok(NotFrozen), - _ => todo!(), - } - } -} diff --git a/pop-api/src/v0/assets/pallets/mod.rs b/pop-api/src/v0/assets/pallets/mod.rs deleted file mode 100644 index 0b8a53a0..00000000 --- a/pop-api/src/v0/assets/pallets/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub(crate) mod assets; diff --git a/pop-api/src/v0/assets/use_cases/mod.rs b/pop-api/src/v0/assets/use_cases/mod.rs deleted file mode 100644 index 182590df..00000000 --- a/pop-api/src/v0/assets/use_cases/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod fungibles; diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs index 56c3ca72..ae2709e7 100644 --- a/pop-api/src/v0/balances.rs +++ b/pop-api/src/v0/balances.rs @@ -1,6 +1,8 @@ -use crate::{dispatch, error::PopApiError, primitives::MultiAddress, v0::RuntimeCall, AccountId}; +use crate::{ + dispatch, primitives::MultiAddress, v0::RuntimeCall, AccountId, PopApiError, StatusCode, +}; -type Result = core::result::Result; +type Result = core::result::Result; pub fn transfer_keep_alive( dest: impl Into>, diff --git a/pop-api/src/v0/cross_chain/mod.rs b/pop-api/src/v0/cross_chain/mod.rs index 1d3c5b7d..583447b1 100644 --- a/pop-api/src/v0/cross_chain/mod.rs +++ b/pop-api/src/v0/cross_chain/mod.rs @@ -1,8 +1,15 @@ pub mod coretime; -use crate::error::PopApiError; +use crate::StatusCode; -type Result = core::result::Result; +type Result = core::result::Result; +type BlockNumber = ::BlockNumber; + +pub fn relay_chain_block_number() -> std::result::Result { + crate::v0::state::read(RuntimeStateKeys::ParachainSystem( + ParachainSystemKeys::LastRelayChainBlockNumber, + )) +} #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] @@ -63,7 +70,7 @@ pub enum Error { } impl TryFrom for Error { - type Error = PopApiError; + type Error = Error; fn try_from(status_code: u32) -> core::result::Result { use Error::*; diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 75bcb878..41574cfb 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -1,24 +1,22 @@ -use crate::{ - primitives::storage_keys::{ParachainSystemKeys, RuntimeStateKeys}, - BlockNumber, PopApiError, -}; - +#[cfg(feature = "assets")] pub mod assets; +#[cfg(feature = "balances")] pub mod balances; +#[cfg(feature = "cross-chain")] pub mod cross_chain; +#[cfg(feature = "nfts")] pub mod nfts; pub mod state; -pub fn relay_chain_block_number() -> Result { - state::read(RuntimeStateKeys::ParachainSystem(ParachainSystemKeys::LastRelayChainBlockNumber)) -} - #[derive(scale::Encode)] pub(crate) enum RuntimeCall { - #[codec(index = 10)] - Balances(balances::BalancesCall), - #[codec(index = 50)] - Nfts(nfts::NftCalls), + // #[codec(index = 10)] + // #[cfg(feature = "balances")] + // Balances(balances::BalancesCall), + // #[codec(index = 50)] + // #[cfg(feature = "nfts")] + // Nfts(nfts::NftCalls), #[codec(index = 52)] - Assets(assets::pallets::assets::AssetsCall), + #[cfg(feature = "assets")] + Assets(assets::AssetsCall), } diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs index 2de306a9..1e4406e5 100644 --- a/pop-api/src/v0/nfts.rs +++ b/pop-api/src/v0/nfts.rs @@ -1,12 +1,14 @@ use super::RuntimeCall; -use crate::{PopApiError, *}; +use crate::*; use ink::prelude::vec::Vec; use primitives::{ApprovalsLimit, BoundedBTreeMap, KeyLimit, MultiAddress}; pub use primitives::{CollectionId, ItemId}; use scale::Encode; pub use types::*; -type Result = core::result::Result; +type Result = core::result::Result; +type StringLimit = u32; +type MaxTips = u32; /// Issue a new collection of non-fungible items pub fn create( @@ -610,7 +612,7 @@ pub enum Error { } impl TryFrom for Error { - type Error = PopApiError; + type Error = Error; fn try_from(status_code: u32) -> core::result::Result { use Error::*; diff --git a/pop-api/src/v0/state.rs b/pop-api/src/v0/state.rs index 9f5e4c0c..1aca01cf 100644 --- a/pop-api/src/v0/state.rs +++ b/pop-api/src/v0/state.rs @@ -2,5 +2,6 @@ use crate::{primitives::storage_keys::RuntimeStateKeys, read_state, PopApiError} use scale::Decode; pub fn read(key: RuntimeStateKeys) -> crate::Result { - read_state(key).and_then(|v| T::decode(&mut &v[..]).map_err(|_e| PopApiError::DecodingFailed)) + read_state(key) + .and_then(|v| T::decode(&mut &v[..]).map_err(|_e| PopApiError::DecodingFailed.into())) } diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index 46208d8f..daa5457e 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -91,7 +91,7 @@ parachain-info.workspace = true env_logger = "0.11.2" hex = "0.4.3" enumflags2 = "0.7.9" -pop-api = { path = "../../pop-api", default-features = false } +pop-api = { path = "../../pop-api", defeult-features = false, features = ["assets"] } [features] default = ["std"] diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions.rs index 32667d16..b4c6ba84 100644 --- a/runtime/devnet/src/extensions.rs +++ b/runtime/devnet/src/extensions.rs @@ -72,16 +72,11 @@ where } } } - pub(crate) fn convert_to_status_code(error: DispatchError) -> u32 { - match error { - _ => { - let mut encoded_error = error.encode(); - // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). - encoded_error.resize(4, 0); - u32::decode(&mut &encoded_error[..]).unwrap() - }, - } + let mut encoded_error = error.encode(); + // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). + encoded_error.resize(4, 0); + u32::decode(&mut &encoded_error[..]).expect("qid, resized to 4 bytes line above") } pub mod v0 { diff --git a/runtime/devnet/src/tests/local_fungibles.rs b/runtime/devnet/src/tests/local_fungibles.rs index 9f208b15..154e9897 100644 --- a/runtime/devnet/src/tests/local_fungibles.rs +++ b/runtime/devnet/src/tests/local_fungibles.rs @@ -269,7 +269,7 @@ fn create_works() { // No balance to pay for fees. assert_eq!( decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), - UseCaseError(NoBalance) + Module { index: 10, error: 2 }, ); // Instantiate a contract without balance (relay token). let addr = @@ -278,7 +278,7 @@ fn create_works() { // No balance to pay fe deposit. assert_eq!( decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), - UseCaseError(NoBalance) + Module { index: 10, error: 2 }, ); // Instantiate a contract with balance. let addr = instantiate( @@ -290,12 +290,12 @@ fn create_works() { // Asset ID is already taken. assert_eq!( decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), - UseCaseError(InUse) + Module { index: 52, error: 5 }, ); // The minimal balance for an asset must be non zero. assert_eq!( decoded::(create(addr.clone(), new_asset, BOB, 0)), - UseCaseError(MinBalanceZero) + Module { index: 52, error: 7 }, ); let result = create(addr.clone(), new_asset, BOB, 1); assert!(!result.did_revert(), "Contract reverted!"); @@ -347,7 +347,7 @@ fn transfer_from_mint_works() { amount, &[0u8] )), - UseCaseError(NoPermission) + Module { index: 52, error: 2 }, ); // Minimum balance of an asset can not be zero. assert_eq!( @@ -366,7 +366,7 @@ fn transfer_from_mint_works() { amount, &[0u8] )), - UseCaseError(AssetNotLive) + Module { index: 52, error: 16 }, ); thaw_asset(asset, addr.clone()); // Successful mint. @@ -398,7 +398,7 @@ fn transfer_from_mint_works() { amount, &[0u8] )), - UseCaseError(AssetNotLive) + Module { index: 52, error: 16 }, ); }); } @@ -418,7 +418,7 @@ fn transfer_works() { // Asset does not exist. assert_eq!( decoded::(transfer(addr.clone(), 1, BOB, amount,)), - UseCaseError(Unknown) + Module { index: 52, error: 3 }, ); // Create asset with Alice as owner and mint `amount` to contract address. let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); @@ -426,18 +426,18 @@ fn transfer_works() { freeze_asset(asset, ALICE); assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount,)), - UseCaseError(AssetNotLive) + Module { index: 52, error: 16 }, ); thaw_asset(asset, ALICE); // Not enough balance. assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), - UseCaseError(InsufficientBalance) + Module { index: 52, error: 0 }, ); // Not enough balance due to ED. assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount)), - UseCaseError(InsufficientBalance) + Module { index: 52, error: 0 }, ); // Successful transfer. let bob_balance_before_mint = Assets::balance(asset, &BOB); @@ -454,7 +454,7 @@ fn transfer_works() { start_destroy_asset(asset, ALICE); assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), - UseCaseError(AssetNotLive) + Module { index: 52, error: 16 }, ); }); } diff --git a/runtime/devnet/src/tests/mod.rs b/runtime/devnet/src/tests/mod.rs index c13030a3..dcb97ae1 100644 --- a/runtime/devnet/src/tests/mod.rs +++ b/runtime/devnet/src/tests/mod.rs @@ -256,7 +256,7 @@ fn dispatch_error_to_status_code_to_pop_api_error_works() { for (error, pop_api_error) in test_cases { // Show that the encoding and decoding of the PopApiError <> u32 (status code) works. let status_code = crate::extensions::convert_to_status_code(error); - let error = pop_api::error::convert_to_pop_api_error(status_code); - assert_eq!(pop_api_error, error,); + // let error = pop_api::error::convert_to_pop_api_error(status_code); + // assert_eq!(pop_api_error, error,); } } From f88dd89b8fbbfebc28126f0262fc8b5397b903d6 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Tue, 25 Jun 2024 16:58:18 +0200 Subject: [PATCH 011/161] refactor: apply comments part 2 --- pop-api/Cargo.toml | 6 +- .../{balance-transfer => }/.gitignore | 2 +- pop-api/examples/fungibles/.gitignore | 9 - pop-api/examples/fungibles/lib.rs | 2 +- pop-api/examples/nfts/.gitignore | 9 - pop-api/examples/place-spot-order/.gitignore | 9 - .../examples/read-runtime-state/.gitignore | 9 - pop-api/src/error.rs | 317 ++++++++++------- pop-api/src/lib.rs | 12 +- pop-api/src/primitives.rs | 1 - pop-api/src/v0/assets/fungibles.rs | 64 ++++ pop-api/src/v0/assets/mod.rs | 8 +- pop-api/src/v0/balances.rs | 6 +- pop-api/src/v0/cross_chain/mod.rs | 9 +- pop-api/src/v0/mod.rs | 12 +- pop-api/src/v0/nfts.rs | 318 +++++++++--------- pop-api/src/v0/state.rs | 5 +- primitives/Cargo.toml | 5 +- primitives/src/lib.rs | 25 +- primitives/src/storage_keys.rs | 10 +- runtime/devnet/Cargo.toml | 4 +- runtime/devnet/src/extensions.rs | 19 +- runtime/devnet/src/lib.rs | 4 +- runtime/devnet/src/tests/local_fungibles.rs | 57 +--- runtime/devnet/src/tests/mod.rs | 311 ++++++++--------- runtime/testnet/Cargo.toml | 2 +- runtime/testnet/src/extensions.rs | 6 +- runtime/testnet/src/lib.rs | 4 +- 28 files changed, 677 insertions(+), 568 deletions(-) rename pop-api/examples/{balance-transfer => }/.gitignore (93%) delete mode 100755 pop-api/examples/fungibles/.gitignore delete mode 100755 pop-api/examples/nfts/.gitignore delete mode 100755 pop-api/examples/place-spot-order/.gitignore delete mode 100755 pop-api/examples/read-runtime-state/.gitignore diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index b80cb3b0..9a868cfa 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -31,7 +31,7 @@ std = [ "sp-io/std", "sp-runtime/std", ] -assets = [] +assets = ["pop-primitives/assets"] balances = [] -nfts = [] -cross-chain = [] +nfts = ["pop-primitives/nfts"] +cross-chain = ["pop-primitives/cross-chain"] diff --git a/pop-api/examples/balance-transfer/.gitignore b/pop-api/examples/.gitignore similarity index 93% rename from pop-api/examples/balance-transfer/.gitignore rename to pop-api/examples/.gitignore index 8de8f877..e0caa493 100755 --- a/pop-api/examples/balance-transfer/.gitignore +++ b/pop-api/examples/.gitignore @@ -1,5 +1,5 @@ # Ignore build artifacts from the local tests sub-crate. -/target/ +/fungibles/target/ # Ignore backup files creates by cargo fmt. **/*.rs.bk diff --git a/pop-api/examples/fungibles/.gitignore b/pop-api/examples/fungibles/.gitignore deleted file mode 100755 index 8de8f877..00000000 --- a/pop-api/examples/fungibles/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Ignore build artifacts from the local tests sub-crate. -/target/ - -# Ignore backup files creates by cargo fmt. -**/*.rs.bk - -# Remove Cargo.lock when creating an executable, leave it for libraries -# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock -Cargo.lock diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 161c7fdd..41ea1b14 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -8,7 +8,7 @@ use ink::prelude::vec::Vec; use pop_api::{ assets::fungibles::{self as api, FungiblesError}, - error::{PopApiError, StatusCode}, + error::{Error, StatusCode}, primitives::{AccountId as AccountId32, AssetId}, }; diff --git a/pop-api/examples/nfts/.gitignore b/pop-api/examples/nfts/.gitignore deleted file mode 100755 index 8de8f877..00000000 --- a/pop-api/examples/nfts/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Ignore build artifacts from the local tests sub-crate. -/target/ - -# Ignore backup files creates by cargo fmt. -**/*.rs.bk - -# Remove Cargo.lock when creating an executable, leave it for libraries -# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock -Cargo.lock diff --git a/pop-api/examples/place-spot-order/.gitignore b/pop-api/examples/place-spot-order/.gitignore deleted file mode 100755 index 8de8f877..00000000 --- a/pop-api/examples/place-spot-order/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Ignore build artifacts from the local tests sub-crate. -/target/ - -# Ignore backup files creates by cargo fmt. -**/*.rs.bk - -# Remove Cargo.lock when creating an executable, leave it for libraries -# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock -Cargo.lock diff --git a/pop-api/examples/read-runtime-state/.gitignore b/pop-api/examples/read-runtime-state/.gitignore deleted file mode 100755 index 8de8f877..00000000 --- a/pop-api/examples/read-runtime-state/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Ignore build artifacts from the local tests sub-crate. -/target/ - -# Ignore backup files creates by cargo fmt. -**/*.rs.bk - -# Remove Cargo.lock when creating an executable, leave it for libraries -# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock -Cargo.lock diff --git a/pop-api/src/error.rs b/pop-api/src/error.rs index 4d5a8fb9..b8a56f55 100644 --- a/pop-api/src/error.rs +++ b/pop-api/src/error.rs @@ -1,6 +1,7 @@ use ink::env::chain_extension::FromStatusCode; use scale::{Decode, Encode}; -use PopApiError::*; + +use Error::*; #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] @@ -30,10 +31,69 @@ impl From for StatusCode { } } +// If an unknown variant of the `DispatchError` is detected the error needs to be converted +// into the encoded value of `Error::Other`. This conversion is performed by shifting the bytes one +// position forward (discarding the last byte as it is not used) and setting the first byte to the +// encoded value of `Other` (0u8). This ensures the error is correctly categorized as an `Other` +// variant which provides all the necessary information to debug which error occurred in the runtime. +// +// Byte layout explanation: +// - Byte 0: index of the variant within `Error` +// - Byte 1: +// - Must be zero for `UNIT_ERRORS`. +// - Represents the nested error in `SINGLE_NESTED_ERRORS`. +// - Represents the first level of nesting in `DOUBLE_NESTED_ERRORS`. +// - Byte 2: +// - Represents the second level of nesting in `DOUBLE_NESTED_ERRORS`. +// - Byte 3: +// - Unused or represents further nested information. +// +// This mechanism ensures backward compatibility by correctly categorizing any unknown errors +// into the `Other` variant, thus preventing issues caused by breaking changes. +fn convert_unknown_errors(encoded_error: &mut [u8; 4]) { + let all_errors = [ + UNIT_ERRORS.as_slice(), + SINGLE_NESTED_ERRORS.as_slice(), + DOUBLE_NESTED_ERRORS.as_slice(), + // `DecodingFailed`. + &[255u8], + ] + .concat(); + // Unknown errors, i.e. an encoded value where the first byte is non-zero (indicating a variant + // in `Error`) but unknown. + if !all_errors.contains(&encoded_error[0]) { + encoded_error[..].rotate_right(1); + encoded_error[0] = 0u8; + } + convert_unknown_nested_errors(encoded_error); +} + +// If an unknown nested variant of the `DispatchError` is detected (i.e. when any of the subsequent +// bytes are non-zero). +fn convert_unknown_nested_errors(encoded_error: &mut [u8; 4]) { + // Converts single nested errors that are known to the Pop API as unit errors into `Other`. + if UNIT_ERRORS.contains(&encoded_error[0]) && encoded_error[1..].iter().any(|x| *x != 0u8) { + encoded_error[..].rotate_right(1); + encoded_error[0] = 0u8; + // Converts double nested errors that are known to the Pop API as single nested errors into + // `Other`. + } else if SINGLE_NESTED_ERRORS.contains(&encoded_error[0]) + && encoded_error[2..].iter().any(|x| *x != 0u8) + { + encoded_error[..].rotate_right(1); + encoded_error[0] = 0u8; + } else if DOUBLE_NESTED_ERRORS.contains(&encoded_error[0]) + && encoded_error[3..].iter().any(|x| *x != 0u8) + { + encoded_error[..].rotate_right(1); + encoded_error[0] = 0u8; + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] #[repr(u8)] -pub enum PopApiError { +pub enum Error { /// Some unknown error occurred. Go to the Pop API docs section `Pop API error`. Other { // Index within the `DispatchError` @@ -76,8 +136,34 @@ pub enum PopApiError { DecodingFailed = 255, } -impl From for StatusCode { - fn from(value: PopApiError) -> Self { +// Unit `Error` variants. +// (variant: index): +// - CannotLookup: 1, +// - BadOrigin: 2, +// - ConsumerRemaining: 4, +// - NoProviders: 5, +// - TooManyConsumers: 6, +// - Exhausted: 10, +// - Corruption: 11, +// - Unavailable: 12, +// - RootNotAllowed: 13, +// - DecodingFailed: 255, +const UNIT_ERRORS: [u8; 10] = [1, 2, 4, 5, 6, 10, 11, 12, 13, 255]; + +// Single nested `Error` variants. +// (variant: index): +// - Token: 7, +// - Arithmetic: 8, +// - Transaction: 9, +const SINGLE_NESTED_ERRORS: [u8; 3] = [7, 8, 9]; + +// Double nested `Error` variants +// (variant: index): +// - Module: 3, +const DOUBLE_NESTED_ERRORS: [u8; 1] = [3]; + +impl From for StatusCode { + fn from(value: Error) -> Self { let mut encoded_error = value.encode(); // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). encoded_error.resize(4, 0); @@ -87,71 +173,11 @@ impl From for StatusCode { } } -impl From for PopApiError { - // `pub` because it is used in `runtime/devnet/src/extensions/tests/mod.rs`'s test: - // `dispatch_error_to_status_code_to_pop_api_error_works` - // - // This function converts a given `status_code` (u32) into a `PopApiError`. +impl From for Error { fn from(value: StatusCode) -> Self { let encoded: [u8; 4] = value.0.to_le_bytes(); - PopApiError::decode(&mut &encoded[..]).unwrap_or(DecodingFailed) - } -} - -// If an unknown nested variant of the `DispatchError` is detected (i.e., any of the subsequent -// bytes are non-zero, indicating a breaking change in the `DispatchError`), the error needs to be -// converted into the encoded value of `PopApiError::Other`. This conversion is performed by -// shifting the bytes one position forward (discarding the last byte as it is not used) and setting -// the first byte to the encoded value of `Other` (0u8). This ensures the error is correctly -// categorized as an `Other` variant. -// -// Byte layout explanation: -// - Byte 0: PopApiError -// - Byte 1: -// - Must be zero for `UNIT_ERRORS`. -// - Represents the nested error in `SINGLE_NESTED_ERRORS`. -// - Represents the first level of nesting in `DOUBLE_NESTED_ERRORS`. -// - Byte 2: -// - Represents the second level of nesting in `DOUBLE_NESTED_ERRORS`. -// - Byte 3: -// - Unused or represents further nested information. -// -// This mechanism ensures backward compatibility by correctly categorizing any unknown nested errors -// into the `Other` variant, thus preventing issues caused by new or unexpected error formats. -pub(crate) fn convert_unknown_nested_errors(encoded_error: &mut [u8; 4]) { - // Converts single nested errors that are known to the Pop API as unit errors into `Other`. - if UNIT_ERRORS.contains(&encoded_error[0]) && encoded_error[1..].iter().any(|x| *x != 0u8) { - encoded_error[..].rotate_right(1); - encoded_error[0] = 0u8; - // Converts double nested errors that are known to the Pop API as single nested errors into - // `Other`. - } else if SINGLE_NESTED_ERRORS.contains(&encoded_error[0]) - && encoded_error[2..].iter().any(|x| *x != 0u8) - { - encoded_error[..].rotate_right(1); - encoded_error[0] = 0u8; - } else if DOUBLE_NESTED_ERRORS.contains(&encoded_error[0]) - && encoded_error[3..].iter().any(|x| *x != 0u8) - { - encoded_error[..].rotate_right(1); - encoded_error[0] = 0u8; - } -} - -pub(crate) fn convert_unknown_errors(encoded_error: &mut [u8; 4]) { - let all_errors = [ - UNIT_ERRORS.as_slice(), - SINGLE_NESTED_ERRORS.as_slice(), - DOUBLE_NESTED_ERRORS.as_slice(), - // `DecodingFailed`. - &[255u8], - ] - .concat(); - if !all_errors.contains(&encoded_error[0]) { - encoded_error[..].rotate_right(1); - encoded_error[0] = 0u8; + Error::decode(&mut &encoded[..]).unwrap_or(DecodingFailed) } - convert_unknown_nested_errors(encoded_error); } #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] @@ -200,26 +226,6 @@ pub enum TransactionalError { NoLayer, } -// Unit `DispatchError` variants (variant: index): -// - CannotLookup: 1, -// - BadOrigin: 2, -// - ConsumerRemaining: 4, -// - NoProviders: 5, -// - TooManyConsumers: 6, -// - Exhausted: 10, -// - Corruption: 11, -// - Unavailable: 12, -// - RootNotAllowed: 13, -const UNIT_ERRORS: [u8; 9] = [1, 2, 4, 5, 6, 10, 11, 12, 13]; - -// Single nested `DispatchError` variants (variant: index): -// - Token: 3, -// - Arithmetic: 8, -// - Transaction: 9, -const SINGLE_NESTED_ERRORS: [u8; 3] = [7, 8, 9]; - -const DOUBLE_NESTED_ERRORS: [u8; 1] = [3]; - #[cfg(test)] mod tests { use super::*; @@ -231,20 +237,30 @@ mod tests { assert_eq!(u32::MAX.encode().len(), 4); } - // Decodes into `StatusCode(u32)` and converts it into the `PopApiError`. - fn into_pop_api_error(encoded_error: [u8; 4]) -> PopApiError { - let status_code = - StatusCode::from_status_code(u32::decode(&mut &encoded_error[..]).unwrap()) - .unwrap_err(); + // Decodes 4 bytes into a `u32` and converts it into `StatusCode`. + fn into_status_code(encoded_error: [u8; 4]) -> StatusCode { + let decoded_u32 = u32::decode(&mut &encoded_error[..]).unwrap(); + StatusCode::from_status_code(decoded_u32).unwrap_err() + } + + // Decodes 4 bytes into a `u32` and converts it into `Error`. + fn into_error(encoded_error: [u8; 4]) -> Error { + let decoded_u32 = u32::decode(&mut &encoded_error[..]).unwrap(); + let status_code = StatusCode::from_status_code(decoded_u32).unwrap_err(); status_code.into() } - // Tests for the `From` implementation for `PopApiError`. + // Tests the `From` implementation for `Error`. // - // If the encoded value indicates a nested `PopApiError` which is not handled by the Pop API - // version, the encoded value is converted into `PopApiError::Other`. + // Unit variants: + // If the encoded value indicates a nested `Error` which is known by the Pop API version as a + // unit variant, the encoded value is converted into `Error::Other`. + // + // Example: the error `BadOrigin` (encoded: `[2, 0, 0, 0]`) with a non-zero value for one + // of the bytes [1..4]: `[2, 0, 1, 0]` is converted into `[0, 2, 0, 1]`. This is decoded to + // `Error::Other { dispatch_error: 2, index: 0, error: 1 }`. #[test] - fn test_unit_pop_api_error_variants() { + fn unit_error_variants() { let errors = vec![ CannotLookup, BadOrigin, @@ -255,73 +271,134 @@ mod tests { Corruption, Unavailable, RootNotAllowed, + DecodingFailed, ]; + // Four scenarios, 2 tests each: + // 1. Compare a `StatusCode`, which is converted from an encoded value, with a `StatusCode` + // converted from an `Error`. + // 2. Compare an `Error, which is converted from an encoded value, with the expected `Error`. for (i, &error_code) in UNIT_ERRORS.iter().enumerate() { - assert_eq!(into_pop_api_error([error_code, 0, 0, 0]), errors[i]); + // No nesting and unit variant correctly returned. + assert_eq!(into_status_code([error_code, 0, 0, 0]), errors[i].into()); + assert_eq!(into_error([error_code, 0, 0, 0]), errors[i]); + // Unexpected second byte nested. + assert_eq!( + into_status_code([error_code, 1, 0, 0]), + (Other { dispatch_error_index: error_code, error_index: 1, error: 0 }).into(), + ); assert_eq!( - into_pop_api_error([error_code, 1, 0, 0]), + into_error([error_code, 1, 0, 0]), Other { dispatch_error_index: error_code, error_index: 1, error: 0 }, ); + // Unexpected third byte nested. + assert_eq!( + into_status_code([error_code, 1, 1, 0]), + (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), + ); assert_eq!( - into_pop_api_error([error_code, 1, 1, 0]), + into_error([error_code, 1, 1, 0]), Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, ); + // Unexpected fourth byte nested. assert_eq!( - into_pop_api_error([error_code, 1, 1, 1]), + into_status_code([error_code, 1, 1, 1]), + (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), + ); + assert_eq!( + into_error([error_code, 1, 1, 1]), Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, ); } } + // Single nested variants: + // If the encoded value indicates a double nested `Error` which is known by the Pop API version + // as a single nested variant, the encoded value is converted into `Error::Other`. + // + // Example: the error `Arithmetic(Overflow)` (encoded: `[8, 1, 0, 0]`) with a non-zero + // value for one of the bytes [2..4]: `[8, 1, 1, 0]` is converted into `[0, 8, 1, 1]`. This is + // decoded to `Error::Other { dispatch_error: 8, index: 1, error: 1 }`. #[test] - fn test_single_nested_pop_api_error_variants() { + fn single_nested_error_variants() { let errors = vec![ [Token(FundsUnavailable), Token(OnlyProvider)], [Arithmetic(Underflow), Arithmetic(Overflow)], [Transactional(LimitReached), Transactional(NoLayer)], ]; + // Four scenarios, 2 tests each: + // 1. Compare a `StatusCode`, which is converted from an encoded value, with a `StatusCode` + // converted from an `Error`. + // 2. Compare an `Error, which is converted from an encoded value, with the expected `Error`. for (i, &error_code) in SINGLE_NESTED_ERRORS.iter().enumerate() { - assert_eq!(into_pop_api_error([error_code, 0, 0, 0]), errors[i][0]); - assert_eq!(into_pop_api_error([error_code, 1, 0, 0]), errors[i][1]); + // No nesting and unit variant correctly returned. + assert_eq!(into_status_code([error_code, 0, 0, 0]), errors[i][0].into()); + assert_eq!(into_error([error_code, 0, 0, 0]), errors[i][0]); + // Allowed single nesting variant correctly returned. + assert_eq!(into_status_code([error_code, 1, 0, 0]), errors[i][1].into()); + assert_eq!(into_error([error_code, 1, 0, 0]), errors[i][1]); + // Unexpected third byte nested. + assert_eq!( + into_status_code([error_code, 1, 1, 0]), + (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), + ); assert_eq!( - into_pop_api_error([error_code, 1, 1, 0]), + into_error([error_code, 1, 1, 0]), Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, ); + // Unexpected fourth byte nested. + assert_eq!( + into_status_code([error_code, 1, 1, 1]), + (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), + ); assert_eq!( - into_pop_api_error([error_code, 1, 1, 1]), + into_error([error_code, 1, 1, 1]), Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, ); } } + // Double nested variants: + // If the encoded value indicates a triple nested `Error` which is known by the Pop API version + // as a double nested variant, the encoded value is converted into `Error::Other`. + // + // Example: the error `Module { index: 10, error 5 }` (encoded: `[3, 10, 5, 0]`) with a non-zero + // value for the last byte: `[3, 10, 5, 3]` is converted into `[0, 3, 10, 5]`. This is + // decoded to `Error::Other { dispatch_error: 3, index: 10, error: 5 }`. #[test] - fn test_double_nested_pop_api_error_variants() { - assert_eq!(into_pop_api_error([3, 0, 0, 0]), Module { index: 0, error: 0 }); - assert_eq!(into_pop_api_error([3, 1, 0, 0]), Module { index: 1, error: 0 }); - assert_eq!(into_pop_api_error([3, 1, 1, 0]), Module { index: 1, error: 1 }); - // TODO: doesn't make sense. + fn double_nested_error_variants() { + // Four scenarios, 2 tests each: + // 1. Compare a `StatusCode`, which is converted from an encoded value, with a `StatusCode` + // converted from an `Error`. + // 2. Compare an `Error, which is converted from an encoded value, with the expected `Error`. + // + // No nesting and unit variant correctly returned. + assert_eq!(into_status_code([3, 0, 0, 0]), (Module { index: 0, error: 0 }).into()); + assert_eq!(into_error([3, 0, 0, 0]), Module { index: 0, error: 0 }); + // Allowed single nesting and variant correctly returned. + assert_eq!(into_status_code([3, 1, 0, 0]), (Module { index: 1, error: 0 }).into()); + assert_eq!(into_error([3, 1, 0, 0]), Module { index: 1, error: 0 }); + // Allowed double nesting and variant correctly returned. + assert_eq!(into_status_code([3, 1, 1, 0]), (Module { index: 1, error: 1 }).into()); + assert_eq!(into_error([3, 1, 1, 0]), Module { index: 1, error: 1 }); + // Unexpected fourth byte nested. assert_eq!( - into_pop_api_error([3, 1, 1, 1]), + into_status_code([3, 1, 1, 1]), + (Other { dispatch_error_index: 3, error_index: 1, error: 1 }).into(), + ); + assert_eq!( + into_error([3, 1, 1, 1]), Other { dispatch_error_index: 3, error_index: 1, error: 1 }, ); } - #[test] - fn test_decoding_failed() { - assert_eq!(into_pop_api_error([255, 0, 0, 0]), DecodingFailed); - assert_eq!(into_pop_api_error([255, 255, 0, 0]), DecodingFailed); - assert_eq!(into_pop_api_error([255, 255, 255, 0]), DecodingFailed); - assert_eq!(into_pop_api_error([255, 255, 255, 255]), DecodingFailed); - } - #[test] fn test_random_encoded_values() { assert_eq!( - into_pop_api_error([100, 100, 100, 100]), + into_error([100, 100, 100, 100]), Other { dispatch_error_index: 100, error_index: 100, error: 100 } ); assert_eq!( - into_pop_api_error([200, 200, 200, 200]), + into_error([200, 200, 200, 200]), Other { dispatch_error_index: 200, error_index: 200, error: 200 } ); } diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 90c81998..3e9ead7f 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -3,7 +3,7 @@ use ink::{prelude::vec::Vec, ChainExtensionInstance}; pub use sp_runtime::{BoundedVec, MultiAddress, MultiSignature}; -use crate::error::{PopApiError, StatusCode}; +use crate::error::{Error, StatusCode}; use primitives::{storage_keys::*, AccountId as AccountId32}; #[cfg(feature = "assets")] pub use v0::assets; @@ -21,7 +21,11 @@ pub mod v0; type AccountId = AccountId32; // TODO: do the same as the AccountId above and check expanded macro code. -type Balance = ::Balance; +// type Balance = ::Balance; +type Balance = u128; +#[cfg(any(feature = "nfts", feature = "cross-chain"))] +type BlockNumber = ::BlockNumber; + pub type Result = core::result::Result; #[derive(Debug, Clone, PartialEq, Eq)] @@ -56,7 +60,7 @@ pub trait PopApi { #[cfg(feature = "cross-chain")] #[ink(function = 2)] #[allow(private_interfaces)] - fn send_xcm(xcm: CrossChainMessage) -> Result<()>; + fn send_xcm(xcm: primitives::cross_chain::CrossChainMessage) -> Result<()>; } fn dispatch(call: RuntimeCall) -> Result<()> { @@ -72,7 +76,7 @@ fn read_state(key: RuntimeStateKeys) -> Result> { } #[cfg(feature = "cross-chain")] -fn send_xcm(xcm: CrossChainMessage) -> Result<()> { +fn send_xcm(xcm: primitives::cross_chain::CrossChainMessage) -> Result<()> { <::ChainExtension as ChainExtensionInstance>::instantiate( ) .send_xcm(xcm) diff --git a/pop-api/src/primitives.rs b/pop-api/src/primitives.rs index e8098f69..e174a111 100644 --- a/pop-api/src/primitives.rs +++ b/pop-api/src/primitives.rs @@ -1,2 +1 @@ pub use pop_primitives::*; -pub use sp_runtime::{BoundedVec, MultiAddress}; diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index b1bb86a7..eaf1c6f5 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -356,3 +356,67 @@ impl From for FungiblesError { } } } + +#[cfg(test)] +mod tests { + use super::FungiblesError; + use crate::error::{ + ArithmeticError::*, + Error::{self, *}, + StatusCode, + TokenError::*, + TransactionalError::*, + }; + + fn into_fungibles_error(error: Error) -> FungiblesError { + let status_code: StatusCode = error.into(); + status_code.into() + } + + #[test] + fn conversion_status_code_into_fungibles_error_works() { + let errors = vec![ + Other { dispatch_error_index: 5, error_index: 5, error: 1 }, + CannotLookup, + BadOrigin, + Module { index: 2, error: 5 }, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Token(OnlyProvider), + Arithmetic(Overflow), + Transactional(NoLayer), + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + DecodingFailed, + ]; + for error in errors { + let status_code: StatusCode = error.into(); + let fungibles_error: FungiblesError = status_code.into(); + assert_eq!(fungibles_error, FungiblesError::Other(status_code)) + } + + assert_eq!(into_fungibles_error(Module { index: 10, error: 2 }), FungiblesError::NoBalance); + assert_eq!(into_fungibles_error(Module { index: 52, error: 0 }), FungiblesError::NoAccount); + assert_eq!( + into_fungibles_error(Module { index: 52, error: 1 }), + FungiblesError::NoPermission + ); + assert_eq!(into_fungibles_error(Module { index: 52, error: 2 }), FungiblesError::Unknown); + assert_eq!(into_fungibles_error(Module { index: 52, error: 3 }), FungiblesError::InUse); + assert_eq!( + into_fungibles_error(Module { index: 52, error: 5 }), + FungiblesError::MinBalanceZero + ); + assert_eq!( + into_fungibles_error(Module { index: 52, error: 7 }), + FungiblesError::InsufficientAllowance + ); + assert_eq!( + into_fungibles_error(Module { index: 52, error: 10 }), + FungiblesError::AssetNotLive + ); + } +} diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 4ce68219..d67d30bd 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,8 +1,8 @@ #![allow(dead_code)] -use crate::{Balance, RuntimeCall, *}; +use crate::{Balance, MultiAddress, RuntimeCall, *}; use ink::prelude::vec::Vec; -use primitives::{AssetId, MultiAddress}; +use primitives::AssetId; use scale::{Compact, Encode}; pub mod fungibles; @@ -13,7 +13,7 @@ type Result = core::result::Result; /// 1. Dispatchables /// 2. Read state functions /// -/// 1. Dispatchables within pallet assets (TrustBackedAssets instance) that can be used via the pop api on Pop Network: +/// 1. Dispatchables within pallet assets (TrustBackedAssets instance): /// - create /// - start_destroy /// - destroy_accounts @@ -464,7 +464,7 @@ pub enum AssetsError { } impl TryFrom for AssetsError { - type Error = PopApiError; + type Error = Error; fn try_from(status_code: u32) -> core::result::Result { use AssetsError::*; diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs index ae2709e7..e14e6e32 100644 --- a/pop-api/src/v0/balances.rs +++ b/pop-api/src/v0/balances.rs @@ -1,6 +1,4 @@ -use crate::{ - dispatch, primitives::MultiAddress, v0::RuntimeCall, AccountId, PopApiError, StatusCode, -}; +use crate::{dispatch, primitives::MultiAddress, v0::RuntimeCall, AccountId, Error, StatusCode}; type Result = core::result::Result; @@ -57,7 +55,7 @@ pub enum BalancesError { } impl TryFrom for BalancesError { - type Error = PopApiError; + type Error = Error; fn try_from(status_code: u32) -> core::result::Result { use BalancesError::*; diff --git a/pop-api/src/v0/cross_chain/mod.rs b/pop-api/src/v0/cross_chain/mod.rs index 583447b1..5a0dda6c 100644 --- a/pop-api/src/v0/cross_chain/mod.rs +++ b/pop-api/src/v0/cross_chain/mod.rs @@ -1,11 +1,8 @@ -pub mod coretime; - -use crate::StatusCode; +use crate::{BlockNumber, ParachainSystemKeys, Result, RuntimeStateKeys}; -type Result = core::result::Result; -type BlockNumber = ::BlockNumber; +pub mod coretime; -pub fn relay_chain_block_number() -> std::result::Result { +pub fn relay_chain_block_number() -> Result { crate::v0::state::read(RuntimeStateKeys::ParachainSystem( ParachainSystemKeys::LastRelayChainBlockNumber, )) diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 41574cfb..20dc6476 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -10,12 +10,12 @@ pub mod state; #[derive(scale::Encode)] pub(crate) enum RuntimeCall { - // #[codec(index = 10)] - // #[cfg(feature = "balances")] - // Balances(balances::BalancesCall), - // #[codec(index = 50)] - // #[cfg(feature = "nfts")] - // Nfts(nfts::NftCalls), + #[codec(index = 10)] + #[cfg(feature = "balances")] + Balances(balances::BalancesCall), + #[codec(index = 50)] + #[cfg(feature = "nfts")] + Nfts(nfts::NftCalls), #[codec(index = 52)] #[cfg(feature = "assets")] Assets(assets::AssetsCall), diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs index 1e4406e5..29219c66 100644 --- a/pop-api/src/v0/nfts.rs +++ b/pop-api/src/v0/nfts.rs @@ -1,9 +1,15 @@ -use super::RuntimeCall; -use crate::*; use ink::prelude::vec::Vec; -use primitives::{ApprovalsLimit, BoundedBTreeMap, KeyLimit, MultiAddress}; -pub use primitives::{CollectionId, ItemId}; use scale::Encode; + +use crate::{ + dispatch, + primitives::{ + nfts::{ApprovalsLimit, CollectionId, ItemId, KeyLimit}, + BoundedBTreeMap, + }, + state, AccountId, Balance, BlockNumber, BoundedVec, MultiAddress, NftsKeys, RuntimeCall, + RuntimeStateKeys, StatusCode, +}; pub use types::*; type Result = core::result::Result; @@ -515,163 +521,163 @@ pub(crate) enum NftCalls { receive_item: ItemId, }, } - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum Error { - /// The signing account has no permission to do the operation. - NoPermission, - /// The given item ID is unknown. - UnknownCollection, - /// The item ID has already been used for an item. - AlreadyExists, - /// The approval had a deadline that expired, so the approval isn't valid anymore. - ApprovalExpired, - /// The owner turned out to be different to what was expected. - WrongOwner, - /// The witness data given does not match the current state of the chain. - BadWitness, - /// Collection ID is already taken. - CollectionIdInUse, - /// Items within that collection are non-transferable. - ItemsNonTransferable, - /// The provided account is not a delegate. - NotDelegate, - /// The delegate turned out to be different to what was expected. - WrongDelegate, - /// No approval exists that would allow the transfer. - Unapproved, - /// The named owner has not signed ownership acceptance of the collection. - Unaccepted, - /// The item is locked (non-transferable). - ItemLocked, - /// Item's attributes are locked. - LockedItemAttributes, - /// Collection's attributes are locked. - LockedCollectionAttributes, - /// Item's metadata is locked. - LockedItemMetadata, - /// Collection's metadata is locked. - LockedCollectionMetadata, - /// All items have been minted. - MaxSupplyReached, - /// The max supply is locked and can't be changed. - MaxSupplyLocked, - /// The provided max supply is less than the number of items a collection already has. - MaxSupplyTooSmall, - /// The given item ID is unknown. - UnknownItem, - /// Swap doesn't exist. - UnknownSwap, - /// The given item has no metadata set. - MetadataNotFound, - /// The provided attribute can't be found. - AttributeNotFound, - /// Item is not for sale. - NotForSale, - /// The provided bid is too low. - BidTooLow, - /// The item has reached its approval limit. - ReachedApprovalLimit, - /// The deadline has already expired. - DeadlineExpired, - /// The duration provided should be less than or equal to `MaxDeadlineDuration`. - WrongDuration, - /// The method is disabled by system settings. - MethodDisabled, - /// The provided setting can't be set. - WrongSetting, - /// Item's config already exists and should be equal to the provided one. - InconsistentItemConfig, - /// Config for a collection or an item can't be found. - NoConfig, - /// Some roles were not cleared. - RolesNotCleared, - /// Mint has not started yet. - MintNotStarted, - /// Mint has already ended. - MintEnded, - /// The provided Item was already used for claiming. - AlreadyClaimed, - /// The provided data is incorrect. - IncorrectData, - /// The extrinsic was sent by the wrong origin. - WrongOrigin, - /// The provided signature is incorrect. - WrongSignature, - /// The provided metadata might be too long. - IncorrectMetadata, - /// Can't set more attributes per one call. - MaxAttributesLimitReached, - /// The provided namespace isn't supported in this call. - WrongNamespace, - /// Can't delete non-empty collections. - CollectionNotEmpty, - /// The witness data should be provided. - WitnessRequired, -} - -impl TryFrom for Error { - type Error = Error; - - fn try_from(status_code: u32) -> core::result::Result { - use Error::*; - match status_code { - 0 => Ok(NoPermission), - 1 => Ok(UnknownCollection), - 2 => Ok(AlreadyExists), - 3 => Ok(ApprovalExpired), - 4 => Ok(WrongOwner), - 5 => Ok(BadWitness), - 6 => Ok(CollectionIdInUse), - 7 => Ok(ItemsNonTransferable), - 8 => Ok(NotDelegate), - 9 => Ok(WrongDelegate), - 10 => Ok(Unapproved), - 11 => Ok(Unaccepted), - 12 => Ok(ItemLocked), - 13 => Ok(LockedItemAttributes), - 14 => Ok(LockedCollectionAttributes), - 15 => Ok(LockedItemMetadata), - 16 => Ok(LockedCollectionMetadata), - 17 => Ok(MaxSupplyReached), - 18 => Ok(MaxSupplyLocked), - 19 => Ok(MaxSupplyTooSmall), - 20 => Ok(UnknownItem), - 21 => Ok(UnknownSwap), - 22 => Ok(MetadataNotFound), - 23 => Ok(AttributeNotFound), - 24 => Ok(NotForSale), - 25 => Ok(BidTooLow), - 26 => Ok(ReachedApprovalLimit), - 27 => Ok(DeadlineExpired), - 28 => Ok(WrongDuration), - 29 => Ok(MethodDisabled), - 30 => Ok(WrongSetting), - 31 => Ok(InconsistentItemConfig), - 32 => Ok(NoConfig), - 33 => Ok(RolesNotCleared), - 34 => Ok(MintNotStarted), - 35 => Ok(MintEnded), - 36 => Ok(AlreadyClaimed), - 37 => Ok(IncorrectData), - 38 => Ok(WrongOrigin), - 39 => Ok(WrongSignature), - 40 => Ok(IncorrectMetadata), - 41 => Ok(MaxAttributesLimitReached), - 42 => Ok(WrongNamespace), - 43 => Ok(CollectionNotEmpty), - 44 => Ok(WitnessRequired), - _ => todo!(), - } - } -} +// +// #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] +// #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +// pub enum Error { +// /// The signing account has no permission to do the operation. +// NoPermission, +// /// The given item ID is unknown. +// UnknownCollection, +// /// The item ID has already been used for an item. +// AlreadyExists, +// /// The approval had a deadline that expired, so the approval isn't valid anymore. +// ApprovalExpired, +// /// The owner turned out to be different to what was expected. +// WrongOwner, +// /// The witness data given does not match the current state of the chain. +// BadWitness, +// /// Collection ID is already taken. +// CollectionIdInUse, +// /// Items within that collection are non-transferable. +// ItemsNonTransferable, +// /// The provided account is not a delegate. +// NotDelegate, +// /// The delegate turned out to be different to what was expected. +// WrongDelegate, +// /// No approval exists that would allow the transfer. +// Unapproved, +// /// The named owner has not signed ownership acceptance of the collection. +// Unaccepted, +// /// The item is locked (non-transferable). +// ItemLocked, +// /// Item's attributes are locked. +// LockedItemAttributes, +// /// Collection's attributes are locked. +// LockedCollectionAttributes, +// /// Item's metadata is locked. +// LockedItemMetadata, +// /// Collection's metadata is locked. +// LockedCollectionMetadata, +// /// All items have been minted. +// MaxSupplyReached, +// /// The max supply is locked and can't be changed. +// MaxSupplyLocked, +// /// The provided max supply is less than the number of items a collection already has. +// MaxSupplyTooSmall, +// /// The given item ID is unknown. +// UnknownItem, +// /// Swap doesn't exist. +// UnknownSwap, +// /// The given item has no metadata set. +// MetadataNotFound, +// /// The provided attribute can't be found. +// AttributeNotFound, +// /// Item is not for sale. +// NotForSale, +// /// The provided bid is too low. +// BidTooLow, +// /// The item has reached its approval limit. +// ReachedApprovalLimit, +// /// The deadline has already expired. +// DeadlineExpired, +// /// The duration provided should be less than or equal to `MaxDeadlineDuration`. +// WrongDuration, +// /// The method is disabled by system settings. +// MethodDisabled, +// /// The provided setting can't be set. +// WrongSetting, +// /// Item's config already exists and should be equal to the provided one. +// InconsistentItemConfig, +// /// Config for a collection or an item can't be found. +// NoConfig, +// /// Some roles were not cleared. +// RolesNotCleared, +// /// Mint has not started yet. +// MintNotStarted, +// /// Mint has already ended. +// MintEnded, +// /// The provided Item was already used for claiming. +// AlreadyClaimed, +// /// The provided data is incorrect. +// IncorrectData, +// /// The extrinsic was sent by the wrong origin. +// WrongOrigin, +// /// The provided signature is incorrect. +// WrongSignature, +// /// The provided metadata might be too long. +// IncorrectMetadata, +// /// Can't set more attributes per one call. +// MaxAttributesLimitReached, +// /// The provided namespace isn't supported in this call. +// WrongNamespace, +// /// Can't delete non-empty collections. +// CollectionNotEmpty, +// /// The witness data should be provided. +// WitnessRequired, +// } +// +// impl TryFrom for Error { +// type Error = Error; +// +// fn try_from(status_code: u32) -> core::result::Result { +// use Error::*; +// match status_code { +// 0 => Ok(NoPermission), +// 1 => Ok(UnknownCollection), +// 2 => Ok(AlreadyExists), +// 3 => Ok(ApprovalExpired), +// 4 => Ok(WrongOwner), +// 5 => Ok(BadWitness), +// 6 => Ok(CollectionIdInUse), +// 7 => Ok(ItemsNonTransferable), +// 8 => Ok(NotDelegate), +// 9 => Ok(WrongDelegate), +// 10 => Ok(Unapproved), +// 11 => Ok(Unaccepted), +// 12 => Ok(ItemLocked), +// 13 => Ok(LockedItemAttributes), +// 14 => Ok(LockedCollectionAttributes), +// 15 => Ok(LockedItemMetadata), +// 16 => Ok(LockedCollectionMetadata), +// 17 => Ok(MaxSupplyReached), +// 18 => Ok(MaxSupplyLocked), +// 19 => Ok(MaxSupplyTooSmall), +// 20 => Ok(UnknownItem), +// 21 => Ok(UnknownSwap), +// 22 => Ok(MetadataNotFound), +// 23 => Ok(AttributeNotFound), +// 24 => Ok(NotForSale), +// 25 => Ok(BidTooLow), +// 26 => Ok(ReachedApprovalLimit), +// 27 => Ok(DeadlineExpired), +// 28 => Ok(WrongDuration), +// 29 => Ok(MethodDisabled), +// 30 => Ok(WrongSetting), +// 31 => Ok(InconsistentItemConfig), +// 32 => Ok(NoConfig), +// 33 => Ok(RolesNotCleared), +// 34 => Ok(MintNotStarted), +// 35 => Ok(MintEnded), +// 36 => Ok(AlreadyClaimed), +// 37 => Ok(IncorrectData), +// 38 => Ok(WrongOrigin), +// 39 => Ok(WrongSignature), +// 40 => Ok(IncorrectMetadata), +// 41 => Ok(MaxAttributesLimitReached), +// 42 => Ok(WrongNamespace), +// 43 => Ok(CollectionNotEmpty), +// 44 => Ok(WitnessRequired), +// _ => todo!(), +// } +// } +// } // Local implementations of pallet-nfts types mod types { use super::*; use crate::{ - primitives::{CollectionId, ItemId}, + primitives::nfts::{CollectionId, ItemId}, Balance, BlockNumber, }; pub use enumflags2::{bitflags, BitFlags}; diff --git a/pop-api/src/v0/state.rs b/pop-api/src/v0/state.rs index 1aca01cf..e3d38129 100644 --- a/pop-api/src/v0/state.rs +++ b/pop-api/src/v0/state.rs @@ -1,7 +1,6 @@ -use crate::{primitives::storage_keys::RuntimeStateKeys, read_state, PopApiError}; +use crate::{primitives::storage_keys::RuntimeStateKeys, read_state, Error}; use scale::Decode; pub fn read(key: RuntimeStateKeys) -> crate::Result { - read_state(key) - .and_then(|v| T::decode(&mut &v[..]).map_err(|_e| PopApiError::DecodingFailed.into())) + read_state(key).and_then(|v| T::decode(&mut &v[..]).map_err(|_e| Error::DecodingFailed.into())) } diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index e7237b51..6ba3fea7 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -22,4 +22,7 @@ std = [ "scale-info/std", ] devnet = [] -testnet = [] \ No newline at end of file +testnet = [] +assets = [] +cross-chain = [] +nfts = [] diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 1e008c31..3b91f713 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -1,10 +1,11 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -pub use bounded_collections::{BoundedBTreeMap, BoundedBTreeSet, BoundedVec, ConstU32}; +pub use bounded_collections::{BoundedBTreeMap, BoundedBTreeSet, BoundedVec}; use scale::{Decode, Encode, MaxEncodedLen}; #[cfg(feature = "std")] use {scale_decode::DecodeAsType, scale_encode::EncodeAsType, scale_info::TypeInfo}; +#[cfg(feature = "cross-chain")] pub mod cross_chain; pub mod storage_keys; @@ -14,11 +15,17 @@ pub struct AccountId(pub [u8; 32]); // Identifier for the class of asset. pub type AssetId = u32; -// Id used for identifying non-fungible collections. -pub type CollectionId = u32; -// Id used for identifying non-fungible items. -pub type ItemId = u32; -/// The maximum length of an attribute key. -pub type KeyLimit = ConstU32<64>; -/// The maximum approvals an item could have. -pub type ApprovalsLimit = ConstU32<20>; + +#[cfg(feature = "nfts")] +pub mod nfts { + use bounded_collections::ConstU32; + + // Id used for identifying non-fungible collections. + pub type CollectionId = u32; + // Id used for identifying non-fungible items. + pub type ItemId = u32; + /// The maximum length of an attribute key. + pub type KeyLimit = ConstU32<64>; + /// The maximum approvals an item could have. + pub type ApprovalsLimit = ConstU32<20>; +} diff --git a/primitives/src/storage_keys.rs b/primitives/src/storage_keys.rs index fc7234aa..4be95986 100644 --- a/primitives/src/storage_keys.rs +++ b/primitives/src/storage_keys.rs @@ -1,13 +1,18 @@ +#[cfg(feature = "nfts")] +use super::nfts::*; use super::*; #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum RuntimeStateKeys { + #[cfg(feature = "nfts")] Nfts(NftsKeys), + #[cfg(feature = "cross-chain")] ParachainSystem(ParachainSystemKeys), - #[cfg(feature = "devnet")] + #[cfg(feature = "assets")] Assets(AssetsKeys), } +#[cfg(feature = "cross-chain")] #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum ParachainSystemKeys { /// Get the last relay chain block number seen by the parachain. @@ -15,6 +20,7 @@ pub enum ParachainSystemKeys { } // https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/nfts/src/impl_nonfungibles.rs +#[cfg(feature = "nfts")] #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum NftsKeys { // Get the details of a collection. @@ -34,7 +40,7 @@ pub enum NftsKeys { } /// The required input for state queries in pallet assets. -#[cfg(feature = "devnet")] +#[cfg(feature = "assets")] #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum AssetsKeys { Allowance(AssetId, AccountId, AccountId), diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index daa5457e..b72bf4f7 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -22,7 +22,7 @@ scale-info.workspace = true smallvec.workspace = true # Local -pop-primitives = { workspace = true, default-features = false, features = ["devnet"] } +pop-primitives = { workspace = true, default-features = false, features = ["assets", "cross-chain", "nfts"] } pop-runtime-common = { workspace = true, default-features = false } # Substrate @@ -91,7 +91,7 @@ parachain-info.workspace = true env_logger = "0.11.2" hex = "0.4.3" enumflags2 = "0.7.9" -pop-api = { path = "../../pop-api", defeult-features = false, features = ["assets"] } +pop-api = { path = "../../pop-api", features = ["assets", "cross-chain", "nfts"] } [features] default = ["std"] diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions.rs index b4c6ba84..9db31e83 100644 --- a/runtime/devnet/src/extensions.rs +++ b/runtime/devnet/src/extensions.rs @@ -11,11 +11,6 @@ use frame_support::{ use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, }; -use pop_primitives::{ - cross_chain::CrossChainMessage, - storage_keys::{AssetsKeys, NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, - AssetId, CollectionId, ItemId, -}; use sp_core::crypto::UncheckedFrom; use sp_runtime::traits::{BlockNumberProvider, Dispatchable}; use sp_std::{boxed::Box, vec::Vec}; @@ -25,9 +20,15 @@ use xcm::{ }; use crate::{ - config::assets::TrustBackedAssetsInstance, AccountId, AllowedPopApiCalls, RuntimeCall, + config::assets::TrustBackedAssetsInstance, AccountId, AllowedApiCalls, RuntimeCall, RuntimeOrigin, UNIT, }; +use pop_primitives::{ + cross_chain::CrossChainMessage, + nfts::{CollectionId, ItemId}, + storage_keys::{AssetsKeys, NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, + AssetId, +}; const LOG_TARGET: &str = "pop-api::extension"; @@ -122,7 +123,7 @@ where log::debug!(target:LOG_TARGET, "{} Inputted RuntimeCall: {:?}", log_prefix, call); - origin.add_filter(AllowedPopApiCalls::contains); + origin.add_filter(AllowedApiCalls::contains); match call.dispatch(origin) { Ok(info) => { @@ -222,7 +223,7 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, - RuntimeStateKeys::Assets(key) => read_trust_backed_assets_state::(key, &mut env), + RuntimeStateKeys::Assets(key) => read_assets_state::(key, &mut env), }? .encode(); @@ -299,7 +300,7 @@ where } } -fn read_trust_backed_assets_state( +fn read_assets_state( key: AssetsKeys, env: &mut Environment, ) -> Result, DispatchError> diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 416a3298..b03bdac6 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -253,8 +253,8 @@ impl Contains for FilteredCalls { } /// A type to identify allowed calls to the Runtime from contracts. Used by Pop API -pub struct AllowedPopApiCalls; -impl Contains for crate::AllowedPopApiCalls { +pub struct AllowedApiCalls; +impl Contains for crate::AllowedApiCalls { fn contains(c: &RuntimeCall) -> bool { use config::assets::AssetsCall; use pallet_nfts::Call as NftsCall; diff --git a/runtime/devnet/src/tests/local_fungibles.rs b/runtime/devnet/src/tests/local_fungibles.rs index 154e9897..ac2b8ca0 100644 --- a/runtime/devnet/src/tests/local_fungibles.rs +++ b/runtime/devnet/src/tests/local_fungibles.rs @@ -9,8 +9,8 @@ use super::*; use pop_api::{ - error::{ArithmeticError::*, PopApiError::*, TokenError::*}, - v0::assets::use_cases::fungibles::FungiblesError::*, + error::{ArithmeticError::*, Error::*, TokenError::*}, + v0::assets::fungibles::FungiblesError::*, }; const ASSET_ID: AssetId = 1; @@ -268,7 +268,7 @@ fn create_works() { instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); // No balance to pay for fees. assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), + decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), Module { index: 10, error: 2 }, ); // Instantiate a contract without balance (relay token). @@ -277,7 +277,7 @@ fn create_works() { // TODO: make sure it has enough for the fees but not for the deposit. // No balance to pay fe deposit. assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), + decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), Module { index: 10, error: 2 }, ); // Instantiate a contract with balance. @@ -289,12 +289,12 @@ fn create_works() { create_asset(ALICE, ASSET_ID, 1); // Asset ID is already taken. assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), + decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), Module { index: 52, error: 5 }, ); // The minimal balance for an asset must be non zero. assert_eq!( - decoded::(create(addr.clone(), new_asset, BOB, 0)), + decoded::(create(addr.clone(), new_asset, BOB, 0)), Module { index: 52, error: 7 }, ); let result = create(addr.clone(), new_asset, BOB, 1); @@ -333,39 +333,25 @@ fn transfer_from_mint_works() { // Asset does not exist. assert_eq!( - decoded::(transfer_from(addr.clone(), 1, None, Some(BOB), amount, &[0u8])), + decoded::(transfer_from(addr.clone(), 1, None, Some(BOB), amount, &[0u8])), Token(UnknownAsset) ); let asset = create_asset(ALICE, 1, 2); // Minting can only be done by the owner. assert_eq!( - decoded::(transfer_from( - addr.clone(), - asset, - None, - Some(BOB), - amount, - &[0u8] - )), + decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), Module { index: 52, error: 2 }, ); // Minimum balance of an asset can not be zero. assert_eq!( - decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), 1, &[0u8])), + decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), 1, &[0u8])), Token(BelowMinimum) ); let asset = create_asset(addr.clone(), 2, 2); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(asset, addr.clone()); assert_eq!( - decoded::(transfer_from( - addr.clone(), - asset, - None, - Some(BOB), - amount, - &[0u8] - )), + decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), Module { index: 52, error: 16 }, ); thaw_asset(asset, addr.clone()); @@ -377,7 +363,7 @@ fn transfer_from_mint_works() { assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount); // Can not mint more tokens than Balance::MAX. assert_eq!( - decoded::(transfer_from( + decoded::(transfer_from( addr.clone(), asset, None, @@ -390,14 +376,7 @@ fn transfer_from_mint_works() { // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(asset, addr.clone()); assert_eq!( - decoded::(transfer_from( - addr.clone(), - asset, - None, - Some(BOB), - amount, - &[0u8] - )), + decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), Module { index: 52, error: 16 }, ); }); @@ -417,7 +396,7 @@ fn transfer_works() { // Asset does not exist. assert_eq!( - decoded::(transfer(addr.clone(), 1, BOB, amount,)), + decoded::(transfer(addr.clone(), 1, BOB, amount,)), Module { index: 52, error: 3 }, ); // Create asset with Alice as owner and mint `amount` to contract address. @@ -425,18 +404,18 @@ fn transfer_works() { // Asset is not live, i.e. frozen or being destroyed. freeze_asset(asset, ALICE); assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount,)), + decoded::(transfer(addr.clone(), asset, BOB, amount,)), Module { index: 52, error: 16 }, ); thaw_asset(asset, ALICE); // Not enough balance. assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), + decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), Module { index: 52, error: 0 }, ); // Not enough balance due to ED. assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount)), + decoded::(transfer(addr.clone(), asset, BOB, amount)), Module { index: 52, error: 0 }, ); // Successful transfer. @@ -447,13 +426,13 @@ fn transfer_works() { assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); // Transfer asset to account that does not exist. assert_eq!( - decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), + decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), Token(CannotCreate) ); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(asset, ALICE); assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), + decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), Module { index: 52, error: 16 }, ); }); diff --git a/runtime/devnet/src/tests/mod.rs b/runtime/devnet/src/tests/mod.rs index dcb97ae1..828aa06b 100644 --- a/runtime/devnet/src/tests/mod.rs +++ b/runtime/devnet/src/tests/mod.rs @@ -1,16 +1,13 @@ #![cfg(test)] -use crate::{ - config::assets::TrustBackedAssetsInstance, Assets, Contracts, Runtime, RuntimeOrigin, System, - Weight, UNIT, -}; use codec::{Decode, Encode}; use frame_support::traits::fungibles::{approvals::Inspect as ApprovalInspect, Inspect}; use frame_system::Config; use pallet_contracts::{Code, CollectEvents, Determinism, ExecReturnValue}; -use pop_api::error::{ArithmeticError, PopApiError, TokenError, TransactionalError}; use sp_runtime::{traits::Hash, AccountId32, BuildStorage, DispatchError}; +use crate::{Assets, Contracts, Runtime, RuntimeOrigin, System, Weight, UNIT}; + mod local_fungibles; type Balance = u128; @@ -97,166 +94,174 @@ fn instantiate(contract: &str, init_value: u128, salt: Vec) -> AccountId32 { result.account_id } -pub fn get_pallet_index() -> u8 { - // Get the index of the pallet (module) - <::PalletInfo as frame_support::traits::PalletInfo>::index::() - .expect("Every active module has an index in the runtime; qed") as u8 -} - -#[test] -fn encoding_decoding_dispatch_error() { - use codec::{Decode, Encode}; - use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; +mod encoding { + use super::*; + use crate::config::assets::TrustBackedAssetsInstance; + use crate::Runtime; + use sp_runtime::DispatchError; - new_test_ext().execute_with(|| { - let error = DispatchError::Module(ModuleError { - index: 255, - error: [2, 0, 0, 0], - message: Some("error message"), - }); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); - assert_eq!( - decoded, - // `message` is skipped for encoding. - DispatchError::Module(ModuleError { index: 255, error: [2, 0, 0, 0], message: None }) - ); - println!("Encoded Module Error: {:?}", encoded); + #[test] + fn encoding_decoding_dispatch_error() { + use codec::{Decode, Encode}; + use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; - // Example pallet assets Error into ModuleError - let index = get_pallet_index::(); - let mut error = - pallet_assets::Error::NotFrozen::.encode(); - error.resize(sp_runtime::MAX_MODULE_ERROR_ENCODED_SIZE, 0); - let message = None; - let error = DispatchError::Module(ModuleError { - index, - error: TryInto::try_into(error).expect("should work"), - message, - }); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 52, 18, 0, 0, 0]); - assert_eq!( - decoded, - DispatchError::Module(ModuleError { index: 52, error: [18, 0, 0, 0], message: None }) - ); - println!("Encoded Module Error: {:?}", encoded); + new_test_ext().execute_with(|| { + let error = DispatchError::Module(ModuleError { + index: 255, + error: [2, 0, 0, 0], + message: Some("error message"), + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); + assert_eq!( + decoded, + // `message` is skipped for encoding. + DispatchError::Module(ModuleError { + index: 255, + error: [2, 0, 0, 0], + message: None + }) + ); + println!("Encoded Module Error: {:?}", encoded); - // Example DispatchError::Token - let error = DispatchError::Token(TokenError::UnknownAsset); - let encoded = error.encode(); - assert_eq!(encoded, vec![7, 4]); - println!("Encoded Token Error: {:?}", encoded); + // Example pallet assets Error into ModuleError. + let index = + <::PalletInfo as frame_support::traits::PalletInfo>::index::< + Assets, + >() + .expect("Every active module has an index in the runtime; qed") as u8; - // Example DispatchError::Arithmetic - let error = DispatchError::Arithmetic(ArithmeticError::Overflow); - let encoded = error.encode(); - assert_eq!(encoded, vec![8, 1]); - println!("Encoded Arithmetic Error: {:?}", encoded); - }); -} + let mut error = + pallet_assets::Error::NotFrozen::.encode(); + error.resize(sp_runtime::MAX_MODULE_ERROR_ENCODED_SIZE, 0); + let error = DispatchError::Module(ModuleError { + index, + error: TryInto::try_into(error).expect("should work"), + message: None, + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 52, 18, 0, 0, 0]); + assert_eq!( + decoded, + DispatchError::Module(ModuleError { + index: 52, + error: [18, 0, 0, 0], + message: None + }) + ); + println!("Encoded Module Error: {:?}", encoded); -#[test] -fn encoding_of_enum() { - use codec::{Decode, Encode}; + // Example DispatchError::Token + let error = DispatchError::Token(TokenError::UnknownAsset); + let encoded = error.encode(); + assert_eq!(encoded, vec![7, 4]); + println!("Encoded Token Error: {:?}", encoded); - // Comprehensive enum with all different type of variants. - #[derive(Debug, PartialEq, Encode, Decode)] - enum ComprehensiveEnum { - SimpleVariant, - DataVariant(u8), - NamedFields { w: u8 }, - NestedEnum(InnerEnum), - OptionVariant(Option), - VecVariant(Vec), - TupleVariant(u8, u8), - NestedStructVariant(NestedStruct), - NestedEnumStructVariant(NestedEnumStruct), + // Example DispatchError::Arithmetic + let error = DispatchError::Arithmetic(ArithmeticError::Overflow); + let encoded = error.encode(); + assert_eq!(encoded, vec![8, 1]); + println!("Encoded Arithmetic Error: {:?}", encoded); + }); } - #[derive(Debug, PartialEq, Encode, Decode)] - enum InnerEnum { - A, - B { inner_data: u8 }, - C(u8), - } + #[test] + fn encoding_of_enum() { + use codec::{Decode, Encode}; - #[derive(Debug, PartialEq, Encode, Decode)] - struct NestedStruct { - x: u8, - y: u8, - } + // Comprehensive enum with all different type of variants. + #[derive(Debug, PartialEq, Encode, Decode)] + enum ComprehensiveEnum { + SimpleVariant, + DataVariant(u8), + NamedFields { w: u8 }, + NestedEnum(InnerEnum), + OptionVariant(Option), + VecVariant(Vec), + TupleVariant(u8, u8), + NestedStructVariant(NestedStruct), + NestedEnumStructVariant(NestedEnumStruct), + } - #[derive(Debug, PartialEq, Encode, Decode)] - struct NestedEnumStruct { - inner_enum: InnerEnum, - } + #[derive(Debug, PartialEq, Encode, Decode)] + enum InnerEnum { + A, + B { inner_data: u8 }, + C(u8), + } - // Creating each possible variant for an enum. - let enum_simple = ComprehensiveEnum::SimpleVariant; - let enum_data = ComprehensiveEnum::DataVariant(42); - let enum_named = ComprehensiveEnum::NamedFields { w: 42 }; - let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 }); - let enum_option = ComprehensiveEnum::OptionVariant(Some(42)); - let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]); - let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42); - let enum_nested_struct = ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 }); - let enum_nested_enum_struct = ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { - inner_enum: InnerEnum::C(42), - }); + #[derive(Debug, PartialEq, Encode, Decode)] + struct NestedStruct { + x: u8, + y: u8, + } - // Encode and print each variant individually to see their encoded values. - println!("{:?} -> {:?}", enum_simple, enum_simple.encode()); - println!("{:?} -> {:?}", enum_data, enum_data.encode()); - println!("{:?} -> {:?}", enum_named, enum_named.encode()); - println!("{:?} -> {:?}", enum_nested, enum_nested.encode()); - println!("{:?} -> {:?}", enum_option, enum_option.encode()); - println!("{:?} -> {:?}", enum_vec, enum_vec.encode()); - println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode()); - println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode()); - println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); -} + #[derive(Debug, PartialEq, Encode, Decode)] + struct NestedEnumStruct { + inner_enum: InnerEnum, + } -#[test] -fn dispatch_error_to_status_code_to_pop_api_error_works() { - // Create all the different `DispatchError` variants with its respective `PopApiError`. - let test_cases = vec![ - (DispatchError::CannotLookup, PopApiError::CannotLookup), - (DispatchError::BadOrigin, PopApiError::BadOrigin), - ( - DispatchError::Module(sp_runtime::ModuleError { - index: 1, - error: [2, 0, 0, 0], - message: Some("hallo"), - }), - PopApiError::Module { index: 1, error: 2 }, - ), - (DispatchError::ConsumerRemaining, PopApiError::ConsumerRemaining), - (DispatchError::NoProviders, PopApiError::NoProviders), - (DispatchError::TooManyConsumers, PopApiError::TooManyConsumers), - ( - DispatchError::Token(sp_runtime::TokenError::FundsUnavailable), - PopApiError::Token(TokenError::FundsUnavailable), - ), - ( - DispatchError::Arithmetic(sp_runtime::ArithmeticError::Overflow), - PopApiError::Arithmetic(ArithmeticError::Overflow), - ), - ( - DispatchError::Transactional(sp_runtime::TransactionalError::LimitReached), - PopApiError::Transactional(TransactionalError::LimitReached), - ), - (DispatchError::Exhausted, PopApiError::Exhausted), - (DispatchError::Corruption, PopApiError::Corruption), - (DispatchError::Unavailable, PopApiError::Unavailable), - (DispatchError::RootNotAllowed, PopApiError::RootNotAllowed), - ]; - for (error, pop_api_error) in test_cases { - // Show that the encoding and decoding of the PopApiError <> u32 (status code) works. - let status_code = crate::extensions::convert_to_status_code(error); - // let error = pop_api::error::convert_to_pop_api_error(status_code); - // assert_eq!(pop_api_error, error,); + // Creating each possible variant for an enum. + let enum_simple = ComprehensiveEnum::SimpleVariant; + let enum_data = ComprehensiveEnum::DataVariant(42); + let enum_named = ComprehensiveEnum::NamedFields { w: 42 }; + let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 }); + let enum_option = ComprehensiveEnum::OptionVariant(Some(42)); + let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]); + let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42); + let enum_nested_struct = + ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 }); + let enum_nested_enum_struct = + ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { + inner_enum: InnerEnum::C(42), + }); + + // Encode and print each variant individually to see their encoded values. + println!("{:?} -> {:?}", enum_simple, enum_simple.encode()); + println!("{:?} -> {:?}", enum_data, enum_data.encode()); + println!("{:?} -> {:?}", enum_named, enum_named.encode()); + println!("{:?} -> {:?}", enum_nested, enum_nested.encode()); + println!("{:?} -> {:?}", enum_option, enum_option.encode()); + println!("{:?} -> {:?}", enum_vec, enum_vec.encode()); + println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode()); + println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode()); + println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); + } + + #[test] + fn dispatch_error_to_status_code() { + // Create all the different `DispatchError` variants with its respective `PopApiError`. + let test_cases = vec![ + (DispatchError::Other("hallo"), [0, 0, 0, 0]), + (DispatchError::CannotLookup, [1, 0, 0, 0]), + (DispatchError::BadOrigin, [2, 0, 0, 0]), + ( + DispatchError::Module(sp_runtime::ModuleError { + index: 1, + error: [2, 0, 0, 0], + message: Some("hallo"), + }), + [3, 1, 2, 0], + ), + (DispatchError::ConsumerRemaining, [4, 0, 0, 0]), + (DispatchError::NoProviders, [5, 0, 0, 0]), + (DispatchError::TooManyConsumers, [6, 0, 0, 0]), + (DispatchError::Token(sp_runtime::TokenError::BelowMinimum), [7, 2, 0, 0]), + (DispatchError::Arithmetic(sp_runtime::ArithmeticError::Overflow), [8, 1, 0, 0]), + ( + DispatchError::Transactional(sp_runtime::TransactionalError::LimitReached), + [9, 0, 0, 0], + ), + (DispatchError::Exhausted, [10, 0, 0, 0]), + (DispatchError::Corruption, [11, 0, 0, 0]), + (DispatchError::Unavailable, [12, 0, 0, 0]), + (DispatchError::RootNotAllowed, [13, 0, 0, 0]), + ]; + for (error, encoded_error) in test_cases { + let status_code = crate::extensions::convert_to_status_code(error); + assert_eq!(status_code, u32::decode(&mut &encoded_error[..]).unwrap()); + } } } diff --git a/runtime/testnet/Cargo.toml b/runtime/testnet/Cargo.toml index 43b1e310..b7aa7b76 100644 --- a/runtime/testnet/Cargo.toml +++ b/runtime/testnet/Cargo.toml @@ -22,7 +22,7 @@ scale-info.workspace = true smallvec.workspace = true # Local -pop-primitives = { workspace = true, features = ["testnet"] } +pop-primitives = { workspace = true, features = ["assets", "nfts", "cross-chain"] } pop-runtime-common = { workspace = true, default-features = false } # Substrate diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index a3284ad4..dd2c52bb 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -9,8 +9,8 @@ use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, }; use pop_primitives::{ + nfts::{CollectionId, ItemId}, storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, - CollectionId, ItemId, }; use sp_core::crypto::UncheckedFrom; use sp_runtime::{ @@ -19,7 +19,7 @@ use sp_runtime::{ }; use sp_std::vec::Vec; -use crate::{AccountId, AllowedPopApiCalls, RuntimeCall, RuntimeOrigin}; +use crate::{AccountId, AllowedApiCalls, RuntimeCall, RuntimeOrigin}; const LOG_TARGET: &str = "pop-api::extension"; @@ -110,7 +110,7 @@ where log::debug!(target:LOG_TARGET, "{} inputted RuntimeCall: {:?}", log_prefix, call); - origin.add_filter(AllowedPopApiCalls::contains); + origin.add_filter(AllowedApiCalls::contains); match call.dispatch(origin) { Ok(info) => { diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index 66a5092c..c4178011 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -250,8 +250,8 @@ impl Contains for FilteredCalls { } /// A type to identify allowed calls to the Runtime from contracts. Used by Pop API -pub struct AllowedPopApiCalls; -impl Contains for crate::AllowedPopApiCalls { +pub struct AllowedApiCalls; +impl Contains for AllowedApiCalls { fn contains(c: &RuntimeCall) -> bool { use pallet_nfts::Call as NftsCall; matches!( From 61b3a17d39b9bbbc76f87665a9546da9e0b58f89 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Wed, 26 Jun 2024 10:48:23 +0200 Subject: [PATCH 012/161] refactor: tests local fungibles --- Cargo.lock | 2787 ++++++----------- Cargo.toml | 28 +- pop-api/Cargo.toml | 6 +- pop-api/examples/.gitignore | 4 +- pop-api/examples/fungibles/lib.rs | 18 +- pop-api/integration-tests/Cargo.toml | 31 + pop-api/integration-tests/src/lib.rs | 95 + .../integration-tests/src}/local_fungibles.rs | 71 +- pop-api/src/lib.rs | 3 +- pop-api/src/v0/assets/mod.rs | 8 +- primitives/Cargo.toml | 4 +- primitives/src/storage_keys.rs | 4 +- runtime/devnet/Cargo.toml | 2 - runtime/devnet/src/extensions.rs | 180 ++ runtime/devnet/src/lib.rs | 2 - runtime/devnet/src/tests/mod.rs | 267 -- 16 files changed, 1331 insertions(+), 2179 deletions(-) create mode 100644 pop-api/integration-tests/Cargo.toml create mode 100644 pop-api/integration-tests/src/lib.rs rename {runtime/devnet/src/tests => pop-api/integration-tests/src}/local_fungibles.rs (88%) delete mode 100644 runtime/devnet/src/tests/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 77c563fb..d798562b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -343,7 +343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand 0.8.5", + "rand", ] [[package]] @@ -358,12 +358,6 @@ version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f840fb7195bcfc5e17ea40c26e5ce6d5b9ce5d584466e17703209657e459ae0" -[[package]] -name = "array-init" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" - [[package]] name = "arrayref" version = "0.3.7" @@ -379,12 +373,6 @@ dependencies = [ "nodrop", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "arrayvec" version = "0.7.4" @@ -416,7 +404,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure 0.12.6", + "synstructure", ] [[package]] @@ -498,17 +486,17 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-consensus-aura", - "sp-core 29.0.0", + "sp-core", "sp-genesis-builder", "sp-inherents", "sp-offchain", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", - "sp-std 14.0.0", - "sp-storage 20.0.0", + "sp-std", + "sp-storage", "sp-transaction-pool", "sp-version", - "sp-weights 28.0.0", + "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", @@ -537,9 +525,9 @@ dependencies = [ "parachains-common", "parachains-runtimes-test-utils", "parity-scale-codec", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", @@ -563,8 +551,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -921,7 +909,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", + "rand", "rand_core 0.6.4", "serde", "unicode-normalization", @@ -1024,18 +1012,6 @@ dependencies = [ "constant_time_eq 0.3.0", ] -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.9.0" @@ -1054,15 +1030,6 @@ dependencies = [ "generic-array 0.14.7", ] -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - [[package]] name = "blocking" version = "1.5.1" @@ -1149,7 +1116,7 @@ dependencies = [ "frame-system", "polkadot-primitives", "sp-api", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -1163,8 +1130,8 @@ dependencies = [ "bp-runtime", "frame-support", "sp-api", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -1178,8 +1145,8 @@ dependencies = [ "bp-runtime", "frame-support", "sp-api", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -1195,9 +1162,9 @@ dependencies = [ "scale-info", "serde", "sp-consensus-grandpa", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -1212,8 +1179,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-std", ] [[package]] @@ -1229,9 +1196,9 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -1248,9 +1215,9 @@ dependencies = [ "parity-util-mem", "scale-info", "serde", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -1264,8 +1231,8 @@ dependencies = [ "frame-support", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -1283,13 +1250,13 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", - "trie-db 0.28.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", + "trie-db", ] [[package]] @@ -1302,15 +1269,15 @@ dependencies = [ "bp-parachains", "bp-polkadot-core", "bp-runtime", - "ed25519-dalek 2.1.1", + "ed25519-dalek", "finality-grandpa", "parity-scale-codec", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-consensus-grandpa", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-core", + "sp-runtime", + "sp-std", + "sp-trie", ] [[package]] @@ -1319,7 +1286,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6663e0179d475e30cfcf28cf597cdc8f4bb1c2c39a557b4cbe0057db0657fb67" dependencies = [ - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -1330,8 +1297,8 @@ checksum = "86ff4abe93be7bc1663adc41817b1aa3476fbec953ce361537419924310d5dd4" dependencies = [ "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", ] [[package]] @@ -1361,11 +1328,11 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-trie", "staging-xcm", "staging-xcm-builder", ] @@ -1778,26 +1745,6 @@ dependencies = [ "tiny-keccak", ] -[[package]] -name = "const_env" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9e4f72c6e3398ca6da372abd9affd8f89781fe728869bbf986206e9af9627e" -dependencies = [ - "const_env_impl", -] - -[[package]] -name = "const_env_impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a4f51209740b5e1589e702b3044cdd4562cef41b6da404904192ffffb852d62" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "constant_time_eq" version = "0.1.5" @@ -2097,8 +2044,8 @@ dependencies = [ "sc-client-api", "sc-service", "sp-blockchain", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "url", ] @@ -2121,8 +2068,8 @@ dependencies = [ "sc-client-api", "sp-api", "sp-consensus", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "tracing", ] @@ -2154,16 +2101,16 @@ dependencies = [ "sc-telemetry", "schnellru", "sp-api", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-aura", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-keystore", + "sp-runtime", + "sp-state-machine", "sp-timestamp", "substrate-prometheus-endpoint", "tracing", @@ -2191,10 +2138,10 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-slots", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "sp-timestamp", - "sp-trie 30.0.0", + "sp-trie", "substrate-prometheus-endpoint", "tracing", ] @@ -2210,8 +2157,8 @@ dependencies = [ "cumulus-primitives-parachain-inherent", "sp-consensus", "sp-inherents", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-runtime", + "sp-state-machine", "thiserror", ] @@ -2233,9 +2180,9 @@ dependencies = [ "sc-client-api", "sp-blockchain", "sp-consensus", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-core", + "sp-runtime", + "sp-state-machine", "tracing", ] @@ -2256,11 +2203,11 @@ dependencies = [ "sp-api", "sp-crypto-hashing", "sp-inherents", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-std 14.0.0", - "sp-storage 20.0.0", - "sp-trie 30.0.0", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-storage", + "sp-trie", "tracing", ] @@ -2280,12 +2227,12 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-overseer", "polkadot-primitives", - "rand 0.8.5", + "rand", "sc-client-api", "sc-consensus", "sp-consensus", "sp-maybe-compressed-blob", - "sp-runtime 32.0.0", + "sp-runtime", "tracing", ] @@ -2321,8 +2268,8 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "sp-transaction-pool", ] @@ -2339,10 +2286,10 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-consensus-aura", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -2368,17 +2315,17 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-parachains", "scale-info", - "sp-core 29.0.0", - "sp-externalities 0.26.0", + "sp-core", + "sp-externalities", "sp-inherents", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", "sp-version", "staging-xcm", - "trie-db 0.28.0", + "trie-db", ] [[package]] @@ -2404,8 +2351,8 @@ dependencies = [ "frame-system", "pallet-session", "parity-scale-codec", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -2419,9 +2366,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", "staging-xcm", ] @@ -2443,10 +2390,10 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-parachains", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", "staging-xcm", "staging-xcm-executor", ] @@ -2462,8 +2409,8 @@ dependencies = [ "polkadot-primitives", "sp-api", "sp-consensus-aura", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -2478,9 +2425,9 @@ dependencies = [ "polkadot-primitives", "scale-info", "sp-api", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-runtime", + "sp-std", + "sp-trie", "staging-xcm", ] @@ -2494,10 +2441,10 @@ dependencies = [ "cumulus-primitives-core", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-std", + "sp-trie", ] [[package]] @@ -2506,9 +2453,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b74f9141190b9f4bf96a947ade46da64097b77f1ebfa8d611c81724250e119" dependencies = [ - "sp-externalities 0.26.0", - "sp-runtime-interface 25.0.0", - "sp-trie 30.0.0", + "sp-externalities", + "sp-runtime-interface", + "sp-trie", ] [[package]] @@ -2524,9 +2471,9 @@ dependencies = [ "parity-scale-codec", "polkadot-runtime-common", "polkadot-runtime-parachains", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -2552,9 +2499,9 @@ dependencies = [ "sc-tracing", "sp-api", "sp-consensus", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-core", + "sp-runtime", + "sp-state-machine", ] [[package]] @@ -2572,7 +2519,7 @@ dependencies = [ "sc-client-api", "sp-api", "sp-blockchain", - "sp-state-machine 0.36.0", + "sp-state-machine", "thiserror", ] @@ -2612,7 +2559,7 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-runtime 32.0.0", + "sp-runtime", "substrate-prometheus-endpoint", "tokio", "tracing", @@ -2634,7 +2581,7 @@ dependencies = [ "parity-scale-codec", "pin-project", "polkadot-overseer", - "rand 0.8.5", + "rand", "sc-client-api", "sc-rpc-api", "sc-service", @@ -2646,10 +2593,10 @@ dependencies = [ "sp-api", "sp-authority-discovery", "sp-consensus-babe", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-storage 20.0.0", + "sp-core", + "sp-runtime", + "sp-state-machine", + "sp-storage", "sp-version", "thiserror", "tokio", @@ -2667,23 +2614,10 @@ dependencies = [ "cumulus-primitives-core", "parity-scale-codec", "polkadot-primitives", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", -] - -[[package]] -name = "curve25519-dalek" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" -dependencies = [ - "byteorder", - "digest 0.8.1", - "rand_core 0.5.1", - "subtle 2.5.0", - "zeroize", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", ] [[package]] @@ -3130,19 +3064,10 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", - "signature 2.2.0", + "signature", "spki", ] -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature 1.6.4", -] - [[package]] name = "ed25519" version = "2.2.3" @@ -3150,19 +3075,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", - "signature 2.2.0", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek 3.2.0", - "ed25519 1.5.3", - "sha2 0.9.9", - "zeroize", + "signature", ] [[package]] @@ -3172,7 +3085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek 4.1.2", - "ed25519 2.2.3", + "ed25519", "rand_core 0.6.4", "serde", "sha2 0.10.8", @@ -3201,7 +3114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ "curve25519-dalek 4.1.2", - "ed25519 2.2.3", + "ed25519", "hashbrown 0.14.3", "hex", "rand_core 0.6.4", @@ -3261,8 +3174,8 @@ dependencies = [ "sc-consensus-grandpa", "sp-authority-discovery", "sp-consensus-babe", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "staging-xcm", "xcm-emulator", ] @@ -3509,12 +3422,6 @@ dependencies = [ "syn 2.0.58", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fallible-iterator" version = "0.2.0" @@ -3632,7 +3539,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand 0.8.5", + "rand", "rustc-hex", "static_assertions", ] @@ -3709,13 +3616,13 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto 31.0.0", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-runtime-interface 25.0.0", - "sp-std 14.0.0", - "sp-storage 20.0.0", + "sp-application-crypto", + "sp-core", + "sp-io", + "sp-runtime", + "sp-runtime-interface", + "sp-std", + "sp-storage", "static_assertions", ] @@ -3740,7 +3647,7 @@ dependencies = [ "linked-hash-map", "log", "parity-scale-codec", - "rand 0.8.5", + "rand", "rand_pcg", "sc-block-builder", "sc-cli", @@ -3753,17 +3660,17 @@ dependencies = [ "serde_json", "sp-api", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-database", - "sp-externalities 0.26.0", + "sp-externalities", "sp-inherents", - "sp-io 31.0.0", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-storage 20.0.0", - "sp-trie 30.0.0", - "sp-wasm-interface 20.0.0", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-state-machine", + "sp-storage", + "sp-trie", + "sp-wasm-interface", "thiserror", "thousands", ] @@ -3791,11 +3698,11 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", + "sp-arithmetic", + "sp-core", "sp-npos-elections", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -3810,11 +3717,11 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-tracing 16.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", ] [[package]] @@ -3852,11 +3759,11 @@ dependencies = [ "log", "parity-scale-codec", "serde", - "sp-core 29.0.0", + "sp-core", "sp-crypto-hashing", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-io", + "sp-runtime", + "sp-state-machine", "spinners", "substrate-rpc-client", "tokio", @@ -3887,20 +3794,20 @@ dependencies = [ "serde_json", "smallvec", "sp-api", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", + "sp-arithmetic", + "sp-core", "sp-crypto-hashing-proc-macro", - "sp-debug-derive 14.0.0", + "sp-debug-derive", "sp-genesis-builder", "sp-inherents", - "sp-io 31.0.0", + "sp-io", "sp-metadata-ir", - "sp-runtime 32.0.0", + "sp-runtime", "sp-staking", - "sp-state-machine 0.36.0", - "sp-std 14.0.0", - "sp-tracing 16.0.0", - "sp-weights 28.0.0", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-weights", "static_assertions", "tt-call", ] @@ -3962,12 +3869,12 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", "sp-version", - "sp-weights 28.0.0", + "sp-weights", ] [[package]] @@ -3981,9 +3888,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -4005,8 +3912,8 @@ dependencies = [ "frame-support", "parity-scale-codec", "sp-api", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -4256,7 +4163,7 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" dependencies = [ - "rand 0.8.5", + "rand", "rand_core 0.6.4", ] @@ -4762,206 +4669,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "ink" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4a862aedbfda93175ddf75c9aaa2ae4c4b39ee5cee06c16d50bccce05bf5c7" -dependencies = [ - "derive_more", - "ink_env", - "ink_macro", - "ink_metadata", - "ink_prelude", - "ink_primitives", - "ink_storage", - "pallet-contracts-uapi-next", - "parity-scale-codec", - "scale-info", -] - -[[package]] -name = "ink_allocator" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cee56055bac6d928d425e944c5f3b69baa33c9635822fd1c00cd4afc70fde3e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ink_codegen" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a1f8473fa09e0f9b6f3cb3f8d18c07c14ebf9ea1f7cdfee270f009d45ee8e9" -dependencies = [ - "blake2 0.10.6", - "derive_more", - "either", - "heck 0.4.1", - "impl-serde", - "ink_ir", - "ink_primitives", - "itertools 0.12.1", - "parity-scale-codec", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn 2.0.58", -] - -[[package]] -name = "ink_engine" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f357e2e867f4e222ffc4015a6e61d1073548de89f70a4e36a8b0385562777fa" -dependencies = [ - "blake2 0.10.6", - "derive_more", - "ink_primitives", - "pallet-contracts-uapi-next", - "parity-scale-codec", - "secp256k1 0.28.2", - "sha2 0.10.8", - "sha3", -] - -[[package]] -name = "ink_env" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cec50b7e4f8406aab25801b015d3802a52d76cfbe48ce11cfb4200fa88e296" -dependencies = [ - "blake2 0.10.6", - "cfg-if", - "const_env", - "derive_more", - "ink_allocator", - "ink_engine", - "ink_prelude", - "ink_primitives", - "ink_storage_traits", - "num-traits", - "pallet-contracts-uapi-next", - "parity-scale-codec", - "paste", - "rlibc", - "scale-decode", - "scale-encode", - "scale-info", - "schnorrkel 0.11.4", - "secp256k1 0.28.2", - "sha2 0.10.8", - "sha3", - "static_assertions", -] - -[[package]] -name = "ink_ir" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1ad2975551c4ed800af971289ed6d2c68ac41ffc03a42010b3e01d7360dfb2" -dependencies = [ - "blake2 0.10.6", - "either", - "impl-serde", - "ink_prelude", - "itertools 0.12.1", - "proc-macro2", - "quote", - "syn 2.0.58", -] - -[[package]] -name = "ink_macro" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aee1a546f37eae3b3cd223832d31702033c5369dcfa3405899587c110a7908d3" -dependencies = [ - "ink_codegen", - "ink_ir", - "ink_primitives", - "parity-scale-codec", - "proc-macro2", - "quote", - "syn 2.0.58", - "synstructure 0.13.1", -] - -[[package]] -name = "ink_metadata" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98fcc0ff9292ff68c7ee7b84c93533c9ff13859ec3b148faa822e2da9954fe6" -dependencies = [ - "derive_more", - "impl-serde", - "ink_prelude", - "ink_primitives", - "linkme", - "parity-scale-codec", - "scale-info", - "schemars", - "serde", -] - -[[package]] -name = "ink_prelude" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea1734d058c80aa72e59c8ae75624fd8a51791efba21469f273156c0f4cad5c9" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ink_primitives" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec35ef7f45e67a53b6142d7e7f18e6d9292d76c3a2a1da14cf8423e481813d" -dependencies = [ - "derive_more", - "ink_prelude", - "parity-scale-codec", - "scale-decode", - "scale-encode", - "scale-info", - "xxhash-rust", -] - -[[package]] -name = "ink_storage" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbdb04cad74df858c05bc9cb6f30bbf12da33c3e2cb7ca211749c001fa761aa9" -dependencies = [ - "array-init", - "cfg-if", - "derive_more", - "ink_env", - "ink_metadata", - "ink_prelude", - "ink_primitives", - "ink_storage_traits", - "pallet-contracts-uapi-next", - "parity-scale-codec", - "scale-info", -] - -[[package]] -name = "ink_storage_traits" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ce49e3d2935fc1ec3e73117119712b187d3123339f6a31624e92f75fa2293d" -dependencies = [ - "ink_metadata", - "ink_prelude", - "ink_primitives", - "parity-scale-codec", - "scale-info", -] - [[package]] name = "inout" version = "0.1.3" @@ -5019,8 +4726,8 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "staging-xcm", "staging-xcm-executor", "tracing-subscriber 0.3.18", @@ -5216,7 +4923,7 @@ dependencies = [ "hyper", "jsonrpsee-types 0.20.3", "parking_lot 0.12.1", - "rand 0.8.5", + "rand", "rustc-hash", "serde", "serde_json", @@ -5549,7 +5256,7 @@ dependencies = [ "parking_lot 0.12.1", "pin-project", "quick-protobuf", - "rand 0.8.5", + "rand", "rw-stream-sink", "smallvec", "thiserror", @@ -5600,12 +5307,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" dependencies = [ "bs58 0.4.0", - "ed25519-dalek 2.1.1", + "ed25519-dalek", "log", "multiaddr", "multihash 0.17.0", "quick-protobuf", - "rand 0.8.5", + "rand", "sha2 0.10.8", "thiserror", "zeroize", @@ -5630,7 +5337,7 @@ dependencies = [ "libp2p-swarm", "log", "quick-protobuf", - "rand 0.8.5", + "rand", "sha2 0.10.8", "smallvec", "thiserror", @@ -5652,7 +5359,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "log", - "rand 0.8.5", + "rand", "smallvec", "socket2 0.4.10", "tokio", @@ -5688,7 +5395,7 @@ dependencies = [ "log", "once_cell", "quick-protobuf", - "rand 0.8.5", + "rand", "sha2 0.10.8", "snow", "static_assertions", @@ -5710,7 +5417,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "rand 0.8.5", + "rand", "void", ] @@ -5730,7 +5437,7 @@ dependencies = [ "log", "parking_lot 0.12.1", "quinn-proto", - "rand 0.8.5", + "rand", "rustls 0.20.9", "thiserror", "tokio", @@ -5748,7 +5455,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm", - "rand 0.8.5", + "rand", "smallvec", ] @@ -5767,7 +5474,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm-derive", "log", - "rand 0.8.5", + "rand", "smallvec", "tokio", "void", @@ -5903,7 +5610,7 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand 0.8.5", + "rand", "serde", "sha2 0.9.9", "typenum", @@ -5973,26 +5680,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "linkme" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb76662d78edc9f9bf56360d6919bdacc8b7761227727e5082f128eeb90bbf5" -dependencies = [ - "linkme-impl", -] - -[[package]] -name = "linkme-impl" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dccda732e04fa3baf2e17cf835bfe2601c7c2edafd64417c627dabae3a8cda" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - [[package]] name = "linregress" version = "0.5.3" @@ -6264,18 +5951,6 @@ dependencies = [ "hash-db", ] -[[package]] -name = "merlin" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" -dependencies = [ - "byteorder", - "keccak", - "rand_core 0.5.1", - "zeroize", -] - [[package]] name = "merlin" version = "3.0.0" @@ -6295,7 +5970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69672161530e8aeca1d1400fbf3f1a1747ff60ea604265a4e906c2442df20532" dependencies = [ "futures", - "rand 0.8.5", + "rand", "thrift", ] @@ -6342,7 +6017,7 @@ dependencies = [ "lioness", "log", "parking_lot 0.12.1", - "rand 0.8.5", + "rand", "rand_chacha 0.3.1", "rand_distr", "subtle 2.5.0", @@ -6365,9 +6040,9 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-beefy", - "sp-core 29.0.0", + "sp-core", "sp-mmr-primitives", - "sp-runtime 32.0.0", + "sp-runtime", ] [[package]] @@ -6381,9 +6056,9 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-mmr-primitives", - "sp-runtime 32.0.0", + "sp-runtime", ] [[package]] @@ -6514,7 +6189,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure 0.12.6", + "synstructure", ] [[package]] @@ -6539,7 +6214,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure 0.12.6", + "synstructure", ] [[package]] @@ -6595,7 +6270,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bddcd3bf5144b6392de80e04c347cd7fab2508f6df16a85fc496ecd5cec39bc" dependencies = [ - "rand 0.8.5", + "rand", ] [[package]] @@ -6923,11 +6598,11 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -6942,8 +6617,8 @@ dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -6957,9 +6632,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -6975,10 +6650,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -6993,9 +6668,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -7010,10 +6685,10 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-consensus-aura", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -7027,10 +6702,10 @@ dependencies = [ "pallet-session", "parity-scale-codec", "scale-info", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-authority-discovery", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -7044,8 +6719,8 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -7063,14 +6738,14 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-consensus-babe", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-io", + "sp-runtime", "sp-session", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7089,18 +6764,18 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-tracing 16.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", ] [[package]] name = "pallet-balances" -version = "29.0.1" +version = "29.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27946a57494d7c6231ae8909275bbd3cb5460ee3d27b7a5774a8b8e64d3ab92" +checksum = "a9a54b5d0c7c4c3731883d6b1ac18aff44db20c3d0a3470c8861001a17afdc85" dependencies = [ "docify", "frame-benchmarking", @@ -7109,8 +6784,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -7128,10 +6803,10 @@ dependencies = [ "scale-info", "serde", "sp-consensus-beefy", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7153,11 +6828,11 @@ dependencies = [ "serde", "sp-api", "sp-consensus-beefy", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-std", ] [[package]] @@ -7173,10 +6848,10 @@ dependencies = [ "pallet-treasury", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7196,9 +6871,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-consensus-grandpa", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-runtime", + "sp-std", + "sp-trie", ] [[package]] @@ -7216,8 +6891,8 @@ dependencies = [ "num-traits", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -7237,9 +6912,9 @@ dependencies = [ "pallet-bridge-grandpa", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-runtime", + "sp-std", + "sp-trie", ] [[package]] @@ -7258,27 +6933,28 @@ dependencies = [ "pallet-bridge-messages", "parity-scale-codec", "scale-info", - "sp-arithmetic 24.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-runtime", + "sp-std", ] [[package]] name = "pallet-broker" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8cfe04e8c3f9ca8342ac785f2b1aee6140e1809546fc6f3a99fad20a8dfbf9" +checksum = "574c52fd629191c374c24a18036acac008ea92142309e5dd05e7f03149a667c3" dependencies = [ "bitvec", "frame-benchmarking", "frame-support", "frame-system", + "log", "parity-scale-codec", "scale-info", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -7295,30 +6971,31 @@ dependencies = [ "pallet-treasury", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] name = "pallet-collator-selection" -version = "10.0.0" +version = "10.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5ad46601c613396e92292a24c5b5d76e904c456ece9deb10913f6ea2e2999" +checksum = "49d1157d9a4b7966040158a7b4f1fb29f0cefa8deb6eb9b3452df7ce4161a31c" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "pallet-authorship", + "pallet-balances", "pallet-session", "parity-scale-codec", - "rand 0.8.5", + "rand", "scale-info", - "sp-runtime 32.0.0", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7333,10 +7010,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7356,16 +7033,16 @@ dependencies = [ "pallet-contracts-proc-macro", "pallet-contracts-uapi", "parity-scale-codec", - "rand 0.8.5", + "rand", "rand_pcg", "scale-info", "serde", "smallvec", "sp-api", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", "staging-xcm", "staging-xcm-builder", "wasm-instrument", @@ -7396,17 +7073,6 @@ dependencies = [ "scale-info", ] -[[package]] -name = "pallet-contracts-uapi-next" -version = "6.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd549c16296ea5b2eb7c65c56aba548b286c1be4d7675b424ff6ccb8319c97a9" -dependencies = [ - "bitflags 1.3.2", - "paste", - "polkavm-derive", -] - [[package]] name = "pallet-conviction-voting" version = "29.0.0" @@ -7420,9 +7086,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7438,10 +7104,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7457,14 +7123,14 @@ dependencies = [ "log", "pallet-election-provider-support-benchmarking", "parity-scale-codec", - "rand 0.8.5", + "rand", "scale-info", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-io 31.0.0", + "sp-arithmetic", + "sp-core", + "sp-io", "sp-npos-elections", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", "strum 0.24.1", ] @@ -7479,8 +7145,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "sp-npos-elections", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -7495,12 +7161,12 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", + "sp-core", + "sp-io", "sp-npos-elections", - "sp-runtime 32.0.0", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7517,10 +7183,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io 31.0.0", - "sp-runtime 32.0.0", + "sp-io", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7537,21 +7203,21 @@ dependencies = [ "pallet-session", "parity-scale-codec", "scale-info", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-consensus-grandpa", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-io", + "sp-runtime", "sp-session", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] name = "pallet-identity" -version = "29.0.0" +version = "29.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e1cae19e30e7dc822c419988b30bb1318d79a8d5da92733822d0e84fe760ca" +checksum = "452bba25325b7f0148eeecbde13e7c26dfb677ad46b3f160b359d7643b44c94b" dependencies = [ "enumflags2", "frame-benchmarking", @@ -7560,9 +7226,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7578,12 +7244,12 @@ dependencies = [ "pallet-authorship", "parity-scale-codec", "scale-info", - "sp-application-crypto 31.0.0", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", + "sp-application-crypto", + "sp-core", + "sp-io", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7597,11 +7263,11 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", + "sp-core", + "sp-io", "sp-keyring", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -7616,10 +7282,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7635,12 +7301,12 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-weights 28.0.0", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", ] [[package]] @@ -7655,11 +7321,11 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", + "sp-core", + "sp-io", "sp-mmr-primitives", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -7674,9 +7340,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7693,8 +7359,8 @@ dependencies = [ "pallet-nfts", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -7710,10 +7376,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7725,7 +7391,7 @@ dependencies = [ "pallet-nfts", "parity-scale-codec", "sp-api", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7739,10 +7405,10 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -7757,12 +7423,12 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-io", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", - "sp-tracing 16.0.0", + "sp-std", + "sp-tracing", ] [[package]] @@ -7780,10 +7446,10 @@ dependencies = [ "pallet-staking", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-runtime-interface 25.0.0", + "sp-runtime", + "sp-runtime-interface", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7795,7 +7461,7 @@ dependencies = [ "pallet-nomination-pools", "parity-scale-codec", "sp-api", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7811,9 +7477,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-runtime 32.0.0", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7836,9 +7502,9 @@ dependencies = [ "pallet-staking", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -7853,10 +7519,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7870,9 +7536,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7888,11 +7554,11 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7906,9 +7572,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7925,10 +7591,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-arithmetic 24.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7941,10 +7607,10 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -7960,10 +7626,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-weights 28.0.0", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", ] [[package]] @@ -7979,14 +7645,14 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-io", + "sp-runtime", "sp-session", "sp-staking", - "sp-state-machine 0.36.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-state-machine", + "sp-std", + "sp-trie", ] [[package]] @@ -8001,10 +7667,10 @@ dependencies = [ "pallet-session", "pallet-staking", "parity-scale-codec", - "rand 0.8.5", - "sp-runtime 32.0.0", + "rand", + "sp-runtime", "sp-session", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -8020,17 +7686,17 @@ dependencies = [ "parity-scale-codec", "rand_chacha 0.2.2", "scale-info", - "sp-arithmetic 24.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] name = "pallet-staking" -version = "29.0.2" +version = "29.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668b7d28c499f0d9f295fad26cf6c342472e21842e3b13bcaaac8536358b2d6c" +checksum = "061b00814eb794a40df4eca7972a7c67b26473cd85cc7c54f5816ae49ad6e11b" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -8043,11 +7709,11 @@ dependencies = [ "rand_chacha 0.2.2", "scale-info", "serde", - "sp-application-crypto 31.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", + "sp-application-crypto", + "sp-io", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -8069,7 +7735,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "505d45e08bad052f55fb51f00a6b6244d23ee46ffdc8091f6cddf4e3a880319d" dependencies = [ "log", - "sp-arithmetic 24.0.0", + "sp-arithmetic", ] [[package]] @@ -8095,10 +7761,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -8113,9 +7779,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -8132,10 +7798,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-inherents", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-storage 20.0.0", + "sp-io", + "sp-runtime", + "sp-std", + "sp-storage", "sp-timestamp", ] @@ -8153,27 +7819,27 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] name = "pallet-transaction-payment" -version = "29.0.0" +version = "29.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f690f5c287ad34b28ca951ef7fae80b08cc9218d970723b7a70e4d29396872" +checksum = "0b0c408252aefe10cff96af1e54f06f45cb0dd184b4e450e9a2ecf837dfe506e" dependencies = [ "frame-support", "frame-system", "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -8187,10 +7853,10 @@ dependencies = [ "parity-scale-codec", "sp-api", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-rpc", - "sp-runtime 32.0.0", - "sp-weights 28.0.0", + "sp-runtime", + "sp-weights", ] [[package]] @@ -8202,15 +7868,15 @@ dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "sp-api", - "sp-runtime 32.0.0", - "sp-weights 28.0.0", + "sp-runtime", + "sp-weights", ] [[package]] name = "pallet-treasury" -version = "28.0.0" +version = "28.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1605eb5083a2cd172544f33c6e59eca2e23ac49f02f13d1562b1b8a409df9c60" +checksum = "3eca44990d0d759213744f2d1f6fe1fadec1079a3e4e4da40556d6b4e42abbcd" dependencies = [ "docify", "frame-benchmarking", @@ -8221,9 +7887,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -8238,8 +7904,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -8253,10 +7919,10 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -8271,8 +7937,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -8287,15 +7953,15 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] name = "pallet-xcm" -version = "8.0.1" +version = "8.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0bade2eb6ce40af35a5af150692b4e150638f7f68c15735ab9cdf79650d68e" +checksum = "ba9138b04168b07b1aff4a2079f5514753c31dddba40e5fb471b9cda7da27ad6" dependencies = [ "bounded-collections 0.2.0", "frame-benchmarking", @@ -8306,10 +7972,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -8327,9 +7993,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-runtime", + "sp-std", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -8348,9 +8014,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-runtime", + "sp-std", "staging-xcm", "staging-xcm-builder", ] @@ -8377,10 +8043,10 @@ dependencies = [ "polkadot-primitives", "scale-info", "sp-consensus-aura", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", "staging-parachain-info", "staging-xcm", "staging-xcm-executor", @@ -8407,11 +8073,11 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "sp-consensus-aura", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-tracing 16.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", "staging-parachain-info", "staging-xcm", "staging-xcm-executor", @@ -8439,7 +8105,7 @@ dependencies = [ "lz4", "memmap2 0.5.10", "parking_lot 0.12.1", - "rand 0.8.5", + "rand", "siphasher 0.3.11", "snap", "winapi", @@ -8504,7 +8170,7 @@ checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2", "syn 1.0.109", - "synstructure 0.12.6", + "synstructure", ] [[package]] @@ -8590,18 +8256,9 @@ dependencies = [ [[package]] name = "pbkdf2" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", ] @@ -8770,7 +8427,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.5", + "rand", "tracing-gum", ] @@ -8787,7 +8444,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.5", + "rand", "tracing-gum", ] @@ -8807,10 +8464,10 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.5", + "rand", "schnellru", - "sp-core 29.0.0", - "sp-keystore 0.35.0", + "sp-core", + "sp-keystore", "thiserror", "tracing-gum", ] @@ -8831,7 +8488,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.5", + "rand", "sc-network", "schnellru", "thiserror", @@ -8859,8 +8516,8 @@ dependencies = [ "sc-storage-monitor", "sc-sysinfo", "sc-tracing", - "sp-core 29.0.0", - "sp-io 31.0.0", + "sp-core", + "sp-io", "sp-keyring", "sp-maybe-compressed-blob", "substrate-build-script-utils", @@ -8883,9 +8540,9 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-core 29.0.0", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-keystore", + "sp-runtime", "thiserror", "tokio-util", "tracing-gum", @@ -8899,9 +8556,9 @@ checksum = "b6a08e4e014c853b252ecbbe3ccd67b2d33d78e46988d309b8cccf4ac06e25ef" dependencies = [ "parity-scale-codec", "scale-info", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -8924,8 +8581,8 @@ dependencies = [ "polkadot-primitives", "sc-network", "schnellru", - "sp-application-crypto 31.0.0", - "sp-keystore 0.35.0", + "sp-application-crypto", + "sp-keystore", "thiserror", "tracing-gum", ] @@ -8940,8 +8597,8 @@ dependencies = [ "polkadot-node-primitives", "polkadot-primitives", "reed-solomon-novelpoly", - "sp-core 29.0.0", - "sp-trie 30.0.0", + "sp-core", + "sp-trie", "thiserror", ] @@ -8957,14 +8614,14 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.5", + "rand", "rand_chacha 0.3.1", "sc-network", "sc-network-common", - "sp-application-crypto 31.0.0", - "sp-core 29.0.0", + "sp-application-crypto", + "sp-core", "sp-crypto-hashing", - "sp-keystore 0.35.0", + "sp-keystore", "tracing-gum", ] @@ -9005,7 +8662,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-core 29.0.0", + "sp-core", "sp-maybe-compressed-blob", "thiserror", "tracing-gum", @@ -9023,7 +8680,7 @@ dependencies = [ "futures-timer", "itertools 0.10.5", "kvdb", - "merlin 3.0.0", + "merlin", "parity-scale-codec", "polkadot-node-jaeger", "polkadot-node-primitives", @@ -9031,16 +8688,16 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", - "rand 0.8.5", + "rand", "rand_chacha 0.3.1", "rand_core 0.6.4", "sc-keystore", "schnellru", "schnorrkel 0.11.4", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-consensus", "sp-consensus-slots", - "sp-runtime 32.0.0", + "sp-runtime", "thiserror", "tracing-gum", ] @@ -9084,7 +8741,7 @@ dependencies = [ "polkadot-primitives", "polkadot-statement-table", "schnellru", - "sp-keystore 0.35.0", + "sp-keystore", "thiserror", "tracing-gum", ] @@ -9099,7 +8756,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-keystore 0.35.0", + "sp-keystore", "thiserror", "tracing-gum", "wasm-timer", @@ -9257,11 +8914,11 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-parachain-primitives", "polkadot-primitives", - "rand 0.8.5", + "rand", "slotmap", - "sp-core 29.0.0", + "sp-core", "sp-maybe-compressed-blob", - "sp-wasm-interface 20.0.0", + "sp-wasm-interface", "tempfile", "thiserror", "tokio", @@ -9280,7 +8937,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", - "sp-keystore 0.35.0", + "sp-keystore", "thiserror", "tracing-gum", ] @@ -9304,11 +8961,11 @@ dependencies = [ "sc-executor-common", "sc-executor-wasmtime", "seccompiler", - "sp-core 29.0.0", + "sp-core", "sp-crypto-hashing", - "sp-externalities 0.26.0", - "sp-io 31.0.0", - "sp-tracing 16.0.0", + "sp-externalities", + "sp-io", + "sp-tracing", "thiserror", "tracing-gum", ] @@ -9343,7 +9000,7 @@ dependencies = [ "polkadot-node-primitives", "polkadot-primitives", "sc-network", - "sp-core 29.0.0", + "sp-core", "thiserror", "tokio", ] @@ -9385,7 +9042,7 @@ dependencies = [ "polkadot-node-jaeger", "polkadot-node-primitives", "polkadot-primitives", - "rand 0.8.5", + "rand", "sc-authority-discovery", "sc-network", "strum 0.24.1", @@ -9407,12 +9064,12 @@ dependencies = [ "polkadot-primitives", "schnorrkel 0.11.4", "serde", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-consensus-babe", - "sp-core 29.0.0", - "sp-keystore 0.35.0", + "sp-core", + "sp-keystore", "sp-maybe-compressed-blob", - "sp-runtime 32.0.0", + "sp-runtime", "thiserror", "zstd 0.12.4", ] @@ -9452,7 +9109,7 @@ dependencies = [ "sp-authority-discovery", "sp-blockchain", "sp-consensus-babe", - "sp-runtime 32.0.0", + "sp-runtime", "substrate-prometheus-endpoint", "thiserror", ] @@ -9483,12 +9140,12 @@ dependencies = [ "polkadot-overseer", "polkadot-primitives", "prioritized-metered-channel", - "rand 0.8.5", + "rand", "sc-client-api", "schnellru", - "sp-application-crypto 31.0.0", - "sp-core 29.0.0", - "sp-keystore 0.35.0", + "sp-application-crypto", + "sp-core", + "sp-keystore", "thiserror", "tracing-gum", ] @@ -9511,7 +9168,7 @@ dependencies = [ "polkadot-primitives", "sc-client-api", "sp-api", - "sp-core 29.0.0", + "sp-core", "tikv-jemalloc-ctl", "tracing-gum", ] @@ -9528,10 +9185,10 @@ dependencies = [ "polkadot-core-primitives", "scale-info", "serde", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-weights 28.0.0", + "sp-core", + "sp-runtime", + "sp-std", + "sp-weights", ] [[package]] @@ -9549,17 +9206,17 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto 31.0.0", - "sp-arithmetic 24.0.0", + "sp-application-crypto", + "sp-arithmetic", "sp-authority-discovery", "sp-consensus-slots", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-io 31.0.0", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-io", + "sp-keystore", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -9590,17 +9247,17 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-keystore", + "sp-runtime", "substrate-frame-rpc-system", "substrate-state-trie-migration-rpc", ] [[package]] name = "polkadot-runtime-common" -version = "8.0.1" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06afbb3bd10245ad1907242a98ddffc3c0c1e209738b8382bc5bcfc1f28c0429" +checksum = "d815f0ff0a69dce7235d42c6e7d5e2b8b7429cba1252b4802ddc7879e2e74d4a" dependencies = [ "bitvec", "frame-benchmarking", @@ -9634,14 +9291,14 @@ dependencies = [ "serde_derive", "slot-range-helper", "sp-api", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-io 31.0.0", + "sp-io", "sp-npos-elections", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", "sp-staking", - "sp-std 14.0.0", + "sp-std", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -9658,15 +9315,15 @@ dependencies = [ "frame-benchmarking", "parity-scale-codec", "polkadot-primitives", - "sp-std 14.0.0", - "sp-tracing 16.0.0", + "sp-std", + "sp-tracing", ] [[package]] name = "polkadot-runtime-parachains" -version = "8.0.1" +version = "8.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bcfd672be236fd1c38c702e7e99fe3f3e54df0ddb8127e542423221d1f50669" +checksum = "b8d37cd3e014b06daf396d1483b5327782a0ebadc816423419665166b75b3e3e" dependencies = [ "bitflags 1.3.2", "bitvec", @@ -9691,22 +9348,22 @@ dependencies = [ "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-metrics", - "rand 0.8.5", + "rand", "rand_chacha 0.3.1", "rustc-hex", "scale-info", "serde", "sp-api", - "sp-application-crypto 31.0.0", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", "sp-inherents", - "sp-io 31.0.0", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-io", + "sp-keystore", + "sp-runtime", "sp-session", "sp-staking", - "sp-std 14.0.0", + "sp-std", "staging-xcm", "staging-xcm-executor", "static_assertions", @@ -9809,21 +9466,21 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-io 31.0.0", + "sp-io", "sp-keyring", - "sp-keystore 0.35.0", + "sp-keystore", "sp-mmr-primitives", "sp-offchain", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", - "sp-state-machine 0.36.0", - "sp-storage 20.0.0", + "sp-state-machine", + "sp-storage", "sp-timestamp", "sp-transaction-pool", "sp-version", - "sp-weights 28.0.0", + "sp-weights", "substrate-prometheus-endpoint", "thiserror", "tracing-gum", @@ -9848,7 +9505,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-keystore 0.35.0", + "sp-keystore", "sp-staking", "thiserror", "tracing-gum", @@ -9862,7 +9519,7 @@ checksum = "de5e010da3c6a65d8f263d0f825a04d995ffc8a37f886f674fcbbc73bf158d01" dependencies = [ "parity-scale-codec", "polkadot-primitives", - "sp-core 29.0.0", + "sp-core", "tracing-gum", ] @@ -9948,19 +9605,6 @@ dependencies = [ "universal-hash", ] -[[package]] -name = "pop-api" -version = "0.0.0" -dependencies = [ - "enumflags2", - "ink", - "parity-scale-codec", - "pop-primitives", - "scale-info", - "sp-io 23.0.0", - "sp-runtime 24.0.0", -] - [[package]] name = "pop-node" version = "0.1.0-alpha" @@ -10011,11 +9655,11 @@ dependencies = [ "sp-block-builder", "sp-blockchain", "sp-consensus-aura", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-keystore 0.35.0", + "sp-core", + "sp-io", + "sp-keystore", "sp-offchain", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", "sp-timestamp", "sp-transaction-pool", @@ -10045,8 +9689,8 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -10098,7 +9742,6 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-runtime-common", - "pop-api", "pop-primitives", "pop-runtime-common", "scale-info", @@ -10106,14 +9749,14 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-consensus-aura", - "sp-core 29.0.0", + "sp-core", "sp-genesis-builder", "sp-inherents", - "sp-io 31.0.0", + "sp-io", "sp-offchain", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", - "sp-std 14.0.0", + "sp-std", "sp-transaction-pool", "sp-version", "staging-parachain-info", @@ -10179,14 +9822,14 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-consensus-aura", - "sp-core 29.0.0", + "sp-core", "sp-genesis-builder", "sp-inherents", - "sp-io 31.0.0", + "sp-io", "sp-offchain", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", - "sp-std 14.0.0", + "sp-std", "sp-transaction-pool", "sp-version", "staging-parachain-info", @@ -10546,7 +10189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" dependencies = [ "bytes", - "rand 0.8.5", + "rand", "ring 0.16.20", "rustc-hash", "rustls 0.20.9", @@ -10572,19 +10215,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -10641,16 +10271,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "rand", ] [[package]] @@ -10876,12 +10497,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "rlibc" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" - [[package]] name = "rlp" version = "0.5.2" @@ -10974,22 +10589,22 @@ dependencies = [ "serde_derive", "smallvec", "sp-api", - "sp-arithmetic 24.0.0", + "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-babe", "sp-consensus-beefy", - "sp-core 29.0.0", + "sp-core", "sp-genesis-builder", "sp-inherents", - "sp-io 31.0.0", + "sp-io", "sp-mmr-primitives", "sp-offchain", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", "sp-staking", - "sp-std 14.0.0", - "sp-storage 20.0.0", + "sp-std", + "sp-storage", "sp-transaction-pool", "sp-version", "staging-xcm", @@ -11009,9 +10624,9 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "smallvec", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-weights 28.0.0", + "sp-core", + "sp-runtime", + "sp-weights", "staging-xcm", "staging-xcm-builder", ] @@ -11314,8 +10929,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357127c91373ed6d1ae582f6e3300ab5b13bcde43bbf270a891f44194ef48b70" dependencies = [ "log", - "sp-core 29.0.0", - "sp-wasm-interface 20.0.0", + "sp-core", + "sp-wasm-interface", "thiserror", ] @@ -11336,15 +10951,15 @@ dependencies = [ "parity-scale-codec", "prost 0.12.3", "prost-build", - "rand 0.8.5", + "rand", "sc-client-api", "sc-network", "sp-api", "sp-authority-discovery", "sp-blockchain", - "sp-core 29.0.0", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-keystore", + "sp-runtime", "substrate-prometheus-endpoint", "thiserror", ] @@ -11366,9 +10981,9 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-runtime 32.0.0", + "sp-runtime", "substrate-prometheus-endpoint", ] @@ -11382,10 +10997,10 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-runtime 32.0.0", - "sp-trie 30.0.0", + "sp-runtime", + "sp-trie", ] [[package]] @@ -11407,12 +11022,12 @@ dependencies = [ "serde", "serde_json", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-crypto-hashing", "sp-genesis-builder", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-io", + "sp-runtime", + "sp-state-machine", ] [[package]] @@ -11444,7 +11059,7 @@ dependencies = [ "log", "names", "parity-scale-codec", - "rand 0.8.5", + "rand", "regex", "rpassword", "sc-client-api", @@ -11459,11 +11074,11 @@ dependencies = [ "serde", "serde_json", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-keyring", - "sp-keystore 0.35.0", - "sp-panic-handler 13.0.0", - "sp-runtime 32.0.0", + "sp-keystore", + "sp-panic-handler", + "sp-runtime", "sp-version", "thiserror", "tokio", @@ -11486,14 +11101,14 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core 29.0.0", + "sp-core", "sp-database", - "sp-externalities 0.26.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-externalities", + "sp-runtime", + "sp-state-machine", "sp-statement-store", - "sp-storage 20.0.0", - "sp-trie 30.0.0", + "sp-storage", + "sp-trie", "substrate-prometheus-endpoint", ] @@ -11515,13 +11130,13 @@ dependencies = [ "sc-client-api", "sc-state-db", "schnellru", - "sp-arithmetic 24.0.0", + "sp-arithmetic", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-database", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-trie 30.0.0", + "sp-runtime", + "sp-state-machine", + "sp-trie", ] [[package]] @@ -11543,9 +11158,9 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-core", + "sp-runtime", + "sp-state-machine", "substrate-prometheus-endpoint", "thiserror", ] @@ -11566,16 +11181,16 @@ dependencies = [ "sc-consensus-slots", "sc-telemetry", "sp-api", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-aura", "sp-consensus-slots", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-keystore", + "sp-runtime", "substrate-prometheus-endpoint", "thiserror", ] @@ -11602,17 +11217,17 @@ dependencies = [ "sc-telemetry", "sc-transaction-pool-api", "sp-api", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", "sp-consensus-slots", - "sp-core 29.0.0", + "sp-core", "sp-crypto-hashing", "sp-inherents", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-keystore", + "sp-runtime", "substrate-prometheus-endpoint", "thiserror", ] @@ -11630,13 +11245,13 @@ dependencies = [ "sc-rpc-api", "serde", "sp-api", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-core 29.0.0", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-keystore", + "sp-runtime", "thiserror", ] @@ -11661,16 +11276,16 @@ dependencies = [ "sc-network-sync", "sc-utils", "sp-api", - "sp-application-crypto 31.0.0", - "sp-arithmetic 24.0.0", + "sp-application-crypto", + "sp-arithmetic", "sp-blockchain", "sp-consensus", "sp-consensus-beefy", - "sp-core 29.0.0", + "sp-core", "sp-crypto-hashing", - "sp-keystore 0.35.0", + "sp-keystore", "sp-mmr-primitives", - "sp-runtime 32.0.0", + "sp-runtime", "substrate-prometheus-endpoint", "thiserror", "tokio", @@ -11692,8 +11307,8 @@ dependencies = [ "sc-rpc", "serde", "sp-consensus-beefy", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "thiserror", ] @@ -11708,7 +11323,7 @@ dependencies = [ "sc-client-api", "sc-consensus", "sp-blockchain", - "sp-runtime 32.0.0", + "sp-runtime", ] [[package]] @@ -11728,7 +11343,7 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot 0.12.1", - "rand 0.8.5", + "rand", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -11742,15 +11357,15 @@ dependencies = [ "sc-utils", "serde_json", "sp-api", - "sp-application-crypto 31.0.0", - "sp-arithmetic 24.0.0", + "sp-application-crypto", + "sp-arithmetic", "sp-blockchain", "sp-consensus", "sp-consensus-grandpa", - "sp-core 29.0.0", + "sp-core", "sp-crypto-hashing", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-keystore", + "sp-runtime", "substrate-prometheus-endpoint", "thiserror", ] @@ -11771,8 +11386,8 @@ dependencies = [ "sc-rpc", "serde", "sp-blockchain", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "thiserror", ] @@ -11790,14 +11405,14 @@ dependencies = [ "sc-client-api", "sc-consensus", "sc-telemetry", - "sp-arithmetic 24.0.0", + "sp-arithmetic", "sp-blockchain", "sp-consensus", "sp-consensus-slots", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-runtime", + "sp-state-machine", ] [[package]] @@ -11812,14 +11427,14 @@ dependencies = [ "sc-executor-wasmtime", "schnellru", "sp-api", - "sp-core 29.0.0", - "sp-externalities 0.26.0", - "sp-io 31.0.0", - "sp-panic-handler 13.0.0", - "sp-runtime-interface 25.0.0", - "sp-trie 30.0.0", + "sp-core", + "sp-externalities", + "sp-io", + "sp-panic-handler", + "sp-runtime-interface", + "sp-trie", "sp-version", - "sp-wasm-interface 20.0.0", + "sp-wasm-interface", "tracing", ] @@ -11831,7 +11446,7 @@ checksum = "07498138dee3ddf2c71299ca372d8449880bb3a8a8a299a483094e9c26b0823e" dependencies = [ "sc-allocator", "sp-maybe-compressed-blob", - "sp-wasm-interface 20.0.0", + "sp-wasm-interface", "thiserror", "wasm-instrument", ] @@ -11850,8 +11465,8 @@ dependencies = [ "rustix 0.36.17", "sc-allocator", "sc-executor-common", - "sp-runtime-interface 25.0.0", - "sp-wasm-interface 20.0.0", + "sp-runtime-interface", + "sp-wasm-interface", "wasmtime", ] @@ -11870,7 +11485,7 @@ dependencies = [ "sc-network-common", "sc-network-sync", "sp-blockchain", - "sp-runtime 32.0.0", + "sp-runtime", ] [[package]] @@ -11882,9 +11497,9 @@ dependencies = [ "array-bytes 6.2.2", "parking_lot 0.12.1", "serde_json", - "sp-application-crypto 31.0.0", - "sp-core 29.0.0", - "sp-keystore 0.35.0", + "sp-application-crypto", + "sp-core", + "sp-keystore", "thiserror", ] @@ -11911,10 +11526,10 @@ dependencies = [ "sc-transaction-pool-api", "sp-api", "sp-consensus", - "sp-core 29.0.0", - "sp-keystore 0.35.0", + "sp-core", + "sp-keystore", "sp-mixnet", - "sp-runtime 32.0.0", + "sp-runtime", "thiserror", ] @@ -11942,17 +11557,17 @@ dependencies = [ "parking_lot 0.12.1", "partial_sort", "pin-project", - "rand 0.8.5", + "rand", "sc-client-api", "sc-network-common", "sc-utils", "serde", "serde_json", "smallvec", - "sp-arithmetic 24.0.0", + "sp-arithmetic", "sp-blockchain", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "substrate-prometheus-endpoint", "thiserror", "tokio", @@ -11978,7 +11593,7 @@ dependencies = [ "sc-client-api", "sc-network", "sp-blockchain", - "sp-runtime 32.0.0", + "sp-runtime", "thiserror", "unsigned-varint", ] @@ -11998,7 +11613,7 @@ dependencies = [ "sc-consensus", "sp-consensus", "sp-consensus-grandpa", - "sp-runtime 32.0.0", + "sp-runtime", ] [[package]] @@ -12016,7 +11631,7 @@ dependencies = [ "sc-network-common", "sc-network-sync", "schnellru", - "sp-runtime 32.0.0", + "sp-runtime", "substrate-prometheus-endpoint", "tracing", ] @@ -12038,8 +11653,8 @@ dependencies = [ "sc-client-api", "sc-network", "sp-blockchain", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "thiserror", ] @@ -12068,12 +11683,12 @@ dependencies = [ "sc-utils", "schnellru", "smallvec", - "sp-arithmetic 24.0.0", + "sp-arithmetic", "sp-blockchain", "sp-consensus", "sp-consensus-grandpa", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "substrate-prometheus-endpoint", "thiserror", "tokio", @@ -12096,7 +11711,7 @@ dependencies = [ "sc-network-sync", "sc-utils", "sp-consensus", - "sp-runtime 32.0.0", + "sp-runtime", "substrate-prometheus-endpoint", ] @@ -12119,18 +11734,18 @@ dependencies = [ "once_cell", "parity-scale-codec", "parking_lot 0.12.1", - "rand 0.8.5", + "rand", "sc-client-api", "sc-network", "sc-network-common", "sc-transaction-pool-api", "sc-utils", "sp-api", - "sp-core 29.0.0", - "sp-externalities 0.26.0", - "sp-keystore 0.35.0", + "sp-core", + "sp-externalities", + "sp-keystore", "sp-offchain", - "sp-runtime 32.0.0", + "sp-runtime", "threadpool", "tracing", ] @@ -12167,11 +11782,11 @@ dependencies = [ "serde_json", "sp-api", "sp-blockchain", - "sp-core 29.0.0", - "sp-keystore 0.35.0", + "sp-core", + "sp-keystore", "sp-offchain", "sp-rpc", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", "sp-statement-store", "sp-version", @@ -12192,9 +11807,9 @@ dependencies = [ "scale-info", "serde", "serde_json", - "sp-core 29.0.0", + "sp-core", "sp-rpc", - "sp-runtime 32.0.0", + "sp-runtime", "sp-version", "thiserror", ] @@ -12237,9 +11852,9 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-rpc", - "sp-runtime 32.0.0", + "sp-runtime", "sp-version", "thiserror", "tokio", @@ -12262,7 +11877,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.1", "pin-project", - "rand 0.8.5", + "rand", "sc-chain-spec", "sc-client-api", "sc-client-db", @@ -12290,16 +11905,16 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core 29.0.0", - "sp-externalities 0.26.0", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-externalities", + "sp-keystore", + "sp-runtime", "sp-session", - "sp-state-machine 0.36.0", - "sp-storage 20.0.0", + "sp-state-machine", + "sp-storage", "sp-transaction-pool", "sp-transaction-storage-proof", - "sp-trie 30.0.0", + "sp-trie", "sp-version", "static_init", "substrate-prometheus-endpoint", @@ -12319,7 +11934,7 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot 0.12.1", - "sp-core 29.0.0", + "sp-core", ] [[package]] @@ -12331,7 +11946,7 @@ dependencies = [ "clap", "fs4", "log", - "sp-core 29.0.0", + "sp-core", "thiserror", "tokio", ] @@ -12352,7 +11967,7 @@ dependencies = [ "serde", "serde_json", "sp-blockchain", - "sp-runtime 32.0.0", + "sp-runtime", "thiserror", ] @@ -12366,16 +11981,16 @@ dependencies = [ "futures", "libc", "log", - "rand 0.8.5", + "rand", "rand_pcg", "regex", "sc-telemetry", "serde", "serde_json", - "sp-core 29.0.0", + "sp-core", "sp-crypto-hashing", - "sp-io 31.0.0", - "sp-std 14.0.0", + "sp-io", + "sp-std", ] [[package]] @@ -12390,7 +12005,7 @@ dependencies = [ "log", "parking_lot 0.12.1", "pin-project", - "rand 0.8.5", + "rand", "sc-utils", "serde", "serde_json", @@ -12419,10 +12034,10 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-rpc", - "sp-runtime 32.0.0", - "sp-tracing 16.0.0", + "sp-runtime", + "sp-tracing", "thiserror", "tracing", "tracing-log 0.1.4", @@ -12460,10 +12075,10 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core 29.0.0", + "sp-core", "sp-crypto-hashing", - "sp-runtime 32.0.0", - "sp-tracing 16.0.0", + "sp-runtime", + "sp-tracing", "sp-transaction-pool", "substrate-prometheus-endpoint", "thiserror", @@ -12481,8 +12096,8 @@ dependencies = [ "parity-scale-codec", "serde", "sp-blockchain", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "thiserror", ] @@ -12499,7 +12114,7 @@ dependencies = [ "log", "parking_lot 0.12.1", "prometheus", - "sp-arithmetic 24.0.0", + "sp-arithmetic", ] [[package]] @@ -12580,7 +12195,6 @@ dependencies = [ "derive_more", "parity-scale-codec", "scale-info-derive", - "schemars", "serde", ] @@ -12638,30 +12252,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "schemars" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 2.0.58", -] - [[package]] name = "schnellru" version = "0.2.1" @@ -12673,24 +12263,6 @@ dependencies = [ "hashbrown 0.13.2", ] -[[package]] -name = "schnorrkel" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" -dependencies = [ - "arrayref", - "arrayvec 0.5.2", - "curve25519-dalek 2.1.3", - "getrandom 0.1.16", - "merlin 2.0.1", - "rand 0.7.3", - "rand_core 0.5.1", - "sha2 0.8.2", - "subtle 2.5.0", - "zeroize", -] - [[package]] name = "schnorrkel" version = "0.10.2" @@ -12700,7 +12272,7 @@ dependencies = [ "arrayref", "arrayvec 0.7.4", "curve25519-dalek-ng", - "merlin 3.0.0", + "merlin", "rand_core 0.6.4", "sha2 0.9.9", "subtle-ng", @@ -12718,7 +12290,7 @@ dependencies = [ "arrayvec 0.7.4", "curve25519-dalek 4.1.2", "getrandom_or_panic", - "merlin 3.0.0", + "merlin", "rand_core 0.6.4", "serde_bytes", "sha2 0.10.8", @@ -12771,31 +12343,13 @@ dependencies = [ "libc", ] -[[package]] -name = "secp256k1" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" -dependencies = [ - "secp256k1-sys 0.6.1", -] - [[package]] name = "secp256k1" version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ - "secp256k1-sys 0.9.2", -] - -[[package]] -name = "secp256k1-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" -dependencies = [ - "cc", + "secp256k1-sys", ] [[package]] @@ -12901,17 +12455,6 @@ dependencies = [ "syn 2.0.58", ] -[[package]] -name = "serde_derive_internals" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - [[package]] name = "serde_json" version = "1.0.115" @@ -12956,18 +12499,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha2" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - [[package]] name = "sha2" version = "0.9.9" @@ -13026,12 +12557,6 @@ dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - [[package]] name = "signature" version = "2.2.0" @@ -13097,8 +12622,8 @@ dependencies = [ "enumn", "parity-scale-codec", "paste", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -13177,7 +12702,7 @@ dependencies = [ "hmac 0.12.1", "itertools 0.11.0", "libsecp256k1", - "merlin 3.0.0", + "merlin", "no-std-net", "nom", "num-bigint", @@ -13186,7 +12711,7 @@ dependencies = [ "pbkdf2 0.12.2", "pin-project", "poly1305", - "rand 0.8.5", + "rand", "rand_chacha 0.3.1", "ruzstd 0.4.0", "schnorrkel 0.10.2", @@ -13232,7 +12757,7 @@ dependencies = [ "itertools 0.12.1", "libm", "libsecp256k1", - "merlin 3.0.0", + "merlin", "no-std-net", "nom", "num-bigint", @@ -13241,7 +12766,7 @@ dependencies = [ "pbkdf2 0.12.2", "pin-project", "poly1305", - "rand 0.8.5", + "rand", "rand_chacha 0.3.1", "ruzstd 0.5.0", "schnorrkel 0.11.4", @@ -13284,7 +12809,7 @@ dependencies = [ "no-std-net", "parking_lot 0.12.1", "pin-project", - "rand 0.8.5", + "rand", "rand_chacha 0.3.1", "serde", "serde_json", @@ -13320,7 +12845,7 @@ dependencies = [ "no-std-net", "parking_lot 0.12.1", "pin-project", - "rand 0.8.5", + "rand", "rand_chacha 0.3.1", "serde", "serde_json", @@ -13380,10 +12905,10 @@ dependencies = [ "serde", "snowbridge-ethereum", "snowbridge-milagro-bls", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", "ssz_rs", "ssz_rs_derive", "static_assertions", @@ -13404,11 +12929,11 @@ dependencies = [ "scale-info", "serde", "snowbridge-beacon-primitives", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", "staging-xcm", "staging-xcm-builder", ] @@ -13430,10 +12955,10 @@ dependencies = [ "scale-info", "serde", "serde-big-array", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", ] [[package]] @@ -13445,7 +12970,7 @@ dependencies = [ "hex", "lazy_static", "parity-scale-codec", - "rand 0.8.5", + "rand", "scale-info", "snowbridge-amcl", "zeroize", @@ -13466,10 +12991,10 @@ dependencies = [ "scale-info", "serde", "snowbridge-core", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -13508,37 +13033,37 @@ dependencies = [ "http", "httparse", "log", - "rand 0.8.5", + "rand", "sha-1", ] [[package]] name = "sp-api" -version = "27.0.0" +version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef42aa652381ade883c14ffbbb5c0fec36d382d2217b5bace01b8a0e8634778" +checksum = "2e4f8702afd77f14a32733e2b589c02694bf79d0b3a641963c508016208724d0" dependencies = [ "hash-db", "log", "parity-scale-codec", "scale-info", "sp-api-proc-macro", - "sp-core 29.0.0", - "sp-externalities 0.26.0", + "sp-core", + "sp-externalities", "sp-metadata-ir", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", "sp-version", "thiserror", ] [[package]] name = "sp-api-proc-macro" -version = "15.0.0" +version = "15.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0694be2891593450916d6b53a274d234bccbc86bcbada36ba23fc356989070c7" +checksum = "0301e2f77afb450fbf2b093f8b324c7ad88cc82e5e69bd5dc8658a1f068b2a96" dependencies = [ "Inflector", "blake2 0.10.6", @@ -13549,20 +13074,6 @@ dependencies = [ "syn 2.0.58", ] -[[package]] -name = "sp-application-crypto" -version = "23.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899492ea547816d5dfe9a5a2ecc32f65a7110805af6da3380aa4902371b31dc2" -dependencies = [ - "parity-scale-codec", - "scale-info", - "serde", - "sp-core 21.0.0", - "sp-io 23.0.0", - "sp-std 8.0.0", -] - [[package]] name = "sp-application-crypto" version = "31.0.0" @@ -13572,24 +13083,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-std 14.0.0", -] - -[[package]] -name = "sp-arithmetic" -version = "16.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6020576e544c6824a51d651bc8df8e6ab67cd59f1c9ac09868bb81a5199ded" -dependencies = [ - "integer-sqrt", - "num-traits", - "parity-scale-codec", - "scale-info", - "serde", - "sp-std 8.0.0", - "static_assertions", + "sp-core", + "sp-io", + "sp-std", ] [[package]] @@ -13603,7 +13099,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std 14.0.0", + "sp-std", "static_assertions", ] @@ -13616,9 +13112,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-application-crypto 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-application-crypto", + "sp-runtime", + "sp-std", ] [[package]] @@ -13629,8 +13125,8 @@ checksum = "1b36ce171caa7eb2bbe682c089f755fdefa71d3702e4fb1ba30d10146aef99d5" dependencies = [ "sp-api", "sp-inherents", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -13647,8 +13143,8 @@ dependencies = [ "sp-api", "sp-consensus", "sp-database", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-runtime", + "sp-state-machine", "thiserror", ] @@ -13661,10 +13157,10 @@ dependencies = [ "async-trait", "futures", "log", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-runtime", + "sp-state-machine", "thiserror", ] @@ -13678,11 +13174,11 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-consensus-slots", "sp-inherents", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", "sp-timestamp", ] @@ -13697,12 +13193,12 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto 31.0.0", + "sp-application-crypto", "sp-consensus-slots", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", "sp-timestamp", ] @@ -13717,13 +13213,13 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto 31.0.0", - "sp-core 29.0.0", + "sp-application-crypto", + "sp-core", "sp-crypto-hashing", - "sp-io 31.0.0", + "sp-io", "sp-mmr-primitives", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", "strum 0.24.1", ] @@ -13739,11 +13235,11 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto 31.0.0", - "sp-core 29.0.0", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-application-crypto", + "sp-core", + "sp-keystore", + "sp-runtime", + "sp-std", ] [[package]] @@ -13755,55 +13251,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std 14.0.0", + "sp-std", "sp-timestamp", ] -[[package]] -name = "sp-core" -version = "21.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f18d9e2f67d8661f9729f35347069ac29d92758b59135176799db966947a7336" -dependencies = [ - "array-bytes 4.2.0", - "bitflags 1.3.2", - "blake2 0.10.6", - "bounded-collections 0.1.9", - "bs58 0.4.0", - "dyn-clonable", - "ed25519-zebra 3.1.0", - "futures", - "hash-db", - "hash256-std-hasher", - "impl-serde", - "lazy_static", - "libsecp256k1", - "log", - "merlin 2.0.1", - "parity-scale-codec", - "parking_lot 0.12.1", - "paste", - "primitive-types", - "rand 0.8.5", - "regex", - "scale-info", - "schnorrkel 0.9.1", - "secp256k1 0.24.3", - "secrecy", - "serde", - "sp-core-hashing 9.0.0", - "sp-debug-derive 8.0.0", - "sp-externalities 0.19.0", - "sp-runtime-interface 17.0.0", - "sp-std 8.0.0", - "sp-storage 13.0.0", - "ss58-registry", - "substrate-bip39", - "thiserror", - "tiny-bip39", - "zeroize", -] - [[package]] name = "sp-core" version = "29.0.0" @@ -13825,23 +13276,23 @@ dependencies = [ "itertools 0.10.5", "libsecp256k1", "log", - "merlin 3.0.0", + "merlin", "parity-scale-codec", "parking_lot 0.12.1", "paste", "primitive-types", - "rand 0.8.5", + "rand", "scale-info", "schnorrkel 0.11.4", - "secp256k1 0.28.2", + "secp256k1", "secrecy", "serde", "sp-crypto-hashing", - "sp-debug-derive 14.0.0", - "sp-externalities 0.26.0", - "sp-runtime-interface 25.0.0", - "sp-std 14.0.0", - "sp-storage 20.0.0", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", "ss58-registry", "substrate-bip39", "thiserror", @@ -13850,21 +13301,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "sp-core-hashing" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee599a8399448e65197f9a6cee338ad192e9023e35e31f22382964c3c174c68" -dependencies = [ - "blake2b_simd", - "byteorder", - "digest 0.10.7", - "sha2 0.10.8", - "sha3", - "sp-std 8.0.0", - "twox-hash", -] - [[package]] name = "sp-core-hashing" version = "15.0.0" @@ -13914,17 +13350,6 @@ dependencies = [ "parking_lot 0.12.1", ] -[[package]] -name = "sp-debug-derive" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f531814d2f16995144c74428830ccf7d94ff4a7749632b83ad8199b181140c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - [[package]] name = "sp-debug-derive" version = "14.0.0" @@ -13936,18 +13361,6 @@ dependencies = [ "syn 2.0.58", ] -[[package]] -name = "sp-externalities" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0f71c671e01a8ca60da925d43a1b351b69626e268b8837f8371e320cf1dd100" -dependencies = [ - "environmental", - "parity-scale-codec", - "sp-std 8.0.0", - "sp-storage 13.0.0", -] - [[package]] name = "sp-externalities" version = "0.26.0" @@ -13956,8 +13369,8 @@ checksum = "e7096ed024cec397804864898b093b51e14c7299f1d00c67dd5800330e02bb82" dependencies = [ "environmental", "parity-scale-codec", - "sp-std 14.0.0", - "sp-storage 20.0.0", + "sp-std", + "sp-storage", ] [[package]] @@ -13968,8 +13381,8 @@ checksum = "fd865540ec19479c7349b584ccd78cc34c3f3a628a2a69dbb6365ceec36295ee" dependencies = [ "serde_json", "sp-api", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -13982,38 +13395,11 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", "thiserror", ] -[[package]] -name = "sp-io" -version = "23.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d597e35a9628fe7454b08965b2442e3ec0f264b0a90d41328e87422cec02e99" -dependencies = [ - "bytes", - "ed25519 1.5.3", - "ed25519-dalek 1.0.1", - "futures", - "libsecp256k1", - "log", - "parity-scale-codec", - "rustversion", - "secp256k1 0.24.3", - "sp-core 21.0.0", - "sp-externalities 0.19.0", - "sp-keystore 0.27.0", - "sp-runtime-interface 17.0.0", - "sp-state-machine 0.28.0", - "sp-std 8.0.0", - "sp-tracing 10.0.0", - "sp-trie 22.0.0", - "tracing", - "tracing-core", -] - [[package]] name = "sp-io" version = "31.0.0" @@ -14021,21 +13407,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec43aa073eab35fcb920d7592474d5427ea3be2bf938706a3ad955d7ba54fd8d" dependencies = [ "bytes", - "ed25519-dalek 2.1.1", + "ed25519-dalek", "libsecp256k1", "log", "parity-scale-codec", "rustversion", - "secp256k1 0.28.2", - "sp-core 29.0.0", + "secp256k1", + "sp-core", "sp-crypto-hashing", - "sp-externalities 0.26.0", - "sp-keystore 0.35.0", - "sp-runtime-interface 25.0.0", - "sp-state-machine 0.36.0", - "sp-std 14.0.0", - "sp-tracing 16.0.0", - "sp-trie 30.0.0", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", "tracing", "tracing-core", ] @@ -14046,25 +13432,11 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cf0a2f881958466fc92bc9b39bbc2c0d815ded4a21f8f953372b0ac2e11b02" dependencies = [ - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", "strum 0.24.1", ] -[[package]] -name = "sp-keystore" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be3cdd67cc1d9c1db17c5cbc4ec4924054a8437009d167f21f6590797e4aa45" -dependencies = [ - "futures", - "parity-scale-codec", - "parking_lot 0.12.1", - "sp-core 21.0.0", - "sp-externalities 0.19.0", - "thiserror", -] - [[package]] name = "sp-keystore" version = "0.35.0" @@ -14073,8 +13445,8 @@ checksum = "444f2d53968b1ce5e908882710ff1f3873fcf3e95f59d57432daf685bbacb959" dependencies = [ "parity-scale-codec", "parking_lot 0.12.1", - "sp-core 29.0.0", - "sp-externalities 0.26.0", + "sp-core", + "sp-externalities", "thiserror", ] @@ -14097,7 +13469,7 @@ dependencies = [ "frame-metadata 16.0.0", "parity-scale-codec", "scale-info", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -14109,8 +13481,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-application-crypto 31.0.0", - "sp-std 14.0.0", + "sp-application-crypto", + "sp-std", ] [[package]] @@ -14125,10 +13497,10 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-core 29.0.0", - "sp-debug-derive 14.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-core", + "sp-debug-derive", + "sp-runtime", + "sp-std", "thiserror", ] @@ -14141,10 +13513,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -14154,19 +13526,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d83b955dce0b6d143bec3f60571311168f362b1c16cf044da7037a407b66c19" dependencies = [ "sp-api", - "sp-core 29.0.0", - "sp-runtime 32.0.0", -] - -[[package]] -name = "sp-panic-handler" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd2de46003fa8212426838ca71cd42ee36a26480ba9ffea983506ce03131033" -dependencies = [ - "backtrace", - "lazy_static", - "regex", + "sp-core", + "sp-runtime", ] [[package]] @@ -14188,30 +13549,7 @@ checksum = "9af4b73fe7ddd88b1641cca90048c4e525e721763199e6fd29c4f590884f4d16" dependencies = [ "rustc-hash", "serde", - "sp-core 29.0.0", -] - -[[package]] -name = "sp-runtime" -version = "24.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21c5bfc764a1a8259d7e8f7cfd22c84006275a512c958d3ff966c92151e134d5" -dependencies = [ - "either", - "hash256-std-hasher", - "impl-trait-for-tuples", - "log", - "parity-scale-codec", - "paste", - "rand 0.8.5", - "scale-info", - "serde", - "sp-application-crypto 23.0.0", - "sp-arithmetic 16.0.0", - "sp-core 21.0.0", - "sp-io 23.0.0", - "sp-std 8.0.0", - "sp-weights 20.0.0", + "sp-core", ] [[package]] @@ -14227,35 +13565,16 @@ dependencies = [ "log", "parity-scale-codec", "paste", - "rand 0.8.5", + "rand", "scale-info", "serde", "simple-mermaid", - "sp-application-crypto 31.0.0", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-std 14.0.0", - "sp-weights 28.0.0", -] - -[[package]] -name = "sp-runtime-interface" -version = "17.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e676128182f90015e916f806cba635c8141e341e7abbc45d25525472e1bbce8" -dependencies = [ - "bytes", - "impl-trait-for-tuples", - "parity-scale-codec", - "primitive-types", - "sp-externalities 0.19.0", - "sp-runtime-interface-proc-macro 11.0.0", - "sp-std 8.0.0", - "sp-storage 13.0.0", - "sp-tracing 10.0.0", - "sp-wasm-interface 14.0.0", - "static_assertions", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std", + "sp-weights", ] [[package]] @@ -14268,28 +13587,15 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "primitive-types", - "sp-externalities 0.26.0", - "sp-runtime-interface-proc-macro 17.0.0", - "sp-std 14.0.0", - "sp-storage 20.0.0", - "sp-tracing 16.0.0", - "sp-wasm-interface 20.0.0", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", "static_assertions", ] -[[package]] -name = "sp-runtime-interface-proc-macro" -version = "11.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d5bd5566fe5633ec48dfa35ab152fd29f8a577c21971e1c6db9f28afb9bbb9" -dependencies = [ - "Inflector", - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.58", -] - [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" @@ -14313,11 +13619,11 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-core 29.0.0", - "sp-keystore 0.35.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-keystore", + "sp-runtime", "sp-staking", - "sp-std 14.0.0", + "sp-std", ] [[package]] @@ -14330,30 +13636,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", -] - -[[package]] -name = "sp-state-machine" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef45d31f9e7ac648f8899a0cd038a3608f8499028bff55b6c799702592325b6" -dependencies = [ - "hash-db", - "log", - "parity-scale-codec", - "parking_lot 0.12.1", - "rand 0.8.5", - "smallvec", - "sp-core 21.0.0", - "sp-externalities 0.19.0", - "sp-panic-handler 8.0.0", - "sp-std 8.0.0", - "sp-trie 22.0.0", - "thiserror", - "tracing", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -14366,16 +13651,16 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot 0.12.1", - "rand 0.8.5", + "rand", "smallvec", - "sp-core 29.0.0", - "sp-externalities 0.26.0", - "sp-panic-handler 13.0.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-std", + "sp-trie", "thiserror", "tracing", - "trie-db 0.28.0", + "trie-db", ] [[package]] @@ -14386,50 +13671,30 @@ checksum = "309a9ae4e8134bbed8ffc510cf4d461a4a651f9250b556de782cedd876abe1ff" dependencies = [ "aes-gcm", "curve25519-dalek 4.1.2", - "ed25519-dalek 2.1.1", + "ed25519-dalek", "hkdf", "parity-scale-codec", - "rand 0.8.5", + "rand", "scale-info", "sha2 0.10.8", "sp-api", - "sp-application-crypto 31.0.0", - "sp-core 29.0.0", + "sp-application-crypto", + "sp-core", "sp-crypto-hashing", - "sp-externalities 0.26.0", - "sp-runtime 32.0.0", - "sp-runtime-interface 25.0.0", - "sp-std 14.0.0", + "sp-externalities", + "sp-runtime", + "sp-runtime-interface", + "sp-std", "thiserror", "x25519-dalek 2.0.1", ] -[[package]] -name = "sp-std" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53458e3c57df53698b3401ec0934bea8e8cfce034816873c0b0abbd83d7bac0d" - [[package]] name = "sp-std" version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" -[[package]] -name = "sp-storage" -version = "13.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94294be83f11d4958cfea89ed5798f0b6605f5defc3a996948848458abbcc18e" -dependencies = [ - "impl-serde", - "parity-scale-codec", - "ref-cast", - "serde", - "sp-debug-derive 8.0.0", - "sp-std 8.0.0", -] - [[package]] name = "sp-storage" version = "20.0.0" @@ -14440,8 +13705,8 @@ dependencies = [ "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive 14.0.0", - "sp-std 14.0.0", + "sp-debug-derive", + "sp-std", ] [[package]] @@ -14453,24 +13718,11 @@ dependencies = [ "async-trait", "parity-scale-codec", "sp-inherents", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", "thiserror", ] -[[package]] -name = "sp-tracing" -version = "10.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357f7591980dd58305956d32f8f6646d0a8ea9ea0e7e868e46f53b68ddf00cec" -dependencies = [ - "parity-scale-codec", - "sp-std 8.0.0", - "tracing", - "tracing-core", - "tracing-subscriber 0.2.25", -] - [[package]] name = "sp-tracing" version = "16.0.0" @@ -14478,7 +13730,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0351810b9d074df71c4514c5228ed05c250607cba131c1c9d1526760ab69c05c" dependencies = [ "parity-scale-codec", - "sp-std 14.0.0", + "sp-std", "tracing", "tracing-core", "tracing-subscriber 0.2.25", @@ -14491,7 +13743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9742861c5330bdcb42856a6eed3d3745b58ee1c92ca4c9260032ff4e6c387165" dependencies = [ "sp-api", - "sp-runtime 32.0.0", + "sp-runtime", ] [[package]] @@ -14503,35 +13755,11 @@ dependencies = [ "async-trait", "parity-scale-codec", "scale-info", - "sp-core 29.0.0", + "sp-core", "sp-inherents", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-trie 30.0.0", -] - -[[package]] -name = "sp-trie" -version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4eeb7ef23f79eba8609db79ef9cef242f994f1f87a3c0387b4b5f177fda74" -dependencies = [ - "ahash 0.8.11", - "hash-db", - "hashbrown 0.13.2", - "lazy_static", - "memory-db", - "nohash-hasher", - "parity-scale-codec", - "parking_lot 0.12.1", - "scale-info", - "schnellru", - "sp-core 21.0.0", - "sp-std 8.0.0", - "thiserror", - "tracing", - "trie-db 0.27.1", - "trie-root", + "sp-runtime", + "sp-std", + "sp-trie", ] [[package]] @@ -14547,15 +13775,15 @@ dependencies = [ "nohash-hasher", "parity-scale-codec", "parking_lot 0.12.1", - "rand 0.8.5", + "rand", "scale-info", "schnellru", - "sp-core 29.0.0", - "sp-externalities 0.26.0", - "sp-std 14.0.0", + "sp-core", + "sp-externalities", + "sp-std", "thiserror", "tracing", - "trie-db 0.28.0", + "trie-db", "trie-root", ] @@ -14571,8 +13799,8 @@ dependencies = [ "scale-info", "serde", "sp-crypto-hashing-proc-macro", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", "sp-version-proc-macro", "thiserror", ] @@ -14589,20 +13817,6 @@ dependencies = [ "syn 2.0.58", ] -[[package]] -name = "sp-wasm-interface" -version = "14.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19c122609ca5d8246be6386888596320d03c7bc880959eaa2c36bcd5acd6846" -dependencies = [ - "anyhow", - "impl-trait-for-tuples", - "log", - "parity-scale-codec", - "sp-std 8.0.0", - "wasmtime", -] - [[package]] name = "sp-wasm-interface" version = "20.0.0" @@ -14613,26 +13827,10 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", - "sp-std 14.0.0", + "sp-std", "wasmtime", ] -[[package]] -name = "sp-weights" -version = "20.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45d084c735544f70625b821c3acdbc7a2fc1893ca98b85f1942631284692c75b" -dependencies = [ - "parity-scale-codec", - "scale-info", - "serde", - "smallvec", - "sp-arithmetic 16.0.0", - "sp-core 21.0.0", - "sp-debug-derive 8.0.0", - "sp-std 8.0.0", -] - [[package]] name = "sp-weights" version = "28.0.0" @@ -14644,9 +13842,9 @@ dependencies = [ "scale-info", "serde", "smallvec", - "sp-arithmetic 24.0.0", - "sp-debug-derive 14.0.0", - "sp-std 14.0.0", + "sp-arithmetic", + "sp-debug-derive", + "sp-std", ] [[package]] @@ -14737,8 +13935,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-runtime 32.0.0", - "sp-std 14.0.0", + "sp-runtime", + "sp-std", ] [[package]] @@ -14756,15 +13954,15 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-weights 28.0.0", + "sp-weights", "xcm-procedural", ] [[package]] name = "staging-xcm-builder" -version = "8.0.1" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f6cfc27c1d45f9a67e20ed3f7e60296299688825350291606add10bf3bbff2" +checksum = "988d765ad5ab3b5cc90bb1dd143153ebdbe2b7600e10d5ef3a7f3e8df1bdac5d" dependencies = [ "frame-support", "frame-system", @@ -14774,20 +13972,20 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "scale-info", - "sp-arithmetic 24.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-weights 28.0.0", + "sp-arithmetic", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", "staging-xcm", "staging-xcm-executor", ] [[package]] name = "staging-xcm-executor" -version = "8.0.1" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a638f4c8735cc04b5c93920a1f59e679f48b131315a07d146798e0decebf7720" +checksum = "74b5c5f2a1d610c5e20e5fae2680c9a28380f305afafeed62f341bfbce57b79a" dependencies = [ "environmental", "frame-benchmarking", @@ -14796,12 +13994,12 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-weights 28.0.0", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", "staging-xcm", ] @@ -14940,8 +14138,8 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-blockchain", - "sp-core 29.0.0", - "sp-runtime 32.0.0", + "sp-core", + "sp-runtime", ] [[package]] @@ -14968,7 +14166,7 @@ dependencies = [ "log", "sc-rpc-api", "serde", - "sp-runtime 32.0.0", + "sp-runtime", ] [[package]] @@ -14982,18 +14180,18 @@ dependencies = [ "sc-client-api", "sc-rpc-api", "serde", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", - "sp-trie 30.0.0", - "trie-db 0.28.0", + "sp-core", + "sp-runtime", + "sp-state-machine", + "sp-trie", + "trie-db", ] [[package]] name = "substrate-wasm-builder" -version = "18.0.0" +version = "18.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511bbc2df035f5fe2556d855369a1bbb45df620360391a1f6e3fa1a1d64af79a" +checksum = "4a39a20e17c24ede36b5bd5e7543a4cef8d8a0daf6e1a046dc31832b837a54a0" dependencies = [ "build-helper", "cargo_metadata", @@ -15052,7 +14250,7 @@ dependencies = [ "scale-value", "serde", "serde_json", - "sp-core-hashing 15.0.0", + "sp-core-hashing", "subxt-lightclient", "subxt-macro", "subxt-metadata", @@ -15124,7 +14322,7 @@ dependencies = [ "frame-metadata 16.0.0", "parity-scale-codec", "scale-info", - "sp-core-hashing 15.0.0", + "sp-core-hashing", "thiserror", ] @@ -15141,10 +14339,10 @@ dependencies = [ "pbkdf2 0.12.2", "regex", "schnorrkel 0.11.4", - "secp256k1 0.28.2", + "secp256k1", "secrecy", "sha2 0.10.8", - "sp-core-hashing 15.0.0", + "sp-core-hashing", "subxt", "thiserror", "zeroize", @@ -15184,17 +14382,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - [[package]] name = "system-configuration" version = "0.5.1" @@ -15275,7 +14462,7 @@ dependencies = [ "polkadot-core-primitives", "rococo-runtime-constants", "smallvec", - "sp-runtime 32.0.0", + "sp-runtime", "staging-xcm", "westend-runtime-constants", ] @@ -15410,25 +14597,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-bip39" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" -dependencies = [ - "anyhow", - "hmac 0.12.1", - "once_cell", - "pbkdf2 0.11.0", - "rand 0.8.5", - "rustc-hash", - "sha2 0.10.8", - "thiserror", - "unicode-normalization", - "wasm-bindgen", - "zeroize", -] - [[package]] name = "tiny-keccak" version = "2.0.2" @@ -15490,7 +14658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" dependencies = [ "pin-project", - "rand 0.8.5", + "rand", "tokio", ] @@ -15802,19 +14970,6 @@ dependencies = [ "tracing-log 0.2.0", ] -[[package]] -name = "trie-db" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" -dependencies = [ - "hash-db", - "hashbrown 0.13.2", - "log", - "rustc-hex", - "smallvec", -] - [[package]] name = "trie-db" version = "0.28.0" @@ -15853,7 +15008,7 @@ dependencies = [ "idna 0.2.3", "ipnet", "lazy_static", - "rand 0.8.5", + "rand", "smallvec", "socket2 0.4.10", "thiserror", @@ -15909,19 +15064,19 @@ dependencies = [ "sp-api", "sp-consensus-aura", "sp-consensus-babe", - "sp-core 29.0.0", - "sp-debug-derive 14.0.0", - "sp-externalities 0.26.0", + "sp-core", + "sp-debug-derive", + "sp-externalities", "sp-inherents", - "sp-io 31.0.0", - "sp-keystore 0.35.0", + "sp-io", + "sp-keystore", "sp-rpc", - "sp-runtime 32.0.0", - "sp-state-machine 0.36.0", + "sp-runtime", + "sp-state-machine", "sp-timestamp", "sp-transaction-storage-proof", "sp-version", - "sp-weights 28.0.0", + "sp-weights", "substrate-rpc-client", "zstd 0.12.4", ] @@ -15940,7 +15095,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand 0.8.5", + "rand", "static_assertions", ] @@ -16091,7 +15246,7 @@ dependencies = [ "arrayref", "constcat", "digest 0.10.7", - "rand 0.8.5", + "rand", "rand_chacha 0.3.1", "rand_core 0.6.4", "sha2 0.10.8", @@ -16501,7 +15656,7 @@ dependencies = [ "memfd", "memoffset", "paste", - "rand 0.8.5", + "rand", "rustix 0.36.17", "wasmtime-asm-macros", "wasmtime-environ", @@ -16630,24 +15785,24 @@ dependencies = [ "serde_derive", "smallvec", "sp-api", - "sp-application-crypto 31.0.0", - "sp-arithmetic 24.0.0", + "sp-application-crypto", + "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-babe", "sp-consensus-beefy", - "sp-core 29.0.0", + "sp-core", "sp-genesis-builder", "sp-inherents", - "sp-io 31.0.0", + "sp-io", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", - "sp-runtime 32.0.0", + "sp-runtime", "sp-session", "sp-staking", - "sp-std 14.0.0", - "sp-storage 20.0.0", + "sp-std", + "sp-storage", "sp-transaction-pool", "sp-version", "staging-xcm", @@ -16667,9 +15822,9 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "smallvec", - "sp-core 29.0.0", - "sp-runtime 32.0.0", - "sp-weights 28.0.0", + "sp-core", + "sp-runtime", + "sp-weights", "staging-xcm", "staging-xcm-builder", ] @@ -17061,13 +16216,13 @@ dependencies = [ "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-parachains", - "sp-arithmetic 24.0.0", - "sp-core 29.0.0", + "sp-arithmetic", + "sp-core", "sp-crypto-hashing", - "sp-io 31.0.0", - "sp-runtime 32.0.0", - "sp-std 14.0.0", - "sp-tracing 16.0.0", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", "staging-xcm", "staging-xcm-executor", ] @@ -17084,12 +16239,6 @@ dependencies = [ "syn 2.0.58", ] -[[package]] -name = "xxhash-rust" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" - [[package]] name = "yamux" version = "0.10.2" @@ -17100,7 +16249,7 @@ dependencies = [ "log", "nohash-hasher", "parking_lot 0.12.1", - "rand 0.8.5", + "rand", "static_assertions", ] diff --git a/Cargo.toml b/Cargo.toml index 3f1d6e1c..3719e83d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ subxt-signer = "0.34.0" tokio = { version = "1.36", features = ["macros", "time", "rt-multi-thread"] } # Build -substrate-wasm-builder = "18.0.0" +substrate-wasm-builder = "18.0.1" substrate-build-script-utils = "11.0.0" # Local @@ -76,7 +76,7 @@ sc-transaction-pool-api = "29.0.0" frame-benchmarking = { version = "29.0.0", default-features = false } frame-benchmarking-cli = "33.0.0" frame-executive = { version = "29.0.0", default-features = false } -frame-support = { version = "29.0.0", default-features = false } +frame-support = { version = "29.0.2", default-features = false } frame-system = { version = "29.0.0", default-features = false } frame-system-benchmarking = { version = "29.0.0", default-features = false } frame-system-rpc-runtime-api = { version = "27.0.0", default-features = false } @@ -84,7 +84,7 @@ frame-try-runtime = { version = "0.35.0", default-features = false } pallet-aura = { version = "28.0.0", default-features = false } pallet-authorship = { version = "29.0.0", default-features = false } pallet-assets = { version = "30.0.0", default-features = false } -pallet-balances = { version = "29.0.0", default-features = false } +pallet-balances = { version = "29.0.2", default-features = false } pallet-contracts = { version = "28.0.0", default-features = false } pallet-message-queue = { version = "32.0.0", default-features = false } pallet-multisig = { version = "29.0.0", default-features = false } @@ -97,11 +97,11 @@ pallet-scheduler = { version = "30.0.0", default-features = false } pallet-session = { version = "29.0.0", default-features = false } pallet-sudo = { version = "29.0.0", default-features = false } pallet-timestamp = { version = "28.0.0", default-features = false } -pallet-transaction-payment = { version = "29.0.0", default-features = false } +pallet-transaction-payment = { version = "29.0.1", default-features = false } pallet-transaction-payment-rpc = "31.0.0" pallet-transaction-payment-rpc-runtime-api = { version = "29.0.0", default-features = false } pallet-utility = { version = "29.0.0", default-features = false } -sp-api = { version = "27.0.0", default-features = false } +sp-api = { version = "27.0.1", default-features = false } sp-authority-discovery = { version = "27.0.0", default-features = false } sp-block-builder = { version = "27.0.0", default-features = false } sp-blockchain = "29.0.0" @@ -125,17 +125,17 @@ sp-transaction-pool = { version = "27.0.0", default-features = false } sp-version = { version = "30.0.0", default-features = false } # Polkadot -pallet-xcm = { version = "=8.0.1", default-features = false } +pallet-xcm = { version = "8.0.5", default-features = false } polkadot-cli = "8.0.0" polkadot-parachain-primitives = { version = "7.0.0", default-features = false } -polkadot-runtime-parachains = { version = "8.0.1", default-features = false } +polkadot-runtime-parachains = { version = "8.0.3", default-features = false } polkadot-primitives = { version = "8.0.1", default-features = false } -polkadot-runtime-common = { version = "8.0.1", default-features = false } +polkadot-runtime-common = { version = "8.0.2", default-features = false } rococo-runtime-constants = { version = "8.0.0", default-features = false } rococo-runtime = { version = "8.0.0", default-features = false } -xcm = { package = "staging-xcm", version = "8.0.1", default-features = false } -xcm-builder = { package = "staging-xcm-builder", version = "8.0.1", default-features = false } -xcm-executor = { package = "staging-xcm-executor", version = "8.0.1", default-features = false } +xcm = { version = "8.0.1", package = "staging-xcm", default-features = false } +xcm-builder = { version = "8.0.2", package = "staging-xcm-builder", default-features = false } +xcm-executor = { version = "8.0.2", package = "staging-xcm-executor", default-features = false } # Cumulus asset-hub-rococo-runtime = { version = "0.12.0", default-features = false } @@ -149,9 +149,9 @@ cumulus-primitives-aura = { version = "0.8.0", default-features = false } cumulus-primitives-core = { version = "0.8.0", default-features = false } cumulus-primitives-utility = { version = "0.8.1", default-features = false } emulated-integration-tests-common = { version = "4.0.0", default-features = false } -pallet-collator-selection = { version = "10.0.0", default-features = false } +pallet-collator-selection = { version = "10.0.2", default-features = false } parachains-common = { version = "8.0.0", default-features = false } -parachain-info = { package = "staging-parachain-info", version = "0.8.0", default-features = false } +parachain-info = { version = "0.8.0", package = "staging-parachain-info", default-features = false } cumulus-primitives-parachain-inherent = "0.8.0" cumulus-relay-chain-interface = "0.8.0" color-print = "0.3.4" @@ -160,4 +160,4 @@ cumulus-client-collator = "0.8.0" cumulus-client-consensus-aura = "0.8.0" cumulus-client-consensus-common = "0.8.0" cumulus-client-consensus-proposer = "0.8.0" -cumulus-client-service = "0.8.0" \ No newline at end of file +cumulus-client-service = "0.8.0" diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 9a868cfa..2dd4519c 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -9,9 +9,9 @@ edition = "2021" enumflags2 = { version = "0.7.7" } ink = { version = "5.0.0", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.6", default-features = false, features = ["derive"] } -sp-io = { version = "23.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } -sp-runtime = { version = "24.0", default-features = false } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +sp-io = { version = "31.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } +sp-runtime = { version = "32.0.0", default-features = false } pop-primitives = { path = "../primitives", features = ["devnet"], default-features = false } diff --git a/pop-api/examples/.gitignore b/pop-api/examples/.gitignore index e0caa493..d60800c8 100755 --- a/pop-api/examples/.gitignore +++ b/pop-api/examples/.gitignore @@ -1,9 +1,9 @@ # Ignore build artifacts from the local tests sub-crate. -/fungibles/target/ +**/target/ # Ignore backup files creates by cargo fmt. **/*.rs.bk # Remove Cargo.lock when creating an executable, leave it for libraries # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock -Cargo.lock +**/Cargo.lock diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 41ea1b14..35719ac6 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -12,7 +12,7 @@ use pop_api::{ primitives::{AccountId as AccountId32, AssetId}, }; -pub type Result = core::result::Result; +pub type Result = core::result::Result; #[ink::contract(env = pop_api::Environment)] mod fungibles { @@ -68,9 +68,9 @@ mod fungibles { value, ); - let result = api::transfer(id, to, value).map_err(|e| e.into()); + let result = api::transfer(id, to, value); ink::env::debug_println!("Result: {:?}", result); - result + result.map_err(|e| e.into()) } #[ink(message)] @@ -91,9 +91,9 @@ mod fungibles { value, ); - let result = api::transfer_from(id, from, to, value, &data).map_err(|e| e.into()); + let result = api::transfer_from(id, from, to, value, &data); ink::env::debug_println!("Result: {:?}", result); - result + result.map_err(|e| e.into()) } /// 2. PSP-22 Metadata Interface: @@ -118,9 +118,9 @@ mod fungibles { admin, min_balance, ); - let result = api::create(id, admin, min_balance).map_err(|e| e.into()); + let result = api::create(id, admin, min_balance); ink::env::debug_println!("Result: {:?}", result); - result + result.map_err(|e| e.into()) } #[ink(message)] @@ -138,9 +138,9 @@ mod fungibles { symbol, decimals, ); - let result = api::set_metadata(id, name, symbol, decimals).map_err(|e| e.into()); + let result = api::set_metadata(id, name, symbol, decimals); ink::env::debug_println!("Result: {:?}", result); - result + result.map_err(|e| e.into()) } #[ink(message)] diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml new file mode 100644 index 00000000..84769433 --- /dev/null +++ b/pop-api/integration-tests/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "integration-tests" +version = "0.1.0" +edition = "2021" + +[dev-dependencies] +env_logger = "0.11.2" +scale = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +frame-support = { version = "29.0.0", default-features = false } +frame-system = { version = "29.0.0", default-features = false } +pallet-balances = { version = "29.0.2", default-features = false } +pallet-contracts = { version = "28.0.0", default-features = false } +pop-api = { path = "../.", default-features = false, features = ["assets"] } +pop-runtime-devnet = { path = "../../runtime/devnet", default-features = false } +sp-io = { version = "31.0.0", default-features = false } +sp-runtime = { version = "32.0.0", default-features = false } + + +[features] +default = ["std"] +std = [ + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "pallet-contracts/std", + "pop-api/std", + "pop-runtime-devnet/std", + "scale/std", + "sp-io/std", + "sp-runtime/std", +] \ No newline at end of file diff --git a/pop-api/integration-tests/src/lib.rs b/pop-api/integration-tests/src/lib.rs new file mode 100644 index 00000000..624c3000 --- /dev/null +++ b/pop-api/integration-tests/src/lib.rs @@ -0,0 +1,95 @@ +#![cfg(test)] + +use frame_support::{ + traits::fungibles::{approvals::Inspect as ApprovalInspect, Inspect}, + weights::Weight, +}; +use pallet_contracts::{Code, CollectEvents, Determinism, ExecReturnValue}; +use scale::{Decode, Encode}; +use sp_runtime::{traits::Hash, AccountId32, BuildStorage, DispatchError}; + +use pop_runtime_devnet::{Assets, Contracts, Runtime, RuntimeOrigin, System, UNIT}; + +mod local_fungibles; + +type Balance = u128; +type AssetId = u32; +const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; + +const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); +const BOB: AccountId32 = AccountId32::new([2_u8; 32]); +// FERDIE has no initial balance. +const FERDIE: AccountId32 = AccountId32::new([3_u8; 32]); +const INIT_AMOUNT: Balance = 100_000_000 * UNIT; +const INIT_VALUE: Balance = 100 * UNIT; +const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); + +fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { + balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT)], + } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +fn load_wasm_module(path: &str) -> std::io::Result<(Vec, ::Output)> +where + T: frame_system::Config, +{ + let wasm_binary = std::fs::read(path)?; + let code_hash = T::Hashing::hash(&wasm_binary); + Ok((wasm_binary, code_hash)) +} + +fn function_selector(name: &str) -> Vec { + let hash = sp_io::hashing::blake2_256(name.as_bytes()); + [hash[0..4].to_vec()].concat() +} + +fn do_bare_call( + addr: AccountId32, + input: Vec, + value: u128, +) -> Result { + let result = Contracts::bare_call( + ALICE, + addr.into(), + value.into(), + GAS_LIMIT, + None, + input, + DEBUG_OUTPUT, + CollectEvents::Skip, + Determinism::Enforced, + ); + result.result +} + +// Deploy, instantiate and return contract address. +fn instantiate(contract: &str, init_value: u128, salt: Vec) -> AccountId32 { + let (wasm_binary, _) = + load_wasm_module::(contract).expect("could not read .wasm file"); + let result = Contracts::bare_instantiate( + ALICE, + init_value, + GAS_LIMIT, + None, + Code::Upload(wasm_binary), + function_selector("new"), + salt, + DEBUG_OUTPUT, + CollectEvents::Skip, + ) + .result + .unwrap(); + assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); + result.account_id +} diff --git a/runtime/devnet/src/tests/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs similarity index 88% rename from runtime/devnet/src/tests/local_fungibles.rs rename to pop-api/integration-tests/src/local_fungibles.rs index ac2b8ca0..1b3c6633 100644 --- a/runtime/devnet/src/tests/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -1,16 +1,8 @@ -// Todo - errors: -// - Badorigin: contract is always signed -// - Lookup: is a valid AccountId due to the contract -// - Many errors can occur from calling a dispatchable. All the DispatchErrors are handled by the -// pop api but not all the possible errors for each dipatchable are tested. How should I approach -// this? -#![cfg(test)] - use super::*; - -use pop_api::{ - error::{ArithmeticError::*, Error::*, TokenError::*}, - v0::assets::fungibles::FungiblesError::*, +use pop_api::error::{ + ArithmeticError::*, + Error::{self, *}, + TokenError::*, }; const ASSET_ID: AssetId = 1; @@ -196,11 +188,8 @@ fn total_supply_works() { fn balance_of_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate( - "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", - INIT_VALUE, - vec![], - ); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); // No tokens in circulation. assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr.clone(), ASSET_ID, BOB)); @@ -216,11 +205,8 @@ fn balance_of_works() { fn allowance_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate( - "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", - INIT_VALUE, - vec![], - ); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); // No tokens in circulation. assert_eq!( @@ -242,11 +228,8 @@ fn allowance_works() { fn asset_exists_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate( - "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", - INIT_VALUE, - vec![], - ); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); // No tokens in circulation. assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr.clone(), ASSET_ID)); @@ -264,16 +247,14 @@ fn create_works() { let _ = env_logger::try_init(); let new_asset = 2; // Instantiate a contract without balance (relay token). - let addr = - instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); + let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); // No balance to pay for fees. assert_eq!( decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), Module { index: 10, error: 2 }, ); // Instantiate a contract without balance (relay token). - let addr = - instantiate("../../pop-api/examples/fungibles/target/ink/fungibles.wasm", 100, vec![2]); + let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 100, vec![2]); // TODO: make sure it has enough for the fees but not for the deposit. // No balance to pay fe deposit. assert_eq!( @@ -281,11 +262,8 @@ fn create_works() { Module { index: 10, error: 2 }, ); // Instantiate a contract with balance. - let addr = instantiate( - "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", - INIT_VALUE, - vec![1], - ); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); create_asset(ALICE, ASSET_ID, 1); // Asset ID is already taken. assert_eq!( @@ -307,11 +285,8 @@ fn create_works() { fn set_metadata_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate( - "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", - INIT_VALUE, - vec![], - ); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); create_asset(addr.clone(), ASSET_ID, 1); let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); @@ -324,11 +299,8 @@ fn set_metadata_works() { fn transfer_from_mint_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate( - "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", - INIT_VALUE, - vec![], - ); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); let amount: Balance = 100 * UNIT; // Asset does not exist. @@ -387,11 +359,8 @@ fn transfer_from_mint_works() { fn transfer_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate( - "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", - INIT_VALUE, - vec![], - ); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); let amount: Balance = 100 * UNIT; // Asset does not exist. diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 3e9ead7f..c516adff 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -21,8 +21,7 @@ pub mod v0; type AccountId = AccountId32; // TODO: do the same as the AccountId above and check expanded macro code. -// type Balance = ::Balance; -type Balance = u128; +type Balance = ::Balance; #[cfg(any(feature = "nfts", feature = "cross-chain"))] type BlockNumber = ::BlockNumber; diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index d67d30bd..778387cb 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -298,18 +298,18 @@ pub(crate) fn block(id: AssetId, who: impl Into>) -> /// - pub(crate) fn total_supply(id: AssetId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id))).into() + state::read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id))) } pub(crate) fn balance_of(id: AssetId, owner: AccountId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner))).into() + state::read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner))) } pub(crate) fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender))).into() + state::read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender))) } pub(crate) fn asset_exists(id: AssetId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))).into() + state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))) } // Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 6ba3fea7..cb19b0ab 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" [dependencies] bounded-collections = { version = "0.1", default-features = false } -scale = { package = "parity-scale-codec", version = "3.6.9", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-decode = { version = "0.10.0", default-features = false, features = ["derive"], optional = true } scale-encode = { version = "0.5.0", default-features = false, features = ["derive"], optional = true } -scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +scale-info = { version = "2.10", default-features = false, features = ["derive"], optional = true } [features] default = ["std"] diff --git a/primitives/src/storage_keys.rs b/primitives/src/storage_keys.rs index 4be95986..5fc7cdb3 100644 --- a/primitives/src/storage_keys.rs +++ b/primitives/src/storage_keys.rs @@ -4,12 +4,12 @@ use super::*; #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum RuntimeStateKeys { + #[cfg(feature = "assets")] + Assets(AssetsKeys), #[cfg(feature = "nfts")] Nfts(NftsKeys), #[cfg(feature = "cross-chain")] ParachainSystem(ParachainSystemKeys), - #[cfg(feature = "assets")] - Assets(AssetsKeys), } #[cfg(feature = "cross-chain")] diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index b72bf4f7..5f52b855 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -91,7 +91,6 @@ parachain-info.workspace = true env_logger = "0.11.2" hex = "0.4.3" enumflags2 = "0.7.9" -pop-api = { path = "../../pop-api", features = ["assets", "cross-chain", "nfts"] } [features] default = ["std"] @@ -139,7 +138,6 @@ std = [ "polkadot-parachain-primitives/std", "polkadot-runtime-common/std", "pop-primitives/std", - "pop-api/std", "scale-info/std", "sp-api/std", "sp-io/std", diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions.rs index 9db31e83..904d18ce 100644 --- a/runtime/devnet/src/extensions.rs +++ b/runtime/devnet/src/extensions.rs @@ -390,6 +390,186 @@ where dispatch_call::(&mut env, call, origin, LOG_PREFIX) } +#[cfg(test)] +mod tests { + use super::*; + use crate::{Assets, Runtime, System}; + use sp_runtime::BuildStorage; + + fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::::default() + .build_storage() + .expect("Frame system builds valid default genesis config"); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } + + #[test] + fn encoding_decoding_dispatch_error() { + use codec::{Decode, Encode}; + use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; + + new_test_ext().execute_with(|| { + let error = DispatchError::Module(ModuleError { + index: 255, + error: [2, 0, 0, 0], + message: Some("error message"), + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); + assert_eq!( + decoded, + // `message` is skipped for encoding. + DispatchError::Module(ModuleError { + index: 255, + error: [2, 0, 0, 0], + message: None + }) + ); + println!("Encoded Module Error: {:?}", encoded); + + // Example pallet assets Error into ModuleError. + let index = + <::PalletInfo as frame_support::traits::PalletInfo>::index::< + Assets, + >() + .expect("Every active module has an index in the runtime; qed") as u8; + + let mut error = + pallet_assets::Error::NotFrozen::.encode(); + error.resize(MAX_MODULE_ERROR_ENCODED_SIZE, 0); + let error = DispatchError::Module(ModuleError { + index, + error: TryInto::try_into(error).expect("should work"), + message: None, + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 52, 18, 0, 0, 0]); + assert_eq!( + decoded, + DispatchError::Module(ModuleError { + index: 52, + error: [18, 0, 0, 0], + message: None + }) + ); + println!("Encoded Module Error: {:?}", encoded); + + // Example DispatchError::Token + let error = DispatchError::Token(TokenError::UnknownAsset); + let encoded = error.encode(); + assert_eq!(encoded, vec![7, 4]); + println!("Encoded Token Error: {:?}", encoded); + + // Example DispatchError::Arithmetic + let error = DispatchError::Arithmetic(ArithmeticError::Overflow); + let encoded = error.encode(); + assert_eq!(encoded, vec![8, 1]); + println!("Encoded Arithmetic Error: {:?}", encoded); + }); + } + + #[test] + fn encoding_of_enum() { + use codec::{Decode, Encode}; + + // Comprehensive enum with all different type of variants. + #[derive(Debug, PartialEq, Encode, Decode)] + enum ComprehensiveEnum { + SimpleVariant, + DataVariant(u8), + NamedFields { w: u8 }, + NestedEnum(InnerEnum), + OptionVariant(Option), + VecVariant(Vec), + TupleVariant(u8, u8), + NestedStructVariant(NestedStruct), + NestedEnumStructVariant(NestedEnumStruct), + } + + #[derive(Debug, PartialEq, Encode, Decode)] + enum InnerEnum { + A, + B { inner_data: u8 }, + C(u8), + } + + #[derive(Debug, PartialEq, Encode, Decode)] + struct NestedStruct { + x: u8, + y: u8, + } + + #[derive(Debug, PartialEq, Encode, Decode)] + struct NestedEnumStruct { + inner_enum: InnerEnum, + } + + // Creating each possible variant for an enum. + let enum_simple = ComprehensiveEnum::SimpleVariant; + let enum_data = ComprehensiveEnum::DataVariant(42); + let enum_named = ComprehensiveEnum::NamedFields { w: 42 }; + let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 }); + let enum_option = ComprehensiveEnum::OptionVariant(Some(42)); + let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]); + let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42); + let enum_nested_struct = + ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 }); + let enum_nested_enum_struct = + ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { + inner_enum: InnerEnum::C(42), + }); + + // Encode and print each variant individually to see their encoded values. + println!("{:?} -> {:?}", enum_simple, enum_simple.encode()); + println!("{:?} -> {:?}", enum_data, enum_data.encode()); + println!("{:?} -> {:?}", enum_named, enum_named.encode()); + println!("{:?} -> {:?}", enum_nested, enum_nested.encode()); + println!("{:?} -> {:?}", enum_option, enum_option.encode()); + println!("{:?} -> {:?}", enum_vec, enum_vec.encode()); + println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode()); + println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode()); + println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); + } + + #[test] + fn dispatch_error_to_status_code() { + // Create all the different `DispatchError` variants with its respective `PopApiError`. + let test_cases = vec![ + (DispatchError::Other("hallo"), [0, 0, 0, 0]), + (DispatchError::CannotLookup, [1, 0, 0, 0]), + (DispatchError::BadOrigin, [2, 0, 0, 0]), + ( + DispatchError::Module(sp_runtime::ModuleError { + index: 1, + error: [2, 0, 0, 0], + message: Some("hallo"), + }), + [3, 1, 2, 0], + ), + (DispatchError::ConsumerRemaining, [4, 0, 0, 0]), + (DispatchError::NoProviders, [5, 0, 0, 0]), + (DispatchError::TooManyConsumers, [6, 0, 0, 0]), + (DispatchError::Token(sp_runtime::TokenError::BelowMinimum), [7, 2, 0, 0]), + (DispatchError::Arithmetic(sp_runtime::ArithmeticError::Overflow), [8, 1, 0, 0]), + ( + DispatchError::Transactional(sp_runtime::TransactionalError::LimitReached), + [9, 0, 0, 0], + ), + (DispatchError::Exhausted, [10, 0, 0, 0]), + (DispatchError::Corruption, [11, 0, 0, 0]), + (DispatchError::Unavailable, [12, 0, 0, 0]), + (DispatchError::RootNotAllowed, [13, 0, 0, 0]), + ]; + for (error, encoded_error) in test_cases { + let status_code = crate::extensions::convert_to_status_code(error); + assert_eq!(status_code, u32::decode(&mut &encoded_error[..]).unwrap()); + } + } +} // use enumflags2::BitFlags; // use pallet_nfts::{CollectionConfig, CollectionSetting, CollectionSettings, MintSettings}; // use parachains_common::CollectionId; diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index b03bdac6..9ab64043 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -10,8 +10,6 @@ mod extensions; mod weights; // Public due to integration tests crate. pub mod config; -#[cfg(test)] -mod tests; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; diff --git a/runtime/devnet/src/tests/mod.rs b/runtime/devnet/src/tests/mod.rs deleted file mode 100644 index 828aa06b..00000000 --- a/runtime/devnet/src/tests/mod.rs +++ /dev/null @@ -1,267 +0,0 @@ -#![cfg(test)] - -use codec::{Decode, Encode}; -use frame_support::traits::fungibles::{approvals::Inspect as ApprovalInspect, Inspect}; -use frame_system::Config; -use pallet_contracts::{Code, CollectEvents, Determinism, ExecReturnValue}; -use sp_runtime::{traits::Hash, AccountId32, BuildStorage, DispatchError}; - -use crate::{Assets, Contracts, Runtime, RuntimeOrigin, System, Weight, UNIT}; - -mod local_fungibles; - -type Balance = u128; -type AssetId = u32; -const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; - -const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); -const BOB: AccountId32 = AccountId32::new([2_u8; 32]); -// FERDIE has no initial balance. -const FERDIE: AccountId32 = AccountId32::new([3_u8; 32]); -const INIT_AMOUNT: Balance = 100_000_000 * UNIT; -const INIT_VALUE: Balance = 100 * UNIT; -const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); - -fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default() - .build_storage() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT)], - } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext -} - -fn load_wasm_module(path: &str) -> std::io::Result<(Vec, ::Output)> -where - T: frame_system::Config, -{ - let wasm_binary = std::fs::read(path)?; - let code_hash = T::Hashing::hash(&wasm_binary); - Ok((wasm_binary, code_hash)) -} - -fn function_selector(name: &str) -> Vec { - let hash = sp_io::hashing::blake2_256(name.as_bytes()); - [hash[0..4].to_vec()].concat() -} - -fn do_bare_call( - addr: AccountId32, - input: Vec, - value: u128, -) -> Result { - let result = Contracts::bare_call( - ALICE, - addr.into(), - value.into(), - GAS_LIMIT, - None, - input, - DEBUG_OUTPUT, - CollectEvents::Skip, - Determinism::Enforced, - ); - log::debug!("Contract debug buffer - {:?}", String::from_utf8(result.debug_message.clone())); - log::debug!("result: {:?}", result); - result.result -} - -// Deploy, instantiate and return contract address. -fn instantiate(contract: &str, init_value: u128, salt: Vec) -> AccountId32 { - let (wasm_binary, _) = - load_wasm_module::(contract).expect("could not read .wasm file"); - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - salt, - DEBUG_OUTPUT, - CollectEvents::Skip, - ) - .result - .unwrap(); - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - result.account_id -} - -mod encoding { - use super::*; - use crate::config::assets::TrustBackedAssetsInstance; - use crate::Runtime; - use sp_runtime::DispatchError; - - #[test] - fn encoding_decoding_dispatch_error() { - use codec::{Decode, Encode}; - use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; - - new_test_ext().execute_with(|| { - let error = DispatchError::Module(ModuleError { - index: 255, - error: [2, 0, 0, 0], - message: Some("error message"), - }); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); - assert_eq!( - decoded, - // `message` is skipped for encoding. - DispatchError::Module(ModuleError { - index: 255, - error: [2, 0, 0, 0], - message: None - }) - ); - println!("Encoded Module Error: {:?}", encoded); - - // Example pallet assets Error into ModuleError. - let index = - <::PalletInfo as frame_support::traits::PalletInfo>::index::< - Assets, - >() - .expect("Every active module has an index in the runtime; qed") as u8; - - let mut error = - pallet_assets::Error::NotFrozen::.encode(); - error.resize(sp_runtime::MAX_MODULE_ERROR_ENCODED_SIZE, 0); - let error = DispatchError::Module(ModuleError { - index, - error: TryInto::try_into(error).expect("should work"), - message: None, - }); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 52, 18, 0, 0, 0]); - assert_eq!( - decoded, - DispatchError::Module(ModuleError { - index: 52, - error: [18, 0, 0, 0], - message: None - }) - ); - println!("Encoded Module Error: {:?}", encoded); - - // Example DispatchError::Token - let error = DispatchError::Token(TokenError::UnknownAsset); - let encoded = error.encode(); - assert_eq!(encoded, vec![7, 4]); - println!("Encoded Token Error: {:?}", encoded); - - // Example DispatchError::Arithmetic - let error = DispatchError::Arithmetic(ArithmeticError::Overflow); - let encoded = error.encode(); - assert_eq!(encoded, vec![8, 1]); - println!("Encoded Arithmetic Error: {:?}", encoded); - }); - } - - #[test] - fn encoding_of_enum() { - use codec::{Decode, Encode}; - - // Comprehensive enum with all different type of variants. - #[derive(Debug, PartialEq, Encode, Decode)] - enum ComprehensiveEnum { - SimpleVariant, - DataVariant(u8), - NamedFields { w: u8 }, - NestedEnum(InnerEnum), - OptionVariant(Option), - VecVariant(Vec), - TupleVariant(u8, u8), - NestedStructVariant(NestedStruct), - NestedEnumStructVariant(NestedEnumStruct), - } - - #[derive(Debug, PartialEq, Encode, Decode)] - enum InnerEnum { - A, - B { inner_data: u8 }, - C(u8), - } - - #[derive(Debug, PartialEq, Encode, Decode)] - struct NestedStruct { - x: u8, - y: u8, - } - - #[derive(Debug, PartialEq, Encode, Decode)] - struct NestedEnumStruct { - inner_enum: InnerEnum, - } - - // Creating each possible variant for an enum. - let enum_simple = ComprehensiveEnum::SimpleVariant; - let enum_data = ComprehensiveEnum::DataVariant(42); - let enum_named = ComprehensiveEnum::NamedFields { w: 42 }; - let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 }); - let enum_option = ComprehensiveEnum::OptionVariant(Some(42)); - let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]); - let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42); - let enum_nested_struct = - ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 }); - let enum_nested_enum_struct = - ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { - inner_enum: InnerEnum::C(42), - }); - - // Encode and print each variant individually to see their encoded values. - println!("{:?} -> {:?}", enum_simple, enum_simple.encode()); - println!("{:?} -> {:?}", enum_data, enum_data.encode()); - println!("{:?} -> {:?}", enum_named, enum_named.encode()); - println!("{:?} -> {:?}", enum_nested, enum_nested.encode()); - println!("{:?} -> {:?}", enum_option, enum_option.encode()); - println!("{:?} -> {:?}", enum_vec, enum_vec.encode()); - println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode()); - println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode()); - println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); - } - - #[test] - fn dispatch_error_to_status_code() { - // Create all the different `DispatchError` variants with its respective `PopApiError`. - let test_cases = vec![ - (DispatchError::Other("hallo"), [0, 0, 0, 0]), - (DispatchError::CannotLookup, [1, 0, 0, 0]), - (DispatchError::BadOrigin, [2, 0, 0, 0]), - ( - DispatchError::Module(sp_runtime::ModuleError { - index: 1, - error: [2, 0, 0, 0], - message: Some("hallo"), - }), - [3, 1, 2, 0], - ), - (DispatchError::ConsumerRemaining, [4, 0, 0, 0]), - (DispatchError::NoProviders, [5, 0, 0, 0]), - (DispatchError::TooManyConsumers, [6, 0, 0, 0]), - (DispatchError::Token(sp_runtime::TokenError::BelowMinimum), [7, 2, 0, 0]), - (DispatchError::Arithmetic(sp_runtime::ArithmeticError::Overflow), [8, 1, 0, 0]), - ( - DispatchError::Transactional(sp_runtime::TransactionalError::LimitReached), - [9, 0, 0, 0], - ), - (DispatchError::Exhausted, [10, 0, 0, 0]), - (DispatchError::Corruption, [11, 0, 0, 0]), - (DispatchError::Unavailable, [12, 0, 0, 0]), - (DispatchError::RootNotAllowed, [13, 0, 0, 0]), - ]; - for (error, encoded_error) in test_cases { - let status_code = crate::extensions::convert_to_status_code(error); - assert_eq!(status_code, u32::decode(&mut &encoded_error[..]).unwrap()); - } - } -} From c1616a3611f73f0185f822339c452549c63b2926 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Wed, 26 Jun 2024 15:41:18 +0200 Subject: [PATCH 013/161] refactor: naming pallet error --- pop-api/Cargo.toml | 6 +- pop-api/src/lib.rs | 2 +- pop-api/src/v0/cross_chain/mod.rs | 8 +- pop-api/src/v0/nfts.rs | 308 +++++++++++++++--------------- primitives/src/storage_keys.rs | 11 +- 5 files changed, 170 insertions(+), 165 deletions(-) diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 2dd4519c..8454c1fa 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -5,12 +5,15 @@ license = "GPL-3.0-only" version = "0.0.0" edition = "2021" +[workspace] +exclude = [ + "integration-tests", +] [dependencies] enumflags2 = { version = "0.7.7" } ink = { version = "5.0.0", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -sp-io = { version = "31.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } sp-runtime = { version = "32.0.0", default-features = false } pop-primitives = { path = "../primitives", features = ["devnet"], default-features = false } @@ -28,7 +31,6 @@ std = [ "pop-primitives/std", "scale/std", "scale-info/std", - "sp-io/std", "sp-runtime/std", ] assets = ["pop-primitives/assets"] diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index c516adff..04d08bce 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] use ink::{prelude::vec::Vec, ChainExtensionInstance}; -pub use sp_runtime::{BoundedVec, MultiAddress, MultiSignature}; +pub use sp_runtime::{MultiAddress, MultiSignature}; use crate::error::{Error, StatusCode}; use primitives::{storage_keys::*, AccountId as AccountId32}; diff --git a/pop-api/src/v0/cross_chain/mod.rs b/pop-api/src/v0/cross_chain/mod.rs index 5a0dda6c..ad58e0e8 100644 --- a/pop-api/src/v0/cross_chain/mod.rs +++ b/pop-api/src/v0/cross_chain/mod.rs @@ -10,7 +10,7 @@ pub fn relay_chain_block_number() -> Result { #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum Error { +pub enum CrossChainError { /// The desired destination was unreachable, generally because there is a no way of routing /// to it. Unreachable, @@ -66,11 +66,11 @@ pub enum Error { LocalExecutionIncomplete, } -impl TryFrom for Error { - type Error = Error; +impl TryFrom for CrossChainError { + type Error = crate::error::Error; fn try_from(status_code: u32) -> core::result::Result { - use Error::*; + use CrossChainError::*; match status_code { 0 => Ok(Unreachable), 1 => Ok(SendFailure), diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs index 29219c66..32539576 100644 --- a/pop-api/src/v0/nfts.rs +++ b/pop-api/src/v0/nfts.rs @@ -5,10 +5,10 @@ use crate::{ dispatch, primitives::{ nfts::{ApprovalsLimit, CollectionId, ItemId, KeyLimit}, - BoundedBTreeMap, + BoundedBTreeMap, BoundedVec, }, - state, AccountId, Balance, BlockNumber, BoundedVec, MultiAddress, NftsKeys, RuntimeCall, - RuntimeStateKeys, StatusCode, + state, AccountId, Balance, BlockNumber, MultiAddress, NftsKeys, RuntimeCall, RuntimeStateKeys, + StatusCode, }; pub use types::*; @@ -521,157 +521,157 @@ pub(crate) enum NftCalls { receive_item: ItemId, }, } -// -// #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] -// #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -// pub enum Error { -// /// The signing account has no permission to do the operation. -// NoPermission, -// /// The given item ID is unknown. -// UnknownCollection, -// /// The item ID has already been used for an item. -// AlreadyExists, -// /// The approval had a deadline that expired, so the approval isn't valid anymore. -// ApprovalExpired, -// /// The owner turned out to be different to what was expected. -// WrongOwner, -// /// The witness data given does not match the current state of the chain. -// BadWitness, -// /// Collection ID is already taken. -// CollectionIdInUse, -// /// Items within that collection are non-transferable. -// ItemsNonTransferable, -// /// The provided account is not a delegate. -// NotDelegate, -// /// The delegate turned out to be different to what was expected. -// WrongDelegate, -// /// No approval exists that would allow the transfer. -// Unapproved, -// /// The named owner has not signed ownership acceptance of the collection. -// Unaccepted, -// /// The item is locked (non-transferable). -// ItemLocked, -// /// Item's attributes are locked. -// LockedItemAttributes, -// /// Collection's attributes are locked. -// LockedCollectionAttributes, -// /// Item's metadata is locked. -// LockedItemMetadata, -// /// Collection's metadata is locked. -// LockedCollectionMetadata, -// /// All items have been minted. -// MaxSupplyReached, -// /// The max supply is locked and can't be changed. -// MaxSupplyLocked, -// /// The provided max supply is less than the number of items a collection already has. -// MaxSupplyTooSmall, -// /// The given item ID is unknown. -// UnknownItem, -// /// Swap doesn't exist. -// UnknownSwap, -// /// The given item has no metadata set. -// MetadataNotFound, -// /// The provided attribute can't be found. -// AttributeNotFound, -// /// Item is not for sale. -// NotForSale, -// /// The provided bid is too low. -// BidTooLow, -// /// The item has reached its approval limit. -// ReachedApprovalLimit, -// /// The deadline has already expired. -// DeadlineExpired, -// /// The duration provided should be less than or equal to `MaxDeadlineDuration`. -// WrongDuration, -// /// The method is disabled by system settings. -// MethodDisabled, -// /// The provided setting can't be set. -// WrongSetting, -// /// Item's config already exists and should be equal to the provided one. -// InconsistentItemConfig, -// /// Config for a collection or an item can't be found. -// NoConfig, -// /// Some roles were not cleared. -// RolesNotCleared, -// /// Mint has not started yet. -// MintNotStarted, -// /// Mint has already ended. -// MintEnded, -// /// The provided Item was already used for claiming. -// AlreadyClaimed, -// /// The provided data is incorrect. -// IncorrectData, -// /// The extrinsic was sent by the wrong origin. -// WrongOrigin, -// /// The provided signature is incorrect. -// WrongSignature, -// /// The provided metadata might be too long. -// IncorrectMetadata, -// /// Can't set more attributes per one call. -// MaxAttributesLimitReached, -// /// The provided namespace isn't supported in this call. -// WrongNamespace, -// /// Can't delete non-empty collections. -// CollectionNotEmpty, -// /// The witness data should be provided. -// WitnessRequired, -// } -// -// impl TryFrom for Error { -// type Error = Error; -// -// fn try_from(status_code: u32) -> core::result::Result { -// use Error::*; -// match status_code { -// 0 => Ok(NoPermission), -// 1 => Ok(UnknownCollection), -// 2 => Ok(AlreadyExists), -// 3 => Ok(ApprovalExpired), -// 4 => Ok(WrongOwner), -// 5 => Ok(BadWitness), -// 6 => Ok(CollectionIdInUse), -// 7 => Ok(ItemsNonTransferable), -// 8 => Ok(NotDelegate), -// 9 => Ok(WrongDelegate), -// 10 => Ok(Unapproved), -// 11 => Ok(Unaccepted), -// 12 => Ok(ItemLocked), -// 13 => Ok(LockedItemAttributes), -// 14 => Ok(LockedCollectionAttributes), -// 15 => Ok(LockedItemMetadata), -// 16 => Ok(LockedCollectionMetadata), -// 17 => Ok(MaxSupplyReached), -// 18 => Ok(MaxSupplyLocked), -// 19 => Ok(MaxSupplyTooSmall), -// 20 => Ok(UnknownItem), -// 21 => Ok(UnknownSwap), -// 22 => Ok(MetadataNotFound), -// 23 => Ok(AttributeNotFound), -// 24 => Ok(NotForSale), -// 25 => Ok(BidTooLow), -// 26 => Ok(ReachedApprovalLimit), -// 27 => Ok(DeadlineExpired), -// 28 => Ok(WrongDuration), -// 29 => Ok(MethodDisabled), -// 30 => Ok(WrongSetting), -// 31 => Ok(InconsistentItemConfig), -// 32 => Ok(NoConfig), -// 33 => Ok(RolesNotCleared), -// 34 => Ok(MintNotStarted), -// 35 => Ok(MintEnded), -// 36 => Ok(AlreadyClaimed), -// 37 => Ok(IncorrectData), -// 38 => Ok(WrongOrigin), -// 39 => Ok(WrongSignature), -// 40 => Ok(IncorrectMetadata), -// 41 => Ok(MaxAttributesLimitReached), -// 42 => Ok(WrongNamespace), -// 43 => Ok(CollectionNotEmpty), -// 44 => Ok(WitnessRequired), -// _ => todo!(), -// } -// } -// } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum NftsError { + /// The signing account has no permission to do the operation. + NoPermission, + /// The given item ID is unknown. + UnknownCollection, + /// The item ID has already been used for an item. + AlreadyExists, + /// The approval had a deadline that expired, so the approval isn't valid anymore. + ApprovalExpired, + /// The owner turned out to be different to what was expected. + WrongOwner, + /// The witness data given does not match the current state of the chain. + BadWitness, + /// Collection ID is already taken. + CollectionIdInUse, + /// Items within that collection are non-transferable. + ItemsNonTransferable, + /// The provided account is not a delegate. + NotDelegate, + /// The delegate turned out to be different to what was expected. + WrongDelegate, + /// No approval exists that would allow the transfer. + Unapproved, + /// The named owner has not signed ownership acceptance of the collection. + Unaccepted, + /// The item is locked (non-transferable). + ItemLocked, + /// Item's attributes are locked. + LockedItemAttributes, + /// Collection's attributes are locked. + LockedCollectionAttributes, + /// Item's metadata is locked. + LockedItemMetadata, + /// Collection's metadata is locked. + LockedCollectionMetadata, + /// All items have been minted. + MaxSupplyReached, + /// The max supply is locked and can't be changed. + MaxSupplyLocked, + /// The provided max supply is less than the number of items a collection already has. + MaxSupplyTooSmall, + /// The given item ID is unknown. + UnknownItem, + /// Swap doesn't exist. + UnknownSwap, + /// The given item has no metadata set. + MetadataNotFound, + /// The provided attribute can't be found. + AttributeNotFound, + /// Item is not for sale. + NotForSale, + /// The provided bid is too low. + BidTooLow, + /// The item has reached its approval limit. + ReachedApprovalLimit, + /// The deadline has already expired. + DeadlineExpired, + /// The duration provided should be less than or equal to `MaxDeadlineDuration`. + WrongDuration, + /// The method is disabled by system settings. + MethodDisabled, + /// The provided setting can't be set. + WrongSetting, + /// Item's config already exists and should be equal to the provided one. + InconsistentItemConfig, + /// Config for a collection or an item can't be found. + NoConfig, + /// Some roles were not cleared. + RolesNotCleared, + /// Mint has not started yet. + MintNotStarted, + /// Mint has already ended. + MintEnded, + /// The provided Item was already used for claiming. + AlreadyClaimed, + /// The provided data is incorrect. + IncorrectData, + /// The extrinsic was sent by the wrong origin. + WrongOrigin, + /// The provided signature is incorrect. + WrongSignature, + /// The provided metadata might be too long. + IncorrectMetadata, + /// Can't set more attributes per one call. + MaxAttributesLimitReached, + /// The provided namespace isn't supported in this call. + WrongNamespace, + /// Can't delete non-empty collections. + CollectionNotEmpty, + /// The witness data should be provided. + WitnessRequired, +} + +impl TryFrom for NftsError { + type Error = crate::error::Error; + + fn try_from(status_code: u32) -> core::result::Result { + use NftsError::*; + match status_code { + 0 => Ok(NoPermission), + 1 => Ok(UnknownCollection), + 2 => Ok(AlreadyExists), + 3 => Ok(ApprovalExpired), + 4 => Ok(WrongOwner), + 5 => Ok(BadWitness), + 6 => Ok(CollectionIdInUse), + 7 => Ok(ItemsNonTransferable), + 8 => Ok(NotDelegate), + 9 => Ok(WrongDelegate), + 10 => Ok(Unapproved), + 11 => Ok(Unaccepted), + 12 => Ok(ItemLocked), + 13 => Ok(LockedItemAttributes), + 14 => Ok(LockedCollectionAttributes), + 15 => Ok(LockedItemMetadata), + 16 => Ok(LockedCollectionMetadata), + 17 => Ok(MaxSupplyReached), + 18 => Ok(MaxSupplyLocked), + 19 => Ok(MaxSupplyTooSmall), + 20 => Ok(UnknownItem), + 21 => Ok(UnknownSwap), + 22 => Ok(MetadataNotFound), + 23 => Ok(AttributeNotFound), + 24 => Ok(NotForSale), + 25 => Ok(BidTooLow), + 26 => Ok(ReachedApprovalLimit), + 27 => Ok(DeadlineExpired), + 28 => Ok(WrongDuration), + 29 => Ok(MethodDisabled), + 30 => Ok(WrongSetting), + 31 => Ok(InconsistentItemConfig), + 32 => Ok(NoConfig), + 33 => Ok(RolesNotCleared), + 34 => Ok(MintNotStarted), + 35 => Ok(MintEnded), + 36 => Ok(AlreadyClaimed), + 37 => Ok(IncorrectData), + 38 => Ok(WrongOrigin), + 39 => Ok(WrongSignature), + 40 => Ok(IncorrectMetadata), + 41 => Ok(MaxAttributesLimitReached), + 42 => Ok(WrongNamespace), + 43 => Ok(CollectionNotEmpty), + 44 => Ok(WitnessRequired), + _ => todo!(), + } + } +} // Local implementations of pallet-nfts types mod types { diff --git a/primitives/src/storage_keys.rs b/primitives/src/storage_keys.rs index 5fc7cdb3..748d0662 100644 --- a/primitives/src/storage_keys.rs +++ b/primitives/src/storage_keys.rs @@ -4,12 +4,15 @@ use super::*; #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum RuntimeStateKeys { - #[cfg(feature = "assets")] - Assets(AssetsKeys), - #[cfg(feature = "nfts")] - Nfts(NftsKeys), #[cfg(feature = "cross-chain")] + #[codec(index = 1)] ParachainSystem(ParachainSystemKeys), + #[cfg(feature = "nfts")] + #[codec(index = 50)] + Nfts(NftsKeys), + #[cfg(feature = "assets")] + #[codec(index = 52)] + Assets(AssetsKeys), } #[cfg(feature = "cross-chain")] From 13e947e74f82430bc50865ca6a44ec234620728e Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Wed, 26 Jun 2024 17:10:42 +0200 Subject: [PATCH 014/161] refactor: optimising pop api and additional logic + test --- pop-api/Cargo.toml | 6 +- pop-api/examples/fungibles/lib.rs | 161 +++++-- pop-api/src/error.rs | 166 ++----- pop-api/src/lib.rs | 6 +- pop-api/src/primitives.rs | 1 + pop-api/src/v0/assets/fungibles.rs | 314 +++++++------ pop-api/src/v0/assets/mod.rs | 718 +++++++++++++++-------------- pop-api/src/v0/state.rs | 5 +- primitives/src/lib.rs | 2 +- primitives/src/storage_keys.rs | 7 +- 10 files changed, 710 insertions(+), 676 deletions(-) diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 8454c1fa..a88d8892 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -5,15 +5,12 @@ license = "GPL-3.0-only" version = "0.0.0" edition = "2021" -[workspace] -exclude = [ - "integration-tests", -] [dependencies] enumflags2 = { version = "0.7.7" } ink = { version = "5.0.0", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +sp-io = { version = "31.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } sp-runtime = { version = "32.0.0", default-features = false } pop-primitives = { path = "../primitives", features = ["devnet"], default-features = false } @@ -31,6 +28,7 @@ std = [ "pop-primitives/std", "scale/std", "scale-info/std", +"sp-io/std", "sp-runtime/std", ] assets = ["pop-primitives/assets"] diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 35719ac6..bd51d760 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -7,12 +7,12 @@ /// use ink::prelude::vec::Vec; use pop_api::{ - assets::fungibles::{self as api, FungiblesError}, - error::{Error, StatusCode}, + assets::fungibles::{self as api}, + error::StatusCode, primitives::{AccountId as AccountId32, AssetId}, }; -pub type Result = core::result::Result; +pub type Result = core::result::Result; #[ink::contract(env = pop_api::Environment)] mod fungibles { @@ -41,12 +41,14 @@ mod fungibles { #[ink(message)] pub fn total_supply(&self, id: AssetId) -> Result { - api::total_supply(id).map_err(|e| e.into()) + // api::total_supply(id).map_err(|e| e.into()) + api::total_supply(id) } #[ink(message)] pub fn balance_of(&self, id: AssetId, owner: AccountId32) -> Result { - api::balance_of(id, owner).map_err(|e| e.into()) + // api::balance_of(id, owner).map_err(|e| e.into()) + api::balance_of(id, owner) } #[ink(message)] @@ -56,7 +58,8 @@ mod fungibles { owner: AccountId32, spender: AccountId32, ) -> Result { - api::allowance(id, owner, spender).map_err(|e| e.into()) + // api::allowance(id, owner, spender).map_err(|e| e.into()) + api::allowance(id, owner, spender) } #[ink(message)] @@ -70,15 +73,16 @@ mod fungibles { let result = api::transfer(id, to, value); ink::env::debug_println!("Result: {:?}", result); - result.map_err(|e| e.into()) + // result.map_err(|e| e.into()) + result } #[ink(message)] pub fn transfer_from( &self, id: AssetId, - from: Option, - to: Option, + from: AccountId32, + to: AccountId32, value: Balance, // In the standard a `[u8]`, but the size needs to be known at compile time. data: Vec, @@ -93,60 +97,137 @@ mod fungibles { let result = api::transfer_from(id, from, to, value, &data); ink::env::debug_println!("Result: {:?}", result); - result.map_err(|e| e.into()) + // result.map_err(|e| e.into()) + result } - /// 2. PSP-22 Metadata Interface: - /// - token_name - /// - token_symbol - /// - token_decimals + #[ink(message)] + pub fn approve(&self, id: AssetId, spender: AccountId32, value: Balance) -> Result<()> { + ink::env::debug_println!( + "PopApiFungiblesExample::approve: id: {:?}, spender {:?}, value: {:?}", + id, + spender, + value, + ); - /// 3. Asset Management: - /// - create - /// - start_destroy - /// - destroy_accounts - /// - destroy_approvals - /// - finish_destroy - /// - set_metadata - /// - clear_metadata + let result = api::approve(id, spender, value); + ink::env::debug_println!("Result: {:?}", result); + // result.map_err(|e| e.into()) + result + } #[ink(message)] - pub fn create(&self, id: AssetId, admin: AccountId32, min_balance: Balance) -> Result<()> { + pub fn increase_allowance( + &self, + id: AssetId, + spender: AccountId32, + value: Balance, + ) -> Result<()> { ink::env::debug_println!( - "PopApiFungiblesExample::create: id: {:?} admin: {:?} min_balance: {:?}", + "PopApiFungiblesExample::increase_allowance: id: {:?}, spender {:?}, value: {:?}", id, - admin, - min_balance, + spender, + value, ); - let result = api::create(id, admin, min_balance); + + let result = api::increase_allowance(id, spender, value); ink::env::debug_println!("Result: {:?}", result); - result.map_err(|e| e.into()) + // result.map_err(|e| e.into()) + result } #[ink(message)] - pub fn set_metadata( + pub fn decrease_allowance( &self, id: AssetId, - name: Vec, - symbol: Vec, - decimals: u8, + spender: AccountId32, + value: Balance, ) -> Result<()> { ink::env::debug_println!( - "PopApiFungiblesExample::set_metadata: id: {:?} name: {:?} symbol: {:?}, decimals: {:?}", + "PopApiFungiblesExample::decrease_allowance: id: {:?}, spender {:?}, value: {:?}", id, - name, - symbol, - decimals, + spender, + value, ); - let result = api::set_metadata(id, name, symbol, decimals); + + let result = api::decrease_allowance(id, spender, value); ink::env::debug_println!("Result: {:?}", result); - result.map_err(|e| e.into()) + // result.map_err(|e| e.into()) + result + } + + /// 2. PSP-22 Metadata Interface: + /// - token_name + /// - token_symbol + /// - token_decimals + + #[ink(message)] + pub fn token_name(&self, id: AssetId) -> Result> { + // api::token_name(id).map_err(|e| e.into()) + api::token_name(id) } #[ink(message)] - pub fn asset_exists(&self, id: AssetId) -> Result { - api::asset_exists(id).map_err(|e| e.into()) + pub fn token_symbol(&self, id: AssetId) -> Result> { + // api::token_symbol(id).map_err(|e| e.into()) + api::token_symbol(id) } + + #[ink(message)] + pub fn token_decimals(&self, id: AssetId) -> Result { + // api::token_decimals(id).map_err(|e| e.into()) + api::token_decimals(id) + } + + // 3. Asset Management: + // - create + // - start_destroy + // - destroy_accounts + // - destroy_approvals + // - finish_destroy + // - set_metadata + // - clear_metadata + + // #[ink(message)] + // pub fn create(&self, id: AssetId, admin: AccountId32, min_balance: Balance) -> Result<()> { + // ink::env::debug_println!( + // "PopApiFungiblesExample::create: id: {:?} admin: {:?} min_balance: {:?}", + // id, + // admin, + // min_balance, + // ); + // let result = api::create(id, admin, min_balance); + // ink::env::debug_println!("Result: {:?}", result); + // // result.map_err(|e| e.into()) + // result + // } + + // #[ink(message)] + // pub fn set_metadata( + // &self, + // id: AssetId, + // name: Vec, + // symbol: Vec, + // decimals: u8, + // ) -> Result<()> { + // ink::env::debug_println!( + // "PopApiFungiblesExample::set_metadata: id: {:?} name: {:?} symbol: {:?}, decimals: {:?}", + // id, + // name, + // symbol, + // decimals, + // ); + // let result = api::set_metadata(id, name, symbol, decimals); + // ink::env::debug_println!("Result: {:?}", result); + // // result.map_err(|e| e.into()) + // result + // } + // + // #[ink(message)] + // pub fn asset_exists(&self, id: AssetId) -> Result { + // // api::asset_exists(id).map_err(|e| e.into()) + // api::asset_exists(id) + // } } #[cfg(test)] diff --git a/pop-api/src/error.rs b/pop-api/src/error.rs index b8a56f55..54681e6d 100644 --- a/pop-api/src/error.rs +++ b/pop-api/src/error.rs @@ -14,79 +14,16 @@ impl From for StatusCode { } impl FromStatusCode for StatusCode { fn from_status_code(status_code: u32) -> Result<(), Self> { - match status_code { - 0 => Ok(()), - _ => { - let mut encoded = status_code.to_le_bytes(); - convert_unknown_errors(&mut encoded); - Err(StatusCode::from(u32::from_le_bytes(encoded))) - }, + if status_code == 0 { + return Ok(()); } + Err(StatusCode(status_code)) } } impl From for StatusCode { fn from(_: scale::Error) -> Self { - DecodingFailed.into() - } -} - -// If an unknown variant of the `DispatchError` is detected the error needs to be converted -// into the encoded value of `Error::Other`. This conversion is performed by shifting the bytes one -// position forward (discarding the last byte as it is not used) and setting the first byte to the -// encoded value of `Other` (0u8). This ensures the error is correctly categorized as an `Other` -// variant which provides all the necessary information to debug which error occurred in the runtime. -// -// Byte layout explanation: -// - Byte 0: index of the variant within `Error` -// - Byte 1: -// - Must be zero for `UNIT_ERRORS`. -// - Represents the nested error in `SINGLE_NESTED_ERRORS`. -// - Represents the first level of nesting in `DOUBLE_NESTED_ERRORS`. -// - Byte 2: -// - Represents the second level of nesting in `DOUBLE_NESTED_ERRORS`. -// - Byte 3: -// - Unused or represents further nested information. -// -// This mechanism ensures backward compatibility by correctly categorizing any unknown errors -// into the `Other` variant, thus preventing issues caused by breaking changes. -fn convert_unknown_errors(encoded_error: &mut [u8; 4]) { - let all_errors = [ - UNIT_ERRORS.as_slice(), - SINGLE_NESTED_ERRORS.as_slice(), - DOUBLE_NESTED_ERRORS.as_slice(), - // `DecodingFailed`. - &[255u8], - ] - .concat(); - // Unknown errors, i.e. an encoded value where the first byte is non-zero (indicating a variant - // in `Error`) but unknown. - if !all_errors.contains(&encoded_error[0]) { - encoded_error[..].rotate_right(1); - encoded_error[0] = 0u8; - } - convert_unknown_nested_errors(encoded_error); -} - -// If an unknown nested variant of the `DispatchError` is detected (i.e. when any of the subsequent -// bytes are non-zero). -fn convert_unknown_nested_errors(encoded_error: &mut [u8; 4]) { - // Converts single nested errors that are known to the Pop API as unit errors into `Other`. - if UNIT_ERRORS.contains(&encoded_error[0]) && encoded_error[1..].iter().any(|x| *x != 0u8) { - encoded_error[..].rotate_right(1); - encoded_error[0] = 0u8; - // Converts double nested errors that are known to the Pop API as single nested errors into - // `Other`. - } else if SINGLE_NESTED_ERRORS.contains(&encoded_error[0]) - && encoded_error[2..].iter().any(|x| *x != 0u8) - { - encoded_error[..].rotate_right(1); - encoded_error[0] = 0u8; - } else if DOUBLE_NESTED_ERRORS.contains(&encoded_error[0]) - && encoded_error[3..].iter().any(|x| *x != 0u8) - { - encoded_error[..].rotate_right(1); - encoded_error[0] = 0u8; + StatusCode(255u32) } } @@ -136,32 +73,7 @@ pub enum Error { DecodingFailed = 255, } -// Unit `Error` variants. -// (variant: index): -// - CannotLookup: 1, -// - BadOrigin: 2, -// - ConsumerRemaining: 4, -// - NoProviders: 5, -// - TooManyConsumers: 6, -// - Exhausted: 10, -// - Corruption: 11, -// - Unavailable: 12, -// - RootNotAllowed: 13, -// - DecodingFailed: 255, -const UNIT_ERRORS: [u8; 10] = [1, 2, 4, 5, 6, 10, 11, 12, 13, 255]; - -// Single nested `Error` variants. -// (variant: index): -// - Token: 7, -// - Arithmetic: 8, -// - Transaction: 9, -const SINGLE_NESTED_ERRORS: [u8; 3] = [7, 8, 9]; - -// Double nested `Error` variants -// (variant: index): -// - Module: 3, -const DOUBLE_NESTED_ERRORS: [u8; 1] = [3]; - +#[cfg(test)] impl From for StatusCode { fn from(value: Error) -> Self { let mut encoded_error = value.encode(); @@ -175,8 +87,15 @@ impl From for StatusCode { impl From for Error { fn from(value: StatusCode) -> Self { - let encoded: [u8; 4] = value.0.to_le_bytes(); - Error::decode(&mut &encoded[..]).unwrap_or(DecodingFailed) + let mut encoded: [u8; 4] = value.0.to_le_bytes(); + match Error::decode(&mut &encoded[..]) { + Err(_) => { + encoded[..].rotate_right(1); + encoded[0] = 0u8; + Error::decode(&mut &encoded[..]).unwrap_or(DecodingFailed) + }, + Ok(error) => error, + } } } @@ -286,28 +205,19 @@ mod tests { into_status_code([error_code, 1, 0, 0]), (Other { dispatch_error_index: error_code, error_index: 1, error: 0 }).into(), ); - assert_eq!( - into_error([error_code, 1, 0, 0]), - Other { dispatch_error_index: error_code, error_index: 1, error: 0 }, - ); + assert_eq!(into_error([error_code, 1, 0, 0]), errors[i]); // Unexpected third byte nested. assert_eq!( into_status_code([error_code, 1, 1, 0]), (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), ); - assert_eq!( - into_error([error_code, 1, 1, 0]), - Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, - ); + assert_eq!(into_error([error_code, 1, 1, 0]), errors[i]); // Unexpected fourth byte nested. assert_eq!( into_status_code([error_code, 1, 1, 1]), (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), ); - assert_eq!( - into_error([error_code, 1, 1, 1]), - Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, - ); + assert_eq!(into_error([error_code, 1, 1, 1]), errors[i]); } } @@ -341,19 +251,13 @@ mod tests { into_status_code([error_code, 1, 1, 0]), (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), ); - assert_eq!( - into_error([error_code, 1, 1, 0]), - Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, - ); + assert_eq!(into_error([error_code, 1, 1, 0]), errors[i][1]); // Unexpected fourth byte nested. assert_eq!( into_status_code([error_code, 1, 1, 1]), (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), ); - assert_eq!( - into_error([error_code, 1, 1, 1]), - Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, - ); + assert_eq!(into_error([error_code, 1, 1, 1]), errors[i][1]); } } @@ -385,9 +289,37 @@ mod tests { into_status_code([3, 1, 1, 1]), (Other { dispatch_error_index: 3, error_index: 1, error: 1 }).into(), ); + assert_eq!(into_error([3, 1, 1, 1]), Module { index: 1, error: 1 }); + } + + #[test] + fn single_nested_unknown_variants() { + // Unknown `TokenError` variant. + assert_eq!( + into_error([7, 10, 0, 0]), + Other { dispatch_error_index: 7, error_index: 10, error: 0 } + ); + assert_eq!( + into_status_code([7, 10, 0, 0]), + Other { dispatch_error_index: 7, error_index: 10, error: 0 }.into() + ); + // Unknown `Arithmetic` variant. + assert_eq!( + into_error([8, 3, 0, 0]), + Other { dispatch_error_index: 8, error_index: 3, error: 0 } + ); + assert_eq!( + into_status_code([8, 3, 0, 0]), + Other { dispatch_error_index: 8, error_index: 3, error: 0 }.into() + ); + // Unknown `Transactional` variant. + assert_eq!( + into_error([9, 2, 0, 0]), + Other { dispatch_error_index: 9, error_index: 2, error: 0 } + ); assert_eq!( - into_error([3, 1, 1, 1]), - Other { dispatch_error_index: 3, error_index: 1, error: 1 }, + into_status_code([9, 2, 0, 0]), + Other { dispatch_error_index: 9, error_index: 2, error: 0 }.into() ); } diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 04d08bce..53bbadc6 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,9 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] use ink::{prelude::vec::Vec, ChainExtensionInstance}; -pub use sp_runtime::{MultiAddress, MultiSignature}; +pub use sp_runtime::MultiAddress; -use crate::error::{Error, StatusCode}; +use crate::error::StatusCode; use primitives::{storage_keys::*, AccountId as AccountId32}; #[cfg(feature = "assets")] pub use v0::assets; @@ -62,12 +62,14 @@ pub trait PopApi { fn send_xcm(xcm: primitives::cross_chain::CrossChainMessage) -> Result<()>; } +#[inline] fn dispatch(call: RuntimeCall) -> Result<()> { <::ChainExtension as ChainExtensionInstance>::instantiate( ) .dispatch(call) } +#[inline] fn read_state(key: RuntimeStateKeys) -> Result> { <::ChainExtension as ChainExtensionInstance>::instantiate( ) diff --git a/pop-api/src/primitives.rs b/pop-api/src/primitives.rs index e174a111..17419d5b 100644 --- a/pop-api/src/primitives.rs +++ b/pop-api/src/primitives.rs @@ -1 +1,2 @@ pub use pop_primitives::*; +pub use sp_runtime::MultiAddress; diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index eaf1c6f5..e7c3f41c 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,7 +1,12 @@ -use crate::{assets, primitives::AssetId, AccountId, Balance, MultiAddress, StatusCode}; use ink::prelude::vec::Vec; use scale::Encode; +use crate::{ + assets, + primitives::{AssetId, MultiAddress}, + AccountId, Balance, StatusCode, +}; + type Result = core::result::Result; /// Local Fungibles: @@ -26,6 +31,7 @@ type Result = core::result::Result; /// /// # Returns /// The total supply of the token, or an error if the operation fails. +#[inline] pub fn total_supply(id: AssetId) -> Result { assets::total_supply(id) } @@ -39,6 +45,7 @@ pub fn total_supply(id: AssetId) -> Result { /// /// # Returns /// The balance of the specified account, or an error if the operation fails. +#[inline] pub fn balance_of(id: AssetId, owner: AccountId) -> Result { assets::balance_of(id, owner) } @@ -53,6 +60,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { /// /// # Returns /// The remaining allowance, or an error if the operation fails. +#[inline] pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { assets::allowance(id, owner, spender) } @@ -67,6 +75,7 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result>, @@ -87,19 +96,15 @@ pub fn transfer( /// /// # Returns /// Returns `Ok(())` if successful, or an error if the transfer fails. +#[inline] pub fn transfer_from( id: AssetId, - from: Option>>, - to: Option>>, + from: impl Into>, + to: impl Into>, value: Balance, _data: &[u8], ) -> Result<()> { - match (from, to) { - (None, Some(to)) => assets::mint(id, to, value), - (Some(from), None) => assets::burn(id, from, value), - (Some(from), Some(to)) => assets::transfer_approved(id, from, to, value), - _ => Ok(()), - } + assets::transfer_approved(id, from, to, value) } /// Approves an account to spend a specified number of tokens on behalf of the caller. @@ -111,16 +116,10 @@ pub fn transfer_from( /// /// # Returns /// Returns `Ok(())` if successful, or an error if the approval fails. -// #[allow(unused_variables)] -// fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { -// todo!() -// // TODO: read allowance and increase or decrease. -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { -// // id: id.into(), -// // delegate: spender.into(), -// // amount: Compact(value), -// // }))?) -// } +#[inline] +pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + assets::approve_transfer(id, spender, value) +} /// Increases the allowance of a spender. /// @@ -131,13 +130,10 @@ pub fn transfer_from( /// /// # Returns /// Returns `Ok(())` if successful, or an error if the operation fails. -// fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { -// id: id.into(), -// delegate: spender.into(), -// amount: Compact(value), -// }))?) -// } +#[inline] +pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + assets::approve_transfer(id, spender, value) +} /// Decreases the allowance of a spender. /// @@ -148,20 +144,11 @@ pub fn transfer_from( /// /// # Returns /// Returns `Ok(())` if successful, or an error if the operation fails. -// #[allow(unused_variables)] -// fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { -// todo!() -// // TODO: cancel_approval + approve_transfer -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::CancelApproval { -// // id: id.into(), -// // delegate: delegate.into(), -// // }))?) -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { -// // id: id.into(), -// // delegate: spender.into(), -// // amount: Compact(value), -// // }))?) -// } +#[inline] +pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + assets::cancel_approval(id, spender.clone())?; + assets::approve_transfer(id, spender, value) +} /// 2. PSP-22 Metadata Interface: /// - token_name @@ -175,11 +162,10 @@ pub fn transfer_from( /// /// # Returns /// The name of the token as a byte vector, or an error if the operation fails. -// #[allow(unused_variables)] -// pub fn token_name(id: AssetId) -> Result>> { -// todo!() -// // Ok(state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenName(id)))?) -// } +#[inline] +pub fn token_name(id: AssetId) -> Result> { + assets::token_name(id) +} /// Returns the token symbol for a given asset ID. /// @@ -188,10 +174,10 @@ pub fn transfer_from( /// /// # Returns /// The symbol of the token as a byte vector, or an error if the operation fails. -// #[allow(unused_variables)] -// fn token_symbol(id: AssetId) -> Result>> { -// todo!() -// } +#[inline] +pub fn token_symbol(id: AssetId) -> Result> { + assets::token_symbol(id) +} /// Returns the token decimals for a given asset ID. /// @@ -200,118 +186,114 @@ pub fn transfer_from( /// /// # Returns /// The number of decimals of the token as a byte vector, or an error if the operation fails. -// #[allow(unused_variables)] -// fn token_decimals(id: AssetId) -> Result>> { -// todo!() -// } - -/// 3. Asset Management: -/// - create -/// - start_destroy -/// - destroy_accounts -/// - destroy_approvals -/// - finish_destroy -/// - set_metadata -/// - clear_metadata - -/// Create a new token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `admin` - The account that will administer the asset. -/// * `min_balance` - The minimum balance required for accounts holding this asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the creation fails. -pub fn create( - id: AssetId, - admin: impl Into>, - min_balance: Balance, -) -> Result<()> { - assets::create(id, admin, min_balance) +#[inline] +pub fn token_decimals(id: AssetId) -> Result { + assets::token_decimals(id) } -/// Start the process of destroying a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn start_destroy(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { -// id: id.into(), -// }))?) +// /// 3. Asset Management: +// /// - create +// /// - start_destroy +// /// - destroy_accounts +// /// - destroy_approvals +// /// - finish_destroy +// /// - set_metadata +// /// - clear_metadata +// +// /// Create a new token with a given asset ID. +// /// +// /// # Arguments +// /// * `id` - The ID of the asset. +// /// * `admin` - The account that will administer the asset. +// /// * `min_balance` - The minimum balance required for accounts holding this asset. +// /// +// /// # Returns +// /// Returns `Ok(())` if successful, or an error if the creation fails. +// // pub fn create(id: AssetId, admin: impl Into>, min_balance: Balance) -> Result<()> { +// // assets::create(id, admin, min_balance) +// // } +// +// /// Start the process of destroying a token with a given asset ID. +// /// +// /// # Arguments +// /// * `id` - The ID of the asset. +// /// +// /// # Returns +// /// Returns `Ok(())` if successful, or an error if the operation fails. +// // fn start_destroy(id: AssetId) -> Result<()> { +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { +// // id: id.into(), +// // }))?) +// // } +// +// /// Destroy all accounts associated with a token with a given asset ID. +// /// +// /// # Arguments +// /// * `id` - The ID of the asset. +// /// +// /// # Returns +// /// Returns `Ok(())` if successful, or an error if the operation fails. +// // fn destroy_accounts(id: AssetId) -> Result<()> { +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { +// // id: id.into(), +// // }))?) +// // } +// +// /// Destroy all approvals associated with a token with a given asset ID. +// /// +// /// # Arguments +// /// * `id` - The ID of the asset. +// /// +// /// # Returns +// /// Returns `Ok(())` if successful, or an error if the operation fails. +// // fn destroy_approvals(id: AssetId) -> Result<()> { +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { +// // id: id.into(), +// // }))?) +// // } +// +// /// Complete the process of destroying a token with a given asset ID. +// /// +// /// # Arguments +// /// * `id` - The ID of the asset. +// /// +// /// # Returns +// /// Returns `Ok(())` if successful, or an error if the operation fails. +// // fn finish_destroy(id: AssetId) -> Result<()> { +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { +// // id: id.into(), +// // }))?) +// // } +// +// /// Set the metadata for a token with a given asset ID. +// /// +// /// # Arguments +// /// * `id` - The ID of the asset. +// /// +// /// # Returns +// /// Returns `Ok(())` if successful, or an error if the operation fails. +// // pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { +// // assets::set_metadata(id, name, symbol, decimals) +// // } +// +// /// Clear the metadata for a token with a given asset ID. +// /// +// /// # Arguments +// /// * `id` - The ID of the asset. +// /// +// /// # Returns +// /// Returns `Ok(())` if successful, or an error if the operation fails. +// // fn clear_metadata(id: AssetId) -> Result<()> { +// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { +// // id: id.into(), +// // }))?) +// // } +// +// pub fn asset_exists(id: AssetId) -> Result { +// assets::asset_exists(id) // } -/// Destroy all accounts associated with a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn destroy_accounts(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { -// id: id.into(), -// }))?) -// } - -/// Destroy all approvals associated with a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn destroy_approvals(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { -// id: id.into(), -// }))?) -// } - -/// Complete the process of destroying a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn finish_destroy(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { -// id: id.into(), -// }))?) -// } - -/// Set the metadata for a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { - assets::set_metadata(id, name, symbol, decimals) -} - -/// Clear the metadata for a token with a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. -// fn clear_metadata(id: AssetId) -> Result<()> { -// Ok(dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { -// id: id.into(), -// }))?) -// } - -pub fn asset_exists(id: AssetId) -> Result { - assets::asset_exists(id) -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] +#[derive(Encode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum FungiblesError { Other(StatusCode), @@ -359,11 +341,13 @@ impl From for FungiblesError { #[cfg(test)] mod tests { + use scale::Decode; + use super::FungiblesError; - use crate::error::{ + use crate::StatusCode; + use pop_primitives::{ ArithmeticError::*, Error::{self, *}, - StatusCode, TokenError::*, TransactionalError::*, }; @@ -373,6 +357,18 @@ mod tests { status_code.into() } + #[test] + fn status_code_vs_encoded() { + assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 0, 0][..]).unwrap(), 13315u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 1, 0][..]).unwrap(), 78851u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 2, 0][..]).unwrap(), 144387u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 3, 0][..]).unwrap(), 209923u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 5, 0][..]).unwrap(), 340995u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 7, 0][..]).unwrap(), 472067u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 10, 0][..]).unwrap(), 668675u32); + } + #[test] fn conversion_status_code_into_fungibles_error_works() { let errors = vec![ diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 778387cb..22e32d47 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,10 +1,9 @@ -#![allow(dead_code)] - -use crate::{Balance, MultiAddress, RuntimeCall, *}; use ink::prelude::vec::Vec; -use primitives::AssetId; use scale::{Compact, Encode}; +use crate::{state::read, Balance, RuntimeCall, *}; +use primitives::{AssetId, MultiAddress}; + pub mod fungibles; type Result = core::result::Result; @@ -44,65 +43,62 @@ type Result = core::result::Result; /// - block /// Issue a new class of fungible assets from a public origin. -pub(crate) fn create( - id: AssetId, - admin: impl Into>, - min_balance: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Create { - id: id.into(), - admin: admin.into(), - min_balance, - })) -} - -/// Start the process of destroying a fungible asset class. -pub(crate) fn start_destroy(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { id: id.into() })) -} - -/// Destroy all accounts associated with a given asset. -pub(crate) fn destroy_accounts(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { id: id.into() })) -} - -/// Destroy all approvals associated with a given asset up to the max (see runtime configuration Assets `RemoveItemsLimit`). -pub(crate) fn destroy_approvals(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { id: id.into() })) -} - -/// Complete destroying asset and unreserve currency. -pub(crate) fn finish_destroy(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { id: id.into() })) -} - -/// Mint assets of a particular class. -pub(crate) fn mint( - id: AssetId, - beneficiary: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Mint { - id: id.into(), - beneficiary: beneficiary.into(), - amount: Compact(amount), - })) -} - -/// Reduce the balance of `who` by as much as possible up to `amount` assets of `id`. -pub(crate) fn burn( - id: AssetId, - who: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Burn { - id: id.into(), - who: who.into(), - amount: Compact(amount), - })) -} - -/// Move some assets from the sender account to another. +// pub(crate) fn create( +// id: AssetId, +// admin: impl Into>, +// min_balance: Balance, +// ) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::Create { +// id: id.into(), +// admin: admin.into(), +// min_balance, +// })) +// } +// +// /// Start the process of destroying a fungible asset class. +// pub(crate) fn start_destroy(id: AssetId) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { id: id.into() })) +// } +// +// /// Destroy all accounts associated with a given asset. +// pub(crate) fn destroy_accounts(id: AssetId) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { id: id.into() })) +// } +// +// /// Destroy all approvals associated with a given asset up to the max (see runtime configuration Assets `RemoveItemsLimit`). +// pub(crate) fn destroy_approvals(id: AssetId) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { id: id.into() })) +// } +// +// /// Complete destroying asset and unreserve currency. +// pub(crate) fn finish_destroy(id: AssetId) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { id: id.into() })) +// } + +// /// Mint assets of a particular class. +// pub(crate) fn mint( +// id: AssetId, +// beneficiary: impl Into>, +// amount: Balance, +// ) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::Mint { +// id: id.into(), +// beneficiary: beneficiary.into(), +// amount: Compact(amount), +// })) +// } +// +// /// Reduce the balance of `who` by as much as possible up to `amount` assets of `id`. +// pub(crate) fn burn(id: AssetId, who: impl Into>, amount: Balance) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::Burn { +// id: id.into(), +// who: who.into(), +// amount: Compact(amount), +// })) +// } + +// /// Move some assets from the sender account to another. +#[inline] pub(crate) fn transfer( id: AssetId, target: impl Into>, @@ -115,98 +111,96 @@ pub(crate) fn transfer( })) } -/// Move some assets from the sender account to another, keeping the sender account alive. -pub(crate) fn transfer_keep_alive( - id: AssetId, - target: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { - id: id.into(), - target: target.into(), - amount: Compact(amount), - })) -} - -/// Move some assets from one account to another. Sender should be the Admin of the asset `id`. -pub(crate) fn force_transfer( - id: AssetId, - source: impl Into>, - dest: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ForceTransfer { - id: id.into(), - source: source.into(), - dest: dest.into(), - amount: Compact(amount), - })) -} - -/// Disallow further unprivileged transfers of an asset `id` from an account `who`. `who` -/// must already exist as an entry in `Account`s of the asset. If you want to freeze an -/// account that does not have an entry, use `touch_other` first. -pub(crate) fn freeze(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Freeze { id: id.into(), who: who.into() })) -} - -/// Allow unprivileged transfers to and from an account again. -pub(crate) fn thaw(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Thaw { id: id.into(), who: who.into() })) -} - -/// Disallow further unprivileged transfers for the asset class. -pub(crate) fn freeze_asset(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::FreezeAsset { id: id.into() })) -} - -/// Allow unprivileged transfers for the asset again. -pub(crate) fn thaw_asset(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ThawAsset { id: id.into() })) -} - -/// Change the Owner of an asset. -pub(crate) fn transfer_ownership( - id: AssetId, - owner: impl Into>, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TransferOwnership { - id: id.into(), - owner: owner.into(), - })) -} - -/// Change the Issuer, Admin and Freezer of an asset. -pub(crate) fn set_team( - id: AssetId, - issuer: impl Into>, - admin: impl Into>, - freezer: impl Into>, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::SetTeam { - id: id.into(), - issuer: issuer.into(), - admin: admin.into(), - freezer: freezer.into(), - })) -} +// /// Move some assets from the sender account to another, keeping the sender account alive. +// pub(crate) fn transfer_keep_alive( +// id: AssetId, +// target: impl Into>, +// amount: Balance, +// ) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { +// id: id.into(), +// target: target.into(), +// amount: Compact(amount), +// })) +// } +// +// /// Move some assets from one account to another. Sender should be the Admin of the asset `id`. +// pub(crate) fn force_transfer( +// id: AssetId, +// source: impl Into>, +// dest: impl Into>, +// amount: Balance, +// ) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::ForceTransfer { +// id: id.into(), +// source: source.into(), +// dest: dest.into(), +// amount: Compact(amount), +// })) +// } +// +// /// Disallow further unprivileged transfers of an asset `id` from an account `who`. `who` +// /// must already exist as an entry in `Account`s of the asset. If you want to freeze an +// /// account that does not have an entry, use `touch_other` first. +// pub(crate) fn freeze(id: AssetId, who: impl Into>) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::Freeze { id: id.into(), who: who.into() })) +// } +// +// /// Allow unprivileged transfers to and from an account again. +// pub(crate) fn thaw(id: AssetId, who: impl Into>) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::Thaw { id: id.into(), who: who.into() })) +// } +// +// /// Disallow further unprivileged transfers for the asset class. +// pub(crate) fn freeze_asset(id: AssetId) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::FreezeAsset { id: id.into() })) +// } +// +// /// Allow unprivileged transfers for the asset again. +// pub(crate) fn thaw_asset(id: AssetId) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::ThawAsset { id: id.into() })) +// } +// +// /// Change the Owner of an asset. +// pub(crate) fn transfer_ownership(id: AssetId, owner: impl Into>) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::TransferOwnership { +// id: id.into(), +// owner: owner.into(), +// })) +// } +// +// /// Change the Issuer, Admin and Freezer of an asset. +// pub(crate) fn set_team( +// id: AssetId, +// issuer: impl Into>, +// admin: impl Into>, +// freezer: impl Into>, +// ) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::SetTeam { +// id: id.into(), +// issuer: issuer.into(), +// admin: admin.into(), +// freezer: freezer.into(), +// })) +// } /// Set the metadata for an asset. -pub(crate) fn set_metadata( - id: AssetId, - name: Vec, - symbol: Vec, - decimals: u8, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::SetMetadata { id: id.into(), name, symbol, decimals })) -} - -/// Clear the metadata for an asset. -pub(crate) fn clear_metadata(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { id: id.into() })) -} - -/// Approve an amount of asset for transfer by a delegated third-party account. +// pub(crate) fn set_metadata( +// id: AssetId, +// name: Vec, +// symbol: Vec, +// decimals: u8, +// ) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::SetMetadata { id: id.into(), name, symbol, decimals })) +// } + +// /// Clear the metadata for an asset. +// pub(crate) fn clear_metadata(id: AssetId) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { id: id.into() })) +// } + +// /// Approve an amount of asset for transfer by a delegated third-party account. +#[inline] pub(crate) fn approve_transfer( id: AssetId, delegate: impl Into>, @@ -220,6 +214,7 @@ pub(crate) fn approve_transfer( } /// Cancel all of some asset approved for delegated transfer by a third-party account. +#[inline] pub(crate) fn cancel_approval( id: AssetId, delegate: impl Into>, @@ -230,21 +225,22 @@ pub(crate) fn cancel_approval( })) } -/// Cancel all of some asset approved for delegated transfer by a third-party account. -pub(crate) fn force_cancel_approval( - id: AssetId, - owner: impl Into>, - delegate: impl Into>, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ForceCancelApproval { - id: id.into(), - owner: owner.into(), - delegate: delegate.into(), - })) -} +// /// Cancel all of some asset approved for delegated transfer by a third-party account. +// pub(crate) fn force_cancel_approval( +// id: AssetId, +// owner: impl Into>, +// delegate: impl Into>, +// ) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::ForceCancelApproval { +// id: id.into(), +// owner: owner.into(), +// delegate: delegate.into(), +// })) +// } /// Transfer some asset balance from a previously delegated account to some third-party /// account. +#[inline] pub(crate) fn transfer_approved( id: AssetId, owner: impl Into>, @@ -258,58 +254,81 @@ pub(crate) fn transfer_approved( amount: Compact(amount), })) } - -/// Create an asset account for non-provider assets. -pub(crate) fn touch(id: AssetId) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Touch { id: id.into() })) -} - -/// Return the deposit (if any) of an asset account or a consumer reference (if any) of an -/// account. -pub(crate) fn refund(id: AssetId, allow_burn: bool) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Refund { id: id.into(), allow_burn })) -} - -/// Sets the minimum balance of an asset. -pub(crate) fn set_min_balance(id: AssetId, min_balance: Balance) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::SetMinBalance { - id: id.into(), - min_balance: Compact(min_balance), - })) -} - -/// Create an asset account for `who`. -pub(crate) fn touch_other(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TouchOther { id: id.into(), who: who.into() })) -} - -/// Return the deposit (if any) of a target asset account. Useful if you are the depositor. -pub(crate) fn refund_other(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::RefundOther { id: id.into(), who: who.into() })) -} - -/// Disallow further unprivileged transfers of an asset `id` to and from an account `who`. -pub(crate) fn block(id: AssetId, who: impl Into>) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::Block { id: id.into(), who: who.into() })) -} +// +// /// Create an asset account for non-provider assets. +// pub(crate) fn touch(id: AssetId) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::Touch { id: id.into() })) +// } +// +// /// Return the deposit (if any) of an asset account or a consumer reference (if any) of an +// /// account. +// pub(crate) fn refund(id: AssetId, allow_burn: bool) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::Refund { id: id.into(), allow_burn })) +// } +// +// /// Sets the minimum balance of an asset. +// pub(crate) fn set_min_balance(id: AssetId, min_balance: Balance) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::SetMinBalance { +// id: id.into(), +// min_balance: Compact(min_balance), +// })) +// } +// +// /// Create an asset account for `who`. +// pub(crate) fn touch_other(id: AssetId, who: impl Into>) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::TouchOther { id: id.into(), who: who.into() })) +// } +// +// /// Return the deposit (if any) of a target asset account. Useful if you are the depositor. +// pub(crate) fn refund_other(id: AssetId, who: impl Into>) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::RefundOther { id: id.into(), who: who.into() })) +// } +// +// /// Disallow further unprivileged transfers of an asset `id` to and from an account `who`. +// pub(crate) fn block(id: AssetId, who: impl Into>) -> Result<()> { +// dispatch(RuntimeCall::Assets(AssetsCall::Block { id: id.into(), who: who.into() })) +// } /// 2. Read state functions /// - total_supply -/// - - +/// - balance_of +/// - allowance +/// - asset_exists +/// - token_name +/// - token_symbol +/// - token_decimals +// +#[inline] pub(crate) fn total_supply(id: AssetId) -> Result { state::read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id))) } +#[inline] pub(crate) fn balance_of(id: AssetId, owner: AccountId) -> Result { state::read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner))) } +#[inline] pub(crate) fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { state::read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender))) } -pub(crate) fn asset_exists(id: AssetId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))) +// pub(crate) fn asset_exists(id: AssetId) -> Result { +// state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))) +// } + +#[inline] +pub(crate) fn token_name(id: AssetId) -> Result> { + state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenName(id))) +} +// +#[inline] +pub(crate) fn token_symbol(id: AssetId) -> Result> { + state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenSymbol(id))) +} + +#[inline] +pub(crate) fn token_decimals(id: AssetId) -> Result { + state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenDecimals(id))) } // Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected @@ -321,63 +340,63 @@ pub(crate) fn asset_exists(id: AssetId) -> Result { type AssetIdParameter = Compact; // Balance amount that is compact encoded. type BalanceParameter = Compact; - +// #[derive(Encode)] pub(crate) enum AssetsCall { - #[codec(index = 0)] - Create { id: AssetIdParameter, admin: MultiAddress, min_balance: Balance }, - #[codec(index = 2)] - StartDestroy { id: AssetIdParameter }, - #[codec(index = 3)] - DestroyAccounts { id: AssetIdParameter }, - #[codec(index = 4)] - DestroyApprovals { id: AssetIdParameter }, - #[codec(index = 5)] - FinishDestroy { id: AssetIdParameter }, - #[codec(index = 6)] - Mint { - id: AssetIdParameter, - beneficiary: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 7)] - Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, - #[codec(index = 8)] - Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, + // #[codec(index = 0)] + // Create { id: AssetIdParameter, admin: MultiAddress, min_balance: Balance }, + // #[codec(index = 2)] + // StartDestroy { id: AssetIdParameter }, + // #[codec(index = 3)] + // DestroyAccounts { id: AssetIdParameter }, + // #[codec(index = 4)] + // DestroyApprovals { id: AssetIdParameter }, + // #[codec(index = 5)] + // FinishDestroy { id: AssetIdParameter }, + // #[codec(index = 6)] + // Mint { + // id: AssetIdParameter, + // beneficiary: MultiAddress, + // amount: BalanceParameter, + // }, + // #[codec(index = 7)] + // Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, + // #[codec(index = 8)] + // Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, #[codec(index = 9)] TransferKeepAlive { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter, }, - #[codec(index = 10)] - ForceTransfer { - id: AssetIdParameter, - source: MultiAddress, - dest: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 11)] - Freeze { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 12)] - Thaw { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 13)] - FreezeAsset { id: AssetIdParameter }, - #[codec(index = 14)] - ThawAsset { id: AssetIdParameter }, - #[codec(index = 15)] - TransferOwnership { id: AssetIdParameter, owner: MultiAddress }, - #[codec(index = 16)] - SetTeam { - id: AssetIdParameter, - issuer: MultiAddress, - admin: MultiAddress, - freezer: MultiAddress, - }, - #[codec(index = 17)] - SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, - #[codec(index = 18)] - ClearMetadata { id: AssetIdParameter }, + // #[codec(index = 10)] + // ForceTransfer { + // id: AssetIdParameter, + // source: MultiAddress, + // dest: MultiAddress, + // amount: BalanceParameter, + // }, + // #[codec(index = 11)] + // Freeze { id: AssetIdParameter, who: MultiAddress }, + // #[codec(index = 12)] + // Thaw { id: AssetIdParameter, who: MultiAddress }, + // #[codec(index = 13)] + // FreezeAsset { id: AssetIdParameter }, + // #[codec(index = 14)] + // ThawAsset { id: AssetIdParameter }, + // #[codec(index = 15)] + // TransferOwnership { id: AssetIdParameter, owner: MultiAddress }, + // #[codec(index = 16)] + // SetTeam { + // id: AssetIdParameter, + // issuer: MultiAddress, + // admin: MultiAddress, + // freezer: MultiAddress, + // }, + // #[codec(index = 17)] + // SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, + // #[codec(index = 18)] + // ClearMetadata { id: AssetIdParameter }, #[codec(index = 22)] ApproveTransfer { id: AssetIdParameter, @@ -386,12 +405,12 @@ pub(crate) enum AssetsCall { }, #[codec(index = 23)] CancelApproval { id: AssetIdParameter, delegate: MultiAddress }, - #[codec(index = 24)] - ForceCancelApproval { - id: AssetIdParameter, - owner: MultiAddress, - delegate: MultiAddress, - }, + // #[codec(index = 24)] + // ForceCancelApproval { + // id: AssetIdParameter, + // owner: MultiAddress, + // delegate: MultiAddress, + // }, #[codec(index = 25)] TransferApproved { id: AssetIdParameter, @@ -399,96 +418,97 @@ pub(crate) enum AssetsCall { destination: MultiAddress, amount: BalanceParameter, }, - #[codec(index = 26)] - Touch { id: AssetIdParameter }, - #[codec(index = 27)] - Refund { id: AssetIdParameter, allow_burn: bool }, - #[codec(index = 28)] - SetMinBalance { id: AssetIdParameter, min_balance: BalanceParameter }, - #[codec(index = 29)] - TouchOther { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 30)] - RefundOther { id: AssetIdParameter, who: MultiAddress }, - #[codec(index = 31)] - Block { id: AssetIdParameter, who: MultiAddress }, -} - -// TODO: Not being used atm but necessary if we want to provide access to the -// rest of the pallet, outside of the use cases. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum AssetsError { - /// Account balance must be greater than or equal to the transfer amount. - BalanceLow, - /// The account to alter does not exist. - NoAccount, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given asset ID is unknown. - Unknown, - /// The origin account is frozen. - Frozen, - /// The asset ID is already taken. - InUse, - /// Invalid witness data given. - BadWitness, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// Unable to increment the consumer reference counters on the account. Either no provider - /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one - /// fewer then the maximum number of consumers has been reached. - UnavailableConsumer, - /// Invalid metadata given. - BadMetadata, - /// No approval exists that would allow the transfer. - Unapproved, - /// The source account would not survive the transfer and it needs to stay alive. - WouldDie, - /// The asset-account already exists. - AlreadyExists, - /// The asset-account doesn't have an associated deposit. - NoDeposit, - /// The operation would result in funds being burned. - WouldBurn, - /// The asset is a live asset and is actively being used. Usually emit for operations such - /// as `start_destroy` which require the asset to be in a destroying state. - LiveAsset, - /// The asset is not live, and likely being destroyed. - AssetNotLive, - /// The asset status is not the expected status. - IncorrectStatus, - /// The asset should be frozen before the given operation. - NotFrozen, - /// Callback action resulted in error. - CallbackFailed, + // // #[codec(index = 26)] + // // Touch { id: AssetIdParameter }, + // // #[codec(index = 27)] + // // Refund { id: AssetIdParameter, allow_burn: bool }, + // // #[codec(index = 28)] + // // SetMinBalance { id: AssetIdParameter, min_balance: BalanceParameter }, + // // #[codec(index = 29)] + // // TouchOther { id: AssetIdParameter, who: MultiAddress }, + // // #[codec(index = 30)] + // // RefundOther { id: AssetIdParameter, who: MultiAddress }, + // // #[codec(index = 31)] + // // Block { id: AssetIdParameter, who: MultiAddress }, + // } + + // // TODO: Not being used atm but necessary if we want to provide access to the + // // rest of the pallet, outside of the use cases. + // #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] + // #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + // pub enum AssetsError { + // /// Account balance must be greater than or equal to the transfer amount. + // BalanceLow, + // /// The account to alter does not exist. + // NoAccount, + // /// The signing account has no permission to do the operation. + // NoPermission, + // /// The given asset ID is unknown. + // Unknown, + // /// The origin account is frozen. + // Frozen, + // /// The asset ID is already taken. + // InUse, + // /// Invalid witness data given. + // BadWitness, + // /// Minimum balance should be non-zero. + // MinBalanceZero, + // /// Unable to increment the consumer reference counters on the account. Either no provider + // /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one + // /// fewer then the maximum number of consumers has been reached. + // UnavailableConsumer, + // /// Invalid metadata given. + // BadMetadata, + // /// No approval exists that would allow the transfer. + // Unapproved, + // /// The source account would not survive the transfer and it needs to stay alive. + // WouldDie, + // /// The asset-account already exists. + // AlreadyExists, + // /// The asset-account doesn't have an associated deposit. + // NoDeposit, + // /// The operation would result in funds being burned. + // WouldBurn, + // /// The asset is a live asset and is actively being used. Usually emit for operations such + // /// as `start_destroy` which require the asset to be in a destroying state. + // LiveAsset, + // /// The asset is not live, and likely being destroyed. + // AssetNotLive, + // /// The asset status is not the expected status. + // IncorrectStatus, + // /// The asset should be frozen before the given operation. + // NotFrozen, + // /// Callback action resulted in error. + // CallbackFailed, } -impl TryFrom for AssetsError { - type Error = Error; - - fn try_from(status_code: u32) -> core::result::Result { - use AssetsError::*; - match status_code { - 0 => Ok(BalanceLow), - 1 => Ok(NoAccount), - 2 => Ok(NoPermission), - 3 => Ok(Unknown), - 4 => Ok(Frozen), - 5 => Ok(InUse), - 6 => Ok(BadWitness), - 7 => Ok(MinBalanceZero), - 8 => Ok(UnavailableConsumer), - 9 => Ok(BadMetadata), - 10 => Ok(Unapproved), - 11 => Ok(WouldDie), - 12 => Ok(AlreadyExists), - 13 => Ok(NoDeposit), - 14 => Ok(WouldBurn), - 15 => Ok(LiveAsset), - 16 => Ok(AssetNotLive), - 17 => Ok(IncorrectStatus), - 18 => Ok(NotFrozen), - _ => todo!(), - } - } -} +// +// impl TryFrom for AssetsError { +// type Error = Error; +// +// fn try_from(status_code: u32) -> core::result::Result { +// use AssetsError::*; +// match status_code { +// 0 => Ok(BalanceLow), +// 1 => Ok(NoAccount), +// 2 => Ok(NoPermission), +// 3 => Ok(Unknown), +// 4 => Ok(Frozen), +// 5 => Ok(InUse), +// 6 => Ok(BadWitness), +// 7 => Ok(MinBalanceZero), +// 8 => Ok(UnavailableConsumer), +// 9 => Ok(BadMetadata), +// 10 => Ok(Unapproved), +// 11 => Ok(WouldDie), +// 12 => Ok(AlreadyExists), +// 13 => Ok(NoDeposit), +// 14 => Ok(WouldBurn), +// 15 => Ok(LiveAsset), +// 16 => Ok(AssetNotLive), +// 17 => Ok(IncorrectStatus), +// 18 => Ok(NotFrozen), +// _ => todo!(), +// } +// } +// } diff --git a/pop-api/src/v0/state.rs b/pop-api/src/v0/state.rs index e3d38129..914a9603 100644 --- a/pop-api/src/v0/state.rs +++ b/pop-api/src/v0/state.rs @@ -1,6 +1,7 @@ -use crate::{primitives::storage_keys::RuntimeStateKeys, read_state, Error}; +use crate::{error::StatusCode, primitives::storage_keys::RuntimeStateKeys, read_state}; use scale::Decode; +#[inline] pub fn read(key: RuntimeStateKeys) -> crate::Result { - read_state(key).and_then(|v| T::decode(&mut &v[..]).map_err(|_e| Error::DecodingFailed.into())) + read_state(key).and_then(|v| T::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) } diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 3b91f713..dc0a5245 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -9,7 +9,7 @@ use {scale_decode::DecodeAsType, scale_encode::EncodeAsType, scale_info::TypeInf pub mod cross_chain; pub mod storage_keys; -#[derive(Encode, Decode, Debug, MaxEncodedLen, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Encode, Decode, Clone, Debug, MaxEncodedLen, Eq, PartialEq, Ord, PartialOrd)] #[cfg_attr(feature = "std", derive(TypeInfo, DecodeAsType, EncodeAsType))] pub struct AccountId(pub [u8; 32]); diff --git a/primitives/src/storage_keys.rs b/primitives/src/storage_keys.rs index 748d0662..7992089b 100644 --- a/primitives/src/storage_keys.rs +++ b/primitives/src/storage_keys.rs @@ -47,10 +47,13 @@ pub enum NftsKeys { #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum AssetsKeys { Allowance(AssetId, AccountId, AccountId), - /// Check if the asset exists. - AssetExists(AssetId), + // /// Check if the asset exists. + // // AssetExists(AssetId), /// Check balance. BalanceOf(AssetId, AccountId), /// Returns the total token supply for a given asset ID. TotalSupply(AssetId), + TokenDecimals(AssetId), + TokenSymbol(AssetId), + TokenName(AssetId), } From 7757319213cab9de78b0a3f26eda15cf513af454 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Wed, 3 Jul 2024 08:18:27 +0200 Subject: [PATCH 015/161] refactor: runtime --- pop-api/Cargo.toml | 6 +- pop-api/examples/fungibles/Cargo.toml | 4 - pop-api/examples/fungibles/lib.rs | 4 +- pop-api/src/error.rs | 38 ++-- pop-api/src/lib.rs | 4 +- pop-api/src/v0/assets/fungibles.rs | 10 +- pop-api/src/v0/assets/mod.rs | 22 +- pop-api/src/v0/mod.rs | 3 +- pop-api/src/v0/state.rs | 2 +- runtime/devnet/src/extensions.rs | 295 +++++++++++--------------- 10 files changed, 168 insertions(+), 220 deletions(-) diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index a88d8892..82ee7613 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -8,8 +8,6 @@ edition = "2021" [dependencies] enumflags2 = { version = "0.7.7" } ink = { version = "5.0.0", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } sp-io = { version = "31.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } sp-runtime = { version = "32.0.0", default-features = false } @@ -26,9 +24,7 @@ std = [ "enumflags2/std", "ink/std", "pop-primitives/std", - "scale/std", - "scale-info/std", -"sp-io/std", + "sp-io/std", "sp-runtime/std", ] assets = ["pop-primitives/assets"] diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 514f000f..565b0554 100755 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -7,8 +7,6 @@ edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } pop-api = { path = "../../../pop-api", default-features = false, features = ["assets"] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } [lib] path = "lib.rs" @@ -18,8 +16,6 @@ default = ["std"] std = [ "ink/std", "pop-api/std", - "scale/std", - "scale-info/std", ] ink-as-dependency = [] e2e-tests = [] diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index bd51d760..1794fbe5 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -85,7 +85,7 @@ mod fungibles { to: AccountId32, value: Balance, // In the standard a `[u8]`, but the size needs to be known at compile time. - data: Vec, + _data: Vec, ) -> Result<()> { ink::env::debug_println!( "PopApiFungiblesExample::transfer_from: id: {:?}, from: {:?}, to: {:?} value: {:?}", @@ -95,7 +95,7 @@ mod fungibles { value, ); - let result = api::transfer_from(id, from, to, value, &data); + let result = api::transfer_from(id, from, to, value); ink::env::debug_println!("Result: {:?}", result); // result.map_err(|e| e.into()) result diff --git a/pop-api/src/error.rs b/pop-api/src/error.rs index 54681e6d..8989464f 100644 --- a/pop-api/src/error.rs +++ b/pop-api/src/error.rs @@ -1,10 +1,7 @@ -use ink::env::chain_extension::FromStatusCode; -use scale::{Decode, Encode}; +use ink::{env::chain_extension::FromStatusCode, scale::Decode}; -use Error::*; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] pub struct StatusCode(pub u32); impl From for StatusCode { @@ -14,21 +11,21 @@ impl From for StatusCode { } impl FromStatusCode for StatusCode { fn from_status_code(status_code: u32) -> Result<(), Self> { - if status_code == 0 { - return Ok(()); + match status_code { + 0 => Ok(()), + _ => Err(StatusCode(status_code)), } - Err(StatusCode(status_code)) } } -impl From for StatusCode { - fn from(_: scale::Error) -> Self { +impl From for StatusCode { + fn from(_: ink::scale::Error) -> Self { StatusCode(255u32) } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] #[repr(u8)] pub enum Error { /// Some unknown error occurred. Go to the Pop API docs section `Pop API error`. @@ -70,6 +67,7 @@ pub enum Error { Unavailable = 12, /// Root origin is not allowed. RootNotAllowed = 13, + UnknownFunctionId = 254, DecodingFailed = 255, } @@ -92,15 +90,15 @@ impl From for Error { Err(_) => { encoded[..].rotate_right(1); encoded[0] = 0u8; - Error::decode(&mut &encoded[..]).unwrap_or(DecodingFailed) + Error::decode(&mut &encoded[..]).unwrap_or(Error::DecodingFailed) }, Ok(error) => error, } } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum TokenError { /// Funds are unavailable. FundsUnavailable, @@ -125,8 +123,8 @@ pub enum TokenError { Blocked, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum ArithmeticError { /// Underflow. Underflow, @@ -136,8 +134,8 @@ pub enum ArithmeticError { DivisionByZero, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum TransactionalError { /// Too many transactional layers have been spawned. LimitReached, diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 53bbadc6..55307f3e 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -27,8 +27,8 @@ type BlockNumber = ::BlockNumber; pub type Result = core::result::Result; -#[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +#[derive(Debug, PartialEq, Eq, Clone)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum Environment {} impl ink::env::Environment for Environment { diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index e7c3f41c..376ca898 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,5 +1,4 @@ use ink::prelude::vec::Vec; -use scale::Encode; use crate::{ assets, @@ -102,7 +101,6 @@ pub fn transfer_from( from: impl Into>, to: impl Into>, value: Balance, - _data: &[u8], ) -> Result<()> { assets::transfer_approved(id, from, to, value) } @@ -293,8 +291,8 @@ pub fn token_decimals(id: AssetId) -> Result { // assets::asset_exists(id) // } -#[derive(Encode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum FungiblesError { Other(StatusCode), /// The asset is not live; either frozen or being destroyed. @@ -344,13 +342,13 @@ mod tests { use scale::Decode; use super::FungiblesError; - use crate::StatusCode; - use pop_primitives::{ + use crate::error::{ ArithmeticError::*, Error::{self, *}, TokenError::*, TransactionalError::*, }; + use crate::StatusCode; fn into_fungibles_error(error: Error) -> FungiblesError { let status_code: StatusCode = error.into(); diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 22e32d47..241c5020 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,5 +1,4 @@ -use ink::prelude::vec::Vec; -use scale::{Compact, Encode}; +use ink::{prelude::vec::Vec, scale::Compact}; use crate::{state::read, Balance, RuntimeCall, *}; use primitives::{AssetId, MultiAddress}; @@ -97,7 +96,7 @@ type Result = core::result::Result; // })) // } -// /// Move some assets from the sender account to another. +/// Move some assets from the sender account to another. #[inline] pub(crate) fn transfer( id: AssetId, @@ -199,7 +198,7 @@ pub(crate) fn transfer( // dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { id: id.into() })) // } -// /// Approve an amount of asset for transfer by a delegated third-party account. +/// Approve an amount of asset for transfer by a delegated third-party account. #[inline] pub(crate) fn approve_transfer( id: AssetId, @@ -300,17 +299,17 @@ pub(crate) fn transfer_approved( // #[inline] pub(crate) fn total_supply(id: AssetId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id))) + read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id))) } #[inline] pub(crate) fn balance_of(id: AssetId, owner: AccountId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner))) + read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner))) } #[inline] pub(crate) fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender))) + read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender))) } // pub(crate) fn asset_exists(id: AssetId) -> Result { // state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))) @@ -318,17 +317,17 @@ pub(crate) fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Re #[inline] pub(crate) fn token_name(id: AssetId) -> Result> { - state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenName(id))) + read(RuntimeStateKeys::Assets(AssetsKeys::TokenName(id))) } // #[inline] pub(crate) fn token_symbol(id: AssetId) -> Result> { - state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenSymbol(id))) + read(RuntimeStateKeys::Assets(AssetsKeys::TokenSymbol(id))) } #[inline] pub(crate) fn token_decimals(id: AssetId) -> Result { - state::read(RuntimeStateKeys::Assets(AssetsKeys::TokenDecimals(id))) + read(RuntimeStateKeys::Assets(AssetsKeys::TokenDecimals(id))) } // Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected @@ -341,7 +340,8 @@ type AssetIdParameter = Compact; // Balance amount that is compact encoded. type BalanceParameter = Compact; // -#[derive(Encode)] +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] pub(crate) enum AssetsCall { // #[codec(index = 0)] // Create { id: AssetIdParameter, admin: MultiAddress, min_balance: Balance }, diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 20dc6476..f91c4271 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -8,7 +8,8 @@ pub mod cross_chain; pub mod nfts; pub mod state; -#[derive(scale::Encode)] +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] pub(crate) enum RuntimeCall { #[codec(index = 10)] #[cfg(feature = "balances")] diff --git a/pop-api/src/v0/state.rs b/pop-api/src/v0/state.rs index 914a9603..afe48ba8 100644 --- a/pop-api/src/v0/state.rs +++ b/pop-api/src/v0/state.rs @@ -1,5 +1,5 @@ use crate::{error::StatusCode, primitives::storage_keys::RuntimeStateKeys, read_state}; -use scale::Decode; +use ink::scale::Decode; #[inline] pub fn read(key: RuntimeStateKeys) -> crate::Result { diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions.rs index 904d18ce..6f98bf96 100644 --- a/runtime/devnet/src/extensions.rs +++ b/runtime/devnet/src/extensions.rs @@ -57,24 +57,132 @@ where E: Ext, { log::debug!(target:LOG_TARGET, " extension called "); - match v0::FuncId::try_from(env.func_id())? { - v0::FuncId::Dispatch => match dispatch::(env) { - Ok(()) => Ok(RetVal::Converging(0)), - Err(e) => Ok(RetVal::Converging(convert_to_status_code(e))), - }, - v0::FuncId::ReadState => { - read_state::(env)?; - Ok(RetVal::Converging(0)) - }, - v0::FuncId::SendXcm => { - send_xcm::(env)?; - Ok(RetVal::Converging(0)) + let mut env = env.buf_in_buf_out(); + let contract_host_weight = ContractSchedule::::get().host_fn_weights; + // debug_message weight is a good approximation of the additional overhead of going + // from contract layer to substrate layer. + // reference: https://github.com/paritytech/ink-examples/blob/b8d2caa52cf4691e0ddd7c919e4462311deb5ad0/psp22-extension/runtime/psp22-extension-example.rs#L236 + env.charge_weight(contract_host_weight.debug_message)?; + + let result = match v0::FuncId::try_from(env.func_id()) { + Ok(function) => { + // calculate weight for reading bytes of `len` + // reference: https://github.com/paritytech/polkadot-sdk/blob/117a9433dac88d5ac00c058c9b39c511d47749d2/substrate/frame/contracts/src/wasm/runtime.rs#L267 + let len = env.in_len(); + env.charge_weight(contract_host_weight.return_per_byte.saturating_mul(len.into()))?; + match function { + v0::FuncId::Dispatch => dispatch::(&mut env, len), + v0::FuncId::ReadState => read_state::(&mut env), + v0::FuncId::SendXcm => send_xcm::(&mut env), + } }, + Err(e) => Err(e), + }; + + // Convert any error to a status code and return Ok with RetVal::Converging + match result { + Ok(_) => Ok(RetVal::Converging(0)), + Err(e) => Ok(RetVal::Converging(convert_to_status_code(e))), } } } + +fn dispatch(env: &mut Environment, len: u32) -> Result<(), DispatchError> +where + T: pallet_contracts::Config + + frame_system::Config, + RuntimeOrigin: From>, + E: Ext, +{ + const LOG_PREFIX: &str = " dispatch |"; + + // read the input as RuntimeCall + let call: RuntimeCall = env.read_as_unbounded(len)?; + log::debug!(target: LOG_TARGET, "Read input as call successfully"); + // contract is the origin by default + let origin: RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); + dispatch_call::(env, call, origin, LOG_PREFIX) +} + +fn read_state(env: &mut Environment) -> Result<(), DispatchError> +where + T: pallet_contracts::Config + + pallet_assets::Config + + pallet_nfts::Config + + cumulus_pallet_parachain_system::Config + + frame_system::Config, + E: Ext, +{ + const LOG_PREFIX: &str = " read_state |"; + + let key: RuntimeStateKeys = env.read_as()?; + let result = match key { + RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, env), + RuntimeStateKeys::ParachainSystem(key) => read_parachain_system_state::(key, env), + RuntimeStateKeys::Assets(key) => read_assets_state::(key, env), + }? + .encode(); + + log::trace!( + target:LOG_TARGET, + "{} result: {:?}.", LOG_PREFIX, result + ); + env.write(&result, false, None) +} + +fn send_xcm(env: &mut Environment) -> Result<(), DispatchError> +where + T: pallet_contracts::Config + + frame_system::Config< + RuntimeOrigin = RuntimeOrigin, + AccountId = AccountId, + RuntimeCall = RuntimeCall, + >, + E: Ext, +{ + const LOG_PREFIX: &str = " send_xcm |"; + + // read the input as CrossChainMessage + let xc_call: CrossChainMessage = env.read_as::()?; + // Determine the call to dispatch + let (dest, message) = match xc_call { + CrossChainMessage::Relay(message) => { + let dest = Location::parent().into_versioned(); + let assets: Asset = (Here, 10 * UNIT).into(); + let beneficiary: Location = + AccountId32 { id: (env.ext().address().clone()).into(), network: None }.into(); + let message = Xcm::builder() + .withdraw_asset(assets.clone().into()) + .buy_execution(assets.clone(), Unlimited) + .transact( + SovereignAccount, + Weight::from_parts(250_000_000, 10_000), + message.encode().into(), + ) + .refund_surplus() + .deposit_asset(assets.into(), beneficiary) + .build(); + (dest, message) + }, + }; + + // TODO: revisit to replace with signed contract origin + let origin: RuntimeOrigin = RawOrigin::Root.into(); + + // Generate runtime call to dispatch + let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::send { + dest: Box::new(dest), + message: Box::new(VersionedXcm::V4(message)), + }); + + dispatch_call::(env, call, origin, LOG_PREFIX) +} + pub(crate) fn convert_to_status_code(error: DispatchError) -> u32 { - let mut encoded_error = error.encode(); + let mut encoded_error = match error { + DispatchError::Other("UnknownFunctionId") => vec![254, 0, 0, 0], + _ => error.encode(), + }; // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). encoded_error.resize(4, 0); u32::decode(&mut &encoded_error[..]).expect("qid, resized to 4 bytes line above") @@ -99,8 +207,7 @@ impl TryFrom for v0::FuncId { 0x2 => Self::SendXcm, _ => { log::error!("called an unregistered `func_id`: {:}", func_id); - // TODO: Other error. - return Err(DispatchError::Other("unimplemented func_id")); + return Err(DispatchError::Other("UnknownFuncId")); }, }; @@ -143,101 +250,6 @@ where } } -fn charge_overhead_weight( - env: &mut Environment, - len: u32, - log_prefix: &str, -) -> Result -where - T: pallet_contracts::Config, - E: Ext, -{ - let contract_host_weight = ContractSchedule::::get().host_fn_weights; - - // calculate weight for reading bytes of `len` - // reference: https://github.com/paritytech/polkadot-sdk/blob/117a9433dac88d5ac00c058c9b39c511d47749d2/substrate/frame/contracts/src/wasm/runtime.rs#L267 - let base_weight: Weight = contract_host_weight.return_per_byte.saturating_mul(len.into()); - - // debug_message weight is a good approximation of the additional overhead of going - // from contract layer to substrate layer. - // reference: https://github.com/paritytech/ink-examples/blob/b8d2caa52cf4691e0ddd7c919e4462311deb5ad0/psp22-extension/runtime/psp22-extension-example.rs#L236 - let overhead = contract_host_weight.debug_message; - - let charged_weight = env.charge_weight(base_weight.saturating_add(overhead))?; - log::debug!(target: LOG_TARGET, "{} charged weight: {:?}", log_prefix, charged_weight); - - Ok(charged_weight) -} - -fn dispatch(env: Environment) -> Result<(), DispatchError> -where - T: pallet_contracts::Config - + frame_system::Config, - RuntimeOrigin: From>, - E: Ext, -{ - const LOG_PREFIX: &str = " dispatch |"; - - let mut env = env.buf_in_buf_out(); - let len = env.in_len(); - - charge_overhead_weight::(&mut env, len, LOG_PREFIX)?; - - // read the input as RuntimeCall - let call: RuntimeCall = env.read_as_unbounded(len)?; - - log::debug!(target: LOG_TARGET, "Read input as call successfully"); - - // contract is the origin by default - let origin: RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); - - dispatch_call::(&mut env, call, origin, LOG_PREFIX) -} - -fn read_state(env: Environment) -> Result<(), DispatchError> -where - T: pallet_contracts::Config - + pallet_assets::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config - + frame_system::Config, - E: Ext, -{ - const LOG_PREFIX: &str = " read_state |"; - - let mut env = env.buf_in_buf_out(); - - // To be conservative, we charge the weight for reading the input bytes of a fixed-size type. - let base_weight: Weight = ContractSchedule::::get() - .host_fn_weights - .return_per_byte - .saturating_mul(env.in_len().into()); - let charged_weight = env.charge_weight(base_weight)?; - - log::debug!(target:LOG_TARGET, "{} charged weight: {:?}", LOG_PREFIX, charged_weight); - - let key: RuntimeStateKeys = env.read_as()?; - - let result = match key { - RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, &mut env), - RuntimeStateKeys::ParachainSystem(key) => { - read_parachain_system_state::(key, &mut env) - }, - RuntimeStateKeys::Assets(key) => read_assets_state::(key, &mut env), - }? - .encode(); - - log::trace!( - target:LOG_TARGET, - "{} result: {:?}.", LOG_PREFIX, result - ); - env.write(&result, false, None).map_err(|e| { - log::trace!(target: LOG_TARGET, "{:?}", e); - // TODO: Other error. - DispatchError::Other("unable to write results to contract memory") - }) -} - fn read_parachain_system_state( key: ParachainSystemKeys, env: &mut Environment, @@ -320,10 +332,10 @@ where ) .encode()) }, - AssetsKeys::AssetExists(id) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_assets::Pallet::::asset_exists(id).encode()) - }, + // AssetsKeys::AssetExists(id) => { + // env.charge_weight(T::DbWeight::get().reads(1_u64))?; + // Ok(pallet_assets::Pallet::::asset_exists(id).encode()) + // }, AssetsKeys::BalanceOf(id, owner) => { env.charge_weight(T::DbWeight::get().reads(1_u64))?; Ok(pallet_assets::Pallet::::balance(id, &owner.0.into()) @@ -333,63 +345,10 @@ where env.charge_weight(T::DbWeight::get().reads(1_u64))?; Ok(pallet_assets::Pallet::::total_supply(id).encode()) }, + _ => todo!(), } } -fn send_xcm(env: Environment) -> Result<(), DispatchError> -where - T: pallet_contracts::Config - + frame_system::Config< - RuntimeOrigin = RuntimeOrigin, - AccountId = AccountId, - RuntimeCall = RuntimeCall, - >, - E: Ext, -{ - const LOG_PREFIX: &str = " send_xcm |"; - - let mut env = env.buf_in_buf_out(); - let len = env.in_len(); - - let _ = charge_overhead_weight::(&mut env, len, LOG_PREFIX)?; - - // read the input as CrossChainMessage - let xc_call: CrossChainMessage = env.read_as::()?; - - // Determine the call to dispatch - let (dest, message) = match xc_call { - CrossChainMessage::Relay(message) => { - let dest = Location::parent().into_versioned(); - let assets: Asset = (Here, 10 * UNIT).into(); - let beneficiary: Location = - AccountId32 { id: (env.ext().address().clone()).into(), network: None }.into(); - let message = Xcm::builder() - .withdraw_asset(assets.clone().into()) - .buy_execution(assets.clone(), Unlimited) - .transact( - SovereignAccount, - Weight::from_parts(250_000_000, 10_000), - message.encode().into(), - ) - .refund_surplus() - .deposit_asset(assets.into(), beneficiary) - .build(); - (dest, message) - }, - }; - - // TODO: revisit to replace with signed contract origin - let origin: RuntimeOrigin = RawOrigin::Root.into(); - - // Generate runtime call to dispatch - let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::send { - dest: Box::new(dest), - message: Box::new(VersionedXcm::V4(message)), - }); - - dispatch_call::(&mut env, call, origin, LOG_PREFIX) -} - #[cfg(test)] mod tests { use super::*; From 924df85ebd353cd56ff816f722fc8cdb4a6c5956 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Tue, 2 Jul 2024 15:51:16 +0200 Subject: [PATCH 016/161] refactor: draft final design --- Cargo.lock | 3 +- pop-api/Cargo.toml | 4 +- pop-api/examples/fungibles/lib.rs | 119 ++--- pop-api/integration-tests/Cargo.toml | 4 +- .../integration-tests/src/local_fungibles.rs | 11 +- pop-api/src/error.rs | 335 ------------ pop-api/src/lib.rs | 85 ++- pop-api/src/primitives.rs | 1 - pop-api/src/v0/assets/fungibles.rs | 45 +- pop-api/src/v0/assets/mod.rs | 446 +++------------- pop-api/src/v0/balances.rs | 30 +- pop-api/src/v0/cross_chain/mod.rs | 29 +- pop-api/src/v0/mod.rs | 15 - pop-api/src/v0/nfts.rs | 37 +- pop-api/src/v0/state.rs | 7 - primitives/Cargo.toml | 7 - primitives/src/lib.rs | 124 ++++- primitives/src/storage_keys.rs | 13 +- runtime/devnet/Cargo.toml | 3 +- .../src/{extensions.rs => extensions/mod.rs} | 496 +++++++++++------- runtime/devnet/src/extensions/v0/assets.rs | 39 ++ runtime/devnet/src/extensions/v0/error.rs | 298 +++++++++++ runtime/devnet/src/extensions/v0/mod.rs | 2 + runtime/testnet/Cargo.toml | 2 +- runtime/testnet/src/extensions.rs | 18 +- 25 files changed, 1013 insertions(+), 1160 deletions(-) delete mode 100644 pop-api/src/error.rs delete mode 100644 pop-api/src/v0/state.rs rename runtime/devnet/src/{extensions.rs => extensions/mod.rs} (79%) create mode 100644 runtime/devnet/src/extensions/v0/assets.rs create mode 100644 runtime/devnet/src/extensions/v0/error.rs create mode 100644 runtime/devnet/src/extensions/v0/mod.rs diff --git a/Cargo.lock b/Cargo.lock index d798562b..cf7abf73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9675,8 +9675,6 @@ version = "0.0.0" dependencies = [ "bounded-collections 0.1.9", "parity-scale-codec", - "scale-decode", - "scale-encode", "scale-info", ] @@ -9744,6 +9742,7 @@ dependencies = [ "polkadot-runtime-common", "pop-primitives", "pop-runtime-common", + "rand", "scale-info", "smallvec", "sp-api", diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 82ee7613..dc48ea8a 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -9,9 +9,8 @@ edition = "2021" enumflags2 = { version = "0.7.7" } ink = { version = "5.0.0", default-features = false } sp-io = { version = "31.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } -sp-runtime = { version = "32.0.0", default-features = false } -pop-primitives = { path = "../primitives", features = ["devnet"], default-features = false } +pop-primitives = { path = "../primitives", default-features = false } [lib] name = "pop_api" @@ -25,7 +24,6 @@ std = [ "ink/std", "pop-primitives/std", "sp-io/std", - "sp-runtime/std", ] assets = ["pop-primitives/assets"] balances = [] diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 1794fbe5..03841b74 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -8,13 +8,13 @@ use ink::prelude::vec::Vec; use pop_api::{ assets::fungibles::{self as api}, - error::StatusCode, - primitives::{AccountId as AccountId32, AssetId}, + primitives::AssetId, + StatusCode, }; pub type Result = core::result::Result; -#[ink::contract(env = pop_api::Environment)] +#[ink::contract] mod fungibles { use super::*; @@ -41,141 +41,84 @@ mod fungibles { #[ink(message)] pub fn total_supply(&self, id: AssetId) -> Result { - // api::total_supply(id).map_err(|e| e.into()) api::total_supply(id) } #[ink(message)] - pub fn balance_of(&self, id: AssetId, owner: AccountId32) -> Result { - // api::balance_of(id, owner).map_err(|e| e.into()) + pub fn balance_of(&self, id: AssetId, owner: AccountId) -> Balance { api::balance_of(id, owner) } #[ink(message)] - pub fn allowance( - &self, - id: AssetId, - owner: AccountId32, - spender: AccountId32, - ) -> Result { - // api::allowance(id, owner, spender).map_err(|e| e.into()) + pub fn allowance(&self, id: AssetId, owner: AccountId, spender: AccountId) -> Balance { api::allowance(id, owner, spender) } #[ink(message)] - pub fn transfer(&self, id: AssetId, to: AccountId32, value: Balance) -> Result<()> { - ink::env::debug_println!( - "PopApiFungiblesExample::transfer: id: {:?}, to: {:?} value: {:?}", - id, - to, - value, - ); - - let result = api::transfer(id, to, value); - ink::env::debug_println!("Result: {:?}", result); - // result.map_err(|e| e.into()) - result + pub fn transfer(&self, id: AssetId, to: AccountId, value: Balance) -> Result<()> { + api::transfer(id, to, value)?; + Ok(()) } #[ink(message)] pub fn transfer_from( &self, id: AssetId, - from: AccountId32, - to: AccountId32, + from: AccountId, + to: AccountId, value: Balance, // In the standard a `[u8]`, but the size needs to be known at compile time. _data: Vec, ) -> Result<()> { - ink::env::debug_println!( - "PopApiFungiblesExample::transfer_from: id: {:?}, from: {:?}, to: {:?} value: {:?}", - id, - from, - to, - value, - ); - - let result = api::transfer_from(id, from, to, value); - ink::env::debug_println!("Result: {:?}", result); - // result.map_err(|e| e.into()) - result + api::transfer_from(id, from, to, value)?; + Ok(()) } #[ink(message)] - pub fn approve(&self, id: AssetId, spender: AccountId32, value: Balance) -> Result<()> { - ink::env::debug_println!( - "PopApiFungiblesExample::approve: id: {:?}, spender {:?}, value: {:?}", - id, - spender, - value, - ); - - let result = api::approve(id, spender, value); - ink::env::debug_println!("Result: {:?}", result); - // result.map_err(|e| e.into()) - result + pub fn approve(&self, id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + api::approve(id, spender, value)?; + Ok(()) } #[ink(message)] pub fn increase_allowance( &self, id: AssetId, - spender: AccountId32, + spender: AccountId, value: Balance, ) -> Result<()> { - ink::env::debug_println!( - "PopApiFungiblesExample::increase_allowance: id: {:?}, spender {:?}, value: {:?}", - id, - spender, - value, - ); - - let result = api::increase_allowance(id, spender, value); - ink::env::debug_println!("Result: {:?}", result); - // result.map_err(|e| e.into()) - result + api::increase_allowance(id, spender, value)?; + Ok(()) } #[ink(message)] pub fn decrease_allowance( &self, id: AssetId, - spender: AccountId32, + spender: AccountId, value: Balance, ) -> Result<()> { - ink::env::debug_println!( - "PopApiFungiblesExample::decrease_allowance: id: {:?}, spender {:?}, value: {:?}", - id, - spender, - value, - ); - - let result = api::decrease_allowance(id, spender, value); - ink::env::debug_println!("Result: {:?}", result); - // result.map_err(|e| e.into()) - result + api::decrease_allowance(id, spender, value)?; + Ok(()) } - /// 2. PSP-22 Metadata Interface: - /// - token_name - /// - token_symbol - /// - token_decimals + // 2. PSP-22 Metadata Interface: + // - token_name + // - token_symbol + // - token_decimals #[ink(message)] - pub fn token_name(&self, id: AssetId) -> Result> { - // api::token_name(id).map_err(|e| e.into()) + pub fn token_name(&self, id: AssetId) -> Vec { api::token_name(id) } #[ink(message)] - pub fn token_symbol(&self, id: AssetId) -> Result> { - // api::token_symbol(id).map_err(|e| e.into()) + pub fn token_symbol(&self, id: AssetId) -> Vec { api::token_symbol(id) } #[ink(message)] - pub fn token_decimals(&self, id: AssetId) -> Result { - // api::token_decimals(id).map_err(|e| e.into()) + pub fn token_decimals(&self, id: AssetId) -> u8 { api::token_decimals(id) } @@ -189,7 +132,7 @@ mod fungibles { // - clear_metadata // #[ink(message)] - // pub fn create(&self, id: AssetId, admin: AccountId32, min_balance: Balance) -> Result<()> { + // pub fn create(&self, id: AssetId, admin: AccountId, min_balance: Balance) -> Result<()> { // ink::env::debug_println!( // "PopApiFungiblesExample::create: id: {:?} admin: {:?} min_balance: {:?}", // id, @@ -198,8 +141,8 @@ mod fungibles { // ); // let result = api::create(id, admin, min_balance); // ink::env::debug_println!("Result: {:?}", result); - // // result.map_err(|e| e.into()) - // result + // result.map_err(|e| e.into()) + // result // } // #[ink(message)] diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml index 84769433..c855a884 100644 --- a/pop-api/integration-tests/Cargo.toml +++ b/pop-api/integration-tests/Cargo.toml @@ -10,7 +10,7 @@ frame-support = { version = "29.0.0", default-features = false } frame-system = { version = "29.0.0", default-features = false } pallet-balances = { version = "29.0.2", default-features = false } pallet-contracts = { version = "28.0.0", default-features = false } -pop-api = { path = "../.", default-features = false, features = ["assets"] } +pop-primitives = { path = "../../primitives", default-features = false, features = ["assets"] } pop-runtime-devnet = { path = "../../runtime/devnet", default-features = false } sp-io = { version = "31.0.0", default-features = false } sp-runtime = { version = "32.0.0", default-features = false } @@ -23,7 +23,7 @@ std = [ "frame-system/std", "pallet-balances/std", "pallet-contracts/std", - "pop-api/std", + "pop-primitives/std", "pop-runtime-devnet/std", "scale/std", "sp-io/std", diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs index 1b3c6633..968c43eb 100644 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -1,5 +1,5 @@ use super::*; -use pop_api::error::{ +use pop_primitives::error::{ ArithmeticError::*, Error::{self, *}, TokenError::*, @@ -8,7 +8,10 @@ use pop_api::error::{ const ASSET_ID: AssetId = 1; fn decoded(result: ExecReturnValue) -> T { - ::decode(&mut &result.data[2..]).unwrap() + match ::decode(&mut &result.data[2..]) { + Ok(value) => value, + Err(_) => panic!("\nTest failed by trying to decode result: {:?} into `T`\n", result), + } } fn allowance( @@ -78,7 +81,9 @@ fn transfer( ) -> ExecReturnValue { let function = function_selector("transfer"); let params = [function, asset_id.encode(), to.encode(), value.encode()].concat(); - do_bare_call(addr, params, 0).expect("should work") + let result = do_bare_call(addr, params, 0).expect("should work"); + println!("Transfer result: {:?}", result); + result } fn transfer_from( diff --git a/pop-api/src/error.rs b/pop-api/src/error.rs deleted file mode 100644 index 8989464f..00000000 --- a/pop-api/src/error.rs +++ /dev/null @@ -1,335 +0,0 @@ -use ink::{env::chain_extension::FromStatusCode, scale::Decode}; - -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub struct StatusCode(pub u32); - -impl From for StatusCode { - fn from(value: u32) -> Self { - StatusCode(value) - } -} -impl FromStatusCode for StatusCode { - fn from_status_code(status_code: u32) -> Result<(), Self> { - match status_code { - 0 => Ok(()), - _ => Err(StatusCode(status_code)), - } - } -} - -impl From for StatusCode { - fn from(_: ink::scale::Error) -> Self { - StatusCode(255u32) - } -} - -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -#[repr(u8)] -pub enum Error { - /// Some unknown error occurred. Go to the Pop API docs section `Pop API error`. - Other { - // Index within the `DispatchError` - dispatch_error_index: u8, - // Index within the `DispatchError` variant. - error_index: u8, - // Index for further nesting, e.g. pallet error. - error: u8, - } = 0, - /// Failed to lookup some data. - CannotLookup = 1, - /// A bad origin. - BadOrigin = 2, - /// A custom error in a module. - Module { - index: u8, - error: u8, - } = 3, - /// At least one consumer is remaining so the account cannot be destroyed. - ConsumerRemaining = 4, - /// There are no providers so the account cannot be created. - NoProviders = 5, - /// There are too many consumers so the account cannot be created. - TooManyConsumers = 6, - /// An error to do with tokens. - Token(TokenError) = 7, - /// An arithmetic error. - Arithmetic(ArithmeticError) = 8, - /// The number of transactional layers has been reached, or we are not in a transactional - /// layer. - Transactional(TransactionalError) = 9, - /// Resources exhausted, e.g. attempt to read/write data which is too large to manipulate. - Exhausted = 10, - /// The state is corrupt; this is generally not going to fix itself. - Corruption = 11, - /// Some resource (e.g. a preimage) is unavailable right now. This might fix itself later. - Unavailable = 12, - /// Root origin is not allowed. - RootNotAllowed = 13, - UnknownFunctionId = 254, - DecodingFailed = 255, -} - -#[cfg(test)] -impl From for StatusCode { - fn from(value: Error) -> Self { - let mut encoded_error = value.encode(); - // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). - encoded_error.resize(4, 0); - StatusCode::from( - u32::decode(&mut &encoded_error[..]).expect("qid, resized to 4 bytes line above"), - ) - } -} - -impl From for Error { - fn from(value: StatusCode) -> Self { - let mut encoded: [u8; 4] = value.0.to_le_bytes(); - match Error::decode(&mut &encoded[..]) { - Err(_) => { - encoded[..].rotate_right(1); - encoded[0] = 0u8; - Error::decode(&mut &encoded[..]).unwrap_or(Error::DecodingFailed) - }, - Ok(error) => error, - } - } -} - -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub enum TokenError { - /// Funds are unavailable. - FundsUnavailable, - /// Some part of the balance gives the only provider reference to the account and thus cannot - /// be (re)moved. - OnlyProvider, - /// Account cannot exist with the funds that would be given. - BelowMinimum, - /// Account cannot be created. - CannotCreate, - /// The asset in question is unknown. - UnknownAsset, - /// Funds exist but are frozen. - Frozen, - /// Operation is not supported by the asset. - Unsupported, - /// Account cannot be created for a held balance. - CannotCreateHold, - /// Withdrawal would cause unwanted loss of account. - NotExpendable, - /// Account cannot receive the assets. - Blocked, -} - -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub enum ArithmeticError { - /// Underflow. - Underflow, - /// Overflow. - Overflow, - /// Division by zero. - DivisionByZero, -} - -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub enum TransactionalError { - /// Too many transactional layers have been spawned. - LimitReached, - /// A transactional layer was expected, but does not exist. - NoLayer, -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::error::{ArithmeticError::*, TokenError::*, TransactionalError::*}; - - #[test] - fn u32_always_encodes_to_4_bytes() { - assert_eq!(0u32.encode().len(), 4); - assert_eq!(u32::MAX.encode().len(), 4); - } - - // Decodes 4 bytes into a `u32` and converts it into `StatusCode`. - fn into_status_code(encoded_error: [u8; 4]) -> StatusCode { - let decoded_u32 = u32::decode(&mut &encoded_error[..]).unwrap(); - StatusCode::from_status_code(decoded_u32).unwrap_err() - } - - // Decodes 4 bytes into a `u32` and converts it into `Error`. - fn into_error(encoded_error: [u8; 4]) -> Error { - let decoded_u32 = u32::decode(&mut &encoded_error[..]).unwrap(); - let status_code = StatusCode::from_status_code(decoded_u32).unwrap_err(); - status_code.into() - } - - // Tests the `From` implementation for `Error`. - // - // Unit variants: - // If the encoded value indicates a nested `Error` which is known by the Pop API version as a - // unit variant, the encoded value is converted into `Error::Other`. - // - // Example: the error `BadOrigin` (encoded: `[2, 0, 0, 0]`) with a non-zero value for one - // of the bytes [1..4]: `[2, 0, 1, 0]` is converted into `[0, 2, 0, 1]`. This is decoded to - // `Error::Other { dispatch_error: 2, index: 0, error: 1 }`. - #[test] - fn unit_error_variants() { - let errors = vec![ - CannotLookup, - BadOrigin, - ConsumerRemaining, - NoProviders, - TooManyConsumers, - Exhausted, - Corruption, - Unavailable, - RootNotAllowed, - DecodingFailed, - ]; - // Four scenarios, 2 tests each: - // 1. Compare a `StatusCode`, which is converted from an encoded value, with a `StatusCode` - // converted from an `Error`. - // 2. Compare an `Error, which is converted from an encoded value, with the expected `Error`. - for (i, &error_code) in UNIT_ERRORS.iter().enumerate() { - // No nesting and unit variant correctly returned. - assert_eq!(into_status_code([error_code, 0, 0, 0]), errors[i].into()); - assert_eq!(into_error([error_code, 0, 0, 0]), errors[i]); - // Unexpected second byte nested. - assert_eq!( - into_status_code([error_code, 1, 0, 0]), - (Other { dispatch_error_index: error_code, error_index: 1, error: 0 }).into(), - ); - assert_eq!(into_error([error_code, 1, 0, 0]), errors[i]); - // Unexpected third byte nested. - assert_eq!( - into_status_code([error_code, 1, 1, 0]), - (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), - ); - assert_eq!(into_error([error_code, 1, 1, 0]), errors[i]); - // Unexpected fourth byte nested. - assert_eq!( - into_status_code([error_code, 1, 1, 1]), - (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), - ); - assert_eq!(into_error([error_code, 1, 1, 1]), errors[i]); - } - } - - // Single nested variants: - // If the encoded value indicates a double nested `Error` which is known by the Pop API version - // as a single nested variant, the encoded value is converted into `Error::Other`. - // - // Example: the error `Arithmetic(Overflow)` (encoded: `[8, 1, 0, 0]`) with a non-zero - // value for one of the bytes [2..4]: `[8, 1, 1, 0]` is converted into `[0, 8, 1, 1]`. This is - // decoded to `Error::Other { dispatch_error: 8, index: 1, error: 1 }`. - #[test] - fn single_nested_error_variants() { - let errors = vec![ - [Token(FundsUnavailable), Token(OnlyProvider)], - [Arithmetic(Underflow), Arithmetic(Overflow)], - [Transactional(LimitReached), Transactional(NoLayer)], - ]; - // Four scenarios, 2 tests each: - // 1. Compare a `StatusCode`, which is converted from an encoded value, with a `StatusCode` - // converted from an `Error`. - // 2. Compare an `Error, which is converted from an encoded value, with the expected `Error`. - for (i, &error_code) in SINGLE_NESTED_ERRORS.iter().enumerate() { - // No nesting and unit variant correctly returned. - assert_eq!(into_status_code([error_code, 0, 0, 0]), errors[i][0].into()); - assert_eq!(into_error([error_code, 0, 0, 0]), errors[i][0]); - // Allowed single nesting variant correctly returned. - assert_eq!(into_status_code([error_code, 1, 0, 0]), errors[i][1].into()); - assert_eq!(into_error([error_code, 1, 0, 0]), errors[i][1]); - // Unexpected third byte nested. - assert_eq!( - into_status_code([error_code, 1, 1, 0]), - (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), - ); - assert_eq!(into_error([error_code, 1, 1, 0]), errors[i][1]); - // Unexpected fourth byte nested. - assert_eq!( - into_status_code([error_code, 1, 1, 1]), - (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }).into(), - ); - assert_eq!(into_error([error_code, 1, 1, 1]), errors[i][1]); - } - } - - // Double nested variants: - // If the encoded value indicates a triple nested `Error` which is known by the Pop API version - // as a double nested variant, the encoded value is converted into `Error::Other`. - // - // Example: the error `Module { index: 10, error 5 }` (encoded: `[3, 10, 5, 0]`) with a non-zero - // value for the last byte: `[3, 10, 5, 3]` is converted into `[0, 3, 10, 5]`. This is - // decoded to `Error::Other { dispatch_error: 3, index: 10, error: 5 }`. - #[test] - fn double_nested_error_variants() { - // Four scenarios, 2 tests each: - // 1. Compare a `StatusCode`, which is converted from an encoded value, with a `StatusCode` - // converted from an `Error`. - // 2. Compare an `Error, which is converted from an encoded value, with the expected `Error`. - // - // No nesting and unit variant correctly returned. - assert_eq!(into_status_code([3, 0, 0, 0]), (Module { index: 0, error: 0 }).into()); - assert_eq!(into_error([3, 0, 0, 0]), Module { index: 0, error: 0 }); - // Allowed single nesting and variant correctly returned. - assert_eq!(into_status_code([3, 1, 0, 0]), (Module { index: 1, error: 0 }).into()); - assert_eq!(into_error([3, 1, 0, 0]), Module { index: 1, error: 0 }); - // Allowed double nesting and variant correctly returned. - assert_eq!(into_status_code([3, 1, 1, 0]), (Module { index: 1, error: 1 }).into()); - assert_eq!(into_error([3, 1, 1, 0]), Module { index: 1, error: 1 }); - // Unexpected fourth byte nested. - assert_eq!( - into_status_code([3, 1, 1, 1]), - (Other { dispatch_error_index: 3, error_index: 1, error: 1 }).into(), - ); - assert_eq!(into_error([3, 1, 1, 1]), Module { index: 1, error: 1 }); - } - - #[test] - fn single_nested_unknown_variants() { - // Unknown `TokenError` variant. - assert_eq!( - into_error([7, 10, 0, 0]), - Other { dispatch_error_index: 7, error_index: 10, error: 0 } - ); - assert_eq!( - into_status_code([7, 10, 0, 0]), - Other { dispatch_error_index: 7, error_index: 10, error: 0 }.into() - ); - // Unknown `Arithmetic` variant. - assert_eq!( - into_error([8, 3, 0, 0]), - Other { dispatch_error_index: 8, error_index: 3, error: 0 } - ); - assert_eq!( - into_status_code([8, 3, 0, 0]), - Other { dispatch_error_index: 8, error_index: 3, error: 0 }.into() - ); - // Unknown `Transactional` variant. - assert_eq!( - into_error([9, 2, 0, 0]), - Other { dispatch_error_index: 9, error_index: 2, error: 0 } - ); - assert_eq!( - into_status_code([9, 2, 0, 0]), - Other { dispatch_error_index: 9, error_index: 2, error: 0 }.into() - ); - } - - #[test] - fn test_random_encoded_values() { - assert_eq!( - into_error([100, 100, 100, 100]), - Other { dispatch_error_index: 100, error_index: 100, error: 100 } - ); - assert_eq!( - into_error([200, 200, 200, 200]), - Other { dispatch_error_index: 200, error_index: 200, error: 200 } - ); - } -} diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 55307f3e..cb27b17f 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,10 +1,8 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::{prelude::vec::Vec, ChainExtensionInstance}; -pub use sp_runtime::MultiAddress; +use ink::env::{chain_extension::FromStatusCode, DefaultEnvironment, Environment}; +use primitives::error::Error; -use crate::error::StatusCode; -use primitives::{storage_keys::*, AccountId as AccountId32}; #[cfg(feature = "assets")] pub use v0::assets; #[cfg(feature = "balances")] @@ -13,72 +11,49 @@ pub use v0::balances; pub use v0::cross_chain; #[cfg(feature = "nfts")] pub use v0::nfts; -use v0::{state, RuntimeCall}; -pub mod error; pub mod primitives; pub mod v0; -type AccountId = AccountId32; -// TODO: do the same as the AccountId above and check expanded macro code. -type Balance = ::Balance; +type AccountId = ::AccountId; +type Balance = ::Balance; #[cfg(any(feature = "nfts", feature = "cross-chain"))] -type BlockNumber = ::BlockNumber; +type BlockNumber = ::BlockNumber; pub type Result = core::result::Result; -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] -pub enum Environment {} +pub struct StatusCode(pub u32); -impl ink::env::Environment for Environment { - const MAX_EVENT_TOPICS: usize = - ::MAX_EVENT_TOPICS; - - type AccountId = ::AccountId; - type Balance = ::Balance; - type Hash = ::Hash; - type BlockNumber = ::BlockNumber; - type Timestamp = ::Timestamp; - - type ChainExtension = PopApi; +impl From for StatusCode { + fn from(value: u32) -> Self { + StatusCode(value) + } } - -#[ink::chain_extension(extension = 909)] -pub trait PopApi { - type ErrorCode = StatusCode; - - #[ink(function = 0)] - #[allow(private_interfaces)] - fn dispatch(call: RuntimeCall) -> Result<()>; - - #[ink(function = 1)] - #[allow(private_interfaces)] - fn read_state(key: RuntimeStateKeys) -> Result>; - - #[cfg(feature = "cross-chain")] - #[ink(function = 2)] - #[allow(private_interfaces)] - fn send_xcm(xcm: primitives::cross_chain::CrossChainMessage) -> Result<()>; +impl FromStatusCode for StatusCode { + fn from_status_code(status_code: u32) -> Result<()> { + match status_code { + 0 => Ok(()), + _ => Err(StatusCode(status_code)), + } + } } -#[inline] -fn dispatch(call: RuntimeCall) -> Result<()> { - <::ChainExtension as ChainExtensionInstance>::instantiate( - ) - .dispatch(call) +impl From for StatusCode { + fn from(_: ink::scale::Error) -> Self { + StatusCode(255u32) + } } -#[inline] -fn read_state(key: RuntimeStateKeys) -> Result> { - <::ChainExtension as ChainExtensionInstance>::instantiate( - ) - .read_state(key) +impl From for Error { + fn from(value: StatusCode) -> Self { + value.0.into() + } } -#[cfg(feature = "cross-chain")] -fn send_xcm(xcm: primitives::cross_chain::CrossChainMessage) -> Result<()> { - <::ChainExtension as ChainExtensionInstance>::instantiate( - ) - .send_xcm(xcm) +impl From for StatusCode { + fn from(value: Error) -> Self { + StatusCode::from(u32::from(value)) + } } diff --git a/pop-api/src/primitives.rs b/pop-api/src/primitives.rs index 17419d5b..e174a111 100644 --- a/pop-api/src/primitives.rs +++ b/pop-api/src/primitives.rs @@ -1,2 +1 @@ pub use pop_primitives::*; -pub use sp_runtime::MultiAddress; diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 376ca898..8d0de768 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,12 +1,6 @@ use ink::prelude::vec::Vec; -use crate::{ - assets, - primitives::{AssetId, MultiAddress}, - AccountId, Balance, StatusCode, -}; - -type Result = core::result::Result; +use crate::{assets, primitives::AssetId, AccountId, Balance, Result, StatusCode}; /// Local Fungibles: /// 1. PSP-22 Interface @@ -45,7 +39,7 @@ pub fn total_supply(id: AssetId) -> Result { /// # Returns /// The balance of the specified account, or an error if the operation fails. #[inline] -pub fn balance_of(id: AssetId, owner: AccountId) -> Result { +pub fn balance_of(id: AssetId, owner: AccountId) -> Balance { assets::balance_of(id, owner) } @@ -60,7 +54,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { /// # Returns /// The remaining allowance, or an error if the operation fails. #[inline] -pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { +pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Balance { assets::allowance(id, owner, spender) } @@ -75,11 +69,7 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result>, - value: Balance, -) -> Result<()> { +pub fn transfer(id: AssetId, to: AccountId, value: Balance) -> Result<()> { assets::transfer(id, to, value) } @@ -96,12 +86,7 @@ pub fn transfer( /// # Returns /// Returns `Ok(())` if successful, or an error if the transfer fails. #[inline] -pub fn transfer_from( - id: AssetId, - from: impl Into>, - to: impl Into>, - value: Balance, -) -> Result<()> { +pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { assets::transfer_approved(id, from, to, value) } @@ -161,7 +146,7 @@ pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re /// # Returns /// The name of the token as a byte vector, or an error if the operation fails. #[inline] -pub fn token_name(id: AssetId) -> Result> { +pub fn token_name(id: AssetId) -> Vec { assets::token_name(id) } @@ -173,7 +158,7 @@ pub fn token_name(id: AssetId) -> Result> { /// # Returns /// The symbol of the token as a byte vector, or an error if the operation fails. #[inline] -pub fn token_symbol(id: AssetId) -> Result> { +pub fn token_symbol(id: AssetId) -> Vec { assets::token_symbol(id) } @@ -185,7 +170,7 @@ pub fn token_symbol(id: AssetId) -> Result> { /// # Returns /// The number of decimals of the token as a byte vector, or an error if the operation fails. #[inline] -pub fn token_decimals(id: AssetId) -> Result { +pub fn token_decimals(id: AssetId) -> u8 { assets::token_decimals(id) } @@ -291,6 +276,7 @@ pub fn token_decimals(id: AssetId) -> Result { // assets::asset_exists(id) // } +// TODO: further implement the rest of the interfaces and conclude on the FungiblesError. #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum FungiblesError { @@ -311,13 +297,13 @@ pub enum FungiblesError { NoPermission, /// The given asset ID is unknown. Unknown, - // // TODO: - // // - Originally `InsufficientBalance` for the deposit but this would result in the same error - // // as the error when there is insufficient balance for transferring an asset. + // - Originally `InsufficientBalance` for the deposit but this would result in the same error + // as the error when there is insufficient balance for transferring an asset. /// No balance for creation of assets or fees. NoBalance, } +// TODO: include conversions from TokenError and add conversions based on added interfaces. impl From for FungiblesError { fn from(value: StatusCode) -> Self { let encoded = value.0.to_le_bytes(); @@ -339,10 +325,10 @@ impl From for FungiblesError { #[cfg(test)] mod tests { - use scale::Decode; + use ink::scale::Decode; use super::FungiblesError; - use crate::error::{ + use crate::primitives::error::{ ArithmeticError::*, Error::{self, *}, TokenError::*, @@ -355,6 +341,7 @@ mod tests { status_code.into() } + // If we ever want to change the conversion from bytes to `u32`. #[test] fn status_code_vs_encoded() { assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); @@ -373,6 +360,7 @@ mod tests { Other { dispatch_error_index: 5, error_index: 5, error: 1 }, CannotLookup, BadOrigin, + // `ModuleError` other than assets module. Module { index: 2, error: 5 }, ConsumerRemaining, NoProviders, @@ -384,6 +372,7 @@ mod tests { Corruption, Unavailable, RootNotAllowed, + UnknownFunctionId, DecodingFailed, ]; for error in errors { diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 241c5020..22657323 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,17 +1,18 @@ -use ink::{prelude::vec::Vec, scale::Compact}; +use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec, scale::Decode}; -use crate::{state::read, Balance, RuntimeCall, *}; -use primitives::{AssetId, MultiAddress}; +use crate::{primitives::AssetId, AccountId, Balance, Result, StatusCode}; pub mod fungibles; -type Result = core::result::Result; +const ASSETS_MODULE: u8 = 52; +const VERSION: u8 = 0; /// [Pallet Assets](https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/lib.rs): /// 1. Dispatchables /// 2. Read state functions /// /// 1. Dispatchables within pallet assets (TrustBackedAssets instance): +const DISPATCH: u8 = 0; /// - create /// - start_destroy /// - destroy_accounts @@ -21,25 +22,12 @@ type Result = core::result::Result; /// - burn /// - transfer /// - transfer_keep_alive -/// - force_transfer -/// - freeze -/// - thaw -/// - freeze_asset -/// - thaw_asset -/// - transfer_ownership -/// - set_team +const TRANSFER_KEEP_ALIVE: u8 = 9; /// - set_metadata /// - clear_metadata /// - approve_transfer /// - cancel_approval -/// - force_cancel_approval /// - transfer_approved -/// - touch -/// - refund -/// - set_min_balance -/// - touch_other -/// - refund_other -/// - block /// Issue a new class of fungible assets from a public origin. // pub(crate) fn create( @@ -98,16 +86,18 @@ type Result = core::result::Result; /// Move some assets from the sender account to another. #[inline] -pub(crate) fn transfer( - id: AssetId, - target: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { - id: id.into(), - target: target.into(), - amount: Compact(amount), - })) +pub fn transfer(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { + ChainExtensionMethod::build(u32::from_le_bytes([ + VERSION, + DISPATCH, + ASSETS_MODULE, + // TODO: E.D. is always respected with transferring tokens via the API. + TRANSFER_KEEP_ALIVE, + ])) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, target, amount)) } // /// Move some assets from the sender account to another, keeping the sender account alive. @@ -122,68 +112,8 @@ pub(crate) fn transfer( // amount: Compact(amount), // })) // } -// -// /// Move some assets from one account to another. Sender should be the Admin of the asset `id`. -// pub(crate) fn force_transfer( -// id: AssetId, -// source: impl Into>, -// dest: impl Into>, -// amount: Balance, -// ) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::ForceTransfer { -// id: id.into(), -// source: source.into(), -// dest: dest.into(), -// amount: Compact(amount), -// })) -// } -// -// /// Disallow further unprivileged transfers of an asset `id` from an account `who`. `who` -// /// must already exist as an entry in `Account`s of the asset. If you want to freeze an -// /// account that does not have an entry, use `touch_other` first. -// pub(crate) fn freeze(id: AssetId, who: impl Into>) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::Freeze { id: id.into(), who: who.into() })) -// } -// -// /// Allow unprivileged transfers to and from an account again. -// pub(crate) fn thaw(id: AssetId, who: impl Into>) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::Thaw { id: id.into(), who: who.into() })) -// } -// -// /// Disallow further unprivileged transfers for the asset class. -// pub(crate) fn freeze_asset(id: AssetId) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::FreezeAsset { id: id.into() })) -// } -// -// /// Allow unprivileged transfers for the asset again. -// pub(crate) fn thaw_asset(id: AssetId) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::ThawAsset { id: id.into() })) -// } -// -// /// Change the Owner of an asset. -// pub(crate) fn transfer_ownership(id: AssetId, owner: impl Into>) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::TransferOwnership { -// id: id.into(), -// owner: owner.into(), -// })) -// } -// -// /// Change the Issuer, Admin and Freezer of an asset. -// pub(crate) fn set_team( -// id: AssetId, -// issuer: impl Into>, -// admin: impl Into>, -// freezer: impl Into>, -// ) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::SetTeam { -// id: id.into(), -// issuer: issuer.into(), -// admin: admin.into(), -// freezer: freezer.into(), -// })) -// } -/// Set the metadata for an asset. +// /// Set the metadata for an asset. // pub(crate) fn set_metadata( // id: AssetId, // name: Vec, @@ -200,315 +130,111 @@ pub(crate) fn transfer( /// Approve an amount of asset for transfer by a delegated third-party account. #[inline] -pub(crate) fn approve_transfer( - id: AssetId, - delegate: impl Into>, - amount: Balance, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::ApproveTransfer { - id: id.into(), - delegate: delegate.into(), - amount: Compact(amount), - })) +pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Result<()> { + ChainExtensionMethod::build(u32::from_le_bytes([0u8, 0, 52, 69])) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, delegate, amount)) } /// Cancel all of some asset approved for delegated transfer by a third-party account. #[inline] -pub(crate) fn cancel_approval( - id: AssetId, - delegate: impl Into>, -) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::CancelApproval { - id: id.into(), - delegate: delegate.into(), - })) +pub fn cancel_approval(id: AssetId, delegate: AccountId) -> Result<()> { + ChainExtensionMethod::build(0) + .input::<(AssetId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(id, delegate)) } -// /// Cancel all of some asset approved for delegated transfer by a third-party account. -// pub(crate) fn force_cancel_approval( -// id: AssetId, -// owner: impl Into>, -// delegate: impl Into>, -// ) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::ForceCancelApproval { -// id: id.into(), -// owner: owner.into(), -// delegate: delegate.into(), -// })) -// } - /// Transfer some asset balance from a previously delegated account to some third-party /// account. #[inline] -pub(crate) fn transfer_approved( +pub fn transfer_approved( id: AssetId, - owner: impl Into>, - destination: impl Into>, + from: AccountId, + to: AccountId, amount: Balance, ) -> Result<()> { - dispatch(RuntimeCall::Assets(AssetsCall::TransferApproved { - id: id.into(), - owner: owner.into(), - destination: destination.into(), - amount: Compact(amount), - })) + ChainExtensionMethod::build(0) + .input::<(AssetId, AccountId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, from, to, amount)) } -// -// /// Create an asset account for non-provider assets. -// pub(crate) fn touch(id: AssetId) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::Touch { id: id.into() })) -// } -// -// /// Return the deposit (if any) of an asset account or a consumer reference (if any) of an -// /// account. -// pub(crate) fn refund(id: AssetId, allow_burn: bool) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::Refund { id: id.into(), allow_burn })) -// } -// -// /// Sets the minimum balance of an asset. -// pub(crate) fn set_min_balance(id: AssetId, min_balance: Balance) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::SetMinBalance { -// id: id.into(), -// min_balance: Compact(min_balance), -// })) -// } -// -// /// Create an asset account for `who`. -// pub(crate) fn touch_other(id: AssetId, who: impl Into>) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::TouchOther { id: id.into(), who: who.into() })) -// } -// -// /// Return the deposit (if any) of a target asset account. Useful if you are the depositor. -// pub(crate) fn refund_other(id: AssetId, who: impl Into>) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::RefundOther { id: id.into(), who: who.into() })) -// } -// -// /// Disallow further unprivileged transfers of an asset `id` to and from an account `who`. -// pub(crate) fn block(id: AssetId, who: impl Into>) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::Block { id: id.into(), who: who.into() })) -// } /// 2. Read state functions +const READ_STATE: u8 = 1; /// - total_supply +const TOTAL_SUPPLY: u8 = 0; /// - balance_of /// - allowance /// - asset_exists /// - token_name /// - token_symbol /// - token_decimals -// + #[inline] -pub(crate) fn total_supply(id: AssetId) -> Result { - read(RuntimeStateKeys::Assets(AssetsKeys::TotalSupply(id))) +pub fn total_supply(id: AssetId) -> Result { + ChainExtensionMethod::build(u32::from_le_bytes([ + VERSION, + READ_STATE, + ASSETS_MODULE, + TOTAL_SUPPLY, + ])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) } #[inline] -pub(crate) fn balance_of(id: AssetId, owner: AccountId) -> Result { - read(RuntimeStateKeys::Assets(AssetsKeys::BalanceOf(id, owner))) +pub fn balance_of(id: AssetId, owner: AccountId) -> Balance { + ChainExtensionMethod::build(1) + .input::<(AssetId, AccountId)>() + .output::() + .ignore_error_code() + .call(&(id, owner)) } #[inline] -pub(crate) fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - read(RuntimeStateKeys::Assets(AssetsKeys::Allowance(id, owner, spender))) +pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Balance { + ChainExtensionMethod::build(1) + .input::<(AssetId, AccountId, AccountId)>() + .output::() + .ignore_error_code() + .call(&(id, owner, spender)) } -// pub(crate) fn asset_exists(id: AssetId) -> Result { -// state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))) -// } #[inline] -pub(crate) fn token_name(id: AssetId) -> Result> { - read(RuntimeStateKeys::Assets(AssetsKeys::TokenName(id))) +pub fn token_name(id: AssetId) -> Vec { + ChainExtensionMethod::build(1) + .input::() + .output::, false>() + .ignore_error_code() + .call(&(id)) } // #[inline] -pub(crate) fn token_symbol(id: AssetId) -> Result> { - read(RuntimeStateKeys::Assets(AssetsKeys::TokenSymbol(id))) +pub fn token_symbol(id: AssetId) -> Vec { + ChainExtensionMethod::build(1) + .input::() + .output::, false>() + .ignore_error_code() + .call(&(id)) } #[inline] -pub(crate) fn token_decimals(id: AssetId) -> Result { - read(RuntimeStateKeys::Assets(AssetsKeys::TokenDecimals(id))) +pub fn token_decimals(id: AssetId) -> u8 { + ChainExtensionMethod::build(1) + .input::() + .output::() + .ignore_error_code() + .call(&(id)) } -// Parameters to extrinsics representing an asset id (`AssetIdParameter`) and a balance amount (`Balance`) are expected -// to be compact encoded. The pop api handles that for the developer. -// -// reference: https://substrate.stackexchange.com/questions/1873/what-is-the-meaning-of-palletcompact-in-pallet-development -// -// Asset id that is compact encoded. -type AssetIdParameter = Compact; -// Balance amount that is compact encoded. -type BalanceParameter = Compact; -// -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub(crate) enum AssetsCall { - // #[codec(index = 0)] - // Create { id: AssetIdParameter, admin: MultiAddress, min_balance: Balance }, - // #[codec(index = 2)] - // StartDestroy { id: AssetIdParameter }, - // #[codec(index = 3)] - // DestroyAccounts { id: AssetIdParameter }, - // #[codec(index = 4)] - // DestroyApprovals { id: AssetIdParameter }, - // #[codec(index = 5)] - // FinishDestroy { id: AssetIdParameter }, - // #[codec(index = 6)] - // Mint { - // id: AssetIdParameter, - // beneficiary: MultiAddress, - // amount: BalanceParameter, - // }, - // #[codec(index = 7)] - // Burn { id: AssetIdParameter, who: MultiAddress, amount: BalanceParameter }, - // #[codec(index = 8)] - // Transfer { id: AssetIdParameter, target: MultiAddress, amount: BalanceParameter }, - #[codec(index = 9)] - TransferKeepAlive { - id: AssetIdParameter, - target: MultiAddress, - amount: BalanceParameter, - }, - // #[codec(index = 10)] - // ForceTransfer { - // id: AssetIdParameter, - // source: MultiAddress, - // dest: MultiAddress, - // amount: BalanceParameter, - // }, - // #[codec(index = 11)] - // Freeze { id: AssetIdParameter, who: MultiAddress }, - // #[codec(index = 12)] - // Thaw { id: AssetIdParameter, who: MultiAddress }, - // #[codec(index = 13)] - // FreezeAsset { id: AssetIdParameter }, - // #[codec(index = 14)] - // ThawAsset { id: AssetIdParameter }, - // #[codec(index = 15)] - // TransferOwnership { id: AssetIdParameter, owner: MultiAddress }, - // #[codec(index = 16)] - // SetTeam { - // id: AssetIdParameter, - // issuer: MultiAddress, - // admin: MultiAddress, - // freezer: MultiAddress, - // }, - // #[codec(index = 17)] - // SetMetadata { id: AssetIdParameter, name: Vec, symbol: Vec, decimals: u8 }, - // #[codec(index = 18)] - // ClearMetadata { id: AssetIdParameter }, - #[codec(index = 22)] - ApproveTransfer { - id: AssetIdParameter, - delegate: MultiAddress, - amount: BalanceParameter, - }, - #[codec(index = 23)] - CancelApproval { id: AssetIdParameter, delegate: MultiAddress }, - // #[codec(index = 24)] - // ForceCancelApproval { - // id: AssetIdParameter, - // owner: MultiAddress, - // delegate: MultiAddress, - // }, - #[codec(index = 25)] - TransferApproved { - id: AssetIdParameter, - owner: MultiAddress, - destination: MultiAddress, - amount: BalanceParameter, - }, - // // #[codec(index = 26)] - // // Touch { id: AssetIdParameter }, - // // #[codec(index = 27)] - // // Refund { id: AssetIdParameter, allow_burn: bool }, - // // #[codec(index = 28)] - // // SetMinBalance { id: AssetIdParameter, min_balance: BalanceParameter }, - // // #[codec(index = 29)] - // // TouchOther { id: AssetIdParameter, who: MultiAddress }, - // // #[codec(index = 30)] - // // RefundOther { id: AssetIdParameter, who: MultiAddress }, - // // #[codec(index = 31)] - // // Block { id: AssetIdParameter, who: MultiAddress }, - // } - - // // TODO: Not being used atm but necessary if we want to provide access to the - // // rest of the pallet, outside of the use cases. - // #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] - // #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] - // pub enum AssetsError { - // /// Account balance must be greater than or equal to the transfer amount. - // BalanceLow, - // /// The account to alter does not exist. - // NoAccount, - // /// The signing account has no permission to do the operation. - // NoPermission, - // /// The given asset ID is unknown. - // Unknown, - // /// The origin account is frozen. - // Frozen, - // /// The asset ID is already taken. - // InUse, - // /// Invalid witness data given. - // BadWitness, - // /// Minimum balance should be non-zero. - // MinBalanceZero, - // /// Unable to increment the consumer reference counters on the account. Either no provider - // /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or one - // /// fewer then the maximum number of consumers has been reached. - // UnavailableConsumer, - // /// Invalid metadata given. - // BadMetadata, - // /// No approval exists that would allow the transfer. - // Unapproved, - // /// The source account would not survive the transfer and it needs to stay alive. - // WouldDie, - // /// The asset-account already exists. - // AlreadyExists, - // /// The asset-account doesn't have an associated deposit. - // NoDeposit, - // /// The operation would result in funds being burned. - // WouldBurn, - // /// The asset is a live asset and is actively being used. Usually emit for operations such - // /// as `start_destroy` which require the asset to be in a destroying state. - // LiveAsset, - // /// The asset is not live, and likely being destroyed. - // AssetNotLive, - // /// The asset status is not the expected status. - // IncorrectStatus, - // /// The asset should be frozen before the given operation. - // NotFrozen, - // /// Callback action resulted in error. - // CallbackFailed, -} - -// -// impl TryFrom for AssetsError { -// type Error = Error; -// -// fn try_from(status_code: u32) -> core::result::Result { -// use AssetsError::*; -// match status_code { -// 0 => Ok(BalanceLow), -// 1 => Ok(NoAccount), -// 2 => Ok(NoPermission), -// 3 => Ok(Unknown), -// 4 => Ok(Frozen), -// 5 => Ok(InUse), -// 6 => Ok(BadWitness), -// 7 => Ok(MinBalanceZero), -// 8 => Ok(UnavailableConsumer), -// 9 => Ok(BadMetadata), -// 10 => Ok(Unapproved), -// 11 => Ok(WouldDie), -// 12 => Ok(AlreadyExists), -// 13 => Ok(NoDeposit), -// 14 => Ok(WouldBurn), -// 15 => Ok(LiveAsset), -// 16 => Ok(AssetNotLive), -// 17 => Ok(IncorrectStatus), -// 18 => Ok(NotFrozen), -// _ => todo!(), -// } -// } +// pub(crate) fn asset_exists(id: AssetId) -> Result { +// state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))) // } diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs index e14e6e32..bf029178 100644 --- a/pop-api/src/v0/balances.rs +++ b/pop-api/src/v0/balances.rs @@ -1,6 +1,9 @@ -use crate::{dispatch, primitives::MultiAddress, v0::RuntimeCall, AccountId, Error, StatusCode}; +use crate::{ + dispatch, primitives::MultiAddress, v0::RuntimeCall, AccountId, PopApiError, + PopApiError::UnknownStatusCode, +}; -type Result = core::result::Result; +type Result = core::result::Result; pub fn transfer_keep_alive( dest: impl Into>, @@ -14,7 +17,7 @@ pub fn transfer_keep_alive( #[derive(scale::Encode)] #[allow(dead_code)] -pub enum BalancesCall { +pub(crate) enum BalancesCall { #[codec(index = 3)] TransferKeepAlive { dest: MultiAddress, @@ -23,11 +26,9 @@ pub enum BalancesCall { }, } -// TODO: Not being used atm but necessary if we want to provide access to the -// rest of the pallet, outside of the use cases. #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum BalancesError { +pub enum Error { /// Vesting balance too high to send value. VestingBalance, /// Account liquidity restrictions prevent withdrawal. @@ -54,11 +55,11 @@ pub enum BalancesError { DeltaZero, } -impl TryFrom for BalancesError { - type Error = Error; +impl TryFrom for Error { + type Error = PopApiError; fn try_from(status_code: u32) -> core::result::Result { - use BalancesError::*; + use Error::*; match status_code { 0 => Ok(VestingBalance), 1 => Ok(LiquidityRestrictions), @@ -72,7 +73,16 @@ impl TryFrom for BalancesError { 9 => Ok(TooManyFreezes), 10 => Ok(IssuanceDeactivated), 11 => Ok(DeltaZero), - _ => todo!(), + _ => Err(UnknownStatusCode(status_code)), + } + } +} + +impl From for Error { + fn from(error: PopApiError) -> Self { + match error { + PopApiError::Balances(e) => e, + _ => panic!("expected balances error"), } } } diff --git a/pop-api/src/v0/cross_chain/mod.rs b/pop-api/src/v0/cross_chain/mod.rs index ad58e0e8..6732c119 100644 --- a/pop-api/src/v0/cross_chain/mod.rs +++ b/pop-api/src/v0/cross_chain/mod.rs @@ -1,16 +1,12 @@ -use crate::{BlockNumber, ParachainSystemKeys, Result, RuntimeStateKeys}; - pub mod coretime; -pub fn relay_chain_block_number() -> Result { - crate::v0::state::read(RuntimeStateKeys::ParachainSystem( - ParachainSystemKeys::LastRelayChainBlockNumber, - )) -} +use crate::{PopApiError::UnknownStatusCode, *}; + +type Result = core::result::Result; #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum CrossChainError { +pub enum Error { /// The desired destination was unreachable, generally because there is a no way of routing /// to it. Unreachable, @@ -66,11 +62,11 @@ pub enum CrossChainError { LocalExecutionIncomplete, } -impl TryFrom for CrossChainError { - type Error = crate::error::Error; +impl TryFrom for Error { + type Error = PopApiError; fn try_from(status_code: u32) -> core::result::Result { - use CrossChainError::*; + use Error::*; match status_code { 0 => Ok(Unreachable), 1 => Ok(SendFailure), @@ -96,7 +92,16 @@ impl TryFrom for CrossChainError { 21 => Ok(InvalidAssetUnknownReserve), 22 => Ok(InvalidAssetUnsupportedReserve), 23 => Ok(TooManyReserves), - _ => todo!(), + _ => Err(UnknownStatusCode(status_code)), + } + } +} + +impl From for Error { + fn from(error: PopApiError) -> Self { + match error { + PopApiError::Xcm(e) => e, + _ => panic!("expected xcm error"), } } } diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index f91c4271..310b360c 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -6,18 +6,3 @@ pub mod balances; pub mod cross_chain; #[cfg(feature = "nfts")] pub mod nfts; -pub mod state; - -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub(crate) enum RuntimeCall { - #[codec(index = 10)] - #[cfg(feature = "balances")] - Balances(balances::BalancesCall), - #[codec(index = 50)] - #[cfg(feature = "nfts")] - Nfts(nfts::NftCalls), - #[codec(index = 52)] - #[cfg(feature = "assets")] - Assets(assets::AssetsCall), -} diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs index 32539576..e111c8dc 100644 --- a/pop-api/src/v0/nfts.rs +++ b/pop-api/src/v0/nfts.rs @@ -1,21 +1,17 @@ +use super::RuntimeCall; +use crate::{PopApiError::UnknownStatusCode, *}; use ink::prelude::vec::Vec; +use primitives::{ApprovalsLimit, BoundedBTreeMap, KeyLimit, MultiAddress}; +pub use primitives::{CollectionId, ItemId}; use scale::Encode; - -use crate::{ - dispatch, - primitives::{ - nfts::{ApprovalsLimit, CollectionId, ItemId, KeyLimit}, - BoundedBTreeMap, BoundedVec, - }, - state, AccountId, Balance, BlockNumber, MultiAddress, NftsKeys, RuntimeCall, RuntimeStateKeys, - StatusCode, -}; pub use types::*; type Result = core::result::Result; type StringLimit = u32; type MaxTips = u32; +type Result = core::result::Result; + /// Issue a new collection of non-fungible items pub fn create( admin: impl Into>, @@ -524,7 +520,7 @@ pub(crate) enum NftCalls { #[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum NftsError { +pub enum Error { /// The signing account has no permission to do the operation. NoPermission, /// The given item ID is unknown. @@ -617,11 +613,11 @@ pub enum NftsError { WitnessRequired, } -impl TryFrom for NftsError { - type Error = crate::error::Error; +impl TryFrom for Error { + type Error = PopApiError; fn try_from(status_code: u32) -> core::result::Result { - use NftsError::*; + use Error::*; match status_code { 0 => Ok(NoPermission), 1 => Ok(UnknownCollection), @@ -668,7 +664,16 @@ impl TryFrom for NftsError { 42 => Ok(WrongNamespace), 43 => Ok(CollectionNotEmpty), 44 => Ok(WitnessRequired), - _ => todo!(), + _ => Err(UnknownStatusCode(status_code)), + } + } +} + +impl From for Error { + fn from(error: PopApiError) -> Self { + match error { + PopApiError::Nfts(e) => e, + _ => panic!("expected nfts error"), } } } @@ -677,7 +682,7 @@ impl TryFrom for NftsError { mod types { use super::*; use crate::{ - primitives::nfts::{CollectionId, ItemId}, + primitives::{CollectionId, ItemId}, Balance, BlockNumber, }; pub use enumflags2::{bitflags, BitFlags}; diff --git a/pop-api/src/v0/state.rs b/pop-api/src/v0/state.rs deleted file mode 100644 index afe48ba8..00000000 --- a/pop-api/src/v0/state.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::{error::StatusCode, primitives::storage_keys::RuntimeStateKeys, read_state}; -use ink::scale::Decode; - -#[inline] -pub fn read(key: RuntimeStateKeys) -> crate::Result { - read_state(key).and_then(|v| T::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) -} diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index cb19b0ab..5cbd6d6c 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -6,10 +6,7 @@ edition = "2021" [dependencies] bounded-collections = { version = "0.1", default-features = false } - scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-decode = { version = "0.10.0", default-features = false, features = ["derive"], optional = true } -scale-encode = { version = "0.5.0", default-features = false, features = ["derive"], optional = true } scale-info = { version = "2.10", default-features = false, features = ["derive"], optional = true } [features] @@ -17,12 +14,8 @@ default = ["std"] std = [ "bounded-collections/std", "scale/std", - "scale-decode/std", - "scale-encode/std", "scale-info/std", ] -devnet = [] -testnet = [] assets = [] cross-chain = [] nfts = [] diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index dc0a5245..9d31653a 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -3,14 +3,15 @@ pub use bounded_collections::{BoundedBTreeMap, BoundedBTreeSet, BoundedVec}; use scale::{Decode, Encode, MaxEncodedLen}; #[cfg(feature = "std")] -use {scale_decode::DecodeAsType, scale_encode::EncodeAsType, scale_info::TypeInfo}; +use scale_info::TypeInfo; +pub use v0::error; #[cfg(feature = "cross-chain")] pub mod cross_chain; pub mod storage_keys; -#[derive(Encode, Decode, Clone, Debug, MaxEncodedLen, Eq, PartialEq, Ord, PartialOrd)] -#[cfg_attr(feature = "std", derive(TypeInfo, DecodeAsType, EncodeAsType))] +#[derive(Encode, Decode, Debug, MaxEncodedLen, Eq, PartialEq)] +#[cfg_attr(feature = "std", derive(TypeInfo))] pub struct AccountId(pub [u8; 32]); // Identifier for the class of asset. @@ -29,3 +30,120 @@ pub mod nfts { /// The maximum approvals an item could have. pub type ApprovalsLimit = ConstU32<20>; } + +pub mod v0 { + use super::*; + pub mod error { + use super::*; + + #[derive(Encode, Decode, Debug, Eq, PartialEq)] + #[cfg_attr(feature = "std", derive(TypeInfo))] + #[repr(u8)] + pub enum Error { + /// Some unknown error occurred. Go to the Pop API docs section `Pop API error`. + Other { + // Index within the `DispatchError` + dispatch_error_index: u8, + // Index within the `DispatchError` variant. + error_index: u8, + // Index for further nesting, e.g. pallet error. + error: u8, + } = 0, + /// Failed to lookup some data. + CannotLookup = 1, + /// A bad origin. + BadOrigin = 2, + /// A custom error in a module. + Module { index: u8, error: u8 } = 3, + /// At least one consumer is remaining so the account cannot be destroyed. + ConsumerRemaining = 4, + /// There are no providers so the account cannot be created. + NoProviders = 5, + /// There are too many consumers so the account cannot be created. + TooManyConsumers = 6, + /// An error to do with tokens. + Token(TokenError) = 7, + /// An arithmetic error. + Arithmetic(ArithmeticError) = 8, + /// The number of transactional layers has been reached, or we are not in a transactional + /// layer. + Transactional(TransactionalError) = 9, + /// Resources exhausted, e.g. attempt to read/write data which is too large to manipulate. + Exhausted = 10, + /// The state is corrupt; this is generally not going to fix itself. + Corruption = 11, + /// Some resource (e.g. a preimage) is unavailable right now. This might fix itself later. + Unavailable = 12, + /// Root origin is not allowed. + RootNotAllowed = 13, + /// Unknown function id. + UnknownFunctionId = 254, + /// Decoding failed on the runtime. + DecodingFailed = 255, + } + + impl From for Error { + fn from(value: u32) -> Self { + let encoded = value.to_le_bytes(); + Error::decode(&mut &encoded[..]).unwrap_or(Error::DecodingFailed) + } + } + + impl From for u32 { + fn from(value: Error) -> Self { + let mut encoded_error = value.encode(); + // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). + encoded_error.resize(4, 0); + u32::from_le_bytes( + encoded_error.try_into().expect("qid, resized to 4 bytes line above"), + ) + } + } + + #[derive(Encode, Decode, Clone, Debug, MaxEncodedLen, Eq, PartialEq, Ord, PartialOrd)] + #[cfg_attr(feature = "std", derive(TypeInfo))] + pub enum TokenError { + /// Funds are unavailable. + FundsUnavailable, + /// Some part of the balance gives the only provider reference to the account and thus cannot + /// be (re)moved. + OnlyProvider, + /// Account cannot exist with the funds that would be given. + BelowMinimum, + /// Account cannot be created. + CannotCreate, + /// The asset in question is unknown. + UnknownAsset, + /// Funds exist but are frozen. + Frozen, + /// Operation is not supported by the asset. + Unsupported, + /// Account cannot be created for a held balance. + CannotCreateHold, + /// Withdrawal would cause unwanted loss of account. + NotExpendable, + /// Account cannot receive the assets. + Blocked, + } + + #[derive(Encode, Decode, Debug, Eq, PartialEq)] + #[cfg_attr(feature = "std", derive(TypeInfo))] + pub enum ArithmeticError { + /// Underflow. + Underflow, + /// Overflow. + Overflow, + /// Division by zero. + DivisionByZero, + } + + #[derive(Encode, Decode, Debug, Eq, PartialEq)] + #[cfg_attr(feature = "std", derive(TypeInfo))] + pub enum TransactionalError { + /// Too many transactional layers have been spawned. + LimitReached, + /// A transactional layer was expected, but does not exist. + NoLayer, + } + } +} diff --git a/primitives/src/storage_keys.rs b/primitives/src/storage_keys.rs index 7992089b..e42dbca0 100644 --- a/primitives/src/storage_keys.rs +++ b/primitives/src/storage_keys.rs @@ -46,14 +46,11 @@ pub enum NftsKeys { #[cfg(feature = "assets")] #[derive(Encode, Decode, Debug, MaxEncodedLen)] pub enum AssetsKeys { - Allowance(AssetId, AccountId, AccountId), - // /// Check if the asset exists. - // // AssetExists(AssetId), - /// Check balance. - BalanceOf(AssetId, AccountId), - /// Returns the total token supply for a given asset ID. TotalSupply(AssetId), - TokenDecimals(AssetId), - TokenSymbol(AssetId), + BalanceOf(AssetId, AccountId), + Allowance(AssetId, AccountId, AccountId), TokenName(AssetId), + TokenSymbol(AssetId), + TokenDecimals(AssetId), + // AssetExists(AssetId), } diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index 5f52b855..7db68576 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -89,8 +89,9 @@ parachain-info.workspace = true [dev-dependencies] env_logger = "0.11.2" -hex = "0.4.3" enumflags2 = "0.7.9" +hex = "0.4.3" +rand = "0.8.5" [features] default = ["std"] diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions/mod.rs similarity index 79% rename from runtime/devnet/src/extensions.rs rename to runtime/devnet/src/extensions/mod.rs index 6f98bf96..ac52d5bd 100644 --- a/runtime/devnet/src/extensions.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -1,18 +1,22 @@ +use codec::{Compact, Decode, Encode}; use cumulus_pallet_parachain_system::RelaychainDataProvider; use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, traits::{ - fungibles::{approvals::Inspect as ApprovalInspect, Inspect}, + fungibles::approvals::Inspect as ApprovalInspect, nonfungibles_v2::Inspect as NonFungiblesInspect, }, }; use pallet_contracts::chain_extension::{ - BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, + BufInBufOutState, ChainExtension, Environment, Ext, InitState, RetVal, }; use sp_core::crypto::UncheckedFrom; -use sp_runtime::traits::{BlockNumberProvider, Dispatchable}; +use sp_runtime::{ + traits::{BlockNumberProvider, Dispatchable}, + DispatchError, MultiAddress, +}; use sp_std::{boxed::Box, vec::Vec}; use xcm::{ latest::{prelude::*, OriginKind::SovereignAccount}, @@ -20,17 +24,24 @@ use xcm::{ }; use crate::{ - config::assets::TrustBackedAssetsInstance, AccountId, AllowedApiCalls, RuntimeCall, - RuntimeOrigin, UNIT, + config::assets::TrustBackedAssetsInstance, AccountId, AllowedApiCalls, Balance, Runtime, + RuntimeCall, RuntimeOrigin, UNIT, }; use pop_primitives::{ cross_chain::CrossChainMessage, nfts::{CollectionId, ItemId}, - storage_keys::{AssetsKeys, NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, + storage_keys::{ + AssetsKeys::{self, *}, + NftsKeys, ParachainSystemKeys, RuntimeStateKeys, + }, AssetId, }; +mod v0; + const LOG_TARGET: &str = "pop-api::extension"; +// Versions: +const V0: u8 = 0; type ContractSchedule = ::Schedule; @@ -58,53 +69,162 @@ where { log::debug!(target:LOG_TARGET, " extension called "); let mut env = env.buf_in_buf_out(); - let contract_host_weight = ContractSchedule::::get().host_fn_weights; - // debug_message weight is a good approximation of the additional overhead of going + // Charge weight for making a call from a contract to the runtime. + // `debug_message` weight is a good approximation of the additional overhead of going // from contract layer to substrate layer. // reference: https://github.com/paritytech/ink-examples/blob/b8d2caa52cf4691e0ddd7c919e4462311deb5ad0/psp22-extension/runtime/psp22-extension-example.rs#L236 + let contract_host_weight = ContractSchedule::::get().host_fn_weights; env.charge_weight(contract_host_weight.debug_message)?; - let result = match v0::FuncId::try_from(env.func_id()) { - Ok(function) => { - // calculate weight for reading bytes of `len` + // Extract version and function_id from first two bytes. + let (version, function_id) = { + let bytes = env.func_id().to_le_bytes(); + (bytes[0], bytes[1]) + }; + // Extract pallet index and call / key index from last two bytes. + let (pallet_index, call_index) = { + let bytes = env.ext_id().to_le_bytes(); + (bytes[0], bytes[1]) + }; + + let result = match FuncId::try_from(function_id) { + Ok(function_id) => { + // Read encoded parameters from buffer and calculate weight for reading `len` bytes`. // reference: https://github.com/paritytech/polkadot-sdk/blob/117a9433dac88d5ac00c058c9b39c511d47749d2/substrate/frame/contracts/src/wasm/runtime.rs#L267 let len = env.in_len(); env.charge_weight(contract_host_weight.return_per_byte.saturating_mul(len.into()))?; - match function { - v0::FuncId::Dispatch => dispatch::(&mut env, len), - v0::FuncId::ReadState => read_state::(&mut env), - v0::FuncId::SendXcm => send_xcm::(&mut env), + let params = env.read(len)?; + log::debug!(target: LOG_TARGET, "Read input successfully"); + match function_id { + FuncId::Dispatch => { + dispatch::(&mut env, version, pallet_index, call_index, params) + }, + FuncId::ReadState => { + read_state::(&mut env, version, pallet_index, call_index, params) + }, + // TODO + FuncId::SendXcm => send_xcm::(&mut env), } }, Err(e) => Err(e), }; - // Convert any error to a status code and return Ok with RetVal::Converging match result { Ok(_) => Ok(RetVal::Converging(0)), - Err(e) => Ok(RetVal::Converging(convert_to_status_code(e))), + Err(e) => Ok(RetVal::Converging(convert_to_status_code(e, version))), } } } -fn dispatch(env: &mut Environment, len: u32) -> Result<(), DispatchError> +fn dispatch( + env: &mut Environment, + version: u8, + pallet_index: u8, + call_index: u8, + params: Vec, +) -> Result<(), DispatchError> where - T: pallet_contracts::Config - + frame_system::Config, + T: frame_system::Config, RuntimeOrigin: From>, E: Ext, { const LOG_PREFIX: &str = " dispatch |"; - - // read the input as RuntimeCall - let call: RuntimeCall = env.read_as_unbounded(len)?; - log::debug!(target: LOG_TARGET, "Read input as call successfully"); - // contract is the origin by default + let call = construct_call(version, pallet_index, call_index, params) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + // Contract is the origin by default. let origin: RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); dispatch_call::(env, call, origin, LOG_PREFIX) } -fn read_state(env: &mut Environment) -> Result<(), DispatchError> +fn dispatch_call( + env: &mut Environment, + call: RuntimeCall, + mut origin: RuntimeOrigin, + log_prefix: &str, +) -> Result<(), DispatchError> +where + T: frame_system::Config, + RuntimeOrigin: From>, + E: Ext, +{ + let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; + log::debug!(target:LOG_TARGET, "{} Inputted RuntimeCall: {:?}", log_prefix, call); + origin.add_filter(AllowedApiCalls::contains); + match call.dispatch(origin) { + Ok(info) => { + log::debug!(target:LOG_TARGET, "{} success, actual weight: {:?}", log_prefix, info.actual_weight); + // Refund weight if the actual weight is less than the charged weight. + if let Some(actual_weight) = info.actual_weight { + env.adjust_weight(charged_dispatch_weight, actual_weight); + } + Ok(()) + }, + Err(err) => { + log::debug!(target:LOG_TARGET, "{} failed: error: {:?}", log_prefix, err.error); + Err(err.error) + }, + } +} + +fn construct_call( + version: u8, + pallet_index: u8, + call_index: u8, + params: Vec, +) -> Result { + match pallet_index { + 52 => { + let call = versioned_construct_assets_call(version, call_index, params)?; + Ok(RuntimeCall::Assets(call)) + }, + _ => Err(DispatchError::Other("UnknownFunctionId")), + } +} + +fn construct_key( + version: u8, + pallet_index: u8, + call_index: u8, + params: Vec, +) -> Result { + match pallet_index { + 52 => { + let key = versioned_construct_assets_key(version, call_index, params)?; + Ok(RuntimeStateKeys::Assets(key)) + }, + _ => Err(DispatchError::Other("UnknownFunctionId")), + } +} + +fn versioned_construct_assets_call( + version: u8, + call_index: u8, + params: Vec, +) -> Result, DispatchError> { + match version { + V0 => v0::assets::construct_assets_call(call_index, params), + _ => Err(DispatchError::Other("UnknownFunctionId")), + } +} + +fn versioned_construct_assets_key( + version: u8, + call_index: u8, + params: Vec, +) -> Result { + match version { + V0 => v0::assets::construct_assets_key(call_index, params), + _ => Err(DispatchError::Other("UnknownFunctionId")), + } +} + +fn read_state( + env: &mut Environment, + version: u8, + pallet_index: u8, + call_index: u8, + params: Vec, +) -> Result<(), DispatchError> where T: pallet_contracts::Config + pallet_assets::Config @@ -114,15 +234,13 @@ where E: Ext, { const LOG_PREFIX: &str = " read_state |"; - - let key: RuntimeStateKeys = env.read_as()?; + let key = construct_key(version, pallet_index, call_index, params)?; let result = match key { RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, env), RuntimeStateKeys::ParachainSystem(key) => read_parachain_system_state::(key, env), RuntimeStateKeys::Assets(key) => read_assets_state::(key, env), }? .encode(); - log::trace!( target:LOG_TARGET, "{} result: {:?}.", LOG_PREFIX, result @@ -141,10 +259,9 @@ where E: Ext, { const LOG_PREFIX: &str = " send_xcm |"; - - // read the input as CrossChainMessage + // Read the input as CrossChainMessage. let xc_call: CrossChainMessage = env.read_as::()?; - // Determine the call to dispatch + // Determine the call to dispatch. let (dest, message) = match xc_call { CrossChainMessage::Relay(message) => { let dest = Location::parent().into_versioned(); @@ -165,91 +282,85 @@ where (dest, message) }, }; - // TODO: revisit to replace with signed contract origin let origin: RuntimeOrigin = RawOrigin::Root.into(); - - // Generate runtime call to dispatch + // Generate runtime call to dispatch. let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::send { dest: Box::new(dest), message: Box::new(VersionedXcm::V4(message)), }); - dispatch_call::(env, call, origin, LOG_PREFIX) } -pub(crate) fn convert_to_status_code(error: DispatchError) -> u32 { +// Converts a `DispatchError` to a `u32` status code based on the version of the API the contract uses. +// The contract calling the chain extension can convert the status code to the descriptive `Error`. +// +// For `Error` see `pop_primitives::::error::Error`. +// +// The error encoding can vary per version, allowing for flexible and backward-compatible error handling. +// As a result, contracts maintain compatibility across different versions of the runtime. +// +// # Parameters +// +// - `error`: The `DispatchError` encountered during contract execution. +// - `version`: The version of the chain extension, used to determine the known errors. +pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { + // "UnknownFunctionId" and "DecodingFailed" are mapped to specific errors in the API and will + // never change. let mut encoded_error = match error { DispatchError::Other("UnknownFunctionId") => vec![254, 0, 0, 0], + DispatchError::Other("DecodingFailed") => vec![255, 0, 0, 0], _ => error.encode(), }; // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). encoded_error.resize(4, 0); - u32::decode(&mut &encoded_error[..]).expect("qid, resized to 4 bytes line above") + let mut encoded_error = encoded_error.try_into().expect("qid, resized to 4 bytes line above"); + match version { + // If an unknown variant of the `DispatchError` is detected the error needs to be converted + // into the encoded value of `Error::Other`. This conversion is performed by shifting the bytes one + // position forward (discarding the last byte as it is not used) and setting the first byte to the + // encoded value of `Other` (0u8). This ensures the error is correctly categorized as an `Other` + // variant which provides all the necessary information to debug which error occurred in the runtime. + // + // Byte layout explanation: + // - Byte 0: index of the variant within `Error` + // - Byte 1: + // - Must be zero for `UNIT_ERRORS`. + // - Represents the nested error in `SINGLE_NESTED_ERRORS`. + // - Represents the first level of nesting in `DOUBLE_NESTED_ERRORS`. + // - Byte 2: + // - Represents the second level of nesting in `DOUBLE_NESTED_ERRORS`. + // - Byte 3: + // - Unused or represents further nested information. + 0 => v0::error::handle_unknown_error(&mut encoded_error), + _ => encoded_error = [254, 0, 0, 0], + } + u32::from_le_bytes(encoded_error) } -pub mod v0 { - #[derive(Debug)] - pub enum FuncId { - Dispatch, - ReadState, - SendXcm, - } +#[derive(Debug)] +pub enum FuncId { + Dispatch, + ReadState, + SendXcm, } -impl TryFrom for v0::FuncId { +impl TryFrom for FuncId { type Error = DispatchError; - fn try_from(func_id: u16) -> Result { + fn try_from(func_id: u8) -> Result { let id = match func_id { - 0x0 => Self::Dispatch, - 0x1 => Self::ReadState, - 0x2 => Self::SendXcm, + 0 => Self::Dispatch, + 1 => Self::ReadState, + 2 => Self::SendXcm, _ => { - log::error!("called an unregistered `func_id`: {:}", func_id); return Err(DispatchError::Other("UnknownFuncId")); }, }; - Ok(id) } } -fn dispatch_call( - env: &mut Environment, - call: RuntimeCall, - mut origin: RuntimeOrigin, - log_prefix: &str, -) -> Result<(), DispatchError> -where - T: frame_system::Config, - RuntimeOrigin: From>, - E: Ext, -{ - let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; - - log::debug!(target:LOG_TARGET, "{} Inputted RuntimeCall: {:?}", log_prefix, call); - - origin.add_filter(AllowedApiCalls::contains); - - match call.dispatch(origin) { - Ok(info) => { - log::debug!(target:LOG_TARGET, "{} success, actual weight: {:?}", log_prefix, info.actual_weight); - - // refund weight if the actual weight is less than the charged weight - if let Some(actual_weight) = info.actual_weight { - env.adjust_weight(charged_dispatch_weight, actual_weight); - } - - Ok(()) - }, - Err(err) => { - log::debug!(target:LOG_TARGET, "{} failed: error: {:?}", log_prefix, err.error); - Err(err.error) - }, - } -} - fn read_parachain_system_state( key: ParachainSystemKeys, env: &mut Environment, @@ -323,7 +434,7 @@ where T: frame_system::Config, { match key { - AssetsKeys::Allowance(id, owner, spender) => { + Allowance(id, owner, spender) => { env.charge_weight(T::DbWeight::get().reads(1_u64))?; Ok(pallet_assets::Pallet::::allowance( id, @@ -336,12 +447,12 @@ where // env.charge_weight(T::DbWeight::get().reads(1_u64))?; // Ok(pallet_assets::Pallet::::asset_exists(id).encode()) // }, - AssetsKeys::BalanceOf(id, owner) => { + BalanceOf(id, owner) => { env.charge_weight(T::DbWeight::get().reads(1_u64))?; Ok(pallet_assets::Pallet::::balance(id, &owner.0.into()) .encode()) }, - AssetsKeys::TotalSupply(id) => { + TotalSupply(id) => { env.charge_weight(T::DbWeight::get().reads(1_u64))?; Ok(pallet_assets::Pallet::::total_supply(id).encode()) }, @@ -354,88 +465,51 @@ mod tests { use super::*; use crate::{Assets, Runtime, System}; use sp_runtime::BuildStorage; + // Test ensuring `func_id()` and `ext_id()` work as expected, i.e. extracting the first two + // bytes and the last two bytes, respectively, from a 4 byte array. + #[test] + fn test_byte_extraction() { + use rand::Rng; - fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::::default() - .build_storage() - .expect("Frame system builds valid default genesis config"); - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } + // Helper functions + fn func_id(id: u32) -> u16 { + (id & 0x0000FFFF) as u16 + } + fn ext_id(id: u32) -> u16 { + (id >> 16) as u16 + } - #[test] - fn encoding_decoding_dispatch_error() { - use codec::{Decode, Encode}; - use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; + // Number of test iterations + let test_iterations = 1_000_000; - new_test_ext().execute_with(|| { - let error = DispatchError::Module(ModuleError { - index: 255, - error: [2, 0, 0, 0], - message: Some("error message"), - }); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); - assert_eq!( - decoded, - // `message` is skipped for encoding. - DispatchError::Module(ModuleError { - index: 255, - error: [2, 0, 0, 0], - message: None - }) - ); - println!("Encoded Module Error: {:?}", encoded); + // Create a random number generator + let mut rng = rand::thread_rng(); - // Example pallet assets Error into ModuleError. - let index = - <::PalletInfo as frame_support::traits::PalletInfo>::index::< - Assets, - >() - .expect("Every active module has an index in the runtime; qed") as u8; + // Run the test for a large number of random 4-byte arrays + for _ in 0..test_iterations { + // Generate a random 4-byte array + let bytes: [u8; 4] = rng.gen(); - let mut error = - pallet_assets::Error::NotFrozen::.encode(); - error.resize(MAX_MODULE_ERROR_ENCODED_SIZE, 0); - let error = DispatchError::Module(ModuleError { - index, - error: TryInto::try_into(error).expect("should work"), - message: None, - }); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 52, 18, 0, 0, 0]); - assert_eq!( - decoded, - DispatchError::Module(ModuleError { - index: 52, - error: [18, 0, 0, 0], - message: None - }) - ); - println!("Encoded Module Error: {:?}", encoded); + // Convert the 4-byte array to a u32 value + let value = u32::from_le_bytes(bytes); - // Example DispatchError::Token - let error = DispatchError::Token(TokenError::UnknownAsset); - let encoded = error.encode(); - assert_eq!(encoded, vec![7, 4]); - println!("Encoded Token Error: {:?}", encoded); + // Extract the first two bytes (least significant 2 bytes) + let first_two_bytes = func_id(value); - // Example DispatchError::Arithmetic - let error = DispatchError::Arithmetic(ArithmeticError::Overflow); - let encoded = error.encode(); - assert_eq!(encoded, vec![8, 1]); - println!("Encoded Arithmetic Error: {:?}", encoded); - }); + // Extract the last two bytes (most significant 2 bytes) + let last_two_bytes = ext_id(value); + + // Check if the first two bytes match the expected value + assert_eq!([bytes[0], bytes[1]], first_two_bytes.to_le_bytes()); + + // Check if the last two bytes match the expected value + assert_eq!([bytes[2], bytes[3]], last_two_bytes.to_le_bytes()); + } } + // Test showing all the different type of variants and its encoding. #[test] fn encoding_of_enum() { - use codec::{Decode, Encode}; - - // Comprehensive enum with all different type of variants. #[derive(Debug, PartialEq, Encode, Decode)] enum ComprehensiveEnum { SimpleVariant, @@ -494,39 +568,77 @@ mod tests { println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); } + fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::::default() + .build_storage() + .expect("Frame system builds valid default genesis config"); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } + #[test] - fn dispatch_error_to_status_code() { - // Create all the different `DispatchError` variants with its respective `PopApiError`. - let test_cases = vec![ - (DispatchError::Other("hallo"), [0, 0, 0, 0]), - (DispatchError::CannotLookup, [1, 0, 0, 0]), - (DispatchError::BadOrigin, [2, 0, 0, 0]), - ( - DispatchError::Module(sp_runtime::ModuleError { - index: 1, + fn encoding_decoding_dispatch_error() { + use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; + + new_test_ext().execute_with(|| { + let error = DispatchError::Module(ModuleError { + index: 255, + error: [2, 0, 0, 0], + message: Some("error message"), + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); + assert_eq!( + decoded, + // `message` is skipped for encoding. + DispatchError::Module(ModuleError { + index: 255, error: [2, 0, 0, 0], - message: Some("hallo"), - }), - [3, 1, 2, 0], - ), - (DispatchError::ConsumerRemaining, [4, 0, 0, 0]), - (DispatchError::NoProviders, [5, 0, 0, 0]), - (DispatchError::TooManyConsumers, [6, 0, 0, 0]), - (DispatchError::Token(sp_runtime::TokenError::BelowMinimum), [7, 2, 0, 0]), - (DispatchError::Arithmetic(sp_runtime::ArithmeticError::Overflow), [8, 1, 0, 0]), - ( - DispatchError::Transactional(sp_runtime::TransactionalError::LimitReached), - [9, 0, 0, 0], - ), - (DispatchError::Exhausted, [10, 0, 0, 0]), - (DispatchError::Corruption, [11, 0, 0, 0]), - (DispatchError::Unavailable, [12, 0, 0, 0]), - (DispatchError::RootNotAllowed, [13, 0, 0, 0]), - ]; - for (error, encoded_error) in test_cases { - let status_code = crate::extensions::convert_to_status_code(error); - assert_eq!(status_code, u32::decode(&mut &encoded_error[..]).unwrap()); - } + message: None + }) + ); + + // Example pallet assets Error into ModuleError. + let index = <::PalletInfo as frame_support::traits::PalletInfo>::index::< + Assets, + >() + .expect("Every active module has an index in the runtime; qed") as u8; + let mut error = + pallet_assets::Error::NotFrozen::.encode(); + error.resize(MAX_MODULE_ERROR_ENCODED_SIZE, 0); + let error = DispatchError::Module(ModuleError { + index, + error: TryInto::try_into(error).expect("should work"), + message: None, + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 52, 18, 0, 0, 0]); + assert_eq!( + decoded, + DispatchError::Module(ModuleError { + index: 52, + error: [18, 0, 0, 0], + message: None + }) + ); + + // Example DispatchError::Token + let error = DispatchError::Token(TokenError::UnknownAsset); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![7, 4]); + assert_eq!(decoded, error); + + // Example DispatchError::Arithmetic + let error = DispatchError::Arithmetic(ArithmeticError::Overflow); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![8, 1]); + assert_eq!(decoded, error); + }); } } // use enumflags2::BitFlags; diff --git a/runtime/devnet/src/extensions/v0/assets.rs b/runtime/devnet/src/extensions/v0/assets.rs new file mode 100644 index 00000000..912b116f --- /dev/null +++ b/runtime/devnet/src/extensions/v0/assets.rs @@ -0,0 +1,39 @@ +use crate::extensions::{ + AccountId, AssetId, + AssetsKeys::{self, TotalSupply}, + Balance, Compact, Decode, DispatchError, MultiAddress, Runtime, TrustBackedAssetsInstance, +}; + +pub(crate) fn construct_assets_key( + call_index: u8, + params: Vec, +) -> Result { + match call_index { + 0 => { + let id = ::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + Ok(TotalSupply(id)) + }, + // other calls + _ => Err(DispatchError::Other("UnknownFunctionId")), + } +} + +pub(crate) fn construct_assets_call( + call_index: u8, + params: Vec, +) -> Result, DispatchError> { + match call_index { + 9 => { + let (id, target, amount) = <(AssetId, AccountId, Balance)>::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + Ok(pallet_assets::Call::::transfer_keep_alive { + id: Compact(id), + target: MultiAddress::Id(target), + amount, + }) + }, + // other calls + _ => Err(DispatchError::Other("UnknownFunctionId")), + } +} diff --git a/runtime/devnet/src/extensions/v0/error.rs b/runtime/devnet/src/extensions/v0/error.rs new file mode 100644 index 00000000..b8af2250 --- /dev/null +++ b/runtime/devnet/src/extensions/v0/error.rs @@ -0,0 +1,298 @@ +#[cfg(test)] +use crate::extensions::convert_to_status_code; + +pub(crate) fn handle_unknown_error(encoded_error: &mut [u8; 4]) { + let unknown = match encoded_error[0] { + code if UNIT_ERRORS.contains(&code) => nested_errors(&encoded_error[1..], None), + // Single nested errors with a limit in their nesting. + // + // `TokenError`: has ten variants - translated to a limit of nine. + 7 => nested_errors(&encoded_error[1..], Some(9)), + // `ArithmeticError`: has 3 variants - translated to a limit of two. + 8 => nested_errors(&encoded_error[1..], Some(2)), + // `TransactionalError`: has 2 variants - translated to a limit of one. + 9 => nested_errors(&encoded_error[1..], Some(1)), + code if DOUBLE_NESTED_ERRORS.contains(&code) => nested_errors(&encoded_error[3..], None), + _ => true, + }; + if unknown { + encoded_error[..].rotate_right(1); + encoded_error[0] = 0u8; + } +} + +// Unit `Error` variants. +// (variant: index): +// - CannotLookup: 1, +// - BadOrigin: 2, +// - ConsumerRemaining: 4, +// - NoProviders: 5, +// - TooManyConsumers: 6, +// - Exhausted: 10, +// - Corruption: 11, +// - Unavailable: 12, +// - RootNotAllowed: 13, +// - UnknownFunctionId: 254, +// - DecodingFailed: 255, +const UNIT_ERRORS: [u8; 11] = [1, 2, 4, 5, 6, 10, 11, 12, 13, 254, 255]; + +#[cfg(test)] +const SINGLE_NESTED_ERRORS: [u8; 3] = [7, 8, 9]; + +// Double nested `Error` variants +// (variant: index): +// - Module: 3, +const DOUBLE_NESTED_ERRORS: [u8; 1] = [3]; + +// Checks for unknown nested errors within the `DispatchError`. +// - For single nested errors with a limit, it verifies if the nested value exceeds the limit. +// - For other nested errors, it checks if any subsequent bytes are non-zero. +// +// `nested_error` - The slice of bytes representing the nested error. +// `limit` - An optional limit for single nested errors. +fn nested_errors(nested_error: &[u8], limit: Option) -> bool { + match limit { + Some(l) => nested_error[0] > l || nested_error[1..].iter().any(|&x| x != 0u8), + None => nested_error.iter().any(|&x| x != 0u8), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use pop_primitives::error::{ + ArithmeticError::*, + Error::{self, *}, + TokenError::*, + TransactionalError::*, + }; + use sp_runtime::DispatchError; + + // Compare all the different `DispatchError` variants with the expected `Error`. + #[test] + fn dispatch_error_to_error() { + let test_cases = vec![ + ( + DispatchError::Other(""), + (Other { dispatch_error_index: 0, error_index: 0, error: 0 }), + ), + (DispatchError::Other("UnknownFunctionId"), UnknownFunctionId), + (DispatchError::Other("DecodingFailed"), DecodingFailed), + (DispatchError::CannotLookup, CannotLookup), + (DispatchError::BadOrigin, BadOrigin), + ( + DispatchError::Module(sp_runtime::ModuleError { + index: 1, + error: [2, 0, 0, 0], + message: Some("hallo"), + }), + Module { index: 1, error: 2 }, + ), + (DispatchError::ConsumerRemaining, ConsumerRemaining), + (DispatchError::NoProviders, NoProviders), + (DispatchError::TooManyConsumers, TooManyConsumers), + (DispatchError::Token(sp_runtime::TokenError::BelowMinimum), Token(BelowMinimum)), + ( + DispatchError::Arithmetic(sp_runtime::ArithmeticError::Overflow), + Arithmetic(Overflow), + ), + ( + DispatchError::Transactional(sp_runtime::TransactionalError::LimitReached), + Transactional(LimitReached), + ), + (DispatchError::Exhausted, Exhausted), + (DispatchError::Corruption, Corruption), + (DispatchError::Unavailable, Unavailable), + (DispatchError::RootNotAllowed, RootNotAllowed), + ]; + for (dispatch_error, expected) in test_cases { + let status_code = crate::extensions::convert_to_status_code(dispatch_error, 0); + let error: Error = status_code.into(); + assert_eq!(error, expected); + } + } + + // Compare all the different `DispatchError::Other` possibilities with the expected `Error`. + #[test] + fn other_error() { + let test_cases = vec![ + ( + DispatchError::Other("Random"), + (Other { dispatch_error_index: 0, error_index: 0, error: 0 }), + ), + (DispatchError::Other("UnknownFunctionId"), UnknownFunctionId), + (DispatchError::Other("DecodingFailed"), DecodingFailed), + ]; + for (dispatch_error, expected) in test_cases { + let status_code = convert_to_status_code(dispatch_error, 0); + let error: Error = status_code.into(); + assert_eq!(error, expected); + } + } + + // Compare all the different `DispatchError::Module` nesting possibilities, which can not be + // handled, with the expected `Error`. See `double_nested_error_variants` fourth byte nesting. + #[test] + fn test_module_error() { + let test_cases = vec![ + DispatchError::Module(sp_runtime::ModuleError { + index: 1, + error: [2, 2, 0, 0], + message: Some("Random"), + }), + DispatchError::Module(sp_runtime::ModuleError { + index: 1, + error: [2, 2, 2, 0], + message: Some("Random"), + }), + DispatchError::Module(sp_runtime::ModuleError { + index: 1, + error: [2, 2, 2, 2], + message: Some("Random"), + }), + ]; + for dispatch_error in test_cases { + let status_code = convert_to_status_code(dispatch_error, 0); + let error: Error = status_code.into(); + assert_eq!(error, Other { dispatch_error_index: 3, error_index: 1, error: 2 }); + } + } + + // Converts 4 bytes into `Error` and handles unknown errors (used in `convert_to_status_code`). + fn into_error(mut error_bytes: [u8; 4]) -> Error { + handle_unknown_error(&mut error_bytes); + u32::from_le_bytes(error_bytes).into() + } + + // Tests the `handle_unknown_error` for `Error`, version 0. + // + // Unit variants: + // If the encoded value indicates a nested `Error` which is known by V0 as a + // unit variant, the encoded value is converted into `Error::Other`. + // + // Example: the error `BadOrigin` (encoded: `[2, 0, 0, 0]`) with a non-zero value for one + // of the bytes [1..4]: `[2, 0, 1, 0]` is converted into `[0, 2, 0, 1]` (shifting the bits + // one forward). This is decoded to `Error::Other { dispatch_error: 2, index: 0, error: 1 }`. + #[test] + fn unit_error_variants() { + let errors = vec![ + CannotLookup, + BadOrigin, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + UnknownFunctionId, + DecodingFailed, + ]; + // Compare an `Error`, which is converted from an encoded value, with the expected `Error`. + for (i, &error_code) in UNIT_ERRORS.iter().enumerate() { + // No nesting and unit variant correctly returned. + assert_eq!(into_error([error_code, 0, 0, 0]), errors[i]); + // Unexpected second byte nested. + assert_eq!( + into_error([error_code, 1, 0, 0]), + (Other { dispatch_error_index: error_code, error_index: 1, error: 0 }), + ); + // Unexpected third byte nested. + assert_eq!( + into_error([error_code, 1, 1, 0]), + (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }), + ); + // Unexpected fourth byte nested. + assert_eq!( + into_error([error_code, 1, 1, 1]), + (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }), + ); + } + } + + // Single nested variants: + // If the encoded value indicates a double nested `Error` which is known by V0 + // as a single nested variant, the encoded value is converted into `Error::Other`. + // + // Example: the error `Arithmetic(Overflow)` (encoded: `[8, 1, 0, 0]`) with a non-zero + // value for one of the bytes [2..4]: `[8, 1, 1, 0]` is converted into `[0, 8, 1, 1]`. This is + // decoded to `Error::Other { dispatch_error: 8, index: 1, error: 1 }`. + #[test] + fn single_nested_error_variants() { + let errors = vec![ + [Token(FundsUnavailable), Token(OnlyProvider)], + [Arithmetic(Underflow), Arithmetic(Overflow)], + [Transactional(LimitReached), Transactional(NoLayer)], + ]; + // Compare an `Error`, which is converted from an encoded value, with the expected `Error`. + for (i, &error_code) in SINGLE_NESTED_ERRORS.iter().enumerate() { + // No nested and single nested variant correctly returned. + assert_eq!(into_error([error_code, 0, 0, 0]), errors[i][0]); + assert_eq!(into_error([error_code, 1, 0, 0]), errors[i][1]); + // Unexpected third byte nested. + assert_eq!( + into_error([error_code, 1, 1, 0]), + (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }), + ); + // Unexpected fourth byte nested. + assert_eq!( + into_error([error_code, 1, 1, 1]), + Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, + ); + } + } + + #[test] + fn single_nested_unknown_variants() { + // Unknown `TokenError` variant. + assert_eq!( + into_error([7, 10, 0, 0]), + Other { dispatch_error_index: 7, error_index: 10, error: 0 } + ); + // Unknown `Arithmetic` variant. + assert_eq!( + into_error([8, 3, 0, 0]), + Other { dispatch_error_index: 8, error_index: 3, error: 0 } + ); + // Unknown `Transactional` variant. + assert_eq!( + into_error([9, 2, 0, 0]), + Other { dispatch_error_index: 9, error_index: 2, error: 0 } + ); + } + + // Double nested variants: + // If the encoded value indicates a triple nested `Error` which is known by V0 + // as a double nested variant, the encoded value is converted into `Error::Other`. + // + // Example: the error `Module { index: 10, error 5 }` (encoded: `[3, 10, 5, 0]`) with a non-zero + // value for the last byte: `[3, 10, 5, 3]` is converted into `[0, 3, 10, 5]`. This is + // decoded to `Error::Other { dispatch_error: 3, index: 10, error: 5 }`. + #[test] + fn double_nested_error_variants() { + // Compare an `Error`, which is converted from an encoded value, with the expected `Error`. + // No nesting and unit variant correctly returned. + assert_eq!(into_error([3, 0, 0, 0]), Module { index: 0, error: 0 }); + // Allowed single nesting and variant correctly returned. + assert_eq!(into_error([3, 1, 0, 0]), Module { index: 1, error: 0 }); + // Allowed double nesting and variant correctly returned. + assert_eq!(into_error([3, 1, 1, 0]), Module { index: 1, error: 1 }); + // Unexpected fourth byte nested. + assert_eq!( + into_error([3, 1, 1, 1]), + Other { dispatch_error_index: 3, error_index: 1, error: 1 }, + ); + } + + #[test] + fn test_random_encoded_values() { + assert_eq!( + into_error([100, 100, 100, 100]), + Other { dispatch_error_index: 100, error_index: 100, error: 100 } + ); + assert_eq!( + into_error([200, 200, 200, 200]), + Other { dispatch_error_index: 200, error_index: 200, error: 200 } + ); + } +} diff --git a/runtime/devnet/src/extensions/v0/mod.rs b/runtime/devnet/src/extensions/v0/mod.rs new file mode 100644 index 00000000..6406e08f --- /dev/null +++ b/runtime/devnet/src/extensions/v0/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod assets; +pub(crate) mod error; diff --git a/runtime/testnet/Cargo.toml b/runtime/testnet/Cargo.toml index b7aa7b76..b04c3102 100644 --- a/runtime/testnet/Cargo.toml +++ b/runtime/testnet/Cargo.toml @@ -22,7 +22,7 @@ scale-info.workspace = true smallvec.workspace = true # Local -pop-primitives = { workspace = true, features = ["assets", "nfts", "cross-chain"] } +pop-primitives = { workspace = true, features = ["nfts", "cross-chain"] } pop-runtime-common = { workspace = true, default-features = false } # Substrate diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index dd2c52bb..4c224544 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -3,7 +3,7 @@ use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, - traits::nonfungibles_v2::Inspect as NonFungiblesInspect, + traits::nonfungibles_v2::Inspect, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, @@ -86,7 +86,6 @@ impl TryFrom for v0::FuncId { 0x1 => Self::ReadState, _ => { log::error!("called an unregistered `func_id`: {:}", func_id); - // TODO: Other error. return Err(DispatchError::Other("unimplemented func_id")); }, }; @@ -207,8 +206,6 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, - // TODO: devnet / testnet feature. - _ => Err(DispatchError::Other("Unknown state keys")), }? .encode(); @@ -218,8 +215,7 @@ where ); env.write(&result, false, None).map_err(|e| { log::trace!(target: LOG_TARGET, "{:?}", e); - // TODO: Other error. - DispatchError::Other("Unable to write results to contract memory") + DispatchError::Other("unable to write results to contract memory") }) } @@ -485,7 +481,7 @@ mod tests { log::debug!("result: {:?}", result); } - // Check for revert. + // check for revert assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); assert_eq!(Nfts::owner(collection_id, item_id), Some(BOB.into())); @@ -550,7 +546,7 @@ mod tests { log::debug!("result: {:?}", result); } - // Check for revert with expected error. + // check for revert with expected error let result = result.result.unwrap(); assert!(result.did_revert()); }); @@ -610,7 +606,7 @@ mod tests { log::debug!("result: {:?}", result); } - // Check for revert. + // check for revert assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); }); } @@ -673,7 +669,7 @@ mod tests { log::debug!("result: {:?}", result); } - // Check for revert. + // check for revert assert!( result.result.is_err(), "Contract execution should have failed - unimplemented runtime call!" @@ -735,7 +731,7 @@ mod tests { log::debug!("filtered result: {:?}", result); } - // Check for revert. + // check for revert assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); }); } From 972e4c9e1519279ad351d4d900c65e3a375a6d29 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Fri, 5 Jul 2024 19:13:57 +0200 Subject: [PATCH 017/161] feat: add more interfaces --- pop-api/examples/fungibles/lib.rs | 38 +- pop-api/integration-tests/Cargo.toml | 2 + pop-api/integration-tests/src/lib.rs | 9 +- .../integration-tests/src/local_fungibles.rs | 440 ++++++++++++++---- pop-api/src/v0/assets/fungibles.rs | 19 +- pop-api/src/v0/assets/mod.rs | 140 ++++-- runtime/devnet/src/config/mod.rs | 2 +- runtime/devnet/src/extensions/mod.rs | 45 +- runtime/devnet/src/extensions/v0/assets.rs | 42 +- 9 files changed, 554 insertions(+), 183 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 03841b74..2abc422c 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -45,19 +45,23 @@ mod fungibles { } #[ink(message)] - pub fn balance_of(&self, id: AssetId, owner: AccountId) -> Balance { + pub fn balance_of(&self, id: AssetId, owner: AccountId) -> Result { api::balance_of(id, owner) } #[ink(message)] - pub fn allowance(&self, id: AssetId, owner: AccountId, spender: AccountId) -> Balance { + pub fn allowance( + &self, + id: AssetId, + owner: AccountId, + spender: AccountId, + ) -> Result { api::allowance(id, owner, spender) } #[ink(message)] pub fn transfer(&self, id: AssetId, to: AccountId, value: Balance) -> Result<()> { - api::transfer(id, to, value)?; - Ok(()) + api::transfer(id, to, value) } #[ink(message)] @@ -70,14 +74,12 @@ mod fungibles { // In the standard a `[u8]`, but the size needs to be known at compile time. _data: Vec, ) -> Result<()> { - api::transfer_from(id, from, to, value)?; - Ok(()) + api::transfer_from(id, from, to, value) } #[ink(message)] pub fn approve(&self, id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - api::approve(id, spender, value)?; - Ok(()) + api::approve(id, spender, value) } #[ink(message)] @@ -87,8 +89,7 @@ mod fungibles { spender: AccountId, value: Balance, ) -> Result<()> { - api::increase_allowance(id, spender, value)?; - Ok(()) + api::increase_allowance(id, spender, value) } #[ink(message)] @@ -98,27 +99,26 @@ mod fungibles { spender: AccountId, value: Balance, ) -> Result<()> { - api::decrease_allowance(id, spender, value)?; - Ok(()) + api::decrease_allowance(id, spender, value) } - // 2. PSP-22 Metadata Interface: - // - token_name - // - token_symbol - // - token_decimals + /// 2. PSP-22 Metadata Interface: + /// - token_name + /// - token_symbol + /// - token_decimals #[ink(message)] - pub fn token_name(&self, id: AssetId) -> Vec { + pub fn token_name(&self, id: AssetId) -> Result> { api::token_name(id) } #[ink(message)] - pub fn token_symbol(&self, id: AssetId) -> Vec { + pub fn token_symbol(&self, id: AssetId) -> Result> { api::token_symbol(id) } #[ink(message)] - pub fn token_decimals(&self, id: AssetId) -> u8 { + pub fn token_decimals(&self, id: AssetId) -> Result { api::token_decimals(id) } diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml index c855a884..94c0ba83 100644 --- a/pop-api/integration-tests/Cargo.toml +++ b/pop-api/integration-tests/Cargo.toml @@ -9,6 +9,7 @@ scale = { package = "parity-scale-codec", version = "3.0.0", default-features = frame-support = { version = "29.0.0", default-features = false } frame-system = { version = "29.0.0", default-features = false } pallet-balances = { version = "29.0.2", default-features = false } +pallet-assets = { version = "30.0.0", default-features = false } pallet-contracts = { version = "28.0.0", default-features = false } pop-primitives = { path = "../../primitives", default-features = false, features = ["assets"] } pop-runtime-devnet = { path = "../../runtime/devnet", default-features = false } @@ -22,6 +23,7 @@ std = [ "frame-support/std", "frame-system/std", "pallet-balances/std", + "pallet-assets/std", "pallet-contracts/std", "pop-primitives/std", "pop-runtime-devnet/std", diff --git a/pop-api/integration-tests/src/lib.rs b/pop-api/integration-tests/src/lib.rs index 624c3000..c6732d91 100644 --- a/pop-api/integration-tests/src/lib.rs +++ b/pop-api/integration-tests/src/lib.rs @@ -1,14 +1,19 @@ #![cfg(test)] use frame_support::{ - traits::fungibles::{approvals::Inspect as ApprovalInspect, Inspect}, + traits::fungibles::{ + approvals::Inspect as ApprovalInspect, metadata::Inspect as MetadataInspect, Inspect, + }, weights::Weight, }; use pallet_contracts::{Code, CollectEvents, Determinism, ExecReturnValue}; use scale::{Decode, Encode}; use sp_runtime::{traits::Hash, AccountId32, BuildStorage, DispatchError}; -use pop_runtime_devnet::{Assets, Contracts, Runtime, RuntimeOrigin, System, UNIT}; +use pop_runtime_devnet::{ + config::assets::TrustBackedAssetsInstance, Assets, Contracts, Runtime, RuntimeOrigin, System, + UNIT, +}; mod local_fungibles; diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs index 968c43eb..d0229c84 100644 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -10,10 +10,27 @@ const ASSET_ID: AssetId = 1; fn decoded(result: ExecReturnValue) -> T { match ::decode(&mut &result.data[2..]) { Ok(value) => value, - Err(_) => panic!("\nTest failed by trying to decode result: {:?} into `T`\n", result), + Err(_) => panic!("\nTest failed by trying to decode `{:?}` into `T`\n", result), } } +// Call total_supply contract message. +fn total_supply(addr: AccountId32, asset_id: AssetId) -> Balance { + let function = function_selector("total_supply"); + let params = [function, asset_id.encode()].concat(); + let result = do_bare_call(addr, params, 0).expect("should work"); + decoded::(result) +} + +// Call balance_of contract message. +fn balance_of(addr: AccountId32, asset_id: AssetId, owner: AccountId32) -> Balance { + let function = function_selector("balance_of"); + let params = [function, asset_id.encode(), owner.encode()].concat(); + let result = do_bare_call(addr, params, 0).expect("should work"); + decoded::(result) +} + +// Call allowance contract message. fn allowance( addr: AccountId32, asset_id: AssetId, @@ -26,20 +43,28 @@ fn allowance( decoded::(result) } -// Call balance_of contract message. -fn balance_of(addr: AccountId32, asset_id: AssetId, owner: AccountId32) -> Balance { - let function = function_selector("balance_of"); - let params = [function, asset_id.encode(), owner.encode()].concat(); +// Call token_name contract message. +fn token_name(addr: AccountId32, asset_id: AssetId) -> Vec { + let function = function_selector("token_name"); + let params = [function, asset_id.encode()].concat(); let result = do_bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::>(result) } -// Call total_supply contract message. -fn total_supply(addr: AccountId32, asset_id: AssetId) -> Balance { - let function = function_selector("total_supply"); +// Call token_symbol contract message. +fn token_symbol(addr: AccountId32, asset_id: AssetId) -> Vec { + let function = function_selector("token_symbol"); let params = [function, asset_id.encode()].concat(); let result = do_bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::>(result) +} + +// Call token_decimals contract message. +fn token_decimals(addr: AccountId32, asset_id: AssetId) -> u8 { + let function = function_selector("token_decimals"); + let params = [function, asset_id.encode()].concat(); + let result = do_bare_call(addr, params, 0).expect("should work"); + decoded::(result) } fn asset_exists(addr: AccountId32, asset_id: AssetId) -> bool { @@ -82,7 +107,6 @@ fn transfer( let function = function_selector("transfer"); let params = [function, asset_id.encode(), to.encode(), value.encode()].concat(); let result = do_bare_call(addr, params, 0).expect("should work"); - println!("Transfer result: {:?}", result); result } @@ -101,6 +125,18 @@ fn transfer_from( do_bare_call(addr, params, 0).expect("should work") } +fn increase_allowance( + addr: AccountId32, + asset_id: AssetId, + spender: AccountId32, + value: Balance, +) -> ExecReturnValue { + let function = function_selector("increase_allowance"); + let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); + let result = do_bare_call(addr, params, 0).expect("should work"); + result +} + fn create_asset(owner: AccountId32, asset_id: AssetId, min_balance: Balance) -> AssetId { assert_eq!( Assets::create( @@ -154,20 +190,88 @@ fn create_asset_mint_and_approve( } // Freeze an asset. -fn freeze_asset(asset_id: AssetId, owner: AccountId32) { +fn freeze_asset(owner: AccountId32, asset_id: AssetId) { assert_eq!(Assets::freeze_asset(RuntimeOrigin::signed(owner.into()), asset_id.into()), Ok(())); } // Thaw an asset. -fn thaw_asset(asset_id: AssetId, owner: AccountId32) { +fn thaw_asset(owner: AccountId32, asset_id: AssetId) { assert_eq!(Assets::thaw_asset(RuntimeOrigin::signed(owner.into()), asset_id.into()), Ok(())); } // Start destroying an asset. -fn start_destroy_asset(asset_id: AssetId, owner: AccountId32) { +fn start_destroy_asset(owner: AccountId32, asset_id: AssetId) { assert_eq!(Assets::start_destroy(RuntimeOrigin::signed(owner.into()), asset_id.into()), Ok(())); } +// Create an asset and set metadata. +fn create_asset_and_set_metadata( + owner: AccountId32, + asset_id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, +) { + assert_eq!( + Assets::create( + RuntimeOrigin::signed(owner.clone()), + asset_id.into(), + owner.clone().into(), + 100 + ), + Ok(()) + ); + set_metadata_asset(owner, asset_id, name, symbol, decimals); +} + +// Set metadata of an asset. +fn set_metadata_asset( + owner: AccountId32, + asset_id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, +) { + assert_eq!( + Assets::set_metadata( + RuntimeOrigin::signed(owner.into()), + asset_id.into(), + name, + symbol, + decimals + ), + Ok(()) + ); +} + +fn token_name_asset(asset_id: AssetId) -> Vec { + as MetadataInspect>::name( + asset_id, + ) +} + +fn token_symbol_asset(asset_id: AssetId) -> Vec { + as MetadataInspect>::symbol( + asset_id, + ) +} + +fn token_decimals_asset(asset_id: AssetId) -> u8 { + as MetadataInspect>::decimals( + asset_id, + ) +} + +/// 1. PSP-22 Interface: +/// - total_supply +/// - balance_of +/// - allowance +/// - transfer +/// - transfer_from +/// - approve +/// - increase_allowance +/// - decrease_allowance + #[test] #[ignore] fn total_supply_works() { @@ -181,10 +285,12 @@ fn total_supply_works() { // No tokens in circulation. assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr.clone(), ASSET_ID)); + assert_eq!(0, total_supply(addr.clone(), ASSET_ID)); // Tokens in circulation. create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); - assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr, ASSET_ID)); + assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr.clone(), ASSET_ID)); + assert_eq!(100, total_supply(addr, ASSET_ID)); }); } @@ -198,10 +304,12 @@ fn balance_of_works() { // No tokens in circulation. assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr.clone(), ASSET_ID, BOB)); + assert_eq!(0, balance_of(addr.clone(), ASSET_ID, BOB)); // Tokens in circulation. create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); - assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr, ASSET_ID, BOB)); + assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr.clone(), ASSET_ID, BOB)); + assert_eq!(100, balance_of(addr, ASSET_ID, BOB)); }); } @@ -218,90 +326,240 @@ fn allowance_works() { Assets::allowance(ASSET_ID, &BOB, &ALICE), allowance(addr.clone(), ASSET_ID, BOB, ALICE) ); + assert_eq!(0, allowance(addr.clone(), ASSET_ID, BOB, ALICE)); // Tokens in circulation. create_asset_mint_and_approve(addr.clone(), ASSET_ID, BOB, 100, ALICE, 50); assert_eq!( Assets::allowance(ASSET_ID, &BOB, &ALICE), - allowance(addr, ASSET_ID, BOB, ALICE) + allowance(addr.clone(), ASSET_ID, BOB, ALICE) ); + assert_eq!(50, allowance(addr, ASSET_ID, BOB, ALICE)); }); } #[test] #[ignore] -fn asset_exists_works() { +fn transfer_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); + let amount: Balance = 100 * UNIT; - // No tokens in circulation. - assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr.clone(), ASSET_ID)); - - // Tokens in circulation. - create_asset(addr.clone(), ASSET_ID, 1); - assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr, ASSET_ID)); + // Asset does not exist. + assert_eq!( + decoded::(transfer(addr.clone(), 1, BOB, amount,)), + Module { index: 52, error: 3 }, + ); + // Create asset with Alice as owner and mint `amount` to contract address. + let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(ALICE, asset); + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount,)), + Module { index: 52, error: 16 }, + ); + thaw_asset(ALICE, asset); + // Not enough balance. + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), + Module { index: 52, error: 0 }, + ); + // Not enough balance due to ED. + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount)), + Module { index: 52, error: 0 }, + ); + // Successful transfer. + let bob_balance_before_mint = Assets::balance(asset, &BOB); + let result = transfer(addr.clone(), asset, BOB, amount / 2); + assert!(!result.did_revert(), "Contract reverted!"); + let bob_balance_after_mint = Assets::balance(asset, &BOB); + assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); + // Transfer asset to account that does not exist. + assert_eq!( + decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), + Token(CannotCreate) + ); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(ALICE, asset); + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), + Module { index: 52, error: 16 }, + ); }); } #[test] #[ignore] -fn create_works() { +fn increase_allowance_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let new_asset = 2; - // Instantiate a contract without balance (relay token). - let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); - // No balance to pay for fees. + let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![]); + let amount: Balance = 100 * UNIT; + let asset = 0; + create_asset_and_mint_to(ALICE, asset, addr.clone(), amount); assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), - Module { index: 10, error: 2 }, + decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), + ConsumerRemaining ); - // Instantiate a contract without balance (relay token). - let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 100, vec![2]); - // TODO: make sure it has enough for the fees but not for the deposit. - // No balance to pay fe deposit. + + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); + // Asset does not exist. + let asset = 1; assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), - Module { index: 10, error: 2 }, + decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), + Module { index: 52, error: 3 }, ); - // Instantiate a contract with balance. + // Create asset with Alice as owner and mint `amount` to contract address. + create_asset_and_mint_to(ALICE, asset, addr.clone(), amount); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(ALICE, asset); + assert_eq!( + decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), + Module { index: 52, error: 16 }, + ); + thaw_asset(ALICE, asset); + // Successful approval. + assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); + assert!( + !increase_allowance(addr.clone(), asset, BOB, amount).did_revert(), + "Contract reverted!" + ); + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount); + // Additive. + assert!( + !increase_allowance(addr.clone(), asset, BOB, amount).did_revert(), + "Contract reverted!" + ); + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount * 2); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(ALICE, asset); + assert_eq!( + decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), + Module { index: 52, error: 16 }, + ); + }); +} + +#[test] +#[ignore] +fn transfer_from_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); - create_asset(ALICE, ASSET_ID, 1); - // Asset ID is already taken. + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); + let amount: Balance = 100 * UNIT; + + // Asset does not exist. assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), - Module { index: 52, error: 5 }, + decoded::(transfer(addr.clone(), 1, BOB, amount,)), + Module { index: 52, error: 3 }, ); - // The minimal balance for an asset must be non zero. + // Create asset with Alice as owner and mint `amount` to contract address. + let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(ALICE, asset); assert_eq!( - decoded::(create(addr.clone(), new_asset, BOB, 0)), - Module { index: 52, error: 7 }, + decoded::(transfer(addr.clone(), asset, BOB, amount,)), + Module { index: 52, error: 16 }, ); - let result = create(addr.clone(), new_asset, BOB, 1); + thaw_asset(ALICE, asset); + // Not enough balance. + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), + Module { index: 52, error: 0 }, + ); + // Not enough balance due to ED. + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount)), + Module { index: 52, error: 0 }, + ); + // Successful transfer. + let bob_balance_before_mint = Assets::balance(asset, &BOB); + let result = transfer(addr.clone(), asset, BOB, amount / 2); assert!(!result.did_revert(), "Contract reverted!"); + let bob_balance_after_mint = Assets::balance(asset, &BOB); + assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); + // Transfer asset to account that does not exist. + assert_eq!( + decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), + Token(CannotCreate) + ); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(ALICE, asset); + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), + Module { index: 52, error: 16 }, + ); }); } +/// 2. PSP-22 Metadata Interface: +/// - token_name +/// - token_symbol +/// - token_decimals + #[test] #[ignore] -fn set_metadata_works() { +fn token_metadata_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate( + "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", + INIT_VALUE, + vec![], + ); + + let name: Vec = vec![11, 12, 13]; + let symbol: Vec = vec![21, 22, 23]; + let decimals: u8 = 69; + // Token does not exist. + assert_eq!(token_name_asset(ASSET_ID), token_name(addr.clone(), ASSET_ID)); + assert_eq!(Vec::::new(), token_name(addr.clone(), ASSET_ID)); + assert_eq!(token_symbol_asset(ASSET_ID), token_symbol(addr.clone(), ASSET_ID)); + assert_eq!(Vec::::new(), token_symbol(addr.clone(), ASSET_ID)); + assert_eq!(token_decimals_asset(ASSET_ID), token_decimals(addr.clone(), ASSET_ID)); + assert_eq!(0, token_decimals(addr.clone(), ASSET_ID)); + + create_asset_and_set_metadata( + addr.clone(), + ASSET_ID, + name.clone(), + symbol.clone(), + decimals, + ); + assert_eq!(token_name_asset(ASSET_ID), token_name(addr.clone(), ASSET_ID)); + assert_eq!(name, token_name(addr.clone(), ASSET_ID)); + assert_eq!(token_symbol_asset(ASSET_ID), token_symbol(addr.clone(), ASSET_ID)); + assert_eq!(symbol, token_symbol(addr.clone(), ASSET_ID)); + assert_eq!(token_decimals_asset(ASSET_ID), token_decimals(addr.clone(), ASSET_ID)); + assert_eq!(decimals, token_decimals(addr.clone(), ASSET_ID)); + }); +} + +#[test] +#[ignore] +fn asset_exists_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); + // No tokens in circulation. + assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr.clone(), ASSET_ID)); + + // Tokens in circulation. create_asset(addr.clone(), ASSET_ID, 1); - let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); - assert!(!result.did_revert(), "Contract reverted!"); + assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr, ASSET_ID)); }); } #[test] #[ignore] -fn transfer_from_mint_works() { +fn mint_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); let addr = @@ -326,12 +584,12 @@ fn transfer_from_mint_works() { ); let asset = create_asset(addr.clone(), 2, 2); // Asset is not live, i.e. frozen or being destroyed. - freeze_asset(asset, addr.clone()); + freeze_asset(addr.clone(), asset); assert_eq!( decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), Module { index: 52, error: 16 }, ); - thaw_asset(asset, addr.clone()); + thaw_asset(addr.clone(), asset); // Successful mint. let bob_balance_before_mint = Assets::balance(asset, &BOB); let result = transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8]); @@ -351,7 +609,7 @@ fn transfer_from_mint_works() { Arithmetic(Overflow) ); // Asset is not live, i.e. frozen or being destroyed. - start_destroy_asset(asset, addr.clone()); + start_destroy_asset(addr.clone(), asset); assert_eq!( decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), Module { index: 52, error: 16 }, @@ -361,53 +619,53 @@ fn transfer_from_mint_works() { #[test] #[ignore] -fn transfer_works() { +fn create_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); - let amount: Balance = 100 * UNIT; - - // Asset does not exist. + // Instantiate a contract without balance (relay token). + let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); + // No balance to pay for fees. assert_eq!( - decoded::(transfer(addr.clone(), 1, BOB, amount,)), - Module { index: 52, error: 3 }, + decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), + Module { index: 10, error: 2 }, ); - // Create asset with Alice as owner and mint `amount` to contract address. - let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); - // Asset is not live, i.e. frozen or being destroyed. - freeze_asset(asset, ALICE); + // Instantiate a contract without balance (relay token). + let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 100, vec![2]); + // No balance to pay the deposit. assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount,)), - Module { index: 52, error: 16 }, + decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), + Module { index: 10, error: 2 }, ); - thaw_asset(asset, ALICE); - // Not enough balance. + // Instantiate a contract with balance. + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), - Module { index: 52, error: 0 }, + decoded::(create(addr.clone(), ASSET_ID, BOB, 0)), + Module { index: 52, error: 7 }, ); - // Not enough balance due to ED. + create_asset(ALICE, ASSET_ID, 1); + // Asset ID is already taken. assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 0 }, + decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), + Module { index: 52, error: 5 }, ); - // Successful transfer. - let bob_balance_before_mint = Assets::balance(asset, &BOB); - let result = transfer(addr.clone(), asset, BOB, amount / 2); + // The minimal balance for an asset must be non zero. + let new_asset = 2; + let result = create(addr.clone(), new_asset, BOB, 1); + assert!(!result.did_revert(), "Contract reverted!"); + }); +} + +#[test] +#[ignore] +fn set_metadata_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); + + create_asset(addr.clone(), ASSET_ID, 1); + let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); assert!(!result.did_revert(), "Contract reverted!"); - let bob_balance_after_mint = Assets::balance(asset, &BOB); - assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); - // Transfer asset to account that does not exist. - assert_eq!( - decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), - Token(CannotCreate) - ); - // Asset is not live, i.e. frozen or being destroyed. - start_destroy_asset(asset, ALICE); - assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), - Module { index: 52, error: 16 }, - ); }); } diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 8d0de768..5325cad3 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -39,7 +39,7 @@ pub fn total_supply(id: AssetId) -> Result { /// # Returns /// The balance of the specified account, or an error if the operation fails. #[inline] -pub fn balance_of(id: AssetId, owner: AccountId) -> Balance { +pub fn balance_of(id: AssetId, owner: AccountId) -> Result { assets::balance_of(id, owner) } @@ -54,7 +54,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Balance { /// # Returns /// The remaining allowance, or an error if the operation fails. #[inline] -pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Balance { +pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { assets::allowance(id, owner, spender) } @@ -101,6 +101,7 @@ pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance /// Returns `Ok(())` if successful, or an error if the approval fails. #[inline] pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + assets::cancel_approval(id, spender)?; assets::approve_transfer(id, spender, value) } @@ -128,9 +129,11 @@ pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re /// # Returns /// Returns `Ok(())` if successful, or an error if the operation fails. #[inline] -pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - assets::cancel_approval(id, spender.clone())?; - assets::approve_transfer(id, spender, value) +pub fn decrease_allowance(_id: AssetId, _spender: AccountId, _value: Balance) -> Result<()> { + // let allowance = assets::allowance(id, owner, spender)?; + // assets::cancel_approval(id, spender.clone())?; + // assets::approve_transfer(id, spender, value) + Ok(()) } /// 2. PSP-22 Metadata Interface: @@ -146,7 +149,7 @@ pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re /// # Returns /// The name of the token as a byte vector, or an error if the operation fails. #[inline] -pub fn token_name(id: AssetId) -> Vec { +pub fn token_name(id: AssetId) -> Result> { assets::token_name(id) } @@ -158,7 +161,7 @@ pub fn token_name(id: AssetId) -> Vec { /// # Returns /// The symbol of the token as a byte vector, or an error if the operation fails. #[inline] -pub fn token_symbol(id: AssetId) -> Vec { +pub fn token_symbol(id: AssetId) -> Result> { assets::token_symbol(id) } @@ -170,7 +173,7 @@ pub fn token_symbol(id: AssetId) -> Vec { /// # Returns /// The number of decimals of the token as a byte vector, or an error if the operation fails. #[inline] -pub fn token_decimals(id: AssetId) -> u8 { +pub fn token_decimals(id: AssetId) -> Result { assets::token_decimals(id) } diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 22657323..d14c3322 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -26,8 +26,11 @@ const TRANSFER_KEEP_ALIVE: u8 = 9; /// - set_metadata /// - clear_metadata /// - approve_transfer +const APPROVE_TRANSFER: u8 = 22; /// - cancel_approval +const CANCEL_APPROVAL: u8 = 23; /// - transfer_approved +const TRANSFER_APPROVED: u8 = 25; /// Issue a new class of fungible assets from a public origin. // pub(crate) fn create( @@ -91,7 +94,7 @@ pub fn transfer(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { VERSION, DISPATCH, ASSETS_MODULE, - // TODO: E.D. is always respected with transferring tokens via the API. + // E.D. is always respected with transferring tokens via the API. TRANSFER_KEEP_ALIVE, ])) .input::<(AssetId, AccountId, Balance)>() @@ -131,21 +134,31 @@ pub fn transfer(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { /// Approve an amount of asset for transfer by a delegated third-party account. #[inline] pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([0u8, 0, 52, 69])) - .input::<(AssetId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, delegate, amount)) + ChainExtensionMethod::build(u32::from_le_bytes([ + VERSION, + DISPATCH, + ASSETS_MODULE, + APPROVE_TRANSFER, + ])) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, delegate, amount)) } /// Cancel all of some asset approved for delegated transfer by a third-party account. #[inline] pub fn cancel_approval(id: AssetId, delegate: AccountId) -> Result<()> { - ChainExtensionMethod::build(0) - .input::<(AssetId, AccountId)>() - .output::, true>() - .handle_error_code::() - .call(&(id, delegate)) + ChainExtensionMethod::build(u32::from_le_bytes([ + VERSION, + DISPATCH, + ASSETS_MODULE, + CANCEL_APPROVAL, + ])) + .input::<(AssetId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(id, delegate)) } /// Transfer some asset balance from a previously delegated account to some third-party @@ -157,23 +170,33 @@ pub fn transfer_approved( to: AccountId, amount: Balance, ) -> Result<()> { - ChainExtensionMethod::build(0) - .input::<(AssetId, AccountId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, from, to, amount)) + ChainExtensionMethod::build(u32::from_le_bytes([ + VERSION, + DISPATCH, + ASSETS_MODULE, + TRANSFER_APPROVED, + ])) + .input::<(AssetId, AccountId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, from, to, amount)) } -/// 2. Read state functions +/// 2. Read state functions: const READ_STATE: u8 = 1; /// - total_supply const TOTAL_SUPPLY: u8 = 0; /// - balance_of +const BALANCE_OF: u8 = 1; /// - allowance -/// - asset_exists +const ALLOWANCE: u8 = 2; /// - token_name +const TOKEN_NAME: u8 = 3; /// - token_symbol +const TOKEN_SYMBOL: u8 = 4; /// - token_decimals +const TOKEN_DECIMALS: u8 = 5; +/// - asset_exists #[inline] pub fn total_supply(id: AssetId) -> Result { @@ -191,48 +214,73 @@ pub fn total_supply(id: AssetId) -> Result { } #[inline] -pub fn balance_of(id: AssetId, owner: AccountId) -> Balance { - ChainExtensionMethod::build(1) - .input::<(AssetId, AccountId)>() - .output::() - .ignore_error_code() - .call(&(id, owner)) +pub fn balance_of(id: AssetId, owner: AccountId) -> Result { + ChainExtensionMethod::build(u32::from_le_bytes([ + VERSION, + READ_STATE, + ASSETS_MODULE, + BALANCE_OF, + ])) + .input::<(AssetId, AccountId)>() + .output::>, true>() + .handle_error_code::() + .call(&(id, owner)) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) } #[inline] -pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Balance { - ChainExtensionMethod::build(1) +pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { + ChainExtensionMethod::build(u32::from_le_bytes([VERSION, READ_STATE, ASSETS_MODULE, ALLOWANCE])) .input::<(AssetId, AccountId, AccountId)>() - .output::() - .ignore_error_code() + .output::>, true>() + .handle_error_code::() .call(&(id, owner, spender)) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) } #[inline] -pub fn token_name(id: AssetId) -> Vec { - ChainExtensionMethod::build(1) - .input::() - .output::, false>() - .ignore_error_code() - .call(&(id)) +pub fn token_name(id: AssetId) -> Result> { + ChainExtensionMethod::build(u32::from_le_bytes([ + VERSION, + READ_STATE, + ASSETS_MODULE, + TOKEN_NAME, + ])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) } // #[inline] -pub fn token_symbol(id: AssetId) -> Vec { - ChainExtensionMethod::build(1) - .input::() - .output::, false>() - .ignore_error_code() - .call(&(id)) +pub fn token_symbol(id: AssetId) -> Result> { + ChainExtensionMethod::build(u32::from_le_bytes([ + VERSION, + READ_STATE, + ASSETS_MODULE, + TOKEN_SYMBOL, + ])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) } #[inline] -pub fn token_decimals(id: AssetId) -> u8 { - ChainExtensionMethod::build(1) - .input::() - .output::() - .ignore_error_code() - .call(&(id)) +pub fn token_decimals(id: AssetId) -> Result { + ChainExtensionMethod::build(u32::from_le_bytes([ + VERSION, + READ_STATE, + ASSETS_MODULE, + TOKEN_DECIMALS, + ])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| ::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) } // pub(crate) fn asset_exists(id: AssetId) -> Result { diff --git a/runtime/devnet/src/config/mod.rs b/runtime/devnet/src/config/mod.rs index c370bb1d..e0aaa3a1 100644 --- a/runtime/devnet/src/config/mod.rs +++ b/runtime/devnet/src/config/mod.rs @@ -1,4 +1,4 @@ -pub(crate) mod assets; +pub mod assets; mod contracts; mod proxy; // Public due to integration tests crate. diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index ac52d5bd..8f0a6eda 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -5,7 +5,7 @@ use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, traits::{ - fungibles::approvals::Inspect as ApprovalInspect, + fungibles::{approvals::Inspect as ApprovalInspect, metadata::Inspect as MetadataInspect}, nonfungibles_v2::Inspect as NonFungiblesInspect, }, }; @@ -129,8 +129,7 @@ where E: Ext, { const LOG_PREFIX: &str = " dispatch |"; - let call = construct_call(version, pallet_index, call_index, params) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; + let call = construct_call(version, pallet_index, call_index, params)?; // Contract is the origin by default. let origin: RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); dispatch_call::(env, call, origin, LOG_PREFIX) @@ -434,6 +433,15 @@ where T: frame_system::Config, { match key { + TotalSupply(id) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_assets::Pallet::::total_supply(id).encode()) + }, + BalanceOf(id, owner) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok(pallet_assets::Pallet::::balance(id, &owner.0.into()) + .encode()) + }, Allowance(id, owner, spender) => { env.charge_weight(T::DbWeight::get().reads(1_u64))?; Ok(pallet_assets::Pallet::::allowance( @@ -443,20 +451,31 @@ where ) .encode()) }, - // AssetsKeys::AssetExists(id) => { - // env.charge_weight(T::DbWeight::get().reads(1_u64))?; - // Ok(pallet_assets::Pallet::::asset_exists(id).encode()) - // }, - BalanceOf(id, owner) => { + TokenName(id) => { env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_assets::Pallet::::balance(id, &owner.0.into()) - .encode()) + Ok( as MetadataInspect< + AccountId, + >>::name(id) + .encode()) }, - TotalSupply(id) => { + TokenSymbol(id) => { env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_assets::Pallet::::total_supply(id).encode()) + Ok( as MetadataInspect< + AccountId, + >>::symbol(id) + .encode()) }, - _ => todo!(), + TokenDecimals(id) => { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + Ok( as MetadataInspect< + AccountId, + >>::decimals(id) + .encode()) + }, + // AssetsKeys::AssetExists(id) => { + // env.charge_weight(T::DbWeight::get().reads(1_u64))?; + // Ok(pallet_assets::Pallet::::asset_exists(id).encode()) + // }, } } diff --git a/runtime/devnet/src/extensions/v0/assets.rs b/runtime/devnet/src/extensions/v0/assets.rs index 912b116f..407b0d55 100644 --- a/runtime/devnet/src/extensions/v0/assets.rs +++ b/runtime/devnet/src/extensions/v0/assets.rs @@ -1,8 +1,9 @@ use crate::extensions::{ - AccountId, AssetId, - AssetsKeys::{self, TotalSupply}, + AccountId as AccountId32, AssetId, + AssetsKeys::{self, *}, Balance, Compact, Decode, DispatchError, MultiAddress, Runtime, TrustBackedAssetsInstance, }; +use pop_primitives::AccountId; pub(crate) fn construct_assets_key( call_index: u8, @@ -14,6 +15,31 @@ pub(crate) fn construct_assets_key( .map_err(|_| DispatchError::Other("DecodingFailed"))?; Ok(TotalSupply(id)) }, + 1 => { + let (id, owner) = <(AssetId, AccountId)>::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + Ok(BalanceOf(id, owner)) + }, + 2 => { + let (id, owner, spender) = <(AssetId, AccountId, AccountId)>::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + Ok(Allowance(id, owner, spender)) + }, + 3 => { + let id = ::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + Ok(TokenName(id)) + }, + 4 => { + let id = ::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + Ok(TokenSymbol(id)) + }, + 5 => { + let id = ::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + Ok(TokenDecimals(id)) + }, // other calls _ => Err(DispatchError::Other("UnknownFunctionId")), } @@ -25,7 +51,7 @@ pub(crate) fn construct_assets_call( ) -> Result, DispatchError> { match call_index { 9 => { - let (id, target, amount) = <(AssetId, AccountId, Balance)>::decode(&mut ¶ms[..]) + let (id, target, amount) = <(AssetId, AccountId32, Balance)>::decode(&mut ¶ms[..]) .map_err(|_| DispatchError::Other("DecodingFailed"))?; Ok(pallet_assets::Call::::transfer_keep_alive { id: Compact(id), @@ -33,6 +59,16 @@ pub(crate) fn construct_assets_call( amount, }) }, + 22 => { + let (id, delegate, amount) = + <(AssetId, AccountId32, Balance)>::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + Ok(pallet_assets::Call::::approve_transfer { + id: Compact(id), + delegate: MultiAddress::Id(delegate), + amount, + }) + }, // other calls _ => Err(DispatchError::Other("UnknownFunctionId")), } From 47e2ea6770d0b6fe8fe5b611570cdfa772ed4c04 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Fri, 5 Jul 2024 23:49:03 +0200 Subject: [PATCH 018/161] refactor: final bits --- pop-api/src/v0/assets/fungibles.rs | 10 +++++----- pop-api/src/v0/assets/mod.rs | 17 ++--------------- runtime/devnet/src/extensions/mod.rs | 1 + runtime/devnet/src/extensions/v0/assets.rs | 1 + runtime/testnet/src/extensions.rs | 1 + 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 5325cad3..4abd46a6 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -70,7 +70,7 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result<()> { - assets::transfer(id, to, value) + assets::transfer_keep_alive(id, to, value) } /// Transfers `value` tokens on behalf of `from` to account `to` with additional `data` @@ -279,7 +279,6 @@ pub fn token_decimals(id: AssetId) -> Result { // assets::asset_exists(id) // } -// TODO: further implement the rest of the interfaces and conclude on the FungiblesError. #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum FungiblesError { @@ -300,13 +299,14 @@ pub enum FungiblesError { NoPermission, /// The given asset ID is unknown. Unknown, - // - Originally `InsufficientBalance` for the deposit but this would result in the same error - // as the error when there is insufficient balance for transferring an asset. /// No balance for creation of assets or fees. + // + // Originally `pallet_balances::Error::InsufficientBalance` but collides with the + // `InsufficientBalance` error that is used for `pallet_assets::Error::BalanceLow` to adhere to + // standard. NoBalance, } -// TODO: include conversions from TokenError and add conversions based on added interfaces. impl From for FungiblesError { fn from(value: StatusCode) -> Self { let encoded = value.0.to_le_bytes(); diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index d14c3322..ea8991a7 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -87,9 +87,9 @@ const TRANSFER_APPROVED: u8 = 25; // })) // } -/// Move some assets from the sender account to another. +/// Move some assets from the sender account to another, keeping the sender account alive. #[inline] -pub fn transfer(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { +pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { ChainExtensionMethod::build(u32::from_le_bytes([ VERSION, DISPATCH, @@ -103,19 +103,6 @@ pub fn transfer(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { .call(&(id, target, amount)) } -// /// Move some assets from the sender account to another, keeping the sender account alive. -// pub(crate) fn transfer_keep_alive( -// id: AssetId, -// target: impl Into>, -// amount: Balance, -// ) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::TransferKeepAlive { -// id: id.into(), -// target: target.into(), -// amount: Compact(amount), -// })) -// } - // /// Set the metadata for an asset. // pub(crate) fn set_metadata( // id: AssetId, diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index 8f0a6eda..aa58bcea 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -304,6 +304,7 @@ where // - `error`: The `DispatchError` encountered during contract execution. // - `version`: The version of the chain extension, used to determine the known errors. pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { + use sp_std::vec; // "UnknownFunctionId" and "DecodingFailed" are mapped to specific errors in the API and will // never change. let mut encoded_error = match error { diff --git a/runtime/devnet/src/extensions/v0/assets.rs b/runtime/devnet/src/extensions/v0/assets.rs index 407b0d55..c6b15b4e 100644 --- a/runtime/devnet/src/extensions/v0/assets.rs +++ b/runtime/devnet/src/extensions/v0/assets.rs @@ -4,6 +4,7 @@ use crate::extensions::{ Balance, Compact, Decode, DispatchError, MultiAddress, Runtime, TrustBackedAssetsInstance, }; use pop_primitives::AccountId; +use sp_std::vec::Vec; pub(crate) fn construct_assets_key( call_index: u8, diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index 4c224544..a5eeb3c3 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -206,6 +206,7 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, + _ => Ok(vec![0]), }? .encode(); From 9dcfccbe414ef4de57d12e59db6841fcbed9eeee Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Sat, 6 Jul 2024 10:05:17 +0200 Subject: [PATCH 019/161] fix: compiling --- Cargo.lock | 46 +++++++++++++++++++--------- Cargo.toml | 14 ++++----- runtime/devnet/src/extensions/mod.rs | 1 - runtime/testnet/src/extensions.rs | 2 +- 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf7abf73..e0c87955 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -426,9 +426,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "asset-hub-rococo-runtime" -version = "0.12.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e80dcb69497d50ceef11a046720e1c5a0feeb5575239c5ccb4b0be14a49bcfa" +checksum = "af52c4d3011936f615f3469b3c20f8b13b861f4c06d097bc1922200ce44781d9" dependencies = [ "assets-common", "bp-asset-hub-rococo", @@ -445,6 +445,7 @@ dependencies = [ "cumulus-primitives-utility", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -3747,6 +3748,22 @@ dependencies = [ "serde", ] +[[package]] +name = "frame-metadata-hash-extension" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb1eec9eb46d3e016c95b2fa875118c04609f2150013c56a894cae00581e265" +dependencies = [ + "array-bytes 6.2.2", + "docify", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", +] + [[package]] name = "frame-remote-externalities" version = "0.36.0" @@ -6979,9 +6996,9 @@ dependencies = [ [[package]] name = "pallet-collator-selection" -version = "10.0.2" +version = "10.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d1157d9a4b7966040158a7b4f1fb29f0cefa8deb6eb9b3452df7ce4161a31c" +checksum = "a36858c4275b7d19671b321e95f545e07c9643f97dffed1b333774cb391a4456" dependencies = [ "frame-benchmarking", "frame-support", @@ -7827,9 +7844,9 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" -version = "29.0.1" +version = "29.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0c408252aefe10cff96af1e54f06f45cb0dd184b4e450e9a2ecf837dfe506e" +checksum = "5a5ba71f06f09e955b80dc313c333be3f8d9e8505b051558e0b7af4806b13310" dependencies = [ "frame-support", "frame-system", @@ -8023,9 +8040,9 @@ dependencies = [ [[package]] name = "parachains-common" -version = "8.0.0" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34aa00981a24a2b772afaa49e258f9bcd6bb372db060a05614becc1c74d4456" +checksum = "711a4c073e7c83aac7e414ba16c7c641d6d9e22e6d32f9775ff35b2464ffd7ff" dependencies = [ "cumulus-primitives-core", "cumulus-primitives-utility", @@ -9255,9 +9272,9 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" -version = "8.0.2" +version = "8.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d815f0ff0a69dce7235d42c6e7d5e2b8b7429cba1252b4802ddc7879e2e74d4a" +checksum = "12a70422ca43d30457e2d9502a5e4af35e20fa2ff3f7cd46e0d2997c784f2665" dependencies = [ "bitvec", "frame-benchmarking", @@ -10518,13 +10535,14 @@ dependencies = [ [[package]] name = "rococo-runtime" -version = "8.0.0" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d089e93be2b8b76dd0d4b794a6a995ca3a1d6cb0ea3dd1cd42462f048bcfc926" +checksum = "cfa4cc054efdd3bfbec965da01b1ae16475031308c109c173347717091f6e3a5" dependencies = [ "binary-merkle-tree", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -13959,9 +13977,9 @@ dependencies = [ [[package]] name = "staging-xcm-builder" -version = "8.0.2" +version = "8.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "988d765ad5ab3b5cc90bb1dd143153ebdbe2b7600e10d5ef3a7f3e8df1bdac5d" +checksum = "78b7447c38be3ca9fb21c7434de2243aa6ac74acde8944cda7bb6e2a4f765801" dependencies = [ "frame-support", "frame-system", diff --git a/Cargo.toml b/Cargo.toml index 3719e83d..6b3cde02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,7 +97,7 @@ pallet-scheduler = { version = "30.0.0", default-features = false } pallet-session = { version = "29.0.0", default-features = false } pallet-sudo = { version = "29.0.0", default-features = false } pallet-timestamp = { version = "28.0.0", default-features = false } -pallet-transaction-payment = { version = "29.0.1", default-features = false } +pallet-transaction-payment = { version = "29.0.2", default-features = false } pallet-transaction-payment-rpc = "31.0.0" pallet-transaction-payment-rpc-runtime-api = { version = "29.0.0", default-features = false } pallet-utility = { version = "29.0.0", default-features = false } @@ -130,15 +130,15 @@ polkadot-cli = "8.0.0" polkadot-parachain-primitives = { version = "7.0.0", default-features = false } polkadot-runtime-parachains = { version = "8.0.3", default-features = false } polkadot-primitives = { version = "8.0.1", default-features = false } -polkadot-runtime-common = { version = "8.0.2", default-features = false } +polkadot-runtime-common = { version = "8.0.3", default-features = false } rococo-runtime-constants = { version = "8.0.0", default-features = false } -rococo-runtime = { version = "8.0.0", default-features = false } +rococo-runtime = { version = "8.0.1", default-features = false } xcm = { version = "8.0.1", package = "staging-xcm", default-features = false } -xcm-builder = { version = "8.0.2", package = "staging-xcm-builder", default-features = false } +xcm-builder = { version = "8.0.3", package = "staging-xcm-builder", default-features = false } xcm-executor = { version = "8.0.2", package = "staging-xcm-executor", default-features = false } # Cumulus -asset-hub-rococo-runtime = { version = "0.12.0", default-features = false } +asset-hub-rococo-runtime = { version = "0.12.3", default-features = false } asset-test-utils = { version = "8.0.1", default-features = false } cumulus-pallet-aura-ext = { version = "0.8.0", default-features = false } cumulus-pallet-parachain-system = { version = "0.8.1", default-features = false, features = ["parameterized-consensus-hook"] } @@ -149,8 +149,8 @@ cumulus-primitives-aura = { version = "0.8.0", default-features = false } cumulus-primitives-core = { version = "0.8.0", default-features = false } cumulus-primitives-utility = { version = "0.8.1", default-features = false } emulated-integration-tests-common = { version = "4.0.0", default-features = false } -pallet-collator-selection = { version = "10.0.2", default-features = false } -parachains-common = { version = "8.0.0", default-features = false } +pallet-collator-selection = { version = "10.0.3", default-features = false } +parachains-common = { version = "8.0.1", default-features = false } parachain-info = { version = "0.8.0", package = "staging-parachain-info", default-features = false } cumulus-primitives-parachain-inherent = "0.8.0" cumulus-relay-chain-interface = "0.8.0" diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index aa58bcea..8f0a6eda 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -304,7 +304,6 @@ where // - `error`: The `DispatchError` encountered during contract execution. // - `version`: The version of the chain extension, used to determine the known errors. pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { - use sp_std::vec; // "UnknownFunctionId" and "DecodingFailed" are mapped to specific errors in the API and will // never change. let mut encoded_error = match error { diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index a5eeb3c3..61d3cb43 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -206,7 +206,7 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, - _ => Ok(vec![0]), + _ => Ok(vec![0u8]), }? .encode(); From b067edac54c1cb375dfa72472c03fab75aaa99d2 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Tue, 16 Jul 2024 18:27:27 +0200 Subject: [PATCH 020/161] fix: cannot find macro vec error --- Cargo.lock | 1489 +++++++++++++------------- runtime/devnet/Cargo.toml | 2 +- runtime/devnet/src/extensions/mod.rs | 4 +- runtime/testnet/src/extensions.rs | 2 +- 4 files changed, 755 insertions(+), 742 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0c87955..1983b157 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,11 +23,11 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ - "gimli 0.28.1", + "gimli 0.29.0", ] [[package]] @@ -68,7 +68,7 @@ dependencies = [ "cipher 0.4.4", "ctr", "ghash", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -77,7 +77,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "once_cell", "version_check", ] @@ -89,7 +89,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom 0.2.12", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "always-assert" @@ -142,47 +142,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -190,9 +191,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "approx" @@ -214,7 +215,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -354,9 +355,9 @@ checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" [[package]] name = "array-bytes" -version = "6.2.2" +version = "6.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f840fb7195bcfc5e17ea40c26e5ce6d5b9ce5d584466e17703209657e459ae0" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" [[package]] name = "arrayref" @@ -404,7 +405,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -573,27 +574,25 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", - "event-listener 5.2.0", - "event-listener-strategy 0.5.1", + "event-listener-strategy", "futures-core", "pin-project-lite 0.2.14", ] [[package]] name = "async-executor" -version = "1.9.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b3e585719c2358d2660232671ca8ca4ddb4be4ce8a1842d6c2dc8685303316" +checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" dependencies = [ - "async-lock 3.3.0", "async-task", "concurrent-queue", - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-lite 2.3.0", "slab", ] @@ -612,11 +611,11 @@ dependencies = [ [[package]] name = "async-fs" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc19683171f287921f2405677dd2ed2549c3b3bda697a563ebc3a121ace2aba1" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" dependencies = [ - "async-lock 3.3.0", + "async-lock 3.4.0", "blocking", "futures-lite 2.3.0", ] @@ -643,18 +642,18 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" dependencies = [ - "async-lock 3.3.0", + "async-lock 3.4.0", "cfg-if", "concurrent-queue", "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.6.0", - "rustix 0.38.32", + "polling 3.7.2", + "rustix 0.38.34", "slab", "tracing", "windows-sys 0.52.0", @@ -671,12 +670,12 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", + "event-listener 5.3.1", + "event-listener-strategy", "pin-project-lite 0.2.14", ] @@ -697,7 +696,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" dependencies = [ - "async-io 2.3.2", + "async-io 2.3.3", "blocking", "futures-lite 2.3.0", ] @@ -715,61 +714,63 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.48.0", ] [[package]] name = "async-process" -version = "2.1.0" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451e3cf68011bd56771c79db04a9e333095ab6349f7e47592b788e9b98720cc8" +checksum = "f7eda79bbd84e29c2b308d1dc099d7de8dcc7035e48f4bf5dc4a531a44ff5e2a" dependencies = [ - "async-channel 2.2.0", - "async-io 2.3.2", - "async-lock 3.3.0", + "async-channel 2.3.1", + "async-io 2.3.3", + "async-lock 3.4.0", "async-signal", + "async-task", "blocking", "cfg-if", - "event-listener 5.2.0", + "event-listener 5.3.1", "futures-lite 2.3.0", - "rustix 0.38.32", + "rustix 0.38.34", + "tracing", "windows-sys 0.52.0", ] [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" dependencies = [ - "async-io 2.3.2", - "async-lock 2.8.0", + "async-io 2.3.3", + "async-lock 3.4.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.32", + "rustix 0.38.34", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "async-task" -version = "4.7.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -799,22 +800,22 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ - "addr2line 0.21.0", + "addr2line 0.22.0", "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.32.2", + "object 0.36.1", "rustc-demangle", ] @@ -848,6 +849,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -894,13 +901,13 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "prettyplease 0.2.17", + "prettyplease 0.2.20", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -930,9 +937,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -1002,9 +1009,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec 0.7.4", @@ -1033,18 +1040,15 @@ dependencies = [ [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel 2.2.0", - "async-lock 3.3.0", + "async-channel 2.3.1", "async-task", - "fastrand 2.0.2", "futures-io", "futures-lite 2.3.0", "piper", - "tracing", ] [[package]] @@ -1152,9 +1156,9 @@ dependencies = [ [[package]] name = "bp-header-chain" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96157f586811969b3911d26cc79e02b28cfbecf859d96d7c12b6af10b9ea9350" +checksum = "1c4d2c457d5e18a5dbfe47a2ecd01f95036930a4a7ac0f3e47c2843bb067331b" dependencies = [ "bp-runtime", "finality-grandpa", @@ -1364,9 +1368,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-slice-cast" @@ -1382,9 +1386,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "byteorder" @@ -1394,9 +1398,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "bzip2-sys" @@ -1421,9 +1425,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] @@ -1445,7 +1449,7 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", - "semver 1.0.22", + "semver 1.0.23", "serde", "serde_json", "thiserror", @@ -1453,9 +1457,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.90" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" dependencies = [ "jobserver", "libc", @@ -1472,9 +1476,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" dependencies = [ "smallvec", ] @@ -1527,16 +1531,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -1583,9 +1587,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -1594,9 +1598,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", "clap_derive", @@ -1604,9 +1608,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstream", "anstyle", @@ -1617,21 +1621,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "coarsetime" @@ -1656,39 +1660,39 @@ dependencies = [ [[package]] name = "color-print" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a858372ff14bab9b1b30ea504f2a4bc534582aee3e42ba2d41d2a7baba63d5d" +checksum = "1ee543c60ff3888934877a5671f45494dd27ed4ba25c6670b9a7576b7ed7a8c0" dependencies = [ "color-print-proc-macro", ] [[package]] name = "color-print-proc-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e37866456a721d0a404439a1adae37a31be4e0055590d053dfe6981e05003f" +checksum = "77ff1a80c5f3cb1ca7c06ffdd71b6a6dd6d8f896c42141fbd43f50ed28dcdb93" dependencies = [ "nom", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.71", ] [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "comfy-table" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" +checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" dependencies = [ - "strum 0.25.0", - "strum_macros 0.25.3", + "strum 0.26.3", + "strum_macros 0.26.4", "unicode-width", ] @@ -1700,9 +1704,9 @@ checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -1741,7 +1745,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "once_cell", "tiny-keccak", ] @@ -1923,9 +1927,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -1960,9 +1964,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1978,7 +1982,7 @@ checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -2010,7 +2014,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ "generic-array 0.14.7", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -2020,7 +2024,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" dependencies = [ "generic-array 0.14.7", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -2061,7 +2065,7 @@ dependencies = [ "cumulus-primitives-core", "futures", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-overseer", @@ -2174,7 +2178,7 @@ dependencies = [ "futures", "futures-timer", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-primitives", "polkadot-parachain-primitives", "polkadot-primitives", @@ -2338,7 +2342,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -2530,13 +2534,13 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7718fe298d567adc44fae3dd7024418d6eff08264041e4b0544d1892861cd6" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-trait", "cumulus-primitives-core", "cumulus-relay-chain-interface", "cumulus-relay-chain-rpc-interface", "futures", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-availability-recovery", "polkadot-collator-protocol", "polkadot-core-primitives", @@ -2630,24 +2634,23 @@ dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -2659,7 +2662,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -2677,9 +2680,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dc7287237dd438b926a81a1a5605dad33d286870e5eee2db17bf2bcd9e92a" +checksum = "273dcfd3acd4e1e276af13ed2a43eea7001318823e7a726a6b3ed39b4acc0b82" dependencies = [ "cc", "cxxbridge-flags", @@ -2689,9 +2692,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47c6c8ad7c1a10d3ef0fe3ff6733f4db0d78f08ef0b13121543163ef327058b" +checksum = "d8b2766fbd92be34e9ed143898fce6c572dc009de39506ed6903e5a05b68914e" dependencies = [ "cc", "codespan-reporting", @@ -2699,24 +2702,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "cxxbridge-flags" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "701a1ac7a697e249cdd8dc026d7a7dafbfd0dbcd8bd24ec55889f2bc13dd6287" +checksum = "839fcd5e43464614ffaa989eaf1c139ef1f0c51672a1ed08023307fa1b909ccd" [[package]] name = "cxxbridge-macro" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b404f596046b0bb2d903a9c786b875a126261b52b7c3a64bbb66382c41c771df" +checksum = "4b2c1c1776b986979be68bb2285da855f8d8a35851a769fca8740df7c3d07877" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -2731,12 +2734,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.8", - "darling_macro 0.20.8", + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -2755,16 +2758,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.58", + "strsim 0.11.1", + "syn 2.0.71", ] [[package]] @@ -2780,26 +2783,26 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.8", + "darling_core 0.20.10", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "data-encoding-macro" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" +checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -2807,9 +2810,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" +checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f" dependencies = [ "data-encoding", "syn 1.0.109", @@ -2878,20 +2881,20 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.71", ] [[package]] @@ -2927,7 +2930,7 @@ dependencies = [ "block-buffer 0.10.4", "const-oid", "crypto-common", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -2974,13 +2977,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -3004,9 +3007,9 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.58", + "syn 2.0.71", "termcolor", - "toml 0.8.12", + "toml 0.8.14", "walkdir", ] @@ -3018,9 +3021,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "downcast-rs" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dtoa" @@ -3085,12 +3088,12 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", "rand_core 0.6.4", "serde", "sha2 0.10.8", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -3114,9 +3117,9 @@ version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "rand_core 0.6.4", "sha2 0.10.8", @@ -3125,9 +3128,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -3144,7 +3147,7 @@ dependencies = [ "pkcs8", "rand_core 0.6.4", "sec1", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -3201,22 +3204,22 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" dependencies = [ "enumflags2_derive", ] [[package]] name = "enumflags2_derive" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -3227,7 +3230,7 @@ checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -3280,9 +3283,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3353,15 +3356,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ "concurrent-queue", - "parking", "pin-project-lite 0.2.14", ] [[package]] name = "event-listener" -version = "5.2.0" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -3370,21 +3372,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -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 0.2.14", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 5.2.0", + "event-listener 5.3.1", "pin-project-lite 0.2.14", ] @@ -3411,16 +3403,17 @@ dependencies = [ [[package]] name = "expander" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e83c02035136f1592a47964ea60c05a50e4ed8b5892cfac197063850898d4d" +checksum = "e2c470c71d91ecbd179935b24170459e926382eaaa86b590b78814e180d8a8e2" dependencies = [ "blake2 0.10.6", + "file-guard", "fs-err", - "prettier-please", + "prettyplease 0.2.20", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -3440,9 +3433,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fatality" @@ -3462,7 +3455,7 @@ checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", "indexmap 1.9.3", - "proc-macro-crate 1.3.1", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 1.0.109", @@ -3486,14 +3479,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] name = "fiat-crypto" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" +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" @@ -3529,7 +3532,7 @@ dependencies = [ "log", "num-traits", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "scale-info", ] @@ -3553,9 +3556,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "libz-sys", @@ -3634,7 +3637,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efe02c96362e3c7308cdea7545859f767194a1f3f00928f0e1357f4b8a0b3b2c" dependencies = [ "Inflector", - "array-bytes 6.2.2", + "array-bytes 6.2.3", "chrono", "clap", "comfy-table", @@ -3685,7 +3688,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -3754,7 +3757,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bb1eec9eb46d3e016c95b2fa875118c04609f2150013c56a894cae00581e265" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "docify", "frame-support", "frame-system", @@ -3794,7 +3797,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e52c84b611d2049d9253f83a62ab0f093e4be5c42a7ef42ea5bb16d6611e32" dependencies = [ "aquamarine", - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bitflags 1.3.2", "docify", "environmental", @@ -3838,7 +3841,7 @@ dependencies = [ "Inflector", "cfg-expr", "derive-syn-parse 0.1.5", - "expander 2.1.0", + "expander 2.2.1", "frame-support-procedural-tools", "itertools 0.10.5", "macro_magic", @@ -3846,7 +3849,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -3859,7 +3862,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -3870,7 +3873,7 @@ checksum = "68672b9ec6fe72d259d3879dc212c5e42e977588cdac830c76f54d9f492aeb58" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -3958,7 +3961,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f9df8a11882c4e3335eb2d18a0137c505d9ca927470b0cac9c6f0ae07d28f7" dependencies = [ - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.48.0", ] @@ -4048,7 +4051,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-core", "futures-io", "parking", @@ -4063,7 +4066,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -4165,9 +4168,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -4207,9 +4210,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "glob" @@ -4225,7 +4228,7 @@ checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -4296,9 +4299,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", "allocator-api2", @@ -4311,7 +4314,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -4332,6 +4335,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -4443,9 +4452,9 @@ checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -4461,9 +4470,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -4476,7 +4485,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite 0.2.14", - "socket2 0.5.6", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -4493,7 +4502,7 @@ dependencies = [ "http", "hyper", "log", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", @@ -4565,7 +4574,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" dependencies = [ - "async-io 2.3.2", + "async-io 2.3.3", "core-foundation", "fnv", "futures", @@ -4629,18 +4638,18 @@ dependencies = [ [[package]] name = "include_dir" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" dependencies = [ "include_dir_macros", ] [[package]] name = "include_dir_macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" dependencies = [ "proc-macro2", "quote", @@ -4664,7 +4673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -4697,9 +4706,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -4756,7 +4765,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -4773,7 +4782,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.6", + "socket2 0.5.7", "widestring", "windows-sys 0.48.0", "winreg", @@ -4791,7 +4800,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "windows-sys 0.52.0", ] @@ -4805,6 +4814,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.10.5" @@ -4840,9 +4855,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -4914,7 +4929,7 @@ dependencies = [ "http", "jsonrpsee-core 0.21.0", "pin-project", - "rustls-native-certs 0.7.0", + "rustls-native-certs 0.7.1", "rustls-pki-types", "soketto", "thiserror", @@ -4939,7 +4954,7 @@ dependencies = [ "futures-util", "hyper", "jsonrpsee-types 0.20.3", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "rustc-hash", "serde", @@ -4957,7 +4972,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "776d009e2f591b78c038e0d053a796f94575d66ca4e77dd84bfc5e81419e436c" dependencies = [ "anyhow", - "async-lock 3.3.0", + "async-lock 3.4.0", "async-trait", "beef", "futures-timer", @@ -5021,7 +5036,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29110019693a4fa2dbda04876499d098fa16d70eba06b1e6e2b3f1b251419515" dependencies = [ "heck 0.4.1", - "proc-macro-crate 1.3.1", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 1.0.109", @@ -5134,7 +5149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7a85fe66f9ff9cd74e169fdd2c94c6e1e74c412c99a73b4df3200b5d3760b2" dependencies = [ "kvdb", - "parking_lot 0.12.1", + "parking_lot 0.12.3", ] [[package]] @@ -5145,7 +5160,7 @@ checksum = "b644c70b92285f66bfc2032922a79000ea30af7bc2ab31902992a5dcb9b434f6" dependencies = [ "kvdb", "num_cpus", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "regex", "rocksdb", "smallvec", @@ -5164,9 +5179,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -5176,18 +5191,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -5205,7 +5220,7 @@ dependencies = [ "bytes", "futures", "futures-timer", - "getrandom 0.2.12", + "getrandom 0.2.15", "instant", "libp2p-allow-block-list", "libp2p-connection-limits", @@ -5270,7 +5285,7 @@ dependencies = [ "multihash 0.17.0", "multistream-select", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "quick-protobuf", "rand", @@ -5290,7 +5305,7 @@ dependencies = [ "futures", "libp2p-core", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "smallvec", "trust-dns-resolver", ] @@ -5452,7 +5467,7 @@ dependencies = [ "libp2p-identity", "libp2p-tls", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "quinn-proto", "rand", "rustls 0.20.9", @@ -5568,7 +5583,7 @@ dependencies = [ "futures-rustls", "libp2p-core", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "quicksink", "rw-stream-sink", "soketto", @@ -5595,7 +5610,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -5641,7 +5656,7 @@ checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" dependencies = [ "crunchy", "digest 0.9.0", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -5664,9 +5679,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.16" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" +checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" dependencies = [ "cc", "pkg-config", @@ -5720,9 +5735,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lioness" @@ -5738,9 +5753,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -5748,9 +5763,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" @@ -5782,7 +5797,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -5796,9 +5811,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +checksum = "d6eab492fe7f8651add23237ea56dbf11b3c4ff762ab83d40a47f11433421f91" dependencies = [ "libc", "lz4-sys", @@ -5806,9 +5821,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "e9764018d143cc854c9f17f0b907de70f14393b1f502da6375dce70f00514eb3" dependencies = [ "cc", "libc", @@ -5825,50 +5840,50 @@ dependencies = [ [[package]] name = "macro_magic" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e03844fc635e92f3a0067e25fa4bf3e3dbf3f2927bf3aa01bb7bc8f1c428949d" +checksum = "cc33f9f0351468d26fbc53d9ce00a096c8522ecb42f19b50f34f2c422f76d21d" dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "macro_magic_core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "468155613a44cfd825f1fb0ffa532b018253920d404e6fca1e8d43155198a46d" +checksum = "1687dc887e42f352865a393acae7cf79d98fab6351cde1f58e9e057da89bf150" dependencies = [ "const-random", - "derive-syn-parse 0.1.5", + "derive-syn-parse 0.2.0", "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "macro_magic_core_macros" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" +checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "macro_magic_macros" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" +checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -5919,9 +5934,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memfd" @@ -5929,7 +5944,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.32", + "rustix 0.38.34", ] [[package]] @@ -5999,9 +6014,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -6028,16 +6043,16 @@ dependencies = [ "bitflags 1.3.2", "blake2 0.10.6", "c2-chacha", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "either", "hashlink", "lioness", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "rand_chacha 0.3.1", "rand_distr", - "subtle 2.5.0", + "subtle 2.6.1", "thiserror", "zeroize", ] @@ -6146,7 +6161,7 @@ dependencies = [ "blake3", "core2", "digest 0.10.7", - "multihash-derive 0.8.0", + "multihash-derive 0.8.1", "sha2 0.10.8", "sha3", "unsigned-varint", @@ -6160,7 +6175,7 @@ checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" dependencies = [ "core2", "digest 0.10.7", - "multihash-derive 0.8.0", + "multihash-derive 0.8.1", "sha2 0.10.8", "unsigned-varint", ] @@ -6197,16 +6212,16 @@ dependencies = [ [[package]] name = "multihash-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" +checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 1.1.3", "proc-macro-error", "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -6222,16 +6237,16 @@ dependencies = [ [[package]] name = "multihash-derive-impl" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38685e08adb338659871ecfc6ee47ba9b22dcc8abcf6975d379cc49145c3040" +checksum = "3958713ce794e12f7c6326fac9aa274c68d74c4881dd37b3e2662b8a2046bb19" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 2.0.0", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", - "synstructure", + "syn 2.0.71", + "synstructure 0.13.1", ] [[package]] @@ -6256,9 +6271,9 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.5" +version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea4908d4f23254adda3daa60ffef0f1ac7b8c3e9a864cf3cc154b251908a2ef" +checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" dependencies = [ "approx", "matrixmultiply", @@ -6272,13 +6287,13 @@ dependencies = [ [[package]] name = "nalgebra-macros" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.71", ] [[package]] @@ -6379,7 +6394,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "libc", ] @@ -6420,20 +6435,19 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -6465,11 +6479,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -6477,9 +6490,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -6491,7 +6504,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -6515,9 +6528,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "memchr", ] @@ -6563,9 +6576,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchestra" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2356622ffdfe72362a45a1e5e87bb113b8327e596e39b91f11f0ef4395c8da79" +checksum = "92829eef0328a3d1cd22a02c0e51deb92a5362df3e7d21a4e9bdc38934694e66" dependencies = [ "async-trait", "dyn-clonable", @@ -6580,15 +6593,15 @@ dependencies = [ [[package]] name = "orchestra-proc-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eedb646674596266dc9bb2b5c7eea7c36b32ecc7777eba0d510196972d72c4fd" +checksum = "1344346d5af32c95bbddea91b18a88cc83eac394192d20ef2fc4c40a74332355" dependencies = [ - "expander 2.1.0", + "expander 2.2.1", "indexmap 2.2.6", "itertools 0.11.0", "petgraph", - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -6832,7 +6845,7 @@ version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d334f24d3c0c016d16aa87d069485847d622e8ebebace18ec5cf56609ca3a67" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "binary-merkle-tree", "frame-support", "frame-system", @@ -7074,7 +7087,7 @@ checksum = "3163c6bc21b55a0ccb74c546ba784d9c9e69beb9240c059d28a3052f4cbce509" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -7430,9 +7443,9 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" -version = "26.0.0" +version = "26.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f14519c1c613d2f8c95c27015864c11a37969a23deeba9f6dbaff4276e1b81c" +checksum = "b62091305ec7426e71c3da2b0944c2df5a804109ee4d2e8f4fe34865e049f8ac" dependencies = [ "frame-support", "frame-system", @@ -7742,7 +7755,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -7757,9 +7770,9 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" -version = "15.0.0" +version = "15.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237d7b5a10cb6cba727c3e957fb241776302aa3cce589e6759ba53f50129c1a5" +checksum = "e47c73850103db30b61ef170107afe1ef0dab6905c495bd6dfb57b3c1dd81bc7" dependencies = [ "parity-scale-codec", "sp-api", @@ -8121,7 +8134,7 @@ dependencies = [ "log", "lz4", "memmap2 0.5.10", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "siphasher 0.3.11", "snap", @@ -8130,9 +8143,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec 0.7.4", "bitvec", @@ -8145,11 +8158,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -8173,7 +8186,7 @@ dependencies = [ "impl-trait-for-tuples", "lru 0.8.1", "parity-util-mem-derive", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "primitive-types", "smallvec", "winapi", @@ -8187,7 +8200,7 @@ checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -8215,12 +8228,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", + "parking_lot_core 0.9.10", ] [[package]] @@ -8239,15 +8252,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -8258,9 +8271,9 @@ checksum = "7924d1d0ad836f665c9065e26d016c673ece3993f30d340068b16f282afc1156" [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbkdf2" @@ -8303,9 +8316,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.9" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -8314,9 +8327,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.9" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -8324,22 +8337,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.9" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "pest_meta" -version = "2.7.9" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -8348,9 +8361,9 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", "indexmap 2.2.6", @@ -8373,7 +8386,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -8396,12 +8409,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" dependencies = [ "atomic-waker", - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-io", ] @@ -8421,12 +8434,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "polkadot-approval-distribution" version = "8.0.0" @@ -8654,7 +8661,7 @@ dependencies = [ "fatality", "futures", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-subsystem", @@ -8915,7 +8922,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3bbb1b5f4b966f21a0336e94c0a0222958d2f3cba451da1157af271d07f9748" dependencies = [ "always-assert", - "array-bytes 6.2.2", + "array-bytes 6.2.3", "blake3", "cfg-if", "futures", @@ -9013,7 +9020,7 @@ dependencies = [ "log", "mick-jaeger", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-primitives", "polkadot-primitives", "sc-network", @@ -9146,7 +9153,7 @@ dependencies = [ "kvdb", "parity-db", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "polkadot-node-jaeger", "polkadot-node-metrics", @@ -9177,7 +9184,7 @@ dependencies = [ "futures", "futures-timer", "orchestra", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -9412,7 +9419,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "parity-db", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-approval-distribution", "polkadot-availability-bitfield-distribution", "polkadot-availability-distribution", @@ -9553,7 +9560,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6380dbe1fb03ecc74ad55d841cfc75480222d153ba69ddcb00977866cbdabdb8" dependencies = [ "polkavm-derive-impl", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -9565,7 +9572,7 @@ dependencies = [ "polkavm-common", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -9586,15 +9593,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.6.0" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" +checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.4.0", "pin-project-lite 0.2.14", - "rustix 0.38.32", + "rustix 0.38.34", "tracing", "windows-sys 0.52.0", ] @@ -9903,21 +9910,11 @@ dependencies = [ "termtree", ] -[[package]] -name = "prettier-please" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3" -dependencies = [ - "proc-macro2", - "syn 2.0.58", -] - [[package]] name = "prettyplease" -version = "0.1.11" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28f53e8b192565862cf99343194579a022eb9c7dd3a8d03134734803c7b3125" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" dependencies = [ "proc-macro2", "syn 1.0.109", @@ -9925,12 +9922,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -9966,12 +9963,12 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "thiserror", + "toml 0.5.11", ] [[package]] @@ -10024,29 +10021,29 @@ checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if", "fnv", "lazy_static", "memchr", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "thiserror", ] @@ -10058,7 +10055,7 @@ checksum = "5d6fa99d535dd930d1249e6c79cb3c2915f9172a540fe2b02a4c8f9ca954721e" dependencies = [ "dtoa", "itoa", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "prometheus-client-derive-encode", ] @@ -10070,7 +10067,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -10085,12 +10082,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.12.3", + "prost-derive 0.12.6", ] [[package]] @@ -10106,7 +10103,7 @@ dependencies = [ "log", "multimap", "petgraph", - "prettyplease 0.1.11", + "prettyplease 0.1.25", "prost 0.11.9", "prost-types", "regex", @@ -10130,15 +10127,15 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -10218,9 +10215,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -10277,7 +10274,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", ] [[package]] @@ -10355,13 +10352,22 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "redox_users" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "libredox", "thiserror", ] @@ -10380,22 +10386,22 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -10412,14 +10418,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -10433,13 +10439,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] @@ -10450,9 +10456,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "resolv-conf" @@ -10471,7 +10477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac 0.12.1", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -10497,7 +10503,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.12", + "getrandom 0.2.15", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -10692,9 +10698,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -10714,7 +10720,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.22", + "semver 1.0.23", ] [[package]] @@ -10756,14 +10762,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] @@ -10781,9 +10787,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring 0.17.8", @@ -10793,15 +10799,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.3" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.2", - "subtle 2.5.0", + "rustls-webpki 0.102.5", + "subtle 2.6.1", "zeroize", ] @@ -10819,12 +10825,12 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.1", + "rustls-pemfile 2.1.2", "rustls-pki-types", "schannel", "security-framework", @@ -10841,19 +10847,19 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.4.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" @@ -10867,9 +10873,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -10878,9 +10884,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ruzstd" @@ -10917,15 +10923,15 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safe_arch" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354" +checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" dependencies = [ "bytemuck", ] @@ -10966,7 +10972,7 @@ dependencies = [ "multihash 0.18.1", "multihash-codetable", "parity-scale-codec", - "prost 0.12.3", + "prost 0.12.6", "prost-build", "rand", "sc-client-api", @@ -11026,7 +11032,7 @@ version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f73880050f8b04fed7f6301279ef3899df13a3891bd06156d56f9a1c50fefba" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "docify", "log", "memmap2 0.9.4", @@ -11056,7 +11062,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -11065,7 +11071,7 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a284c10ea92b1fe789b9f0e5815d393f3a1e3bf6a4adaa884f24e36143b83b" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bip39", "chrono", "clap", @@ -11111,7 +11117,7 @@ dependencies = [ "futures", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-executor", "sc-transaction-pool-api", "sc-utils", @@ -11143,7 +11149,7 @@ dependencies = [ "log", "parity-db", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-state-db", "schnellru", @@ -11168,7 +11174,7 @@ dependencies = [ "libp2p-identity", "log", "mockall", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-utils", "serde", @@ -11226,7 +11232,7 @@ dependencies = [ "num-rational", "num-traits", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-consensus", "sc-consensus-epochs", @@ -11278,14 +11284,14 @@ version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9ce3ee15eff7fa642791966d427f185184df3c7f4e58893705f3e7781da8ef5" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-channel 1.9.0", "async-trait", "fnv", "futures", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-consensus", "sc-network", @@ -11319,7 +11325,7 @@ dependencies = [ "jsonrpsee 0.20.3", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-consensus-beefy", "sc-rpc", "serde", @@ -11350,7 +11356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ae91e5b5a120be4d13a59eaf94fd85d7c7af528482b8e21d861fa1167df3083" dependencies = [ "ahash 0.8.11", - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-trait", "dyn-clone", "finality-grandpa", @@ -11359,7 +11365,7 @@ dependencies = [ "futures-timer", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "sc-block-builder", "sc-chain-spec", @@ -11439,7 +11445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa2ac6c356538d67987bbb867e11a12a84ba87250c70fd50005b6d74f570a4f7" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-executor-common", "sc-executor-wasmtime", "schnellru", @@ -11478,7 +11484,7 @@ dependencies = [ "cfg-if", "libc", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rustix 0.36.17", "sc-allocator", "sc-executor-common", @@ -11511,8 +11517,8 @@ version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cc4f6a558dd23e3bae2e9f195da822465258b9aaf211c34360d7f6efb944e54" dependencies = [ - "array-bytes 6.2.2", - "parking_lot 0.12.1", + "array-bytes 6.2.3", + "parking_lot 0.12.3", "serde_json", "sp-application-crypto", "sp-core", @@ -11537,7 +11543,7 @@ dependencies = [ "mixnet", "multiaddr", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-network", "sc-transaction-pool-api", @@ -11556,7 +11562,7 @@ version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f231c7d5e749ec428b4cfa669d759ae76cd3da4f50d7352a2d711acdc7532891" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-channel 1.9.0", "async-trait", "asynchronous-codec", @@ -11571,7 +11577,7 @@ dependencies = [ "log", "mockall", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "partial_sort", "pin-project", "rand", @@ -11605,7 +11611,7 @@ dependencies = [ "futures", "libp2p-identity", "log", - "prost 0.12.3", + "prost 0.12.6", "prost-build", "sc-client-api", "sc-network", @@ -11659,13 +11665,13 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84ef0b212c775f58e0304ec09166089f6b09afddf559b7c2b5702933b3be4" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-channel 1.9.0", "futures", "libp2p-identity", "log", "parity-scale-codec", - "prost 0.12.3", + "prost 0.12.6", "prost-build", "sc-client-api", "sc-network", @@ -11681,7 +11687,7 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aa9377059deece4e7d419d9ec456f657268c0c603e1cf98df4a920f6da83461" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-channel 1.9.0", "async-trait", "fork-tree", @@ -11691,7 +11697,7 @@ dependencies = [ "log", "mockall", "parity-scale-codec", - "prost 0.12.3", + "prost 0.12.6", "prost-build", "sc-client-api", "sc-consensus", @@ -11718,7 +11724,7 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16c9cad4baf348725bd82eadcd1747fc112ec49c76b863755ce79c588fa73fe4" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "futures", "libp2p", "log", @@ -11738,7 +11744,7 @@ version = "30.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aee89f2abd406356bfd688bd7a51155dc963259e4b752bb85d1f8a061a194fd" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bytes", "fnv", "futures", @@ -11750,7 +11756,7 @@ dependencies = [ "num_cpus", "once_cell", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "sc-client-api", "sc-network", @@ -11787,7 +11793,7 @@ dependencies = [ "jsonrpsee 0.20.3", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -11853,14 +11859,14 @@ version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7f10275c62296a785f6e2ac716521e3b6e0fae470416fdf86491cbbfcc2e23d" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "futures", "futures-util", "hex", "jsonrpsee 0.20.3", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-chain-spec", "sc-client-api", "sc-rpc", @@ -11892,7 +11898,7 @@ dependencies = [ "jsonrpsee 0.20.3", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "sc-chain-spec", @@ -11950,7 +11956,7 @@ checksum = "aa842052c41ad379eaecdfddc0d5c953d57e311ae688233f68f461b91d38da0a" dependencies = [ "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sp-core", ] @@ -12020,7 +12026,7 @@ dependencies = [ "futures", "libp2p", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "sc-utils", @@ -12043,7 +12049,7 @@ dependencies = [ "libc", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "regex", "rustc-hash", "sc-client-api", @@ -12070,7 +12076,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -12085,7 +12091,7 @@ dependencies = [ "linked-hash-map", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-transaction-pool-api", "sc-utils", @@ -12129,7 +12135,7 @@ dependencies = [ "futures-timer", "lazy_static", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "prometheus", "sp-arithmetic", ] @@ -12167,7 +12173,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3475108a1b62c7efd1b5c65974f30109a598b2f45f23c9ae030acb9686966db" dependencies = [ "darling 0.14.4", - "proc-macro-crate 1.3.1", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 1.0.109", @@ -12195,7 +12201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "995491f110efdc6bea96d6a746140e32bfceb4ea47510750a5467295a4707a25" dependencies = [ "darling 0.14.4", - "proc-macro-crate 1.3.1", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 1.0.109", @@ -12203,9 +12209,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "788745a868b0e751750388f4e6546eb921ef714a4317fa6954f7cde114eb2eb7" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "bitvec", "cfg-if", @@ -12217,11 +12223,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc2f4e8bc344b9fc3d5f74f72c2e55bfc38d28dc2ebc69c194a3df424e4d9ac" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -12236,7 +12242,7 @@ dependencies = [ "proc-macro2", "quote", "scale-info", - "syn 2.0.58", + "syn 2.0.71", "thiserror", ] @@ -12271,9 +12277,9 @@ dependencies = [ [[package]] name = "schnellru" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" dependencies = [ "ahash 0.8.11", "cfg-if", @@ -12305,13 +12311,13 @@ dependencies = [ "aead", "arrayref", "arrayvec 0.7.4", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "getrandom_or_panic", "merlin", "rand_core 0.6.4", "serde_bytes", "sha2 0.10.8", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -12347,7 +12353,7 @@ dependencies = [ "der", "generic-array 0.14.7", "pkcs8", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -12389,11 +12395,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -12402,9 +12408,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -12421,9 +12427,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -12436,9 +12442,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -12454,29 +12460,29 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", @@ -12485,9 +12491,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -12567,9 +12573,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -12681,13 +12687,13 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e635339259e51ef85ac7aa29a1cd991b957047507288697a690e80ab97d07cad" dependencies = [ - "async-channel 2.2.0", + "async-channel 2.3.1", "async-executor", - "async-fs 2.1.1", - "async-io 2.3.2", - "async-lock 3.3.0", + "async-fs 2.1.2", + "async-io 2.3.3", + "async-lock 3.4.0", "async-net 2.0.0", - "async-process 2.1.0", + "async-process 2.2.3", "blocking", "futures-lite 2.3.0", ] @@ -12714,7 +12720,7 @@ dependencies = [ "fnv", "futures-lite 1.13.0", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "hmac 0.12.1", "itertools 0.11.0", @@ -12753,7 +12759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d1eaa97d77be4d026a1e7ffad1bb3b78448763b357ea6f8188d3e6f736a9b9" dependencies = [ "arrayvec 0.7.4", - "async-lock 3.3.0", + "async-lock 3.4.0", "atomic-take", "base64 0.21.7", "bip39", @@ -12768,7 +12774,7 @@ dependencies = [ "fnv", "futures-lite 2.3.0", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "hmac 0.12.1", "itertools 0.12.1", @@ -12818,13 +12824,13 @@ dependencies = [ "futures-channel", "futures-lite 1.13.0", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "itertools 0.11.0", "log", "lru 0.11.1", "no-std-net", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "rand_chacha 0.3.1", @@ -12843,8 +12849,8 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5496f2d116b7019a526b1039ec2247dd172b8670633b1a64a614c9ea12c9d8c7" dependencies = [ - "async-channel 2.2.0", - "async-lock 3.3.0", + "async-channel 2.3.1", + "async-lock 3.4.0", "base64 0.21.7", "blake2-rfc", "derive_more", @@ -12854,13 +12860,13 @@ dependencies = [ "futures-channel", "futures-lite 2.3.0", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "itertools 0.12.1", "log", "lru 0.12.3", "no-std-net", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "rand_chacha 0.3.1", @@ -12888,12 +12894,12 @@ dependencies = [ "aes-gcm", "blake2 0.10.6", "chacha20poly1305", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "ring 0.17.8", "rustc_version", "sha2 0.10.8", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -12908,9 +12914,9 @@ dependencies = [ [[package]] name = "snowbridge-beacon-primitives" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a73ef707257064bc4ecce8323cdb7c30e8ecd1ce74aa89a6e82e81fa8b9970" +checksum = "5404af73550b39022e08e5500b30fba627e109a56407b7e80b08da2305b11bfe" dependencies = [ "byte-slice-cast", "frame-support", @@ -12933,9 +12939,9 @@ dependencies = [ [[package]] name = "snowbridge-core" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3e2e3b94bfcfc8f363e21a6c5a1d3c67eb4592ada672c868a3236ad1dd563b" +checksum = "aed4ebefed4c40b9c00e9adf5f02ab2760a7a2dad8bf05110c0013a7a59f4097" dependencies = [ "ethabi-decode", "frame-support", @@ -13029,9 +13035,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -13084,11 +13090,11 @@ checksum = "0301e2f77afb450fbf2b093f8b324c7ad88cc82e5e69bd5dc8658a1f068b2a96" dependencies = [ "Inflector", "blake2 0.10.6", - "expander 2.1.0", + "expander 2.2.1", "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -13155,7 +13161,7 @@ dependencies = [ "futures", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "schnellru", "sp-api", "sp-consensus", @@ -13278,7 +13284,7 @@ version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c33c7a1568175250628567d50c4e1c54a6ac5bc1190413b9be29a9e810cbe73" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bip39", "bitflags 1.3.2", "blake2 0.10.6", @@ -13295,7 +13301,7 @@ dependencies = [ "log", "merlin", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "paste", "primitive-types", "rand", @@ -13354,7 +13360,7 @@ checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -13364,7 +13370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "722cbecdbf5b94578137dbd07feb51e95f7de221be0c1ff4dcfe0bb4cd986929" dependencies = [ "kvdb", - "parking_lot 0.12.1", + "parking_lot 0.12.3", ] [[package]] @@ -13375,7 +13381,7 @@ checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -13461,7 +13467,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444f2d53968b1ce5e908882710ff1f3873fcf3e95f59d57432daf685bbacb959" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sp-core", "sp-externalities", "thiserror", @@ -13620,11 +13626,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfaf6e85b2ec12a4b99cd6d8d57d083e30c94b7f1b0d8f93547121495aae6f0c" dependencies = [ "Inflector", - "expander 2.1.0", + "expander 2.2.1", "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -13667,7 +13673,7 @@ dependencies = [ "hash-db", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "smallvec", "sp-core", @@ -13687,7 +13693,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "309a9ae4e8134bbed8ffc510cf4d461a4a651f9250b556de782cedd876abe1ff" dependencies = [ "aes-gcm", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519-dalek", "hkdf", "parity-scale-codec", @@ -13791,7 +13797,7 @@ dependencies = [ "memory-db", "nohash-hasher", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "scale-info", "schnellru", @@ -13831,7 +13837,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -13962,7 +13968,7 @@ version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48fa328b87de3466bc38cc9a07244c42c647b7755b81115e1dfeb47cc13fc6e6" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bounded-collections 0.2.0", "derivative", "environmental", @@ -14063,7 +14069,7 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "keccak", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -14090,9 +14096,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.25.0" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" [[package]] name = "strum_macros" @@ -14109,15 +14115,15 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -14218,7 +14224,7 @@ dependencies = [ "sp-maybe-compressed-blob", "strum 0.24.1", "tempfile", - "toml 0.8.12", + "toml 0.8.14", "walkdir", "wasm-opt", ] @@ -14231,9 +14237,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "subtle-ng" @@ -14293,7 +14299,7 @@ dependencies = [ "scale-info", "scale-typegen", "subxt-metadata", - "syn 2.0.58", + "syn 2.0.71", "thiserror", "tokio", ] @@ -14321,13 +14327,13 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "365251668613323064803427af8c7c7bc366cd8b28e33639640757669dafebd5" dependencies = [ - "darling 0.20.8", + "darling 0.20.10", "parity-scale-codec", "proc-macro-error", "quote", "scale-typegen", "subxt-codegen", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -14378,9 +14384,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" dependencies = [ "proc-macro2", "quote", @@ -14399,6 +14405,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.71", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -14428,9 +14445,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" [[package]] name = "tempfile" @@ -14439,8 +14456,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.0.2", - "rustix 0.38.32", + "fastrand 2.1.0", + "rustix 0.38.34", "windows-sys 0.52.0", ] @@ -14459,7 +14476,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.48.0", ] @@ -14486,9 +14503,9 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" dependencies = [ "thiserror-impl", ] @@ -14510,18 +14527,18 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -14585,9 +14602,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -14606,9 +14623,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -14625,9 +14642,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -14640,32 +14657,32 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project-lite 0.2.14", "signal-hook-registry", - "socket2 0.5.6", + "socket2 0.5.7", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -14685,7 +14702,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", + "rustls 0.21.12", "tokio", ] @@ -14695,7 +14712,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.22.3", + "rustls 0.22.4", "rustls-pki-types", "tokio", ] @@ -14714,9 +14731,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -14724,7 +14741,6 @@ dependencies = [ "futures-sink", "pin-project-lite 0.2.14", "tokio", - "tracing", ] [[package]] @@ -14738,36 +14754,25 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.9", + "toml_edit 0.22.15", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.20.7" @@ -14792,15 +14797,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" dependencies = [ "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.13", ] [[package]] @@ -14824,7 +14829,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "futures-core", "futures-util", @@ -14868,7 +14873,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -14909,11 +14914,11 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f074568687ffdfd0adb6005aa8d1d96840197f2c159f80471285f08694cf0ce" dependencies = [ - "expander 2.1.0", + "expander 2.2.1", "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -15046,7 +15051,7 @@ dependencies = [ "ipconfig", "lazy_static", "lru-cache", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "resolv-conf", "smallvec", "thiserror", @@ -15163,9 +15168,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -15180,7 +15185,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -15209,9 +15214,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna 0.5.0", @@ -15220,9 +15225,9 @@ dependencies = [ [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" @@ -15250,9 +15255,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "w3f-bls" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7335e4c132c28cc43caef6adb339789e599e39adbe78da0c4d547fad48cbc331" +checksum = "9c5da5fa2c6afa2c9158eaa7cd9aee249765eb32b5fb0c63ad8b9e79336a47ec" dependencies = [ "ark-bls12-377", "ark-bls12-381", @@ -15274,9 +15279,9 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "walkdir" @@ -15339,7 +15344,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", "wasm-bindgen-shared", ] @@ -15373,7 +15378,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -15491,9 +15496,9 @@ dependencies = [ [[package]] name = "wasmparser-nostd" -version = "0.100.1" +version = "0.100.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" dependencies = [ "indexmap-nostd", ] @@ -15724,15 +15729,16 @@ dependencies = [ [[package]] name = "westend-runtime" -version = "8.0.0" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2a5cebb4c678a0d1291bb21f9d44ddebceae044b0fb5200fa3bed108a31595" +checksum = "b4aa5580861b05668a6af845aa271c4f699a2fc26646d524e5b0d9375fb0647e" dependencies = [ "binary-merkle-tree", "bitvec", "frame-benchmarking", "frame-election-provider-support", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -15855,14 +15861,14 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.32", + "rustix 0.38.34", ] [[package]] name = "wide" -version = "0.7.15" +version = "0.7.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89beec544f246e679fc25490e3f8e08003bc4bf612068f325120dad4cea02c1c" +checksum = "2caba658a80831539b30698ae9862a72db6697dfdd7151e46920f5f2755c3ce2" dependencies = [ "bytemuck", "safe_arch", @@ -15870,9 +15876,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" [[package]] name = "winapi" @@ -15892,11 +15898,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -15930,7 +15936,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -15957,7 +15963,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -15992,17 +15998,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "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", ] [[package]] @@ -16019,9 +16026,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -16037,9 +16044,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -16055,9 +16062,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -16073,9 +16086,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -16091,9 +16104,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -16109,9 +16122,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -16127,9 +16140,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -16142,9 +16155,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" dependencies = [ "memchr", ] @@ -16185,7 +16198,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "serde", "zeroize", @@ -16253,7 +16266,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -16265,7 +16278,7 @@ dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "static_assertions", ] @@ -16287,29 +16300,29 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -16322,7 +16335,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.71", ] [[package]] @@ -16365,9 +16378,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.12+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" dependencies = [ "cc", "pkg-config", diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index 7db68576..70e6e9c9 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -22,7 +22,7 @@ scale-info.workspace = true smallvec.workspace = true # Local -pop-primitives = { workspace = true, default-features = false, features = ["assets", "cross-chain", "nfts"] } +pop-primitives = { workspace = true, features = ["assets", "cross-chain", "nfts"] } pop-runtime-common = { workspace = true, default-features = false } # Substrate diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index 8f0a6eda..c6bab850 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -307,8 +307,8 @@ pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { // "UnknownFunctionId" and "DecodingFailed" are mapped to specific errors in the API and will // never change. let mut encoded_error = match error { - DispatchError::Other("UnknownFunctionId") => vec![254, 0, 0, 0], - DispatchError::Other("DecodingFailed") => vec![255, 0, 0, 0], + DispatchError::Other("UnknownFunctionId") => Vec::from([254u8, 0, 0, 0]), + DispatchError::Other("DecodingFailed") => Vec::from([255u8, 0, 0, 0]), _ => error.encode(), }; // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index 61d3cb43..866cb12c 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -206,7 +206,7 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, - _ => Ok(vec![0u8]), + _ => Ok(Vec::from([0u8])), }? .encode(); From 8730f90d07dbd1ce564a14a19bb1288a70ddaa4b Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Wed, 17 Jul 2024 17:47:38 +0200 Subject: [PATCH 021/161] refactor: decoding failed and commenting out unimplemented tests --- .../integration-tests/src/local_fungibles.rs | 448 +++++++++--------- pop-api/src/lib.rs | 4 +- pop-api/src/v0/assets/mod.rs | 14 +- primitives/src/lib.rs | 2 +- runtime/devnet/src/extensions/mod.rs | 2 +- 5 files changed, 236 insertions(+), 234 deletions(-) diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs index d0229c84..bef3aa6a 100644 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -67,37 +67,6 @@ fn token_decimals(addr: AccountId32, asset_id: AssetId) -> u8 { decoded::(result) } -fn asset_exists(addr: AccountId32, asset_id: AssetId) -> bool { - let function = function_selector("asset_exists"); - let params = [function, asset_id.encode()].concat(); - let result = do_bare_call(addr, params, 0).expect("should work"); - decoded::(result) -} - -fn create( - addr: AccountId32, - asset_id: AssetId, - admin: AccountId32, - min_balance: Balance, -) -> ExecReturnValue { - let function = function_selector("create"); - let params = [function, asset_id.encode(), admin.encode(), min_balance.encode()].concat(); - do_bare_call(addr, params, 0).expect("should work") -} - -fn set_metadata( - addr: AccountId32, - asset_id: AssetId, - name: Vec, - symbol: Vec, - decimals: u8, -) -> ExecReturnValue { - let function = function_selector("set_metadata"); - let params = - [function, asset_id.encode(), name.encode(), symbol.encode(), decimals.encode()].concat(); - do_bare_call(addr, params, 0).expect("should work") -} - fn transfer( addr: AccountId32, asset_id: AssetId, @@ -137,18 +106,49 @@ fn increase_allowance( result } -fn create_asset(owner: AccountId32, asset_id: AssetId, min_balance: Balance) -> AssetId { - assert_eq!( - Assets::create( - RuntimeOrigin::signed(owner.clone()), - asset_id.into(), - owner.into(), - min_balance - ), - Ok(()) - ); - asset_id -} +// fn asset_exists(addr: AccountId32, asset_id: AssetId) -> bool { +// let function = function_selector("asset_exists"); +// let params = [function, asset_id.encode()].concat(); +// let result = do_bare_call(addr, params, 0).expect("should work"); +// decoded::(result) +// } +// +// fn create( +// addr: AccountId32, +// asset_id: AssetId, +// admin: AccountId32, +// min_balance: Balance, +// ) -> ExecReturnValue { +// let function = function_selector("create"); +// let params = [function, asset_id.encode(), admin.encode(), min_balance.encode()].concat(); +// do_bare_call(addr, params, 0).expect("should work") +// } +// +// fn set_metadata( +// addr: AccountId32, +// asset_id: AssetId, +// name: Vec, +// symbol: Vec, +// decimals: u8, +// ) -> ExecReturnValue { +// let function = function_selector("set_metadata"); +// let params = +// [function, asset_id.encode(), name.encode(), symbol.encode(), decimals.encode()].concat(); +// do_bare_call(addr, params, 0).expect("should work") +// } +// +// fn create_asset(owner: AccountId32, asset_id: AssetId, min_balance: Balance) -> AssetId { +// assert_eq!( +// Assets::create( +// RuntimeOrigin::signed(owner.clone()), +// asset_id.into(), +// owner.into(), +// min_balance +// ), +// Ok(()) +// ); +// asset_id +// } fn mint_asset(owner: AccountId32, asset_id: AssetId, to: AccountId32, value: Balance) -> AssetId { assert_eq!( @@ -393,52 +393,52 @@ fn transfer_works() { #[test] #[ignore] -fn increase_allowance_works() { +fn transfer_from_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![]); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); let amount: Balance = 100 * UNIT; - let asset = 0; - create_asset_and_mint_to(ALICE, asset, addr.clone(), amount); - assert_eq!( - decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - ConsumerRemaining - ); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); // Asset does not exist. - let asset = 1; assert_eq!( - decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), + decoded::(transfer(addr.clone(), 1, BOB, amount,)), Module { index: 52, error: 3 }, ); // Create asset with Alice as owner and mint `amount` to contract address. - create_asset_and_mint_to(ALICE, asset, addr.clone(), amount); + let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(ALICE, asset); assert_eq!( - decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), + decoded::(transfer(addr.clone(), asset, BOB, amount,)), Module { index: 52, error: 16 }, ); thaw_asset(ALICE, asset); - // Successful approval. - assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); - assert!( - !increase_allowance(addr.clone(), asset, BOB, amount).did_revert(), - "Contract reverted!" + // Not enough balance. + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), + Module { index: 52, error: 0 }, ); - assert_eq!(Assets::allowance(asset, &addr, &BOB), amount); - // Additive. - assert!( - !increase_allowance(addr.clone(), asset, BOB, amount).did_revert(), - "Contract reverted!" + // Not enough balance due to ED. + assert_eq!( + decoded::(transfer(addr.clone(), asset, BOB, amount)), + Module { index: 52, error: 0 }, + ); + // Successful transfer. + let bob_balance_before_mint = Assets::balance(asset, &BOB); + let result = transfer(addr.clone(), asset, BOB, amount / 2); + assert!(!result.did_revert(), "Contract reverted!"); + let bob_balance_after_mint = Assets::balance(asset, &BOB); + assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); + // Transfer asset to account that does not exist. + assert_eq!( + decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), + Token(CannotCreate) ); - assert_eq!(Assets::allowance(asset, &addr, &BOB), amount * 2); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(ALICE, asset); assert_eq!( - decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), + decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), Module { index: 52, error: 16 }, ); }); @@ -446,52 +446,52 @@ fn increase_allowance_works() { #[test] #[ignore] -fn transfer_from_works() { +fn increase_allowance_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); + let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![]); let amount: Balance = 100 * UNIT; + let asset = 0; + create_asset_and_mint_to(ALICE, asset, addr.clone(), amount); + assert_eq!( + decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), + ConsumerRemaining + ); + let addr = + instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); // Asset does not exist. + let asset = 1; assert_eq!( - decoded::(transfer(addr.clone(), 1, BOB, amount,)), + decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), Module { index: 52, error: 3 }, ); // Create asset with Alice as owner and mint `amount` to contract address. - let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); + create_asset_and_mint_to(ALICE, asset, addr.clone(), amount); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(ALICE, asset); assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount,)), + decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), Module { index: 52, error: 16 }, ); thaw_asset(ALICE, asset); - // Not enough balance. - assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), - Module { index: 52, error: 0 }, - ); - // Not enough balance due to ED. - assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 0 }, + // Successful approval. + assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); + assert!( + !increase_allowance(addr.clone(), asset, BOB, amount).did_revert(), + "Contract reverted!" ); - // Successful transfer. - let bob_balance_before_mint = Assets::balance(asset, &BOB); - let result = transfer(addr.clone(), asset, BOB, amount / 2); - assert!(!result.did_revert(), "Contract reverted!"); - let bob_balance_after_mint = Assets::balance(asset, &BOB); - assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); - // Transfer asset to account that does not exist. - assert_eq!( - decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), - Token(CannotCreate) + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount); + // Additive. + assert!( + !increase_allowance(addr.clone(), asset, BOB, amount).did_revert(), + "Contract reverted!" ); + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount * 2); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(ALICE, asset); assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), + decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), Module { index: 52, error: 16 }, ); }); @@ -540,132 +540,132 @@ fn token_metadata_works() { }); } -#[test] -#[ignore] -fn asset_exists_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); - - // No tokens in circulation. - assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr.clone(), ASSET_ID)); - - // Tokens in circulation. - create_asset(addr.clone(), ASSET_ID, 1); - assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr, ASSET_ID)); - }); -} - -#[test] -#[ignore] -fn mint_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); - let amount: Balance = 100 * UNIT; - - // Asset does not exist. - assert_eq!( - decoded::(transfer_from(addr.clone(), 1, None, Some(BOB), amount, &[0u8])), - Token(UnknownAsset) - ); - let asset = create_asset(ALICE, 1, 2); - // Minting can only be done by the owner. - assert_eq!( - decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), - Module { index: 52, error: 2 }, - ); - // Minimum balance of an asset can not be zero. - assert_eq!( - decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), 1, &[0u8])), - Token(BelowMinimum) - ); - let asset = create_asset(addr.clone(), 2, 2); - // Asset is not live, i.e. frozen or being destroyed. - freeze_asset(addr.clone(), asset); - assert_eq!( - decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), - Module { index: 52, error: 16 }, - ); - thaw_asset(addr.clone(), asset); - // Successful mint. - let bob_balance_before_mint = Assets::balance(asset, &BOB); - let result = transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8]); - assert!(!result.did_revert(), "Contract reverted!"); - let bob_balance_after_mint = Assets::balance(asset, &BOB); - assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount); - // Can not mint more tokens than Balance::MAX. - assert_eq!( - decoded::(transfer_from( - addr.clone(), - asset, - None, - Some(BOB), - Balance::MAX, - &[0u8] - )), - Arithmetic(Overflow) - ); - // Asset is not live, i.e. frozen or being destroyed. - start_destroy_asset(addr.clone(), asset); - assert_eq!( - decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), - Module { index: 52, error: 16 }, - ); - }); -} - -#[test] -#[ignore] -fn create_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - // Instantiate a contract without balance (relay token). - let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); - // No balance to pay for fees. - assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), - Module { index: 10, error: 2 }, - ); - // Instantiate a contract without balance (relay token). - let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 100, vec![2]); - // No balance to pay the deposit. - assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), - Module { index: 10, error: 2 }, - ); - // Instantiate a contract with balance. - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); - assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, BOB, 0)), - Module { index: 52, error: 7 }, - ); - create_asset(ALICE, ASSET_ID, 1); - // Asset ID is already taken. - assert_eq!( - decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), - Module { index: 52, error: 5 }, - ); - // The minimal balance for an asset must be non zero. - let new_asset = 2; - let result = create(addr.clone(), new_asset, BOB, 1); - assert!(!result.did_revert(), "Contract reverted!"); - }); -} - -#[test] -#[ignore] -fn set_metadata_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); - - create_asset(addr.clone(), ASSET_ID, 1); - let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); - assert!(!result.did_revert(), "Contract reverted!"); - }); -} +// #[test] +// #[ignore] +// fn asset_exists_works() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// let addr = +// instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); +// +// // No tokens in circulation. +// assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr.clone(), ASSET_ID)); +// +// // Tokens in circulation. +// create_asset(addr.clone(), ASSET_ID, 1); +// assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr, ASSET_ID)); +// }); +// } + +// #[test] +// #[ignore] +// fn mint_works() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// let addr = +// instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); +// let amount: Balance = 100 * UNIT; +// +// // Asset does not exist. +// assert_eq!( +// decoded::(transfer_from(addr.clone(), 1, None, Some(BOB), amount, &[0u8])), +// Token(UnknownAsset) +// ); +// let asset = create_asset(ALICE, 1, 2); +// // Minting can only be done by the owner. +// assert_eq!( +// decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), +// Module { index: 52, error: 2 }, +// ); +// // Minimum balance of an asset can not be zero. +// assert_eq!( +// decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), 1, &[0u8])), +// Token(BelowMinimum) +// ); +// let asset = create_asset(addr.clone(), 2, 2); +// // Asset is not live, i.e. frozen or being destroyed. +// freeze_asset(addr.clone(), asset); +// assert_eq!( +// decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), +// Module { index: 52, error: 16 }, +// ); +// thaw_asset(addr.clone(), asset); +// // Successful mint. +// let bob_balance_before_mint = Assets::balance(asset, &BOB); +// let result = transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8]); +// assert!(!result.did_revert(), "Contract reverted!"); +// let bob_balance_after_mint = Assets::balance(asset, &BOB); +// assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount); +// // Can not mint more tokens than Balance::MAX. +// assert_eq!( +// decoded::(transfer_from( +// addr.clone(), +// asset, +// None, +// Some(BOB), +// Balance::MAX, +// &[0u8] +// )), +// Arithmetic(Overflow) +// ); +// // Asset is not live, i.e. frozen or being destroyed. +// start_destroy_asset(addr.clone(), asset); +// assert_eq!( +// decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), +// Module { index: 52, error: 16 }, +// ); +// }); +// } + +// #[test] +// #[ignore] +// fn create_works() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// // Instantiate a contract without balance (relay token). +// let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); +// // No balance to pay for fees. +// assert_eq!( +// decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), +// Module { index: 10, error: 2 }, +// ); +// // Instantiate a contract without balance (relay token). +// let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 100, vec![2]); +// // No balance to pay the deposit. +// assert_eq!( +// decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), +// Module { index: 10, error: 2 }, +// ); +// // Instantiate a contract with balance. +// let addr = +// instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); +// assert_eq!( +// decoded::(create(addr.clone(), ASSET_ID, BOB, 0)), +// Module { index: 52, error: 7 }, +// ); +// create_asset(ALICE, ASSET_ID, 1); +// // Asset ID is already taken. +// assert_eq!( +// decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), +// Module { index: 52, error: 5 }, +// ); +// // The minimal balance for an asset must be non zero. +// let new_asset = 2; +// let result = create(addr.clone(), new_asset, BOB, 1); +// assert!(!result.did_revert(), "Contract reverted!"); +// }); +// } + +// #[test] +// #[ignore] +// fn set_metadata_works() { +// new_test_ext().execute_with(|| { +// let _ = env_logger::try_init(); +// let addr = +// instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); +// +// create_asset(addr.clone(), ASSET_ID, 1); +// let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); +// assert!(!result.did_revert(), "Contract reverted!"); +// }); +// } diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index cb27b17f..9e1deefe 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -26,6 +26,8 @@ pub type Result = core::result::Result; #[ink::scale_derive(Encode, Decode, TypeInfo)] pub struct StatusCode(pub u32); +pub(crate) const DECODING_FAILED: u32 = 255; + impl From for StatusCode { fn from(value: u32) -> Self { StatusCode(value) @@ -42,7 +44,7 @@ impl FromStatusCode for StatusCode { impl From for StatusCode { fn from(_: ink::scale::Error) -> Self { - StatusCode(255u32) + StatusCode(DECODING_FAILED) } } diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index ea8991a7..4d942dc6 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,6 +1,6 @@ use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec, scale::Decode}; -use crate::{primitives::AssetId, AccountId, Balance, Result, StatusCode}; +use crate::{primitives::AssetId, AccountId, Balance, Result, StatusCode, DECODING_FAILED}; pub mod fungibles; @@ -197,7 +197,7 @@ pub fn total_supply(id: AssetId) -> Result { .output::>, true>() .handle_error_code::() .call(&(id)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } #[inline] @@ -212,7 +212,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { .output::>, true>() .handle_error_code::() .call(&(id, owner)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } #[inline] @@ -222,7 +222,7 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result>, true>() .handle_error_code::() .call(&(id, owner, spender)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } #[inline] @@ -237,7 +237,7 @@ pub fn token_name(id: AssetId) -> Result> { .output::>, true>() .handle_error_code::() .call(&(id)) - .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) + .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } // #[inline] @@ -252,7 +252,7 @@ pub fn token_symbol(id: AssetId) -> Result> { .output::>, true>() .handle_error_code::() .call(&(id)) - .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) + .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } #[inline] @@ -267,7 +267,7 @@ pub fn token_decimals(id: AssetId) -> Result { .output::>, true>() .handle_error_code::() .call(&(id)) - .and_then(|v| ::decode(&mut &v[..]).map_err(|_e| StatusCode(255u32))) + .and_then(|v| ::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } // pub(crate) fn asset_exists(id: AssetId) -> Result { diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 9d31653a..c0d9f0d3 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -95,7 +95,7 @@ pub mod v0 { // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). encoded_error.resize(4, 0); u32::from_le_bytes( - encoded_error.try_into().expect("qid, resized to 4 bytes line above"), + encoded_error.try_into().expect("qed, resized to 4 bytes line above"), ) } } diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index c6bab850..f126031b 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -313,7 +313,7 @@ pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { }; // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). encoded_error.resize(4, 0); - let mut encoded_error = encoded_error.try_into().expect("qid, resized to 4 bytes line above"); + let mut encoded_error = encoded_error.try_into().expect("qed, resized to 4 bytes line above"); match version { // If an unknown variant of the `DispatchError` is detected the error needs to be converted // into the encoded value of `Error::Other`. This conversion is performed by shifting the bytes one From b591222168e40099c3d2b759da9765f45ee0a488 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Wed, 17 Jul 2024 18:00:11 +0200 Subject: [PATCH 022/161] style: renaming --- pop-api/examples/fungibles/lib.rs | 2 +- pop-api/integration-tests/src/lib.rs | 2 +- .../integration-tests/src/local_fungibles.rs | 50 +++++++++---------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 2abc422c..1b42fec4 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -71,7 +71,7 @@ mod fungibles { from: AccountId, to: AccountId, value: Balance, - // In the standard a `[u8]`, but the size needs to be known at compile time. + // In the PSP-22 standard a `[u8]`, but the size needs to be known at compile time. _data: Vec, ) -> Result<()> { api::transfer_from(id, from, to, value) diff --git a/pop-api/integration-tests/src/lib.rs b/pop-api/integration-tests/src/lib.rs index c6732d91..8c967855 100644 --- a/pop-api/integration-tests/src/lib.rs +++ b/pop-api/integration-tests/src/lib.rs @@ -59,7 +59,7 @@ fn function_selector(name: &str) -> Vec { [hash[0..4].to_vec()].concat() } -fn do_bare_call( +fn bare_call( addr: AccountId32, input: Vec, value: u128, diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs index bef3aa6a..f39c2327 100644 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -18,7 +18,7 @@ fn decoded(result: ExecReturnValue) -> T { fn total_supply(addr: AccountId32, asset_id: AssetId) -> Balance { let function = function_selector("total_supply"); let params = [function, asset_id.encode()].concat(); - let result = do_bare_call(addr, params, 0).expect("should work"); + let result = bare_call(addr, params, 0).expect("should work"); decoded::(result) } @@ -26,7 +26,7 @@ fn total_supply(addr: AccountId32, asset_id: AssetId) -> Balance { fn balance_of(addr: AccountId32, asset_id: AssetId, owner: AccountId32) -> Balance { let function = function_selector("balance_of"); let params = [function, asset_id.encode(), owner.encode()].concat(); - let result = do_bare_call(addr, params, 0).expect("should work"); + let result = bare_call(addr, params, 0).expect("should work"); decoded::(result) } @@ -39,7 +39,7 @@ fn allowance( ) -> Balance { let function = function_selector("allowance"); let params = [function, asset_id.encode(), owner.encode(), spender.encode()].concat(); - let result = do_bare_call(addr, params, 0).expect("should work"); + let result = bare_call(addr, params, 0).expect("should work"); decoded::(result) } @@ -47,7 +47,7 @@ fn allowance( fn token_name(addr: AccountId32, asset_id: AssetId) -> Vec { let function = function_selector("token_name"); let params = [function, asset_id.encode()].concat(); - let result = do_bare_call(addr, params, 0).expect("should work"); + let result = bare_call(addr, params, 0).expect("should work"); decoded::>(result) } @@ -55,7 +55,7 @@ fn token_name(addr: AccountId32, asset_id: AssetId) -> Vec { fn token_symbol(addr: AccountId32, asset_id: AssetId) -> Vec { let function = function_selector("token_symbol"); let params = [function, asset_id.encode()].concat(); - let result = do_bare_call(addr, params, 0).expect("should work"); + let result = bare_call(addr, params, 0).expect("should work"); decoded::>(result) } @@ -63,7 +63,7 @@ fn token_symbol(addr: AccountId32, asset_id: AssetId) -> Vec { fn token_decimals(addr: AccountId32, asset_id: AssetId) -> u8 { let function = function_selector("token_decimals"); let params = [function, asset_id.encode()].concat(); - let result = do_bare_call(addr, params, 0).expect("should work"); + let result = bare_call(addr, params, 0).expect("should work"); decoded::(result) } @@ -75,7 +75,7 @@ fn transfer( ) -> ExecReturnValue { let function = function_selector("transfer"); let params = [function, asset_id.encode(), to.encode(), value.encode()].concat(); - let result = do_bare_call(addr, params, 0).expect("should work"); + let result = bare_call(addr, params, 0).expect("should work"); result } @@ -91,7 +91,7 @@ fn transfer_from( let params = [function, asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()] .concat(); - do_bare_call(addr, params, 0).expect("should work") + bare_call(addr, params, 0).expect("should work") } fn increase_allowance( @@ -102,14 +102,14 @@ fn increase_allowance( ) -> ExecReturnValue { let function = function_selector("increase_allowance"); let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); - let result = do_bare_call(addr, params, 0).expect("should work"); + let result = bare_call(addr, params, 0).expect("should work"); result } // fn asset_exists(addr: AccountId32, asset_id: AssetId) -> bool { // let function = function_selector("asset_exists"); // let params = [function, asset_id.encode()].concat(); -// let result = do_bare_call(addr, params, 0).expect("should work"); +// let result = bare_call(addr, params, 0).expect("should work"); // decoded::(result) // } // @@ -121,7 +121,7 @@ fn increase_allowance( // ) -> ExecReturnValue { // let function = function_selector("create"); // let params = [function, asset_id.encode(), admin.encode(), min_balance.encode()].concat(); -// do_bare_call(addr, params, 0).expect("should work") +// bare_call(addr, params, 0).expect("should work") // } // // fn set_metadata( @@ -134,22 +134,22 @@ fn increase_allowance( // let function = function_selector("set_metadata"); // let params = // [function, asset_id.encode(), name.encode(), symbol.encode(), decimals.encode()].concat(); -// do_bare_call(addr, params, 0).expect("should work") -// } -// -// fn create_asset(owner: AccountId32, asset_id: AssetId, min_balance: Balance) -> AssetId { -// assert_eq!( -// Assets::create( -// RuntimeOrigin::signed(owner.clone()), -// asset_id.into(), -// owner.into(), -// min_balance -// ), -// Ok(()) -// ); -// asset_id +// bare_call(addr, params, 0).expect("should work") // } +fn create_asset(owner: AccountId32, asset_id: AssetId, min_balance: Balance) -> AssetId { + assert_eq!( + Assets::create( + RuntimeOrigin::signed(owner.clone()), + asset_id.into(), + owner.into(), + min_balance + ), + Ok(()) + ); + asset_id +} + fn mint_asset(owner: AccountId32, asset_id: AssetId, to: AccountId32, value: Balance) -> AssetId { assert_eq!( Assets::mint(RuntimeOrigin::signed(owner.clone()), asset_id.into(), to.into(), value), From c2acbb57ae9be348a9b4b0c2d7e81330b3a8ef47 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Thu, 18 Jul 2024 11:43:37 +0200 Subject: [PATCH 023/161] refactor: bits and pieces --- pop-api/integration-tests/src/lib.rs | 7 +- .../integration-tests/src/local_fungibles.rs | 78 ++++++++----------- pop-api/src/lib.rs | 36 ++++----- pop-api/src/primitives.rs | 6 ++ pop-api/src/v0/assets/fungibles.rs | 58 +++++++++----- pop-api/src/v0/assets/mod.rs | 12 +-- pop-api/src/v0/mod.rs | 17 ++++ pop-api/src/v0/nfts.rs | 3 - primitives/src/lib.rs | 28 +++---- runtime/devnet/src/extensions/mod.rs | 2 +- runtime/testnet/src/extensions.rs | 4 +- 11 files changed, 138 insertions(+), 113 deletions(-) diff --git a/pop-api/integration-tests/src/lib.rs b/pop-api/integration-tests/src/lib.rs index 8c967855..ea5ccb05 100644 --- a/pop-api/integration-tests/src/lib.rs +++ b/pop-api/integration-tests/src/lib.rs @@ -1,6 +1,7 @@ #![cfg(test)] use frame_support::{ + assert_ok, traits::fungibles::{ approvals::Inspect as ApprovalInspect, metadata::Inspect as MetadataInspect, Inspect, }, @@ -17,17 +18,17 @@ use pop_runtime_devnet::{ mod local_fungibles; -type Balance = u128; type AssetId = u32; -const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; +type Balance = u128; const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); const BOB: AccountId32 = AccountId32::new([2_u8; 32]); +const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; // FERDIE has no initial balance. const FERDIE: AccountId32 = AccountId32::new([3_u8; 32]); +const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); const INIT_AMOUNT: Balance = 100_000_000 * UNIT; const INIT_VALUE: Balance = 100 * UNIT; -const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default() diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs index f39c2327..8f0384c0 100644 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -138,23 +138,22 @@ fn increase_allowance( // } fn create_asset(owner: AccountId32, asset_id: AssetId, min_balance: Balance) -> AssetId { - assert_eq!( - Assets::create( - RuntimeOrigin::signed(owner.clone()), - asset_id.into(), - owner.into(), - min_balance - ), - Ok(()) - ); + assert_ok!(Assets::create( + RuntimeOrigin::signed(owner.clone()), + asset_id.into(), + owner.into(), + min_balance + )); asset_id } fn mint_asset(owner: AccountId32, asset_id: AssetId, to: AccountId32, value: Balance) -> AssetId { - assert_eq!( - Assets::mint(RuntimeOrigin::signed(owner.clone()), asset_id.into(), to.into(), value), - Ok(()) - ); + assert_ok!(Assets::mint( + RuntimeOrigin::signed(owner.clone()), + asset_id.into(), + to.into(), + value + )); asset_id } @@ -178,30 +177,27 @@ fn create_asset_mint_and_approve( approve: Balance, ) { create_asset_and_mint_to(owner.clone(), asset_id, to.clone(), mint); - assert_eq!( - Assets::approve_transfer( - RuntimeOrigin::signed(to.into()), - asset_id.into(), - spender.into(), - approve, - ), - Ok(()) - ); + assert_ok!(Assets::approve_transfer( + RuntimeOrigin::signed(to.into()), + asset_id.into(), + spender.into(), + approve, + )); } // Freeze an asset. fn freeze_asset(owner: AccountId32, asset_id: AssetId) { - assert_eq!(Assets::freeze_asset(RuntimeOrigin::signed(owner.into()), asset_id.into()), Ok(())); + assert_ok!(Assets::freeze_asset(RuntimeOrigin::signed(owner.into()), asset_id.into())); } // Thaw an asset. fn thaw_asset(owner: AccountId32, asset_id: AssetId) { - assert_eq!(Assets::thaw_asset(RuntimeOrigin::signed(owner.into()), asset_id.into()), Ok(())); + assert_ok!(Assets::thaw_asset(RuntimeOrigin::signed(owner.into()), asset_id.into())); } // Start destroying an asset. fn start_destroy_asset(owner: AccountId32, asset_id: AssetId) { - assert_eq!(Assets::start_destroy(RuntimeOrigin::signed(owner.into()), asset_id.into()), Ok(())); + assert_ok!(Assets::start_destroy(RuntimeOrigin::signed(owner.into()), asset_id.into())); } // Create an asset and set metadata. @@ -212,15 +208,12 @@ fn create_asset_and_set_metadata( symbol: Vec, decimals: u8, ) { - assert_eq!( - Assets::create( - RuntimeOrigin::signed(owner.clone()), - asset_id.into(), - owner.clone().into(), - 100 - ), - Ok(()) - ); + assert_ok!(Assets::create( + RuntimeOrigin::signed(owner.clone()), + asset_id.into(), + owner.clone().into(), + 100 + )); set_metadata_asset(owner, asset_id, name, symbol, decimals); } @@ -232,16 +225,13 @@ fn set_metadata_asset( symbol: Vec, decimals: u8, ) { - assert_eq!( - Assets::set_metadata( - RuntimeOrigin::signed(owner.into()), - asset_id.into(), - name, - symbol, - decimals - ), - Ok(()) - ); + assert_ok!(Assets::set_metadata( + RuntimeOrigin::signed(owner.into()), + asset_id.into(), + name, + symbol, + decimals + )); } fn token_name_asset(asset_id: AssetId) -> Vec { diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 9e1deefe..8d865f0b 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,7 +1,8 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::env::{chain_extension::FromStatusCode, DefaultEnvironment, Environment}; -use primitives::error::Error; +use ink::env::chain_extension::FromStatusCode; + +use constants::DECODING_FAILED; #[cfg(feature = "assets")] pub use v0::assets; @@ -15,18 +16,25 @@ pub use v0::nfts; pub mod primitives; pub mod v0; -type AccountId = ::AccountId; -type Balance = ::Balance; -#[cfg(any(feature = "nfts", feature = "cross-chain"))] -type BlockNumber = ::BlockNumber; - pub type Result = core::result::Result; #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub struct StatusCode(pub u32); -pub(crate) const DECODING_FAILED: u32 = 255; +mod constants { + // Errors: + pub(crate) const DECODING_FAILED: u32 = 255; + pub(crate) const MODULE_ERROR: u8 = 3; + + // Function IDs: + pub(crate) const DISPATCH: u8 = 0; + pub(crate) const READ_STATE: u8 = 1; + + // Modules: + pub(crate) const ASSETS_MODULE: u8 = 52; + pub(crate) const BALANCES_MODULE: u8 = 10; +} impl From for StatusCode { fn from(value: u32) -> Self { @@ -47,15 +55,3 @@ impl From for StatusCode { StatusCode(DECODING_FAILED) } } - -impl From for Error { - fn from(value: StatusCode) -> Self { - value.0.into() - } -} - -impl From for StatusCode { - fn from(value: Error) -> Self { - StatusCode::from(u32::from(value)) - } -} diff --git a/pop-api/src/primitives.rs b/pop-api/src/primitives.rs index e174a111..b451ce79 100644 --- a/pop-api/src/primitives.rs +++ b/pop-api/src/primitives.rs @@ -1 +1,7 @@ +use ink::env::{DefaultEnvironment, Environment}; pub use pop_primitives::*; + +pub(crate) type AccountId = ::AccountId; +pub(crate) type Balance = ::Balance; +#[cfg(any(feature = "nfts", feature = "cross-chain"))] +type BlockNumber = ::BlockNumber; diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 4abd46a6..8bc7d807 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,6 +1,11 @@ use ink::prelude::vec::Vec; -use crate::{assets, primitives::AssetId, AccountId, Balance, Result, StatusCode}; +use crate::{ + assets, + constants::{ASSETS_MODULE, BALANCES_MODULE, MODULE_ERROR}, + primitives::{AccountId, AssetId, Balance}, + Result, StatusCode, +}; /// Local Fungibles: /// 1. PSP-22 Interface @@ -101,7 +106,7 @@ pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance /// Returns `Ok(())` if successful, or an error if the approval fails. #[inline] pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - assets::cancel_approval(id, spender)?; + assets::cancel_approval(id, spender.clone())?; assets::approve_transfer(id, spender, value) } @@ -312,15 +317,15 @@ impl From for FungiblesError { let encoded = value.0.to_le_bytes(); match encoded { // Balances. - [3, 10, 2, _] => FungiblesError::NoBalance, + [MODULE_ERROR, BALANCES_MODULE, 2, _] => FungiblesError::NoBalance, // Assets. - [3, 52, 0, _] => FungiblesError::NoAccount, - [3, 52, 1, _] => FungiblesError::NoPermission, - [3, 52, 2, _] => FungiblesError::Unknown, - [3, 52, 3, _] => FungiblesError::InUse, - [3, 52, 5, _] => FungiblesError::MinBalanceZero, - [3, 52, 7, _] => FungiblesError::InsufficientAllowance, - [3, 52, 10, _] => FungiblesError::AssetNotLive, + [MODULE_ERROR, ASSETS_MODULE, 0, _] => FungiblesError::NoAccount, + [MODULE_ERROR, ASSETS_MODULE, 1, _] => FungiblesError::NoPermission, + [MODULE_ERROR, ASSETS_MODULE, 2, _] => FungiblesError::Unknown, + [MODULE_ERROR, ASSETS_MODULE, 3, _] => FungiblesError::InUse, + [MODULE_ERROR, ASSETS_MODULE, 5, _] => FungiblesError::MinBalanceZero, + [MODULE_ERROR, ASSETS_MODULE, 7, _] => FungiblesError::InsufficientAllowance, + [MODULE_ERROR, ASSETS_MODULE, 10, _] => FungiblesError::AssetNotLive, _ => FungiblesError::Other(value), } } @@ -328,6 +333,7 @@ impl From for FungiblesError { #[cfg(test)] mod tests { + use crate::constants::{ASSETS_MODULE, BALANCES_MODULE}; use ink::scale::Decode; use super::FungiblesError; @@ -359,7 +365,7 @@ mod tests { #[test] fn conversion_status_code_into_fungibles_error_works() { - let errors = vec![ + let other_errors = vec![ Other { dispatch_error_index: 5, error_index: 5, error: 1 }, CannotLookup, BadOrigin, @@ -378,30 +384,42 @@ mod tests { UnknownFunctionId, DecodingFailed, ]; - for error in errors { + for error in other_errors { let status_code: StatusCode = error.into(); let fungibles_error: FungiblesError = status_code.into(); assert_eq!(fungibles_error, FungiblesError::Other(status_code)) } - assert_eq!(into_fungibles_error(Module { index: 10, error: 2 }), FungiblesError::NoBalance); - assert_eq!(into_fungibles_error(Module { index: 52, error: 0 }), FungiblesError::NoAccount); assert_eq!( - into_fungibles_error(Module { index: 52, error: 1 }), + into_fungibles_error(Module { index: BALANCES_MODULE, error: 2 }), + FungiblesError::NoBalance + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS_MODULE, error: 0 }), + FungiblesError::NoAccount + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS_MODULE, error: 1 }), FungiblesError::NoPermission ); - assert_eq!(into_fungibles_error(Module { index: 52, error: 2 }), FungiblesError::Unknown); - assert_eq!(into_fungibles_error(Module { index: 52, error: 3 }), FungiblesError::InUse); assert_eq!( - into_fungibles_error(Module { index: 52, error: 5 }), + into_fungibles_error(Module { index: ASSETS_MODULE, error: 2 }), + FungiblesError::Unknown + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS_MODULE, error: 3 }), + FungiblesError::InUse + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS_MODULE, error: 5 }), FungiblesError::MinBalanceZero ); assert_eq!( - into_fungibles_error(Module { index: 52, error: 7 }), + into_fungibles_error(Module { index: ASSETS_MODULE, error: 7 }), FungiblesError::InsufficientAllowance ); assert_eq!( - into_fungibles_error(Module { index: 52, error: 10 }), + into_fungibles_error(Module { index: ASSETS_MODULE, error: 10 }), FungiblesError::AssetNotLive ); } diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 4d942dc6..fa7d523b 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,18 +1,19 @@ use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec, scale::Decode}; -use crate::{primitives::AssetId, AccountId, Balance, Result, StatusCode, DECODING_FAILED}; +use crate::{ + constants::{ASSETS_MODULE, DECODING_FAILED, DISPATCH, READ_STATE}, + primitives::{AccountId, AssetId, Balance}, + v0::VERSION, + Result, StatusCode, +}; pub mod fungibles; -const ASSETS_MODULE: u8 = 52; -const VERSION: u8 = 0; - /// [Pallet Assets](https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/lib.rs): /// 1. Dispatchables /// 2. Read state functions /// /// 1. Dispatchables within pallet assets (TrustBackedAssets instance): -const DISPATCH: u8 = 0; /// - create /// - start_destroy /// - destroy_accounts @@ -170,7 +171,6 @@ pub fn transfer_approved( } /// 2. Read state functions: -const READ_STATE: u8 = 1; /// - total_supply const TOTAL_SUPPLY: u8 = 0; /// - balance_of diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 310b360c..56bccfc1 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -1,3 +1,6 @@ +use crate::StatusCode; +use pop_primitives::error::Error; + #[cfg(feature = "assets")] pub mod assets; #[cfg(feature = "balances")] @@ -6,3 +9,17 @@ pub mod balances; pub mod cross_chain; #[cfg(feature = "nfts")] pub mod nfts; + +pub(crate) const VERSION: u8 = 0; + +impl From for Error { + fn from(value: StatusCode) -> Self { + value.0.into() + } +} + +impl From for StatusCode { + fn from(value: Error) -> Self { + StatusCode::from(u32::from(value)) + } +} diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs index e111c8dc..63b90a1f 100644 --- a/pop-api/src/v0/nfts.rs +++ b/pop-api/src/v0/nfts.rs @@ -6,12 +6,9 @@ pub use primitives::{CollectionId, ItemId}; use scale::Encode; pub use types::*; -type Result = core::result::Result; type StringLimit = u32; type MaxTips = u32; -type Result = core::result::Result; - /// Issue a new collection of non-fungible items pub fn create( admin: impl Into>, diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index c0d9f0d3..3b3ff16d 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -48,34 +48,34 @@ pub mod v0 { error_index: u8, // Index for further nesting, e.g. pallet error. error: u8, - } = 0, + }, /// Failed to lookup some data. - CannotLookup = 1, + CannotLookup, /// A bad origin. - BadOrigin = 2, + BadOrigin, /// A custom error in a module. - Module { index: u8, error: u8 } = 3, + Module { index: u8, error: u8 }, /// At least one consumer is remaining so the account cannot be destroyed. - ConsumerRemaining = 4, + ConsumerRemaining, /// There are no providers so the account cannot be created. - NoProviders = 5, + NoProviders, /// There are too many consumers so the account cannot be created. - TooManyConsumers = 6, + TooManyConsumers, /// An error to do with tokens. - Token(TokenError) = 7, + Token(TokenError), /// An arithmetic error. - Arithmetic(ArithmeticError) = 8, + Arithmetic(ArithmeticError), /// The number of transactional layers has been reached, or we are not in a transactional /// layer. - Transactional(TransactionalError) = 9, + Transactional(TransactionalError), /// Resources exhausted, e.g. attempt to read/write data which is too large to manipulate. - Exhausted = 10, + Exhausted, /// The state is corrupt; this is generally not going to fix itself. - Corruption = 11, + Corruption, /// Some resource (e.g. a preimage) is unavailable right now. This might fix itself later. - Unavailable = 12, + Unavailable, /// Root origin is not allowed. - RootNotAllowed = 13, + RootNotAllowed, /// Unknown function id. UnknownFunctionId = 254, /// Decoding failed on the runtime. diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index f126031b..720458c8 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -172,7 +172,7 @@ fn construct_call( params: Vec, ) -> Result { match pallet_index { - 52 => { + index if index == super::Assets::index() as u8 => { let call = versioned_construct_assets_call(version, call_index, params)?; Ok(RuntimeCall::Assets(call)) }, diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index 866cb12c..bcb0f835 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -1,9 +1,9 @@ use cumulus_pallet_parachain_system::RelaychainDataProvider; -use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, traits::nonfungibles_v2::Inspect, + traits::{Contains, OriginTrait}, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, @@ -206,7 +206,7 @@ where RuntimeStateKeys::ParachainSystem(key) => { read_parachain_system_state::(key, &mut env) }, - _ => Ok(Vec::from([0u8])), + _ => Ok(Vec::default()), }? .encode(); From 363932022c62e88e28b1360ff3e8c2a6a1aa6ffb Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Thu, 18 Jul 2024 14:50:52 +0200 Subject: [PATCH 024/161] docs: add docs to code --- pop-api/src/lib.rs | 25 +++++++++++++--- pop-api/src/v0/assets/fungibles.rs | 25 ++++++++++++---- primitives/src/lib.rs | 45 ++++++++++++++++++---------- runtime/devnet/src/extensions/mod.rs | 13 ++++++++ 4 files changed, 84 insertions(+), 24 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 8d865f0b..7a0fe75b 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -16,12 +16,9 @@ pub use v0::nfts; pub mod primitives; pub mod v0; +/// A result type used by the API, with the `StatusCode` as the error type. pub type Result = core::result::Result; -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub struct StatusCode(pub u32); - mod constants { // Errors: pub(crate) const DECODING_FAILED: u32 = 255; @@ -36,12 +33,31 @@ mod constants { pub(crate) const BALANCES_MODULE: u8 = 10; } +/// Represents a status code returned by the runtime. +/// +/// `StatusCode` encapsulates a `u32` value that indicates the status of an operation performed +/// by the runtime. It helps to communicate the success or failure of a chain extension method +/// call to the contract, providing a standardized way to handle errors. +/// +/// This status code can be used to determine if an operation succeeded or if it encountered +/// an error. A `StatusCode` of `0` typically indicates success, while any other value represents +/// an error. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub struct StatusCode(pub u32); + impl From for StatusCode { + /// Converts a `u32` into a `StatusCode`. fn from(value: u32) -> Self { StatusCode(value) } } + impl FromStatusCode for StatusCode { + /// Converts a `u32` status code to a `Result`. + /// + /// `Ok(())` if the status code is `0` and `Err(StatusCode(status_code))` for any other status + /// code. fn from_status_code(status_code: u32) -> Result<()> { match status_code { 0 => Ok(()), @@ -51,6 +67,7 @@ impl FromStatusCode for StatusCode { } impl From for StatusCode { + /// Converts a scale decoding error into a `StatusCode` indicating a decoding failure. fn from(_: ink::scale::Error) -> Self { StatusCode(DECODING_FAILED) } diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 8bc7d807..e3c9b6be 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -284,9 +284,20 @@ pub fn token_decimals(id: AssetId) -> Result { // assets::asset_exists(id) // } +/// Represents various errors related to local fungible assets in the API. +/// +/// The `FungiblesError` provides a detailed and specific set of error types that can occur when +/// interacting with fungible assets through the Pop API. Each variant signifies a particular error +/// condition, facilitating precise error handling and debugging. +/// +/// It is designed to be lightweight, including only the essential errors relevant to fungible asset +/// operations. The `Other` variant serves as a catch-all for any unexpected errors. For more +/// detailed debugging, the `Other` variant can be converted into the richer `Error` type defined in +/// the primitives crate. #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum FungiblesError { + /// An unspecified or unknown error occurred. Other(StatusCode), /// The asset is not live; either frozen or being destroyed. AssetNotLive, @@ -305,14 +316,18 @@ pub enum FungiblesError { /// The given asset ID is unknown. Unknown, /// No balance for creation of assets or fees. - // - // Originally `pallet_balances::Error::InsufficientBalance` but collides with the - // `InsufficientBalance` error that is used for `pallet_assets::Error::BalanceLow` to adhere to - // standard. + // TODO: Originally `pallet_balances::Error::InsufficientBalance` but collides with the + // `InsufficientBalance` error that is used for `pallet_assets::Error::BalanceLow` to adhere to + // standard. This deserves a second look. NoBalance, } impl From for FungiblesError { + /// Converts a `StatusCode` to a `FungiblesError`. + /// + /// This conversion maps a `StatusCode`, returned by the runtime, to a more descriptive + /// `FungiblesError`. This provides better context and understanding of the error, allowing + /// developers to handle the most important errors effectively. fn from(value: StatusCode) -> Self { let encoded = value.0.to_le_bytes(); match encoded { @@ -381,7 +396,7 @@ mod tests { Corruption, Unavailable, RootNotAllowed, - UnknownFunctionId, + UnknownFunctionCall, DecodingFailed, ]; for error in other_errors { diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 3b3ff16d..d177b60f 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -10,20 +10,21 @@ pub use v0::error; pub mod cross_chain; pub mod storage_keys; +/// An opaque 32-byte cryptographic identifier. #[derive(Encode, Decode, Debug, MaxEncodedLen, Eq, PartialEq)] #[cfg_attr(feature = "std", derive(TypeInfo))] pub struct AccountId(pub [u8; 32]); -// Identifier for the class of asset. +/// Identifier for the class of asset. pub type AssetId = u32; #[cfg(feature = "nfts")] pub mod nfts { use bounded_collections::ConstU32; - // Id used for identifying non-fungible collections. + /// Id used for identifying non-fungible collections. pub type CollectionId = u32; - // Id used for identifying non-fungible items. + /// Id used for identifying non-fungible items. pub type ItemId = u32; /// The maximum length of an attribute key. pub type KeyLimit = ConstU32<64>; @@ -36,24 +37,29 @@ pub mod v0 { pub mod error { use super::*; + /// Reason why a Pop API function call failed. #[derive(Encode, Decode, Debug, Eq, PartialEq)] #[cfg_attr(feature = "std", derive(TypeInfo))] #[repr(u8)] pub enum Error { - /// Some unknown error occurred. Go to the Pop API docs section `Pop API error`. - Other { - // Index within the `DispatchError` - dispatch_error_index: u8, - // Index within the `DispatchError` variant. - error_index: u8, - // Index for further nesting, e.g. pallet error. - error: u8, - }, + /// An unknown error occurred. This variant captures any unexpected errors that the + /// contract cannot specifically handle. It is useful for cases where there are breaking + /// changes in the runtime or when an error falls outside the predefined categories. The + /// variant includes: + /// + /// - `dispatch_error_index`: The index within the `DispatchError`. + /// - `error_index`: The index within the `DispatchError` variant (e.g. a `TokenError`). + /// - `error`: The specific error code or sub-index, providing additional context (e.g. + /// `error` in `ModuleError`). + Other { dispatch_error_index: u8, error_index: u8, error: u8 }, /// Failed to lookup some data. CannotLookup, /// A bad origin. BadOrigin, /// A custom error in a module. + /// + /// - `index`: The pallet index. + /// - `error`: The error within the pallet. Module { index: u8, error: u8 }, /// At least one consumer is remaining so the account cannot be destroyed. ConsumerRemaining, @@ -76,13 +82,18 @@ pub mod v0 { Unavailable, /// Root origin is not allowed. RootNotAllowed, - /// Unknown function id. - UnknownFunctionId = 254, - /// Decoding failed on the runtime. + /// Unknown function called. + UnknownFunctionCall = 254, + /// Decoding failed. DecodingFailed = 255, } impl From for Error { + /// Converts a `u32` status code into an `Error`. + /// + /// This conversion maps a raw status code returned by the runtime into the more + /// descriptive `Error` enum variant, providing better context and understanding of the + /// error. fn from(value: u32) -> Self { let encoded = value.to_le_bytes(); Error::decode(&mut &encoded[..]).unwrap_or(Error::DecodingFailed) @@ -90,6 +101,7 @@ pub mod v0 { } impl From for u32 { + /// Converts an `Error` to a `u32` status code. fn from(value: Error) -> Self { let mut encoded_error = value.encode(); // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). @@ -100,6 +112,7 @@ pub mod v0 { } } + /// Description of what went wrong when trying to complete an operation on a token. #[derive(Encode, Decode, Clone, Debug, MaxEncodedLen, Eq, PartialEq, Ord, PartialOrd)] #[cfg_attr(feature = "std", derive(TypeInfo))] pub enum TokenError { @@ -126,6 +139,7 @@ pub mod v0 { Blocked, } + /// Arithmetic errors. #[derive(Encode, Decode, Debug, Eq, PartialEq)] #[cfg_attr(feature = "std", derive(TypeInfo))] pub enum ArithmeticError { @@ -137,6 +151,7 @@ pub mod v0 { DivisionByZero, } + /// Errors related to transactional storage layers. #[derive(Encode, Decode, Debug, Eq, PartialEq)] #[cfg_attr(feature = "std", derive(TypeInfo))] pub enum TransactionalError { diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index 720458c8..ec2d0bc2 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -337,6 +337,15 @@ pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { u32::from_le_bytes(encoded_error) } +/// Enum representing the different function identifiers used in the Pop API chain extension. +/// +/// The `FuncId` enum specifies the available functions that can be called through the Pop API chain +/// extension. Each variant corresponds to a specific functionality provided by the chain extension, +/// facilitating the interaction between smart contracts and the runtime. +/// +/// - `Dispatch`: Represents a function call to dispatch a runtime call. +/// - `ReadState`: Represents a function call to read the state from the runtime. +/// - `SendXcm`: Represents a function call to send an XCM message. #[derive(Debug)] pub enum FuncId { Dispatch, @@ -347,6 +356,10 @@ pub enum FuncId { impl TryFrom for FuncId { type Error = DispatchError; + /// Attempts to convert a `u8` value to its corresponding `FuncId` variant. + /// + /// If the `u8` value does not match any known function identifier, it returns a + /// `DispatchError::Other` indicating an unknown function ID. fn try_from(func_id: u8) -> Result { let id = match func_id { 0 => Self::Dispatch, From 81e9844f056123abe88985e64463a753d50f004a Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Thu, 18 Jul 2024 15:05:42 +0200 Subject: [PATCH 025/161] fix: replace test code to api fungibles --- pop-api/src/v0/assets/fungibles.rs | 15 ++++++++++++--- pop-api/src/v0/mod.rs | 6 ------ primitives/src/lib.rs | 12 ------------ 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index e3c9b6be..9084708d 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -349,7 +349,7 @@ impl From for FungiblesError { #[cfg(test)] mod tests { use crate::constants::{ASSETS_MODULE, BALANCES_MODULE}; - use ink::scale::Decode; + use ink::scale::{Decode, Encode}; use super::FungiblesError; use crate::primitives::error::{ @@ -360,8 +360,17 @@ mod tests { }; use crate::StatusCode; + fn error_into_status_code(error: Error) -> StatusCode { + let mut encoded_error = error.encode(); + encoded_error.resize(4, 0); + let value = u32::from_le_bytes( + encoded_error.try_into().expect("qed, resized to 4 bytes line above"), + ); + value.into() + } + fn into_fungibles_error(error: Error) -> FungiblesError { - let status_code: StatusCode = error.into(); + let status_code: StatusCode = error_into_status_code(error); status_code.into() } @@ -400,7 +409,7 @@ mod tests { DecodingFailed, ]; for error in other_errors { - let status_code: StatusCode = error.into(); + let status_code: StatusCode = error_into_status_code(error); let fungibles_error: FungiblesError = status_code.into(); assert_eq!(fungibles_error, FungiblesError::Other(status_code)) } diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 56bccfc1..8b7a8469 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -17,9 +17,3 @@ impl From for Error { value.0.into() } } - -impl From for StatusCode { - fn from(value: Error) -> Self { - StatusCode::from(u32::from(value)) - } -} diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index d177b60f..b9caf111 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -100,18 +100,6 @@ pub mod v0 { } } - impl From for u32 { - /// Converts an `Error` to a `u32` status code. - fn from(value: Error) -> Self { - let mut encoded_error = value.encode(); - // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). - encoded_error.resize(4, 0); - u32::from_le_bytes( - encoded_error.try_into().expect("qed, resized to 4 bytes line above"), - ) - } - } - /// Description of what went wrong when trying to complete an operation on a token. #[derive(Encode, Decode, Clone, Debug, MaxEncodedLen, Eq, PartialEq, Ord, PartialOrd)] #[cfg_attr(feature = "std", derive(TypeInfo))] From 023d3dcffd96e28fd05dcefe84f088b6b64a4f6a Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Thu, 18 Jul 2024 15:50:44 +0200 Subject: [PATCH 026/161] fix: own review + fixing CI fail --- pop-api/src/lib.rs | 8 +- pop-api/src/primitives.rs | 1 + pop-api/src/v0/assets/fungibles.rs | 57 +++++---- pop-api/src/v0/assets/mod.rs | 140 ++++++++-------------- pop-api/src/v0/mod.rs | 5 +- primitives/src/lib.rs | 6 +- runtime/devnet/src/extensions/mod.rs | 8 +- runtime/devnet/src/extensions/v0/error.rs | 6 +- 8 files changed, 95 insertions(+), 136 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 7a0fe75b..86621c51 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -29,15 +29,15 @@ mod constants { pub(crate) const READ_STATE: u8 = 1; // Modules: - pub(crate) const ASSETS_MODULE: u8 = 52; - pub(crate) const BALANCES_MODULE: u8 = 10; + pub(crate) const ASSETS: u8 = 52; + pub(crate) const BALANCES: u8 = 10; } /// Represents a status code returned by the runtime. /// /// `StatusCode` encapsulates a `u32` value that indicates the status of an operation performed -/// by the runtime. It helps to communicate the success or failure of a chain extension method -/// call to the contract, providing a standardized way to handle errors. +/// by the runtime. It helps to communicate the success or failure of a Pop API call to the contract, +/// providing a standardized way to handle errors. /// /// This status code can be used to determine if an operation succeeded or if it encountered /// an error. A `StatusCode` of `0` typically indicates success, while any other value represents diff --git a/pop-api/src/primitives.rs b/pop-api/src/primitives.rs index b451ce79..33285044 100644 --- a/pop-api/src/primitives.rs +++ b/pop-api/src/primitives.rs @@ -1,4 +1,5 @@ use ink::env::{DefaultEnvironment, Environment}; + pub use pop_primitives::*; pub(crate) type AccountId = ::AccountId; diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 9084708d..255e8502 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -2,7 +2,7 @@ use ink::prelude::vec::Vec; use crate::{ assets, - constants::{ASSETS_MODULE, BALANCES_MODULE, MODULE_ERROR}, + constants::{ASSETS, BALANCES, MODULE_ERROR}, primitives::{AccountId, AssetId, Balance}, Result, StatusCode, }; @@ -106,7 +106,7 @@ pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance /// Returns `Ok(())` if successful, or an error if the approval fails. #[inline] pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - assets::cancel_approval(id, spender.clone())?; + assets::cancel_approval(id, spender)?; assets::approve_transfer(id, spender, value) } @@ -284,7 +284,7 @@ pub fn token_decimals(id: AssetId) -> Result { // assets::asset_exists(id) // } -/// Represents various errors related to local fungible assets in the API. +/// Represents various errors related to local fungible assets in the Pop API. /// /// The `FungiblesError` provides a detailed and specific set of error types that can occur when /// interacting with fungible assets through the Pop API. Each variant signifies a particular error @@ -332,15 +332,15 @@ impl From for FungiblesError { let encoded = value.0.to_le_bytes(); match encoded { // Balances. - [MODULE_ERROR, BALANCES_MODULE, 2, _] => FungiblesError::NoBalance, + [MODULE_ERROR, BALANCES, 2, _] => FungiblesError::NoBalance, // Assets. - [MODULE_ERROR, ASSETS_MODULE, 0, _] => FungiblesError::NoAccount, - [MODULE_ERROR, ASSETS_MODULE, 1, _] => FungiblesError::NoPermission, - [MODULE_ERROR, ASSETS_MODULE, 2, _] => FungiblesError::Unknown, - [MODULE_ERROR, ASSETS_MODULE, 3, _] => FungiblesError::InUse, - [MODULE_ERROR, ASSETS_MODULE, 5, _] => FungiblesError::MinBalanceZero, - [MODULE_ERROR, ASSETS_MODULE, 7, _] => FungiblesError::InsufficientAllowance, - [MODULE_ERROR, ASSETS_MODULE, 10, _] => FungiblesError::AssetNotLive, + [MODULE_ERROR, ASSETS, 0, _] => FungiblesError::NoAccount, + [MODULE_ERROR, ASSETS, 1, _] => FungiblesError::NoPermission, + [MODULE_ERROR, ASSETS, 2, _] => FungiblesError::Unknown, + [MODULE_ERROR, ASSETS, 3, _] => FungiblesError::InUse, + [MODULE_ERROR, ASSETS, 5, _] => FungiblesError::MinBalanceZero, + [MODULE_ERROR, ASSETS, 7, _] => FungiblesError::InsufficientAllowance, + [MODULE_ERROR, ASSETS, 10, _] => FungiblesError::AssetNotLive, _ => FungiblesError::Other(value), } } @@ -348,17 +348,19 @@ impl From for FungiblesError { #[cfg(test)] mod tests { - use crate::constants::{ASSETS_MODULE, BALANCES_MODULE}; use ink::scale::{Decode, Encode}; use super::FungiblesError; - use crate::primitives::error::{ - ArithmeticError::*, - Error::{self, *}, - TokenError::*, - TransactionalError::*, + use crate::{ + constants::{ASSETS, BALANCES}, + primitives::error::{ + ArithmeticError::*, + Error::{self, *}, + TokenError::*, + TransactionalError::*, + }, + StatusCode, }; - use crate::StatusCode; fn error_into_status_code(error: Error) -> StatusCode { let mut encoded_error = error.encode(); @@ -415,35 +417,32 @@ mod tests { } assert_eq!( - into_fungibles_error(Module { index: BALANCES_MODULE, error: 2 }), + into_fungibles_error(Module { index: BALANCES, error: 2 }), FungiblesError::NoBalance ); assert_eq!( - into_fungibles_error(Module { index: ASSETS_MODULE, error: 0 }), + into_fungibles_error(Module { index: ASSETS, error: 0 }), FungiblesError::NoAccount ); assert_eq!( - into_fungibles_error(Module { index: ASSETS_MODULE, error: 1 }), + into_fungibles_error(Module { index: ASSETS, error: 1 }), FungiblesError::NoPermission ); assert_eq!( - into_fungibles_error(Module { index: ASSETS_MODULE, error: 2 }), + into_fungibles_error(Module { index: ASSETS, error: 2 }), FungiblesError::Unknown ); + assert_eq!(into_fungibles_error(Module { index: ASSETS, error: 3 }), FungiblesError::InUse); assert_eq!( - into_fungibles_error(Module { index: ASSETS_MODULE, error: 3 }), - FungiblesError::InUse - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS_MODULE, error: 5 }), + into_fungibles_error(Module { index: ASSETS, error: 5 }), FungiblesError::MinBalanceZero ); assert_eq!( - into_fungibles_error(Module { index: ASSETS_MODULE, error: 7 }), + into_fungibles_error(Module { index: ASSETS, error: 7 }), FungiblesError::InsufficientAllowance ); assert_eq!( - into_fungibles_error(Module { index: ASSETS_MODULE, error: 10 }), + into_fungibles_error(Module { index: ASSETS, error: 10 }), FungiblesError::AssetNotLive ); } diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index fa7d523b..00021fc0 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,9 +1,9 @@ use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec, scale::Decode}; use crate::{ - constants::{ASSETS_MODULE, DECODING_FAILED, DISPATCH, READ_STATE}, + constants::{ASSETS, DECODING_FAILED, DISPATCH, READ_STATE}, primitives::{AccountId, AssetId, Balance}, - v0::VERSION, + v0::V0, Result, StatusCode, }; @@ -92,9 +92,9 @@ const TRANSFER_APPROVED: u8 = 25; #[inline] pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { ChainExtensionMethod::build(u32::from_le_bytes([ - VERSION, + V0, DISPATCH, - ASSETS_MODULE, + ASSETS, // E.D. is always respected with transferring tokens via the API. TRANSFER_KEEP_ALIVE, ])) @@ -122,31 +122,21 @@ pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> R /// Approve an amount of asset for transfer by a delegated third-party account. #[inline] pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([ - VERSION, - DISPATCH, - ASSETS_MODULE, - APPROVE_TRANSFER, - ])) - .input::<(AssetId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, delegate, amount)) + ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, ASSETS, APPROVE_TRANSFER])) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, delegate, amount)) } /// Cancel all of some asset approved for delegated transfer by a third-party account. #[inline] pub fn cancel_approval(id: AssetId, delegate: AccountId) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([ - VERSION, - DISPATCH, - ASSETS_MODULE, - CANCEL_APPROVAL, - ])) - .input::<(AssetId, AccountId)>() - .output::, true>() - .handle_error_code::() - .call(&(id, delegate)) + ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, ASSETS, CANCEL_APPROVAL])) + .input::<(AssetId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(id, delegate)) } /// Transfer some asset balance from a previously delegated account to some third-party @@ -158,16 +148,11 @@ pub fn transfer_approved( to: AccountId, amount: Balance, ) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([ - VERSION, - DISPATCH, - ASSETS_MODULE, - TRANSFER_APPROVED, - ])) - .input::<(AssetId, AccountId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, from, to, amount)) + ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, ASSETS, TRANSFER_APPROVED])) + .input::<(AssetId, AccountId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, from, to, amount)) } /// 2. Read state functions: @@ -187,37 +172,27 @@ const TOKEN_DECIMALS: u8 = 5; #[inline] pub fn total_supply(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([ - VERSION, - READ_STATE, - ASSETS_MODULE, - TOTAL_SUPPLY, - ])) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(id)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOTAL_SUPPLY])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } #[inline] pub fn balance_of(id: AssetId, owner: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([ - VERSION, - READ_STATE, - ASSETS_MODULE, - BALANCE_OF, - ])) - .input::<(AssetId, AccountId)>() - .output::>, true>() - .handle_error_code::() - .call(&(id, owner)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, BALANCE_OF])) + .input::<(AssetId, AccountId)>() + .output::>, true>() + .handle_error_code::() + .call(&(id, owner)) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } #[inline] pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([VERSION, READ_STATE, ASSETS_MODULE, ALLOWANCE])) + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, ALLOWANCE])) .input::<(AssetId, AccountId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -227,47 +202,32 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result> { - ChainExtensionMethod::build(u32::from_le_bytes([ - VERSION, - READ_STATE, - ASSETS_MODULE, - TOKEN_NAME, - ])) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(id)) - .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOKEN_NAME])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } // #[inline] pub fn token_symbol(id: AssetId) -> Result> { - ChainExtensionMethod::build(u32::from_le_bytes([ - VERSION, - READ_STATE, - ASSETS_MODULE, - TOKEN_SYMBOL, - ])) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(id)) - .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOKEN_SYMBOL])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } #[inline] pub fn token_decimals(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([ - VERSION, - READ_STATE, - ASSETS_MODULE, - TOKEN_DECIMALS, - ])) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(id)) - .and_then(|v| ::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOKEN_DECIMALS])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| ::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } // pub(crate) fn asset_exists(id: AssetId) -> Result { diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 8b7a8469..f7dab6b4 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -1,5 +1,4 @@ -use crate::StatusCode; -use pop_primitives::error::Error; +use crate::{primitives::error::Error, StatusCode}; #[cfg(feature = "assets")] pub mod assets; @@ -10,7 +9,7 @@ pub mod cross_chain; #[cfg(feature = "nfts")] pub mod nfts; -pub(crate) const VERSION: u8 = 0; +pub(crate) const V0: u8 = 0; impl From for Error { fn from(value: StatusCode) -> Self { diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index b9caf111..ec6670ba 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -37,7 +37,7 @@ pub mod v0 { pub mod error { use super::*; - /// Reason why a Pop API function call failed. + /// Reason why a Pop API call failed. #[derive(Encode, Decode, Debug, Eq, PartialEq)] #[cfg_attr(feature = "std", derive(TypeInfo))] #[repr(u8)] @@ -82,8 +82,8 @@ pub mod v0 { Unavailable, /// Root origin is not allowed. RootNotAllowed, - /// Unknown function called. - UnknownFunctionCall = 254, + /// Unknown call. + UnknownCall = 254, /// Decoding failed. DecodingFailed = 255, } diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index ec2d0bc2..d2bd63e7 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -337,11 +337,11 @@ pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { u32::from_le_bytes(encoded_error) } -/// Enum representing the different function identifiers used in the Pop API chain extension. +/// Function identifiers used in the Pop API. /// -/// The `FuncId` enum specifies the available functions that can be called through the Pop API chain -/// extension. Each variant corresponds to a specific functionality provided by the chain extension, -/// facilitating the interaction between smart contracts and the runtime. +/// The `FuncId` specifies the available functions that can be called through the Pop API. Each +/// variant corresponds to a specific functionality provided by the API, facilitating the +/// interaction between smart contracts and the runtime. /// /// - `Dispatch`: Represents a function call to dispatch a runtime call. /// - `ReadState`: Represents a function call to read the state from the runtime. diff --git a/runtime/devnet/src/extensions/v0/error.rs b/runtime/devnet/src/extensions/v0/error.rs index b8af2250..b26668f7 100644 --- a/runtime/devnet/src/extensions/v0/error.rs +++ b/runtime/devnet/src/extensions/v0/error.rs @@ -76,7 +76,7 @@ mod tests { DispatchError::Other(""), (Other { dispatch_error_index: 0, error_index: 0, error: 0 }), ), - (DispatchError::Other("UnknownFunctionId"), UnknownFunctionId), + (DispatchError::Other("UnknownFunctionId"), UnknownCall), (DispatchError::Other("DecodingFailed"), DecodingFailed), (DispatchError::CannotLookup, CannotLookup), (DispatchError::BadOrigin, BadOrigin), @@ -120,7 +120,7 @@ mod tests { DispatchError::Other("Random"), (Other { dispatch_error_index: 0, error_index: 0, error: 0 }), ), - (DispatchError::Other("UnknownFunctionId"), UnknownFunctionId), + (DispatchError::Other("UnknownFunctionId"), UnknownCall), (DispatchError::Other("DecodingFailed"), DecodingFailed), ]; for (dispatch_error, expected) in test_cases { @@ -185,7 +185,7 @@ mod tests { Corruption, Unavailable, RootNotAllowed, - UnknownFunctionId, + UnknownCall, DecodingFailed, ]; // Compare an `Error`, which is converted from an encoded value, with the expected `Error`. From e683e160f4a753ecfcd596c823947ab02917c797 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Fri, 19 Jul 2024 10:24:21 +0200 Subject: [PATCH 027/161] refactor: add Error variants index + clippy allowance --- primitives/src/lib.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index ec6670ba..376b440d 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -41,6 +41,7 @@ pub mod v0 { #[derive(Encode, Decode, Debug, Eq, PartialEq)] #[cfg_attr(feature = "std", derive(TypeInfo))] #[repr(u8)] + #[allow(clippy::unnecessary_cast)] pub enum Error { /// An unknown error occurred. This variant captures any unexpected errors that the /// contract cannot specifically handle. It is useful for cases where there are breaking @@ -51,37 +52,37 @@ pub mod v0 { /// - `error_index`: The index within the `DispatchError` variant (e.g. a `TokenError`). /// - `error`: The specific error code or sub-index, providing additional context (e.g. /// `error` in `ModuleError`). - Other { dispatch_error_index: u8, error_index: u8, error: u8 }, + Other { dispatch_error_index: u8, error_index: u8, error: u8 } = 0, /// Failed to lookup some data. - CannotLookup, + CannotLookup = 1, /// A bad origin. - BadOrigin, + BadOrigin = 2, /// A custom error in a module. /// /// - `index`: The pallet index. /// - `error`: The error within the pallet. - Module { index: u8, error: u8 }, + Module { index: u8, error: u8 } = 3, /// At least one consumer is remaining so the account cannot be destroyed. - ConsumerRemaining, + ConsumerRemaining = 4, /// There are no providers so the account cannot be created. - NoProviders, + NoProviders = 5, /// There are too many consumers so the account cannot be created. - TooManyConsumers, + TooManyConsumers = 6, /// An error to do with tokens. - Token(TokenError), + Token(TokenError) = 7, /// An arithmetic error. - Arithmetic(ArithmeticError), + Arithmetic(ArithmeticError) = 8, /// The number of transactional layers has been reached, or we are not in a transactional /// layer. - Transactional(TransactionalError), + Transactional(TransactionalError) = 9, /// Resources exhausted, e.g. attempt to read/write data which is too large to manipulate. - Exhausted, + Exhausted = 10, /// The state is corrupt; this is generally not going to fix itself. - Corruption, + Corruption = 11, /// Some resource (e.g. a preimage) is unavailable right now. This might fix itself later. - Unavailable, + Unavailable = 12, /// Root origin is not allowed. - RootNotAllowed, + RootNotAllowed = 13, /// Unknown call. UnknownCall = 254, /// Decoding failed. From 28d971b11666aa16f3d4fd040f85473ce0d6a401 Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:00:18 +0200 Subject: [PATCH 028/161] feat: api fungibles pallet (#113) Co-authored-by: Frank Bell --- Cargo.lock | 231 ++--- Cargo.toml | 2 + node/src/command.rs | 13 +- pallets/api/Cargo.toml | 55 ++ pallets/api/src/fungibles/benchmarking.rs | 106 +++ pallets/api/src/fungibles/mod.rs | 240 +++++ pallets/api/src/fungibles/tests.rs | 147 +++ pallets/api/src/fungibles/weights.rs | 94 ++ pallets/api/src/lib.rs | 5 + pallets/api/src/mock.rs | 123 +++ pop-api/Cargo.toml | 10 +- pop-api/examples/fungibles/Cargo.toml | 2 +- pop-api/integration-tests/Cargo.toml | 2 +- .../contracts/fungibles/Cargo.toml | 21 + .../contracts/fungibles/lib.rs | 185 ++++ .../integration-tests/src/local_fungibles.rs | 135 +-- pop-api/src/lib.rs | 14 +- pop-api/src/primitives.rs | 3 - pop-api/src/v0/assets/fungibles.rs | 284 +++--- pop-api/src/v0/assets/mod.rs | 235 +---- pop-api/src/v0/balances.rs | 88 -- pop-api/src/v0/cross_chain/coretime.rs | 11 - pop-api/src/v0/cross_chain/mod.rs | 107 --- pop-api/src/v0/mod.rs | 6 - pop-api/src/v0/nfts.rs | 883 ------------------ primitives/Cargo.toml | 14 +- primitives/README.md | 1 + primitives/src/cross_chain.rs | 19 - primitives/src/lib.rs | 28 +- primitives/src/storage_keys.rs | 56 -- runtime/devnet/Cargo.toml | 8 +- runtime/devnet/src/config/api.rs | 34 + runtime/devnet/src/config/assets.rs | 9 +- runtime/devnet/src/config/mod.rs | 1 + runtime/devnet/src/extensions/mod.rs | 824 ++-------------- .../src/extensions/{v0/error.rs => v0.rs} | 0 runtime/devnet/src/extensions/v0/assets.rs | 76 -- runtime/devnet/src/extensions/v0/mod.rs | 2 - runtime/devnet/src/lib.rs | 101 +- runtime/testnet/Cargo.toml | 5 +- runtime/testnet/src/extensions.rs | 558 +---------- runtime/testnet/src/lib.rs | 41 +- scripts/pallet-weights-template.hbs | 122 +++ 43 files changed, 1610 insertions(+), 3291 deletions(-) create mode 100644 pallets/api/Cargo.toml create mode 100644 pallets/api/src/fungibles/benchmarking.rs create mode 100644 pallets/api/src/fungibles/mod.rs create mode 100644 pallets/api/src/fungibles/tests.rs create mode 100644 pallets/api/src/fungibles/weights.rs create mode 100644 pallets/api/src/lib.rs create mode 100644 pallets/api/src/mock.rs create mode 100755 pop-api/integration-tests/contracts/fungibles/Cargo.toml create mode 100755 pop-api/integration-tests/contracts/fungibles/lib.rs delete mode 100644 pop-api/src/v0/balances.rs delete mode 100644 pop-api/src/v0/cross_chain/coretime.rs delete mode 100644 pop-api/src/v0/cross_chain/mod.rs delete mode 100644 pop-api/src/v0/nfts.rs create mode 100644 primitives/README.md delete mode 100644 primitives/src/cross_chain.rs delete mode 100644 primitives/src/storage_keys.rs create mode 100644 runtime/devnet/src/config/api.rs rename runtime/devnet/src/extensions/{v0/error.rs => v0.rs} (100%) delete mode 100644 runtime/devnet/src/extensions/v0/assets.rs delete mode 100644 runtime/devnet/src/extensions/v0/mod.rs create mode 100644 scripts/pallet-weights-template.hbs diff --git a/Cargo.lock b/Cargo.lock index 1983b157..d3ca53e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -215,7 +215,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -361,9 +361,9 @@ checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" @@ -740,9 +740,9 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" +checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" dependencies = [ "async-io 2.3.3", "async-lock 3.4.0", @@ -770,7 +770,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -907,7 +907,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1051,18 +1051,6 @@ dependencies = [ "piper", ] -[[package]] -name = "bounded-collections" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca548b6163b872067dc5eb82fd130c56881435e30367d2073594a3d9744120dd" -dependencies = [ - "log", - "parity-scale-codec", - "scale-info", - "serde", -] - [[package]] name = "bounded-collections" version = "0.2.0" @@ -1457,9 +1445,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" dependencies = [ "jobserver", "libc", @@ -1628,7 +1616,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1676,7 +1664,7 @@ dependencies = [ "nom", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2342,7 +2330,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2383,7 +2371,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa22d6e479a4d3a2790bab291269ba0917a1ac384255a54a2ebc3f7c37e505e" dependencies = [ - "bounded-collections 0.2.0", + "bounded-collections", "bp-xcm-bridge-hub-router", "cumulus-primitives-core", "frame-benchmarking", @@ -2662,7 +2650,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2702,7 +2690,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2719,7 +2707,7 @@ checksum = "4b2c1c1776b986979be68bb2285da855f8d8a35851a769fca8740df7c3d07877" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2767,7 +2755,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2789,7 +2777,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2881,7 +2869,7 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2894,7 +2882,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2983,7 +2971,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -3007,9 +2995,9 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.71", + "syn 2.0.72", "termcolor", - "toml 0.8.14", + "toml 0.8.15", "walkdir", ] @@ -3219,7 +3207,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -3230,7 +3218,7 @@ checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -3413,7 +3401,7 @@ dependencies = [ "prettyplease 0.2.20", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -3688,7 +3676,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -3849,7 +3837,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -3862,7 +3850,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -3873,7 +3861,7 @@ checksum = "68672b9ec6fe72d259d3879dc212c5e42e977588cdac830c76f54d9f492aeb58" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -4066,7 +4054,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -5197,9 +5185,9 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -5847,7 +5835,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -5861,7 +5849,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -5872,7 +5860,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -5883,7 +5871,7 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -6245,7 +6233,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "synstructure 0.13.1", ] @@ -6293,7 +6281,7 @@ checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -6616,6 +6604,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "pallet-api" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-assets", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-asset-conversion" version = "11.0.0" @@ -7087,7 +7092,7 @@ checksum = "3163c6bc21b55a0ccb74c546ba784d9c9e69beb9240c059d28a3052f4cbce509" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -7755,7 +7760,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -7993,7 +7998,7 @@ version = "8.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba9138b04168b07b1aff4a2079f5514753c31dddba40e5fb471b9cda7da27ad6" dependencies = [ - "bounded-collections 0.2.0", + "bounded-collections", "frame-benchmarking", "frame-support", "frame-system", @@ -8345,7 +8350,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -8386,7 +8391,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -9203,7 +9208,7 @@ version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248ab090959a92e61493277e33b7e85104280a4beb4cb0815137d3c8c50a07f4" dependencies = [ - "bounded-collections 0.2.0", + "bounded-collections", "derive_more", "parity-scale-codec", "polkadot-core-primitives", @@ -9560,7 +9565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6380dbe1fb03ecc74ad55d841cfc75480222d153ba69ddcb00977866cbdabdb8" dependencies = [ "polkavm-derive-impl", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -9572,7 +9577,7 @@ dependencies = [ "polkavm-common", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -9697,7 +9702,6 @@ dependencies = [ name = "pop-primitives" version = "0.0.0" dependencies = [ - "bounded-collections 0.1.9", "parity-scale-codec", "scale-info", ] @@ -9727,7 +9731,6 @@ dependencies = [ "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-utility", - "enumflags2", "env_logger 0.11.3", "frame-benchmarking", "frame-executive", @@ -9739,6 +9742,7 @@ dependencies = [ "hex", "hex-literal", "log", + "pallet-api", "pallet-assets", "pallet-aura", "pallet-authorship", @@ -9801,7 +9805,6 @@ dependencies = [ "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-utility", - "enumflags2", "env_logger 0.11.3", "frame-benchmarking", "frame-executive", @@ -9864,9 +9867,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "powerfmt" @@ -9927,7 +9930,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -10021,7 +10024,7 @@ checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -10067,7 +10070,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -10135,7 +10138,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -10401,7 +10404,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -11062,7 +11065,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -12076,7 +12079,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -12242,7 +12245,7 @@ dependencies = [ "proc-macro2", "quote", "scale-info", - "syn 2.0.71", + "syn 2.0.72", "thiserror", ] @@ -12475,7 +12478,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -13094,7 +13097,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -13288,7 +13291,7 @@ dependencies = [ "bip39", "bitflags 1.3.2", "blake2 0.10.6", - "bounded-collections 0.2.0", + "bounded-collections", "bs58 0.5.1", "dyn-clonable", "ed25519-zebra 3.1.0", @@ -13360,7 +13363,7 @@ checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -13381,7 +13384,7 @@ checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -13630,7 +13633,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -13837,7 +13840,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -13860,7 +13863,7 @@ version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3be30aec904994451dcacf841a9168cfbbaf817de6b24b6a1c1418cbf1af2fe" dependencies = [ - "bounded-collections 0.2.0", + "bounded-collections", "parity-scale-codec", "scale-info", "serde", @@ -13969,7 +13972,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48fa328b87de3466bc38cc9a07244c42c647b7755b81115e1dfeb47cc13fc6e6" dependencies = [ "array-bytes 6.2.3", - "bounded-collections 0.2.0", + "bounded-collections", "derivative", "environmental", "impl-trait-for-tuples", @@ -14123,7 +14126,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -14224,7 +14227,7 @@ dependencies = [ "sp-maybe-compressed-blob", "strum 0.24.1", "tempfile", - "toml 0.8.14", + "toml 0.8.15", "walkdir", "wasm-opt", ] @@ -14299,7 +14302,7 @@ dependencies = [ "scale-info", "scale-typegen", "subxt-metadata", - "syn 2.0.71", + "syn 2.0.72", "thiserror", "tokio", ] @@ -14333,7 +14336,7 @@ dependencies = [ "quote", "scale-typegen", "subxt-codegen", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -14384,9 +14387,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.71" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -14413,7 +14416,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -14503,9 +14506,9 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] @@ -14527,18 +14530,18 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -14657,9 +14660,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" dependencies = [ "backtrace", "bytes", @@ -14682,7 +14685,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -14754,14 +14757,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.15", + "toml_edit 0.22.16", ] [[package]] @@ -14797,15 +14800,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.15" +version = "0.22.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" +checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" dependencies = [ "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.13", + "winnow 0.6.14", ] [[package]] @@ -14873,7 +14876,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -14918,7 +14921,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -15344,7 +15347,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -15378,7 +15381,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -15866,9 +15869,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2caba658a80831539b30698ae9862a72db6697dfdd7151e46920f5f2755c3ce2" +checksum = "901e8597c777fa042e9e245bd56c0dc4418c5db3f845b6ff94fbac732c6a0692" dependencies = [ "bytemuck", "safe_arch", @@ -16155,9 +16158,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f" dependencies = [ "memchr", ] @@ -16266,7 +16269,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -16315,7 +16318,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -16335,7 +16338,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6b3cde02..8b2d0a8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ members = [ "runtime/devnet", "runtime/testnet", "integration-tests", + "pallets/*", "primitives", "scripts/fund-dev-accounts", ] @@ -51,6 +52,7 @@ substrate-wasm-builder = "18.0.1" substrate-build-script-utils = "11.0.0" # Local +pallet-api = { path = "pallets/api", default-features = false } pop-runtime-devnet = { path = "runtime/devnet", default-features = true } # default-features=true required for `-p pop-node` builds pop-runtime-testnet = { path = "runtime/testnet", default-features = true } # default-features=true required for `-p pop-node` builds pop-runtime-common = { path = "runtime/common", default-features = false } diff --git a/node/src/command.rs b/node/src/command.rs index 98af5450..8ba956e1 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -64,18 +64,9 @@ impl RuntimeResolver for PathBuf { fn load_spec(id: &str) -> std::result::Result, String> { Ok(match id { - #[cfg(not(feature = "paseo"))] - "dev-rococo" => Box::new(chain_spec::development_config(Relay::RococoLocal)), - #[cfg(feature = "paseo")] - "dev-paseo" => Box::new(chain_spec::development_config(Relay::PaseoLocal)), - #[cfg(not(feature = "paseo"))] - "pop-rococo" => Box::new(chain_spec::testnet_config(Relay::Rococo)), - #[cfg(feature = "paseo")] - "pop-paseo" => Box::new(chain_spec::testnet_config(Relay::Paseo)), - #[cfg(feature = "paseo")] + "dev" | "dev-paseo" => Box::new(chain_spec::development_config(Relay::PaseoLocal)), + "test" | "pop-paseo" => Box::new(chain_spec::testnet_config(Relay::Paseo)), "" | "local" => Box::new(chain_spec::development_config(Relay::PaseoLocal)), - #[cfg(not(feature = "paseo"))] - "" | "local" => Box::new(chain_spec::development_config(Relay::RococoLocal)), path => { let path: PathBuf = path.into(); match path.runtime() { diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml new file mode 100644 index 00000000..a813a09c --- /dev/null +++ b/pallets/api/Cargo.toml @@ -0,0 +1,55 @@ +[package] +name = "pallet-api" +authors.workspace = true +description = "Api pallet, enabling smart(er) contracts with the power of Polkadot" +edition.workspace = true +license.workspace = true +version = "0.1.0" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec.workspace = true +scale-info.workspace = true + +# Substrate +frame-benchmarking.workspace = true +frame-support.workspace = true +frame-system.workspace = true +pallet-assets.workspace = true +sp-runtime.workspace = true +sp-std.workspace = true + +[dev-dependencies] +pallet-balances.workspace = true +sp-core.workspace = true +sp-io.workspace = true + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +std = [ + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "pallet-assets/std", + "pallet-balances/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/pallets/api/src/fungibles/benchmarking.rs b/pallets/api/src/fungibles/benchmarking.rs new file mode 100644 index 00000000..d3d65b97 --- /dev/null +++ b/pallets/api/src/fungibles/benchmarking.rs @@ -0,0 +1,106 @@ +//! Benchmarking setup for pallet-api::fungibles + +use super::{AccountIdOf, AssetIdOf, AssetsInstanceOf, AssetsOf, BalanceOf, Call, Config, Pallet}; +use frame_benchmarking::{account, v2::*}; +use frame_support::{ + assert_ok, + traits::{ + fungibles::{ + approvals::{Inspect as ApprovalInspect, Mutate}, + Create, Inspect, + }, + Currency, + }, +}; +use frame_system::RawOrigin; +use sp_runtime::traits::Zero; + +const SEED: u32 = 1; + +// See if `generic_event` has been emitted. +fn assert_has_event( + generic_event: >>::RuntimeEvent, +) { + frame_system::Pallet::::assert_has_event(generic_event.into()); +} + +#[benchmarks( + where + > as Inspect<::AccountId>>::AssetId: Zero, +)] +mod benchmarks { + use super::*; + + // Parameter: + // - 'a': whether `approve_transfer` is required. + // - 'c': whether `cancel_approval` is required. + #[benchmark] + fn approve(a: Linear<0, 1>, c: Linear<0, 1>) -> Result<(), BenchmarkError> { + let asset_id = AssetIdOf::::zero(); + let min_balance = >::from(1u32); + let owner: AccountIdOf = account("Alice", 0, SEED); + let spender: AccountIdOf = account("Bob", 0, SEED); + let current_allowance = >::from(u32::MAX / 2); + T::Currency::make_free_balance_be(&owner, u32::MAX.into()); + // Set the `current_allowance`. + assert_ok!( as Create>>::create( + asset_id.clone(), + owner.clone(), + true, + min_balance + )); + assert_ok!( as Mutate>>::approve( + asset_id.clone(), + &owner, + &spender, + current_allowance, + )); + let approval_value = match (a, c) { + // Equal to the current allowance. + (0, 0) => current_allowance, + // Greater than the current allowance. + (1, 0) => >::from(u32::MAX), + // Zero. + (0, 1) => >::from(0u32), + // Smaller than the current allowance. + (1, 1) => >::from(u32::MAX / 4), + _ => unreachable!("values can only be 0 or 1"), + }; + + #[extrinsic_call] + _(RawOrigin::Signed(owner.clone()), asset_id.clone(), spender.clone(), approval_value); + + assert_eq!(AssetsOf::::allowance(asset_id.clone(), &owner, &spender), approval_value); + if c == 1 { + assert_has_event::( + pallet_assets::Event::ApprovalCancelled { + asset_id: asset_id.clone(), + owner: owner.clone(), + delegate: spender.clone(), + } + .into(), + ); + } + if a == 1 { + let amount = match c { + // When the allowance was cancelled and then approved with the new value. + 1 => approval_value, + // When the allowance was increased. + 0 => approval_value - current_allowance, + _ => unreachable!("`c` can only be 0 or 1"), + }; + assert_has_event::( + pallet_assets::Event::ApprovedTransfer { + asset_id, + source: owner, + delegate: spender, + amount, + } + .into(), + ); + } + Ok(()) + } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs new file mode 100644 index 00000000..cd34664a --- /dev/null +++ b/pallets/api/src/fungibles/mod.rs @@ -0,0 +1,240 @@ +/// The fungibles pallet serves as a wrapper around the pallet_assets, offering a streamlined +/// interface for interacting with fungible assets. The goal is to provide a simplified, consistent +/// API that adheres to standards in the smart contract space. + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +#[cfg(test)] +mod tests; +pub mod weights; + +use frame_support::traits::fungibles::{metadata::Inspect as MetadataInspect, Inspect}; +pub use pallet::*; +use pallet_assets::WeightInfo as AssetsWeightInfoTrait; +use weights::WeightInfo; + +type AccountIdOf = ::AccountId; +type AssetIdOf = > as Inspect< + ::AccountId, +>>::AssetId; +type AssetIdParameterOf = >>::AssetIdParameter; +type AssetsOf = pallet_assets::Pallet>; +type AssetsInstanceOf = ::AssetsInstance; +type AssetsWeightInfoOf = >>::WeightInfo; +type BalanceOf = > as Inspect< + ::AccountId, +>>::Balance; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::{ + dispatch::{DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo}, + pallet_prelude::*, + traits::fungibles::approvals::Inspect as ApprovalInspect, + }; + use frame_system::pallet_prelude::*; + use sp_runtime::{ + traits::{StaticLookup, Zero}, + Saturating, + }; + use sp_std::vec::Vec; + + /// State reads for the fungibles api with required input. + #[derive(Encode, Decode, Debug, MaxEncodedLen)] + #[repr(u8)] + #[allow(clippy::unnecessary_cast)] + pub enum Read { + /// Total token supply for a given asset ID. + #[codec(index = 0)] + TotalSupply(AssetIdOf), + /// Account balance for a given asset ID. + #[codec(index = 1)] + BalanceOf { + /// The asset ID. + id: AssetIdOf, + /// The account ID of the owner. + owner: AccountIdOf, + }, + /// Allowance for a spender approved by an owner, for a given asset ID. + #[codec(index = 2)] + Allowance { + /// The asset ID. + id: AssetIdOf, + /// The account ID of the owner. + owner: AccountIdOf, + /// The account ID of the spender. + spender: AccountIdOf, + }, + /// Token name for a given asset ID. + #[codec(index = 8)] + TokenName(AssetIdOf), + /// Token symbol for a given asset ID. + #[codec(index = 9)] + TokenSymbol(AssetIdOf), + /// Token decimals for a given asset ID. + #[codec(index = 10)] + TokenDecimals(AssetIdOf), + } + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config + pallet_assets::Config { + /// The instance of pallet assets it is tightly coupled to. + type AssetsInstance; + /// Weight information for dispatchables in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call] + impl Pallet { + /// Transfers `value` amount of tokens from the caller's account to account `to`, with additional + /// `data` in unspecified format. + /// + /// # Parameters + /// * `id` - The ID of the asset. + /// * `to` - The recipient account. + /// * `value` - The number of tokens to transfer. + #[pallet::call_index(3)] + #[pallet::weight(AssetsWeightInfoOf::::transfer_keep_alive())] + pub fn transfer( + origin: OriginFor, + id: AssetIdOf, + target: AccountIdOf, + amount: BalanceOf, + ) -> DispatchResult { + let target = T::Lookup::unlookup(target); + AssetsOf::::transfer_keep_alive(origin, id.into(), target, amount) + } + + /// Approves an account to spend a specified number of tokens on behalf of the caller. + /// + /// # Parameters + /// * `id` - The ID of the asset. + /// * `spender` - The account that is allowed to spend the tokens. + /// * `value` - The number of tokens to approve. + #[pallet::call_index(5)] + #[pallet::weight(::WeightInfo::approve(1, 1))] + pub fn approve( + origin: OriginFor, + id: AssetIdOf, + spender: AccountIdOf, + value: BalanceOf, + ) -> DispatchResultWithPostInfo { + let weight = |approve: u32, cancel: u32| -> Weight { + ::WeightInfo::approve(cancel, approve) + }; + let who = ensure_signed(origin.clone()).map_err(|e| e.with_weight(weight(0, 0)))?; + let current_allowance = AssetsOf::::allowance(id.clone(), &who, &spender); + let spender = T::Lookup::unlookup(spender); + let id: AssetIdParameterOf = id.into(); + + // If the new value is equal to the current allowance, do nothing. + let return_weight = if value == current_allowance { + weight(0, 0) + } + // If the new value is greater than the current allowance, approve the difference + // because `approve_transfer` works additively (see `pallet-assets`). + else if value > current_allowance { + AssetsOf::::approve_transfer( + origin, + id, + spender, + value.saturating_sub(current_allowance), + ) + .map_err(|e| e.with_weight(weight(1, 0)))?; + weight(1, 0) + } else { + // If the new value is less than the current allowance, cancel the approval and set the new value + AssetsOf::::cancel_approval(origin.clone(), id.clone(), spender.clone()) + .map_err(|e| e.with_weight(weight(0, 1)))?; + if value.is_zero() { + return Ok(Some(weight(0, 1)).into()); + } + AssetsOf::::approve_transfer(origin, id, spender, value)?; + weight(1, 1) + }; + Ok(Some(return_weight).into()) + } + + /// Increases the allowance of a spender. + /// + /// # Parameters + /// * `id` - The ID of the asset. + /// * `spender` - The account that is allowed to spend the tokens. + /// * `value` - The number of tokens to increase the allowance by. + #[pallet::call_index(6)] + #[pallet::weight(AssetsWeightInfoOf::::approve_transfer())] + pub fn increase_allowance( + origin: OriginFor, + id: AssetIdOf, + spender: AccountIdOf, + value: BalanceOf, + ) -> DispatchResult { + let spender = T::Lookup::unlookup(spender); + AssetsOf::::approve_transfer(origin, id.into(), spender, value) + } + } + + impl Pallet { + /// Returns the total token supply for a given asset ID. + /// + /// # Parameters + /// * `id` - The ID of the asset. + pub fn total_supply(id: AssetIdOf) -> BalanceOf { + AssetsOf::::total_supply(id) + } + + /// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if + /// the account is non-existent. + /// + /// # Parameters + /// * `id` - The ID of the asset. + /// * `owner` - The account whose balance is being queried. + pub fn balance_of(id: AssetIdOf, owner: &AccountIdOf) -> BalanceOf { + AssetsOf::::balance(id, owner) + } + + /// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given + /// asset ID. Returns `0` if no allowance has been set. + /// + /// # Parameters + /// * `id` - The ID of the asset. + /// * `owner` - The account that owns the tokens. + /// * `spender` - The account that is allowed to spend the tokens. + pub fn allowance( + id: AssetIdOf, + owner: &AccountIdOf, + spender: &AccountIdOf, + ) -> BalanceOf { + AssetsOf::::allowance(id, owner, spender) + } + + /// Returns the token name for a given asset ID. + /// + /// # Parameters + /// * `id` - The ID of the asset. + pub fn token_name(id: AssetIdOf) -> Vec { + as MetadataInspect>>::name(id) + } + + /// Returns the token symbol for a given asset ID. + /// + /// # Parameters + /// * `id` - The ID of the asset. + pub fn token_symbol(id: AssetIdOf) -> Vec { + as MetadataInspect>>::symbol(id) + } + + /// Returns the token decimals for a given asset ID. + /// + /// # Parameters + /// * `id` - The ID of the asset. + pub fn token_decimals(id: AssetIdOf) -> u8 { + as MetadataInspect>>::decimals(id) + } + } +} diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs new file mode 100644 index 00000000..dbfa0b34 --- /dev/null +++ b/pallets/api/src/fungibles/tests.rs @@ -0,0 +1,147 @@ +use crate::mock::*; +use frame_support::{ + assert_ok, + traits::fungibles::{approvals::Inspect, metadata::Inspect as MetadataInspect}, +}; + +const ASSET: u32 = 42; + +#[test] +fn transfer_works() { + new_test_ext().execute_with(|| { + let amount: Balance = 100 * UNIT; + create_asset_and_mint_to(ALICE, ASSET, ALICE, amount); + let balance_before_transfer = Assets::balance(ASSET, &BOB); + assert_ok!(Fungibles::transfer(signed(ALICE), ASSET, BOB, amount / 2)); + let balance_after_transfer = Assets::balance(ASSET, &BOB); + assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2); + }); +} + +// Non-additive, sets new value. +#[test] +fn approve_works() { + new_test_ext().execute_with(|| { + let amount: Balance = 100 * UNIT; + create_asset_and_mint_to(ALICE, ASSET, ALICE, amount); + assert_eq!(0, Assets::allowance(ASSET, &ALICE, &BOB)); + assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, amount)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); + // Approves an amount to spend that is lower than the current allowance. + assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, amount / 2)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount / 2); + // Approves an amount to spend that is higher than the current allowance. + assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, amount * 2)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount * 2); + // Approves an amount to spend that is equal to the current allowance. + assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, amount * 2)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount * 2); + // Sets allowance to zero. + assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, 0)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), 0); + }); +} + +#[test] +fn increase_allowance_works() { + new_test_ext().execute_with(|| { + let amount: Balance = 100 * UNIT; + create_asset_and_mint_to(ALICE, ASSET, ALICE, amount); + assert_eq!(0, Assets::allowance(ASSET, &ALICE, &BOB)); + assert_ok!(Fungibles::increase_allowance(signed(ALICE), ASSET, BOB, amount)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); + // Additive. + assert_ok!(Fungibles::increase_allowance(signed(ALICE), ASSET, BOB, amount)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount * 2); + }); +} + +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + create_asset_and_mint_to(ALICE, ASSET, ALICE, 100); + assert_eq!(Assets::total_supply(ASSET), Fungibles::total_supply(ASSET)); + }); +} + +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + create_asset_and_mint_to(ALICE, ASSET, ALICE, 100); + assert_eq!(Assets::balance(ASSET, ALICE), Fungibles::balance_of(ASSET, &ALICE)); + }); +} + +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + create_asset_mint_and_approve(ALICE, ASSET, BOB, 100, ALICE, 50); + assert_eq!( + Assets::allowance(ASSET, &ALICE, &BOB), + Fungibles::allowance(ASSET, &ALICE, &BOB) + ); + }); +} + +#[test] +fn token_metadata_works() { + new_test_ext().execute_with(|| { + let name: Vec = vec![11, 12, 13]; + let symbol: Vec = vec![21, 22, 23]; + let decimals: u8 = 69; + create_asset_and_set_metadata(ALICE, ASSET, name.clone(), symbol.clone(), decimals); + assert_eq!(Assets::name(ASSET), Fungibles::token_name(ASSET)); + assert_eq!(Assets::symbol(ASSET), Fungibles::token_symbol(ASSET)); + assert_eq!(Assets::decimals(ASSET), Fungibles::token_decimals(ASSET)); + }); +} + +fn signed(account: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account) +} + +fn create_asset(owner: AccountId, asset_id: AssetId, min_balance: Balance) { + assert_ok!(Assets::create(signed(owner), asset_id, owner, min_balance)); +} + +fn mint_asset(owner: AccountId, asset_id: AssetId, to: AccountId, value: Balance) { + assert_ok!(Assets::mint(signed(owner), asset_id, to, value)); +} + +fn create_asset_and_mint_to(owner: AccountId, asset_id: AssetId, to: AccountId, value: Balance) { + create_asset(owner, asset_id, 1); + mint_asset(owner, asset_id, to, value) +} + +fn create_asset_mint_and_approve( + owner: AccountId, + asset_id: AssetId, + to: AccountId, + mint: Balance, + spender: AccountId, + approve: Balance, +) { + create_asset_and_mint_to(owner, asset_id, to, mint); + assert_ok!(Assets::approve_transfer(signed(to), asset_id, spender, approve,)); +} + +fn create_asset_and_set_metadata( + owner: AccountId, + asset_id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, +) { + assert_ok!(Assets::create(signed(owner), asset_id, owner, 100)); + set_metadata_asset(owner, asset_id, name, symbol, decimals); +} + +fn set_metadata_asset( + owner: AccountId, + asset_id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, +) { + assert_ok!(Assets::set_metadata(signed(owner), asset_id, name, symbol, decimals)); +} diff --git a/pallets/api/src/fungibles/weights.rs b/pallets/api/src/fungibles/weights.rs new file mode 100644 index 00000000..a6c31654 --- /dev/null +++ b/pallets/api/src/fungibles/weights.rs @@ -0,0 +1,94 @@ + +//! Autogenerated weights for `pallet_api::fungibles` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 33.0.0 +//! DATE: 2024-07-25, STEPS: `20`, REPEAT: `5`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `R0GUE`, CPU: `` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/release/pop-node +// benchmark +// pallet +// --chain=dev +// --wasm-execution=compiled +// --pallet=pallet_api::fungibles +// --steps=20 +// --repeat=5 +// --json +// --template +// ./scripts/pallet-weights-template.hbs +// --output=./pallets/api/src/fungibles/weights.rs +// --extrinsic= + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_api::fungibles`. +pub trait WeightInfo { + fn approve(a: u32, c: u32, ) -> Weight; +} + +/// Weights for `pallet_api::fungibles` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `Assets::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `a` is `[0, 1]`. + /// The range of component `c` is `[0, 1]`. + fn approve(a: u32, c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `413 + c * (102 ±0)` + // Estimated: `3675 + c * (1797 ±0)` + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(1_207_482, 3675) + // Standard Error: 948_955 + .saturating_add(Weight::from_parts(34_649_659, 0).saturating_mul(a.into())) + // Standard Error: 948_955 + .saturating_add(Weight::from_parts(56_976_190, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) + .saturating_add(Weight::from_parts(0, 1797).saturating_mul(c.into())) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `Assets::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `a` is `[0, 1]`. + /// The range of component `c` is `[0, 1]`. + fn approve(a: u32, c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `413 + c * (102 ±0)` + // Estimated: `3675 + c * (1797 ±0)` + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(1_207_482, 3675) + // Standard Error: 948_955 + .saturating_add(Weight::from_parts(34_649_659, 0).saturating_mul(a.into())) + // Standard Error: 948_955 + .saturating_add(Weight::from_parts(56_976_190, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(c.into()))) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(c.into()))) + .saturating_add(Weight::from_parts(0, 1797).saturating_mul(c.into())) + } +} + diff --git a/pallets/api/src/lib.rs b/pallets/api/src/lib.rs new file mode 100644 index 00000000..5cba0551 --- /dev/null +++ b/pallets/api/src/lib.rs @@ -0,0 +1,5 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod fungibles; +#[cfg(test)] +mod mock; diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs new file mode 100644 index 00000000..f5d155ef --- /dev/null +++ b/pallets/api/src/mock.rs @@ -0,0 +1,123 @@ +use frame_support::{ + derive_impl, parameter_types, + traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, Everything}, +}; +use frame_system::{EnsureRoot, EnsureSigned}; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; + +type Block = frame_system::mocking::MockBlock; +pub(crate) type AccountId = u64; +pub(crate) type AssetId = u32; +pub(crate) type Balance = u128; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + Assets: pallet_assets::, + Balances: pallet_balances, + Fungibles: crate::fungibles, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +impl pallet_balances::Config for Test { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU128<1>; + type AccountStore = System; + type FreezeIdentifier = (); + type MaxFreezes = ConstU32<0>; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeFreezeReason = RuntimeFreezeReason; +} + +type AssetsInstance = pallet_assets::Instance1; +impl pallet_assets::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type RemoveItemsLimit = ConstU32<5>; + type AssetId = AssetId; + type AssetIdParameter = u32; + type Currency = Balances; + type CreateOrigin = AsEnsureOriginWithArg>; + type ForceOrigin = EnsureRoot; + type AssetDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; + type MetadataDepositBase = ConstU128<1>; + type MetadataDepositPerByte = ConstU128<1>; + type ApprovalDeposit = ConstU128<1>; + type StringLimit = ConstU32<50>; + type Freezer = (); + type Extra = (); + type CallbackHandle = (); + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} +impl crate::fungibles::Config for Test { + type AssetsInstance = AssetsInstance; + type WeightInfo = (); +} + +pub(crate) const ALICE: AccountId = 1; +pub(crate) const BOB: AccountId = 2; +pub(crate) const INIT_AMOUNT: Balance = 100_000_000 * UNIT; +pub(crate) const UNIT: Balance = 10_000_000_000; + +pub(crate) fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { + balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT)], + } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index dc48ea8a..9946abf7 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -1,12 +1,11 @@ [package] name = "pop-api" -description = "Easily access the power of Polkadot via the Pop Network" +description = "Enabling smart(er) contracts with the power of Polkadot" license = "GPL-3.0-only" version = "0.0.0" edition = "2021" [dependencies] -enumflags2 = { version = "0.7.7" } ink = { version = "5.0.0", default-features = false } sp-io = { version = "31.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } @@ -20,12 +19,9 @@ crate-type = ["rlib"] [features] default = ["std"] std = [ - "enumflags2/std", "ink/std", "pop-primitives/std", "sp-io/std", ] -assets = ["pop-primitives/assets"] -balances = [] -nfts = ["pop-primitives/nfts"] -cross-chain = ["pop-primitives/cross-chain"] +assets = [] +fungibles = ["assets"] diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 565b0554..19d9ce12 100755 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false, features = ["assets"] } +pop-api = { path = "../../../pop-api", default-features = false, features = ["fungibles"] } [lib] path = "lib.rs" diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml index 94c0ba83..cc56630a 100644 --- a/pop-api/integration-tests/Cargo.toml +++ b/pop-api/integration-tests/Cargo.toml @@ -11,7 +11,7 @@ frame-system = { version = "29.0.0", default-features = false } pallet-balances = { version = "29.0.2", default-features = false } pallet-assets = { version = "30.0.0", default-features = false } pallet-contracts = { version = "28.0.0", default-features = false } -pop-primitives = { path = "../../primitives", default-features = false, features = ["assets"] } +pop-primitives = { path = "../../primitives", default-features = false } pop-runtime-devnet = { path = "../../runtime/devnet", default-features = false } sp-io = { version = "31.0.0", default-features = false } sp-runtime = { version = "32.0.0", default-features = false } diff --git a/pop-api/integration-tests/contracts/fungibles/Cargo.toml b/pop-api/integration-tests/contracts/fungibles/Cargo.toml new file mode 100755 index 00000000..7c322004 --- /dev/null +++ b/pop-api/integration-tests/contracts/fungibles/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "fungibles" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { version = "5.0.0", default-features = false } +pop-api = { path = "../../../../pop-api", default-features = false, features = ["fungibles"] } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "pop-api/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/pop-api/integration-tests/contracts/fungibles/lib.rs b/pop-api/integration-tests/contracts/fungibles/lib.rs new file mode 100755 index 00000000..1b42fec4 --- /dev/null +++ b/pop-api/integration-tests/contracts/fungibles/lib.rs @@ -0,0 +1,185 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +/// Local Fungibles: +/// 1. PSP-22 Interface +/// 2. PSP-22 Metadata Interface +/// 3. Asset Management +/// +use ink::prelude::vec::Vec; +use pop_api::{ + assets::fungibles::{self as api}, + primitives::AssetId, + StatusCode, +}; + +pub type Result = core::result::Result; + +#[ink::contract] +mod fungibles { + use super::*; + + #[ink(storage)] + #[derive(Default)] + pub struct Fungibles; + + impl Fungibles { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("PopApiFungiblesExample::new"); + Default::default() + } + + /// 1. PSP-22 Interface: + /// - total_supply + /// - balance_of + /// - allowance + /// - transfer + /// - transfer_from + /// - approve + /// - increase_allowance + /// - decrease_allowance + + #[ink(message)] + pub fn total_supply(&self, id: AssetId) -> Result { + api::total_supply(id) + } + + #[ink(message)] + pub fn balance_of(&self, id: AssetId, owner: AccountId) -> Result { + api::balance_of(id, owner) + } + + #[ink(message)] + pub fn allowance( + &self, + id: AssetId, + owner: AccountId, + spender: AccountId, + ) -> Result { + api::allowance(id, owner, spender) + } + + #[ink(message)] + pub fn transfer(&self, id: AssetId, to: AccountId, value: Balance) -> Result<()> { + api::transfer(id, to, value) + } + + #[ink(message)] + pub fn transfer_from( + &self, + id: AssetId, + from: AccountId, + to: AccountId, + value: Balance, + // In the PSP-22 standard a `[u8]`, but the size needs to be known at compile time. + _data: Vec, + ) -> Result<()> { + api::transfer_from(id, from, to, value) + } + + #[ink(message)] + pub fn approve(&self, id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + api::approve(id, spender, value) + } + + #[ink(message)] + pub fn increase_allowance( + &self, + id: AssetId, + spender: AccountId, + value: Balance, + ) -> Result<()> { + api::increase_allowance(id, spender, value) + } + + #[ink(message)] + pub fn decrease_allowance( + &self, + id: AssetId, + spender: AccountId, + value: Balance, + ) -> Result<()> { + api::decrease_allowance(id, spender, value) + } + + /// 2. PSP-22 Metadata Interface: + /// - token_name + /// - token_symbol + /// - token_decimals + + #[ink(message)] + pub fn token_name(&self, id: AssetId) -> Result> { + api::token_name(id) + } + + #[ink(message)] + pub fn token_symbol(&self, id: AssetId) -> Result> { + api::token_symbol(id) + } + + #[ink(message)] + pub fn token_decimals(&self, id: AssetId) -> Result { + api::token_decimals(id) + } + + // 3. Asset Management: + // - create + // - start_destroy + // - destroy_accounts + // - destroy_approvals + // - finish_destroy + // - set_metadata + // - clear_metadata + + // #[ink(message)] + // pub fn create(&self, id: AssetId, admin: AccountId, min_balance: Balance) -> Result<()> { + // ink::env::debug_println!( + // "PopApiFungiblesExample::create: id: {:?} admin: {:?} min_balance: {:?}", + // id, + // admin, + // min_balance, + // ); + // let result = api::create(id, admin, min_balance); + // ink::env::debug_println!("Result: {:?}", result); + // result.map_err(|e| e.into()) + // result + // } + + // #[ink(message)] + // pub fn set_metadata( + // &self, + // id: AssetId, + // name: Vec, + // symbol: Vec, + // decimals: u8, + // ) -> Result<()> { + // ink::env::debug_println!( + // "PopApiFungiblesExample::set_metadata: id: {:?} name: {:?} symbol: {:?}, decimals: {:?}", + // id, + // name, + // symbol, + // decimals, + // ); + // let result = api::set_metadata(id, name, symbol, decimals); + // ink::env::debug_println!("Result: {:?}", result); + // // result.map_err(|e| e.into()) + // result + // } + // + // #[ink(message)] + // pub fn asset_exists(&self, id: AssetId) -> Result { + // // api::asset_exists(id).map_err(|e| e.into()) + // api::asset_exists(id) + // } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[ink::test] + fn default_works() { + PopApiFungiblesExample::new(); + } + } +} diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs index 8f0384c0..c62f0713 100644 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -6,6 +6,7 @@ use pop_primitives::error::{ }; const ASSET_ID: AssetId = 1; +const CONTRACT: &str = "contracts/fungibles/target/ink/fungibles.wasm"; fn decoded(result: ExecReturnValue) -> T { match ::decode(&mut &result.data[2..]) { @@ -79,19 +80,16 @@ fn transfer( result } -fn transfer_from( +fn approve( addr: AccountId32, asset_id: AssetId, - from: Option, - to: Option, + spender: AccountId32, value: Balance, - data: &[u8], ) -> ExecReturnValue { - let function = function_selector("transfer_from"); - let params = - [function, asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()] - .concat(); - bare_call(addr, params, 0).expect("should work") + let function = function_selector("approve"); + let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + result } fn increase_allowance( @@ -263,15 +261,10 @@ fn token_decimals_asset(asset_id: AssetId) -> u8 { /// - decrease_allowance #[test] -#[ignore] fn total_supply_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate( - "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", - INIT_VALUE, - vec![], - ); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); // No tokens in circulation. assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr.clone(), ASSET_ID)); @@ -285,12 +278,10 @@ fn total_supply_works() { } #[test] -#[ignore] fn balance_of_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); // No tokens in circulation. assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr.clone(), ASSET_ID, BOB)); @@ -304,12 +295,10 @@ fn balance_of_works() { } #[test] -#[ignore] fn allowance_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); // No tokens in circulation. assert_eq!( @@ -329,12 +318,10 @@ fn allowance_works() { } #[test] -#[ignore] fn transfer_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); let amount: Balance = 100 * UNIT; // Asset does not exist. @@ -362,11 +349,11 @@ fn transfer_works() { Module { index: 52, error: 0 }, ); // Successful transfer. - let bob_balance_before_mint = Assets::balance(asset, &BOB); + let balance_before_transfer = Assets::balance(asset, &BOB); let result = transfer(addr.clone(), asset, BOB, amount / 2); assert!(!result.did_revert(), "Contract reverted!"); - let bob_balance_after_mint = Assets::balance(asset, &BOB); - assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); + let balance_after_transfer = Assets::balance(asset, &BOB); + assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2); // Transfer asset to account that does not exist. assert_eq!( decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), @@ -382,82 +369,65 @@ fn transfer_works() { } #[test] -#[ignore] -fn transfer_from_works() { +fn approve_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); + let addr = instantiate(CONTRACT, 0, vec![]); let amount: Balance = 100 * UNIT; - // Asset does not exist. assert_eq!( - decoded::(transfer(addr.clone(), 1, BOB, amount,)), + decoded::(approve(addr.clone(), 0, BOB, amount)), Module { index: 52, error: 3 }, ); + let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); + assert_eq!(decoded::(approve(addr.clone(), asset, BOB, amount)), ConsumerRemaining); + + let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); // Create asset with Alice as owner and mint `amount` to contract address. let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(ALICE, asset); assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount,)), + decoded::(approve(addr.clone(), asset, BOB, amount)), Module { index: 52, error: 16 }, ); thaw_asset(ALICE, asset); - // Not enough balance. - assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), - Module { index: 52, error: 0 }, - ); - // Not enough balance due to ED. - assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 0 }, - ); - // Successful transfer. - let bob_balance_before_mint = Assets::balance(asset, &BOB); - let result = transfer(addr.clone(), asset, BOB, amount / 2); - assert!(!result.did_revert(), "Contract reverted!"); - let bob_balance_after_mint = Assets::balance(asset, &BOB); - assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount / 2); - // Transfer asset to account that does not exist. - assert_eq!( - decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), - Token(CannotCreate) - ); + // Successful approvals: + assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); + assert!(!approve(addr.clone(), asset, BOB, amount).did_revert(), "Contract reverted!"); + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount); + // Non-additive, sets new value. + assert!(!approve(addr.clone(), asset, BOB, amount / 2).did_revert(), "Contract reverted!"); + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount / 2); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(ALICE, asset); assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), + decoded::(approve(addr.clone(), asset, BOB, amount)), Module { index: 52, error: 16 }, ); }); } #[test] -#[ignore] fn increase_allowance_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![]); + let addr = instantiate(CONTRACT, 0, vec![]); let amount: Balance = 100 * UNIT; - let asset = 0; - create_asset_and_mint_to(ALICE, asset, addr.clone(), amount); + // Asset does not exist. assert_eq!( - decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - ConsumerRemaining + decoded::(increase_allowance(addr.clone(), 0, BOB, amount)), + Module { index: 52, error: 3 }, ); - - let addr = - instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); - // Asset does not exist. - let asset = 1; + let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); assert_eq!( decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 3 }, + ConsumerRemaining ); + + let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); // Create asset with Alice as owner and mint `amount` to contract address. - create_asset_and_mint_to(ALICE, asset, addr.clone(), amount); + let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(ALICE, asset); assert_eq!( @@ -465,7 +435,7 @@ fn increase_allowance_works() { Module { index: 52, error: 16 }, ); thaw_asset(ALICE, asset); - // Successful approval. + // Successful approvals: assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); assert!( !increase_allowance(addr.clone(), asset, BOB, amount).did_revert(), @@ -493,15 +463,10 @@ fn increase_allowance_works() { /// - token_decimals #[test] -#[ignore] fn token_metadata_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); - let addr = instantiate( - "../../pop-api/examples/fungibles/target/ink/fungibles.wasm", - INIT_VALUE, - vec![], - ); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); let name: Vec = vec![11, 12, 13]; let symbol: Vec = vec![21, 22, 23]; @@ -536,7 +501,7 @@ fn token_metadata_works() { // new_test_ext().execute_with(|| { // let _ = env_logger::try_init(); // let addr = -// instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); +// instantiate(CONTRACT, INIT_VALUE, vec![]); // // // No tokens in circulation. // assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr.clone(), ASSET_ID)); @@ -553,7 +518,7 @@ fn token_metadata_works() { // new_test_ext().execute_with(|| { // let _ = env_logger::try_init(); // let addr = -// instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); +// instantiate(CONTRACT, INIT_VALUE, vec![]); // let amount: Balance = 100 * UNIT; // // // Asset does not exist. @@ -581,11 +546,11 @@ fn token_metadata_works() { // ); // thaw_asset(addr.clone(), asset); // // Successful mint. -// let bob_balance_before_mint = Assets::balance(asset, &BOB); +// let balance_before_mint = Assets::balance(asset, &BOB); // let result = transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8]); // assert!(!result.did_revert(), "Contract reverted!"); -// let bob_balance_after_mint = Assets::balance(asset, &BOB); -// assert_eq!(bob_balance_after_mint, bob_balance_before_mint + amount); +// let balance_after_mint = Assets::balance(asset, &BOB); +// assert_eq!(balance_after_mint, balance_before_mint + amount); // // Can not mint more tokens than Balance::MAX. // assert_eq!( // decoded::(transfer_from( @@ -613,14 +578,14 @@ fn token_metadata_works() { // new_test_ext().execute_with(|| { // let _ = env_logger::try_init(); // // Instantiate a contract without balance (relay token). -// let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 0, vec![0]); +// let addr = instantiate(CONTRACT, 0, vec![0]); // // No balance to pay for fees. // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), // Module { index: 10, error: 2 }, // ); // // Instantiate a contract without balance (relay token). -// let addr = instantiate("../examples/fungibles/target/ink/fungibles.wasm", 100, vec![2]); +// let addr = instantiate(CONTRACT, 100, vec![2]); // // No balance to pay the deposit. // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), @@ -628,7 +593,7 @@ fn token_metadata_works() { // ); // // Instantiate a contract with balance. // let addr = -// instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![1]); +// instantiate(CONTRACT, INIT_VALUE, vec![1]); // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, BOB, 0)), // Module { index: 52, error: 7 }, @@ -652,7 +617,7 @@ fn token_metadata_works() { // new_test_ext().execute_with(|| { // let _ = env_logger::try_init(); // let addr = -// instantiate("../examples/fungibles/target/ink/fungibles.wasm", INIT_VALUE, vec![]); +// instantiate(CONTRACT, INIT_VALUE, vec![]); // // create_asset(addr.clone(), ASSET_ID, 1); // let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 86621c51..a984bb9e 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,17 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::env::chain_extension::FromStatusCode; - use constants::DECODING_FAILED; - +use ink::env::chain_extension::FromStatusCode; #[cfg(feature = "assets")] pub use v0::assets; -#[cfg(feature = "balances")] -pub use v0::balances; -#[cfg(feature = "cross-chain")] -pub use v0::cross_chain; -#[cfg(feature = "nfts")] -pub use v0::nfts; pub mod primitives; pub mod v0; @@ -22,7 +14,8 @@ pub type Result = core::result::Result; mod constants { // Errors: pub(crate) const DECODING_FAILED: u32 = 255; - pub(crate) const MODULE_ERROR: u8 = 3; + // TODO: will be used in the future when the remaining fungibles features will be implemented. + pub(crate) const _MODULE_ERROR: u8 = 3; // Function IDs: pub(crate) const DISPATCH: u8 = 0; @@ -31,6 +24,7 @@ mod constants { // Modules: pub(crate) const ASSETS: u8 = 52; pub(crate) const BALANCES: u8 = 10; + pub(crate) const FUNGIBLES: u8 = 150; } /// Represents a status code returned by the runtime. diff --git a/pop-api/src/primitives.rs b/pop-api/src/primitives.rs index 33285044..a3d596a5 100644 --- a/pop-api/src/primitives.rs +++ b/pop-api/src/primitives.rs @@ -1,8 +1,5 @@ use ink::env::{DefaultEnvironment, Environment}; - pub use pop_primitives::*; pub(crate) type AccountId = ::AccountId; pub(crate) type Balance = ::Balance; -#[cfg(any(feature = "nfts", feature = "cross-chain"))] -type BlockNumber = ::BlockNumber; diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 255e8502..42373cd7 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,26 +1,55 @@ -use ink::prelude::vec::Vec; +use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec, scale::Decode}; use crate::{ - assets, - constants::{ASSETS, BALANCES, MODULE_ERROR}, + constants::{ASSETS, BALANCES, DECODING_FAILED, DISPATCH, FUNGIBLES, READ_STATE}, primitives::{AccountId, AssetId, Balance}, + v0::V0, Result, StatusCode, }; +use constants::*; +pub use metadata::*; /// Local Fungibles: /// 1. PSP-22 Interface /// 2. PSP-22 Metadata Interface /// 3. Asset Management -/// 1. PSP-22 Interface: -/// - total_supply -/// - balance_of -/// - allowance -/// - transfer -/// - transfer_from -/// - approve -/// - increase_allowance -/// - decrease_allowance +mod constants { + /// 1. PSP-22 Interface: + /// - total_supply + pub const TOTAL_SUPPLY: u8 = 0; + /// - balance_of + pub const BALANCE_OF: u8 = 1; + /// - allowance + pub const ALLOWANCE: u8 = 2; + /// - transfer + pub(super) const TRANSFER: u8 = 3; + /// - transfer_from + pub(super) const TRANSFER_FROM: u8 = 4; + /// - approve + pub(super) const APPROVE: u8 = 5; + /// - increase_allowance + pub(super) const INCREASE_ALLOWANCE: u8 = 6; + /// - decrease_allowance + pub(super) const DECREASE_ALLOWANCE: u8 = 7; + + /// 2. PSP-22 Metadata Interface: + /// - token_name + pub const TOKEN_NAME: u8 = 8; + /// - token_symbol + pub const TOKEN_SYMBOL: u8 = 9; + /// - token_decimals + pub const TOKEN_DECIMALS: u8 = 10; + + // 3. Asset Management: + // - create + // - start_destroy + // - destroy_accounts + // - destroy_approvals + // - finish_destroy + // - set_metadata + // - clear_metadata +} /// Returns the total token supply for a given asset ID. /// @@ -31,7 +60,12 @@ use crate::{ /// The total supply of the token, or an error if the operation fails. #[inline] pub fn total_supply(id: AssetId) -> Result { - assets::total_supply(id) + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOTAL_SUPPLY])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } /// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if @@ -45,7 +79,12 @@ pub fn total_supply(id: AssetId) -> Result { /// The balance of the specified account, or an error if the operation fails. #[inline] pub fn balance_of(id: AssetId, owner: AccountId) -> Result { - assets::balance_of(id, owner) + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, BALANCE_OF])) + .input::<(AssetId, AccountId)>() + .output::>, true>() + .handle_error_code::() + .call(&(id, owner)) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } /// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given @@ -60,7 +99,12 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { /// The remaining allowance, or an error if the operation fails. #[inline] pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - assets::allowance(id, owner, spender) + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, ALLOWANCE])) + .input::<(AssetId, AccountId, AccountId)>() + .output::>, true>() + .handle_error_code::() + .call(&(id, owner, spender)) + .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } /// Transfers `value` amount of tokens from the caller's account to account `to`, with additional @@ -74,8 +118,12 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result<()> { - assets::transfer_keep_alive(id, to, value) +pub fn transfer(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { + ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, TRANSFER])) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, target, amount)) } /// Transfers `value` tokens on behalf of `from` to account `to` with additional `data` @@ -91,8 +139,12 @@ pub fn transfer(id: AssetId, to: AccountId, value: Balance) -> Result<()> { /// # Returns /// Returns `Ok(())` if successful, or an error if the transfer fails. #[inline] -pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { - assets::transfer_approved(id, from, to, value) +pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, amount: Balance) -> Result<()> { + ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, TRANSFER_FROM])) + .input::<(AssetId, AccountId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, from, to, amount)) } /// Approves an account to spend a specified number of tokens on behalf of the caller. @@ -105,9 +157,12 @@ pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance /// # Returns /// Returns `Ok(())` if successful, or an error if the approval fails. #[inline] -pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - assets::cancel_approval(id, spender)?; - assets::approve_transfer(id, spender, value) +pub fn approve(id: AssetId, spender: AccountId, amount: Balance) -> Result<()> { + ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, APPROVE])) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, spender, amount)) } /// Increases the allowance of a spender. @@ -121,7 +176,11 @@ pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { /// Returns `Ok(())` if successful, or an error if the operation fails. #[inline] pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - assets::approve_transfer(id, spender, value) + ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, INCREASE_ALLOWANCE])) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, spender, value)) } /// Decreases the allowance of a spender. @@ -134,63 +193,69 @@ pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re /// # Returns /// Returns `Ok(())` if successful, or an error if the operation fails. #[inline] -pub fn decrease_allowance(_id: AssetId, _spender: AccountId, _value: Balance) -> Result<()> { - // let allowance = assets::allowance(id, owner, spender)?; - // assets::cancel_approval(id, spender.clone())?; - // assets::approve_transfer(id, spender, value) - Ok(()) +pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, DECREASE_ALLOWANCE])) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, spender, value)) } -/// 2. PSP-22 Metadata Interface: -/// - token_name -/// - token_symbol -/// - token_decimals - -/// Returns the token name for a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// The name of the token as a byte vector, or an error if the operation fails. -#[inline] -pub fn token_name(id: AssetId) -> Result> { - assets::token_name(id) -} +pub mod metadata { + use super::*; + /// Returns the token name for a given asset ID. + /// + /// # Arguments + /// * `id` - The ID of the asset. + /// + /// # Returns + /// The name of the token as a byte vector, or an error if the operation fails. + #[inline] + pub fn token_name(id: AssetId) -> Result> { + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOKEN_NAME])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) + } -/// Returns the token symbol for a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// The symbol of the token as a byte vector, or an error if the operation fails. -#[inline] -pub fn token_symbol(id: AssetId) -> Result> { - assets::token_symbol(id) -} + /// Returns the token symbol for a given asset ID. + /// + /// # Arguments + /// * `id` - The ID of the asset. + /// + /// # Returns + /// The symbol of the token as a byte vector, or an error if the operation fails. + #[inline] + pub fn token_symbol(id: AssetId) -> Result> { + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOKEN_SYMBOL])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) + } -/// Returns the token decimals for a given asset ID. -/// -/// # Arguments -/// * `id` - The ID of the asset. -/// -/// # Returns -/// The number of decimals of the token as a byte vector, or an error if the operation fails. -#[inline] -pub fn token_decimals(id: AssetId) -> Result { - assets::token_decimals(id) + /// Returns the token decimals for a given asset ID. + /// + /// # Arguments + /// * `id` - The ID of the asset. + /// + /// # Returns + /// The number of decimals of the token as a byte vector, or an error if the operation fails. + #[inline] + pub fn token_decimals(id: AssetId) -> Result { + ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOKEN_DECIMALS])) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(id)) + .and_then(|v| ::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) + } } -// /// 3. Asset Management: -// /// - create -// /// - start_destroy -// /// - destroy_accounts -// /// - destroy_approvals -// /// - finish_destroy -// /// - set_metadata -// /// - clear_metadata -// +// pub asset_management { // /// Create a new token with a given asset ID. // /// // /// # Arguments @@ -200,9 +265,9 @@ pub fn token_decimals(id: AssetId) -> Result { // /// // /// # Returns // /// Returns `Ok(())` if successful, or an error if the creation fails. -// // pub fn create(id: AssetId, admin: impl Into>, min_balance: Balance) -> Result<()> { -// // assets::create(id, admin, min_balance) -// // } +// pub fn create(id: AssetId, admin: impl Into>, min_balance: Balance) -> Result<()> { +// Ok(()) +// } // // /// Start the process of destroying a token with a given asset ID. // /// @@ -211,11 +276,9 @@ pub fn token_decimals(id: AssetId) -> Result { // /// // /// # Returns // /// Returns `Ok(())` if successful, or an error if the operation fails. -// // fn start_destroy(id: AssetId) -> Result<()> { -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { -// // id: id.into(), -// // }))?) -// // } +// fn start_destroy(id: AssetId) -> Result<()> { +// Ok(()) +// } // // /// Destroy all accounts associated with a token with a given asset ID. // /// @@ -224,11 +287,9 @@ pub fn token_decimals(id: AssetId) -> Result { // /// // /// # Returns // /// Returns `Ok(())` if successful, or an error if the operation fails. -// // fn destroy_accounts(id: AssetId) -> Result<()> { -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { -// // id: id.into(), -// // }))?) -// // } +// fn destroy_accounts(id: AssetId) -> Result<()> { +// Ok(()) +// } // // /// Destroy all approvals associated with a token with a given asset ID. // /// @@ -237,11 +298,9 @@ pub fn token_decimals(id: AssetId) -> Result { // /// // /// # Returns // /// Returns `Ok(())` if successful, or an error if the operation fails. -// // fn destroy_approvals(id: AssetId) -> Result<()> { -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { -// // id: id.into(), -// // }))?) -// // } +// fn destroy_approvals(id: AssetId) -> Result<()> { +// Ok(()) +// } // // /// Complete the process of destroying a token with a given asset ID. // /// @@ -250,11 +309,9 @@ pub fn token_decimals(id: AssetId) -> Result { // /// // /// # Returns // /// Returns `Ok(())` if successful, or an error if the operation fails. -// // fn finish_destroy(id: AssetId) -> Result<()> { -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { -// // id: id.into(), -// // }))?) -// // } +// fn finish_destroy(id: AssetId) -> Result<()> { +// Ok(()) +// } // // /// Set the metadata for a token with a given asset ID. // /// @@ -263,9 +320,9 @@ pub fn token_decimals(id: AssetId) -> Result { // /// // /// # Returns // /// Returns `Ok(())` if successful, or an error if the operation fails. -// // pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { -// // assets::set_metadata(id, name, symbol, decimals) -// // } +// pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { +// Ok(()) +// } // // /// Clear the metadata for a token with a given asset ID. // /// @@ -274,11 +331,10 @@ pub fn token_decimals(id: AssetId) -> Result { // /// // /// # Returns // /// Returns `Ok(())` if successful, or an error if the operation fails. -// // fn clear_metadata(id: AssetId) -> Result<()> { -// // Ok(dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { -// // id: id.into(), -// // }))?) -// // } +// fn clear_metadata(id: AssetId) -> Result<()> { +// Ok(()) +// } +// } // // pub fn asset_exists(id: AssetId) -> Result { // assets::asset_exists(id) @@ -332,15 +388,15 @@ impl From for FungiblesError { let encoded = value.0.to_le_bytes(); match encoded { // Balances. - [MODULE_ERROR, BALANCES, 2, _] => FungiblesError::NoBalance, + [_, BALANCES, 2, _] => FungiblesError::NoBalance, // Assets. - [MODULE_ERROR, ASSETS, 0, _] => FungiblesError::NoAccount, - [MODULE_ERROR, ASSETS, 1, _] => FungiblesError::NoPermission, - [MODULE_ERROR, ASSETS, 2, _] => FungiblesError::Unknown, - [MODULE_ERROR, ASSETS, 3, _] => FungiblesError::InUse, - [MODULE_ERROR, ASSETS, 5, _] => FungiblesError::MinBalanceZero, - [MODULE_ERROR, ASSETS, 7, _] => FungiblesError::InsufficientAllowance, - [MODULE_ERROR, ASSETS, 10, _] => FungiblesError::AssetNotLive, + [_, ASSETS, 0, _] => FungiblesError::NoAccount, + [_, ASSETS, 1, _] => FungiblesError::NoPermission, + [_, ASSETS, 2, _] => FungiblesError::Unknown, + [_, ASSETS, 3, _] => FungiblesError::InUse, + [_, ASSETS, 5, _] => FungiblesError::MinBalanceZero, + [_, ASSETS, 7, _] => FungiblesError::InsufficientAllowance, + [_, ASSETS, 10, _] => FungiblesError::AssetNotLive, _ => FungiblesError::Other(value), } } @@ -407,7 +463,7 @@ mod tests { Corruption, Unavailable, RootNotAllowed, - UnknownFunctionCall, + UnknownCall, DecodingFailed, ]; for error in other_errors { diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 00021fc0..197db710 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,235 +1,2 @@ -use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec, scale::Decode}; - -use crate::{ - constants::{ASSETS, DECODING_FAILED, DISPATCH, READ_STATE}, - primitives::{AccountId, AssetId, Balance}, - v0::V0, - Result, StatusCode, -}; - +#[cfg(feature = "fungibles")] pub mod fungibles; - -/// [Pallet Assets](https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/assets/src/lib.rs): -/// 1. Dispatchables -/// 2. Read state functions -/// -/// 1. Dispatchables within pallet assets (TrustBackedAssets instance): -/// - create -/// - start_destroy -/// - destroy_accounts -/// - destroy_approvals -/// - finish_destroy -/// - mint -/// - burn -/// - transfer -/// - transfer_keep_alive -const TRANSFER_KEEP_ALIVE: u8 = 9; -/// - set_metadata -/// - clear_metadata -/// - approve_transfer -const APPROVE_TRANSFER: u8 = 22; -/// - cancel_approval -const CANCEL_APPROVAL: u8 = 23; -/// - transfer_approved -const TRANSFER_APPROVED: u8 = 25; - -/// Issue a new class of fungible assets from a public origin. -// pub(crate) fn create( -// id: AssetId, -// admin: impl Into>, -// min_balance: Balance, -// ) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::Create { -// id: id.into(), -// admin: admin.into(), -// min_balance, -// })) -// } -// -// /// Start the process of destroying a fungible asset class. -// pub(crate) fn start_destroy(id: AssetId) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::StartDestroy { id: id.into() })) -// } -// -// /// Destroy all accounts associated with a given asset. -// pub(crate) fn destroy_accounts(id: AssetId) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::DestroyAccounts { id: id.into() })) -// } -// -// /// Destroy all approvals associated with a given asset up to the max (see runtime configuration Assets `RemoveItemsLimit`). -// pub(crate) fn destroy_approvals(id: AssetId) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::DestroyApprovals { id: id.into() })) -// } -// -// /// Complete destroying asset and unreserve currency. -// pub(crate) fn finish_destroy(id: AssetId) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::FinishDestroy { id: id.into() })) -// } - -// /// Mint assets of a particular class. -// pub(crate) fn mint( -// id: AssetId, -// beneficiary: impl Into>, -// amount: Balance, -// ) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::Mint { -// id: id.into(), -// beneficiary: beneficiary.into(), -// amount: Compact(amount), -// })) -// } -// -// /// Reduce the balance of `who` by as much as possible up to `amount` assets of `id`. -// pub(crate) fn burn(id: AssetId, who: impl Into>, amount: Balance) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::Burn { -// id: id.into(), -// who: who.into(), -// amount: Compact(amount), -// })) -// } - -/// Move some assets from the sender account to another, keeping the sender account alive. -#[inline] -pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([ - V0, - DISPATCH, - ASSETS, - // E.D. is always respected with transferring tokens via the API. - TRANSFER_KEEP_ALIVE, - ])) - .input::<(AssetId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, target, amount)) -} - -// /// Set the metadata for an asset. -// pub(crate) fn set_metadata( -// id: AssetId, -// name: Vec, -// symbol: Vec, -// decimals: u8, -// ) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::SetMetadata { id: id.into(), name, symbol, decimals })) -// } - -// /// Clear the metadata for an asset. -// pub(crate) fn clear_metadata(id: AssetId) -> Result<()> { -// dispatch(RuntimeCall::Assets(AssetsCall::ClearMetadata { id: id.into() })) -// } - -/// Approve an amount of asset for transfer by a delegated third-party account. -#[inline] -pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, ASSETS, APPROVE_TRANSFER])) - .input::<(AssetId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, delegate, amount)) -} - -/// Cancel all of some asset approved for delegated transfer by a third-party account. -#[inline] -pub fn cancel_approval(id: AssetId, delegate: AccountId) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, ASSETS, CANCEL_APPROVAL])) - .input::<(AssetId, AccountId)>() - .output::, true>() - .handle_error_code::() - .call(&(id, delegate)) -} - -/// Transfer some asset balance from a previously delegated account to some third-party -/// account. -#[inline] -pub fn transfer_approved( - id: AssetId, - from: AccountId, - to: AccountId, - amount: Balance, -) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, ASSETS, TRANSFER_APPROVED])) - .input::<(AssetId, AccountId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, from, to, amount)) -} - -/// 2. Read state functions: -/// - total_supply -const TOTAL_SUPPLY: u8 = 0; -/// - balance_of -const BALANCE_OF: u8 = 1; -/// - allowance -const ALLOWANCE: u8 = 2; -/// - token_name -const TOKEN_NAME: u8 = 3; -/// - token_symbol -const TOKEN_SYMBOL: u8 = 4; -/// - token_decimals -const TOKEN_DECIMALS: u8 = 5; -/// - asset_exists - -#[inline] -pub fn total_supply(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOTAL_SUPPLY])) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(id)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) -} - -#[inline] -pub fn balance_of(id: AssetId, owner: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, BALANCE_OF])) - .input::<(AssetId, AccountId)>() - .output::>, true>() - .handle_error_code::() - .call(&(id, owner)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) -} - -#[inline] -pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, ALLOWANCE])) - .input::<(AssetId, AccountId, AccountId)>() - .output::>, true>() - .handle_error_code::() - .call(&(id, owner, spender)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) -} - -#[inline] -pub fn token_name(id: AssetId) -> Result> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOKEN_NAME])) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(id)) - .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) -} -// -#[inline] -pub fn token_symbol(id: AssetId) -> Result> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOKEN_SYMBOL])) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(id)) - .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) -} - -#[inline] -pub fn token_decimals(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOKEN_DECIMALS])) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(id)) - .and_then(|v| ::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) -} - -// pub(crate) fn asset_exists(id: AssetId) -> Result { -// state::read(RuntimeStateKeys::Assets(AssetsKeys::AssetExists(id))) -// } diff --git a/pop-api/src/v0/balances.rs b/pop-api/src/v0/balances.rs deleted file mode 100644 index bf029178..00000000 --- a/pop-api/src/v0/balances.rs +++ /dev/null @@ -1,88 +0,0 @@ -use crate::{ - dispatch, primitives::MultiAddress, v0::RuntimeCall, AccountId, PopApiError, - PopApiError::UnknownStatusCode, -}; - -type Result = core::result::Result; - -pub fn transfer_keep_alive( - dest: impl Into>, - value: u128, -) -> Result<()> { - Ok(dispatch(RuntimeCall::Balances(BalancesCall::TransferKeepAlive { - dest: dest.into(), - value, - }))?) -} - -#[derive(scale::Encode)] -#[allow(dead_code)] -pub(crate) enum BalancesCall { - #[codec(index = 3)] - TransferKeepAlive { - dest: MultiAddress, - #[codec(compact)] - value: u128, - }, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum Error { - /// Vesting balance too high to send value. - VestingBalance, - /// Account liquidity restrictions prevent withdrawal. - LiquidityRestrictions, - /// Balance too low to send value. - InsufficientBalance, - /// Value too low to create account due to existential deposit. - ExistentialDeposit, - /// Transfer/payment would kill account. - Expendability, - /// A vesting schedule already exists for this account. - ExistingVestingSchedule, - /// Beneficiary account must pre-exist. - DeadAccount, - /// Number of named reserves exceed `MaxReserves`. - TooManyReserves, - /// Number of holds exceed `VariantCountOf`. - TooManyHolds, - /// Number of freezes exceed `MaxFreezes`. - TooManyFreezes, - /// The issuance cannot be modified since it is already deactivated. - IssuanceDeactivated, - /// The delta cannot be zero. - DeltaZero, -} - -impl TryFrom for Error { - type Error = PopApiError; - - fn try_from(status_code: u32) -> core::result::Result { - use Error::*; - match status_code { - 0 => Ok(VestingBalance), - 1 => Ok(LiquidityRestrictions), - 2 => Ok(InsufficientBalance), - 3 => Ok(ExistentialDeposit), - 4 => Ok(Expendability), - 5 => Ok(ExistingVestingSchedule), - 6 => Ok(DeadAccount), - 7 => Ok(TooManyReserves), - 8 => Ok(TooManyHolds), - 9 => Ok(TooManyFreezes), - 10 => Ok(IssuanceDeactivated), - 11 => Ok(DeltaZero), - _ => Err(UnknownStatusCode(status_code)), - } - } -} - -impl From for Error { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Balances(e) => e, - _ => panic!("expected balances error"), - } - } -} diff --git a/pop-api/src/v0/cross_chain/coretime.rs b/pop-api/src/v0/cross_chain/coretime.rs deleted file mode 100644 index 0039ed20..00000000 --- a/pop-api/src/v0/cross_chain/coretime.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::{ - primitives::cross_chain::{CrossChainMessage, OnDemand, RelayChainMessage}, - send_xcm, -}; - -/// Send a cross-chain message to place a sport order for instantaneous coretime. -pub fn place_spot_order(max_amount: u128, para_id: u32) -> crate::cross_chain::Result<()> { - Ok(send_xcm(CrossChainMessage::Relay(RelayChainMessage::OnDemand( - OnDemand::PlaceOrderKeepAlive { max_amount, para_id }, - )))?) -} diff --git a/pop-api/src/v0/cross_chain/mod.rs b/pop-api/src/v0/cross_chain/mod.rs deleted file mode 100644 index 6732c119..00000000 --- a/pop-api/src/v0/cross_chain/mod.rs +++ /dev/null @@ -1,107 +0,0 @@ -pub mod coretime; - -use crate::{PopApiError::UnknownStatusCode, *}; - -type Result = core::result::Result; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum Error { - /// The desired destination was unreachable, generally because there is a no way of routing - /// to it. - Unreachable, - /// There was some other issue (i.e. not to do with routing) in sending the message. - /// Perhaps a lack of space for buffering the message. - SendFailure, - /// The message execution fails the filter. - Filtered, - /// The message's weight could not be determined. - UnweighableMessage, - /// The destination `Location` provided cannot be inverted. - DestinationNotInvertible, - /// The assets to be sent are empty. - Empty, - /// Could not re-anchor the assets to declare the fees for the destination chain. - CannotReanchor, - /// Too many assets have been attempted for transfer. - TooManyAssets, - /// Origin is invalid for sending. - InvalidOrigin, - /// The version of the `Versioned` value used is not able to be interpreted. - BadVersion, - /// The given location could not be used (e.g. because it cannot be expressed in the - /// desired version of XCM). - BadLocation, - /// The referenced subscription could not be found. - NoSubscription, - /// The location is invalid since it already has a subscription from us. - AlreadySubscribed, - /// Could not check-out the assets for teleportation to the destination chain. - CannotCheckOutTeleport, - /// The owner does not own (all) of the asset that they wish to do the operation on. - LowBalance, - /// The asset owner has too many locks on the asset. - TooManyLocks, - /// The given account is not an identifiable sovereign account for any location. - AccountNotSovereign, - /// The operation required fees to be paid which the initiator could not meet. - FeesNotMet, - /// A remote lock with the corresponding data could not be found. - LockNotFound, - /// The unlock operation cannot succeed because there are still consumers of the lock. - InUse, - /// Invalid non-concrete asset. - InvalidAssetNotConcrete, - /// Invalid asset, reserve chain could not be determined for it. - InvalidAssetUnknownReserve, - /// Invalid asset, do not support remote asset reserves with different fees reserves. - InvalidAssetUnsupportedReserve, - /// Too many assets with different reserve locations have been attempted for transfer. - TooManyReserves, - /// Local XCM execution incomplete. - LocalExecutionIncomplete, -} - -impl TryFrom for Error { - type Error = PopApiError; - - fn try_from(status_code: u32) -> core::result::Result { - use Error::*; - match status_code { - 0 => Ok(Unreachable), - 1 => Ok(SendFailure), - 2 => Ok(Filtered), - 3 => Ok(UnweighableMessage), - 4 => Ok(DestinationNotInvertible), - 5 => Ok(Empty), - 6 => Ok(CannotReanchor), - 7 => Ok(TooManyAssets), - 8 => Ok(InvalidOrigin), - 9 => Ok(BadVersion), - 10 => Ok(BadLocation), - 11 => Ok(NoSubscription), - 12 => Ok(AlreadySubscribed), - 13 => Ok(CannotCheckOutTeleport), - 14 => Ok(LowBalance), - 15 => Ok(TooManyLocks), - 16 => Ok(AccountNotSovereign), - 17 => Ok(FeesNotMet), - 18 => Ok(LockNotFound), - 19 => Ok(InUse), - 20 => Ok(InvalidAssetNotConcrete), - 21 => Ok(InvalidAssetUnknownReserve), - 22 => Ok(InvalidAssetUnsupportedReserve), - 23 => Ok(TooManyReserves), - _ => Err(UnknownStatusCode(status_code)), - } - } -} - -impl From for Error { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Xcm(e) => e, - _ => panic!("expected xcm error"), - } - } -} diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index f7dab6b4..1c3642e1 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -2,12 +2,6 @@ use crate::{primitives::error::Error, StatusCode}; #[cfg(feature = "assets")] pub mod assets; -#[cfg(feature = "balances")] -pub mod balances; -#[cfg(feature = "cross-chain")] -pub mod cross_chain; -#[cfg(feature = "nfts")] -pub mod nfts; pub(crate) const V0: u8 = 0; diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs deleted file mode 100644 index 63b90a1f..00000000 --- a/pop-api/src/v0/nfts.rs +++ /dev/null @@ -1,883 +0,0 @@ -use super::RuntimeCall; -use crate::{PopApiError::UnknownStatusCode, *}; -use ink::prelude::vec::Vec; -use primitives::{ApprovalsLimit, BoundedBTreeMap, KeyLimit, MultiAddress}; -pub use primitives::{CollectionId, ItemId}; -use scale::Encode; -pub use types::*; - -type StringLimit = u32; -type MaxTips = u32; - -/// Issue a new collection of non-fungible items -pub fn create( - admin: impl Into>, - config: CollectionConfig, -) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::Create { admin: admin.into(), config }))?) -} - -/// Destroy a collection of fungible items. -pub fn destroy(collection: CollectionId) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::Destroy { collection }))?) -} - -/// Mint an item of a particular collection. -pub fn mint( - collection: CollectionId, - item: ItemId, - mint_to: impl Into>, -) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::Mint { - collection, - item, - mint_to: mint_to.into(), - witness_data: None, - }))?) -} - -/// Destroy a single item. -pub fn burn(collection: CollectionId, item: ItemId) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::Burn { collection, item }))?) -} - -/// Move an item from the sender account to another. -pub fn transfer( - collection: CollectionId, - item: ItemId, - dest: impl Into>, -) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::Transfer { collection, item, dest: dest.into() }))?) -} - -/// Re-evaluate the deposits on some items. -pub fn redeposit(collection: CollectionId, items: Vec) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::Redeposit { collection, items }))?) -} - -/// Change the Owner of a collection. -pub fn transfer_ownership( - collection: CollectionId, - new_owner: impl Into>, -) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::TransferOwnership { - collection, - new_owner: new_owner.into(), - }))?) -} - -/// Set (or reset) the acceptance of ownership for a particular account. -pub fn set_accept_ownership( - collection: CollectionId, - maybe_collection: Option, -) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::SetAcceptOwnership { collection, maybe_collection }))?) -} - -/// Set the maximum number of items a collection could have. -pub fn set_collection_max_supply(collection: CollectionId, max_supply: u32) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::SetCollectionMaxSupply { collection, max_supply }))?) -} - -/// Update mint settings. -pub fn update_mint_settings(collection: CollectionId, mint_settings: MintSettings) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::UpdateMintSettings { collection, mint_settings }))?) -} - -/// Get the owner of the item, if the item exists. -pub fn owner(collection: CollectionId, item: ItemId) -> Result> { - Ok(state::read(RuntimeStateKeys::Nfts(NftsKeys::Owner(collection, item)))?) -} - -/// Get the owner of the collection, if the collection exists. -pub fn collection_owner(collection: CollectionId) -> Result> { - Ok(state::read(RuntimeStateKeys::Nfts(NftsKeys::CollectionOwner(collection)))?) -} - -/// Get the details of a collection. -pub fn collection(collection: CollectionId) -> Result> { - Ok(state::read(RuntimeStateKeys::Nfts(NftsKeys::Collection(collection)))?) -} - -/// Get the details of an item. -pub fn item(collection: CollectionId, item: ItemId) -> Result> { - Ok(state::read(RuntimeStateKeys::Nfts(NftsKeys::Item(collection, item)))?) -} - -pub mod approvals { - use super::*; - - /// Approve an item to be transferred by a delegated third-party account. - pub fn approve_transfer( - collection: CollectionId, - item: ItemId, - delegate: impl Into>, - maybe_deadline: Option, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::ApproveTransfer { - collection, - item, - delegate: delegate.into(), - maybe_deadline, - }))?) - } - - /// Cancel one of the transfer approvals for a specific item. - pub fn cancel_approval( - collection: CollectionId, - item: ItemId, - delegate: impl Into>, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::CancelApproval { - collection, - item, - delegate: delegate.into(), - }))?) - } - - /// Cancel all the approvals of a specific item. - pub fn clear_all_transfer_approvals(collection: CollectionId, item: ItemId) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::ClearAllTransferApprovals { collection, item }))?) - } -} - -pub mod attributes { - use super::*; - - /// Approve item's attributes to be changed by a delegated third-party account. - pub fn approve_item_attribute( - collection: CollectionId, - item: ItemId, - delegate: impl Into>, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::ApproveItemAttributes { - collection, - item, - delegate: delegate.into(), - }))?) - } - - /// Cancel the previously provided approval to change item's attributes. - pub fn cancel_item_attributes_approval( - collection: CollectionId, - item: ItemId, - delegate: impl Into>, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::CancelItemAttributesApproval { - collection, - item, - delegate: delegate.into(), - }))?) - } - - /// Set an attribute for a collection or item. - pub fn set_attribute( - collection: CollectionId, - maybe_item: Option, - namespace: AttributeNamespace, - key: BoundedVec, - value: BoundedVec, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::SetAttribute { - collection, - maybe_item, - namespace, - key, - value, - }))?) - } - - /// Clear an attribute for a collection or item. - pub fn clear_attribute( - collection: CollectionId, - maybe_item: Option, - namespace: AttributeNamespace, - key: BoundedVec, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::ClearAttribute { - collection, - maybe_item, - namespace, - key, - }))?) - } - - /// Get the attribute value of `item` of `collection` corresponding to `key`. - pub fn attribute( - collection: CollectionId, - item: ItemId, - key: BoundedVec, - ) -> Result>> { - Ok(state::read(RuntimeStateKeys::Nfts(NftsKeys::Attribute(collection, item, key)))?) - } - - // /// Get the custom attribute value of `item` of `collection` corresponding to `key`. - // pub fn custom_attribute( - // account: AccountId, - // collection: CollectionId, - // item: ItemId, - // key: BoundedVec, - // ) -> Result>> { - // Ok(state::read(RuntimeStateKeys::Nfts(NftsKeys::CustomAttribute( - // account, collection, item, key, - // )))?) - // } - - /// Get the system attribute value of `item` of `collection` corresponding to `key` if - /// `item` is `Some`. Otherwise, returns the system attribute value of `collection` - /// corresponding to `key`. - pub fn system_attribute( - collection: CollectionId, - item: Option, - key: BoundedVec, - ) -> Result>> { - Ok(state::read(RuntimeStateKeys::Nfts(NftsKeys::SystemAttribute(collection, item, key)))?) - } - - /// Get the attribute value of `item` of `collection` corresponding to `key`. - pub fn collection_attribute( - collection: CollectionId, - key: BoundedVec, - ) -> Result>> { - Ok(state::read(RuntimeStateKeys::Nfts(NftsKeys::CollectionAttribute(collection, key)))?) - } -} - -pub mod locking { - use super::*; - - /// Disallows changing the metadata or attributes of the item. - pub fn lock_item_properties( - collection: CollectionId, - item: ItemId, - lock_metadata: bool, - lock_attributes: bool, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::LockItemProperties { - collection, - item, - lock_metadata, - lock_attributes, - }))?) - } - - /// Disallow further unprivileged transfer of an item. - pub fn lock_item_transfer(collection: CollectionId, item: ItemId) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::LockItemTransfer { collection, item }))?) - } - - /// Re-allow unprivileged transfer of an item. - pub fn unlock_item_transfer(collection: CollectionId, item: ItemId) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::UnlockItemTransfer { collection, item }))?) - } - - /// Disallows specified settings for the whole collection. - pub fn lock_collection( - collection: CollectionId, - lock_settings: CollectionSettings, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::LockCollection { collection, lock_settings }))?) - } -} - -pub mod metadata { - use super::*; - - /// Set the metadata for an item. - pub fn set_metadata( - collection: CollectionId, - item: ItemId, - data: BoundedVec, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::SetMetadata { collection, item, data }))?) - } - - /// Clear the metadata for an item. - pub fn clear_metadata(collection: CollectionId, item: ItemId) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::ClearMetadata { collection, item }))?) - } - - /// Set the metadata for a collection. - pub fn set_collection_metadata( - collection: CollectionId, - data: BoundedVec, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::SetCollectionMetadata { collection, data }))?) - } - - /// Clear the metadata for a collection. - pub fn clear_collection_metadata(collection: CollectionId) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::ClearCollectionMetadata { collection }))?) - } -} - -pub mod roles { - use super::*; - - /// Change the Issuer, Admin and Freezer of a collection. - pub fn set_team( - collection: CollectionId, - issuer: Option>>, - admin: Option>>, - freezer: Option>>, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::SetTeam { - collection, - issuer: issuer.map(|i| i.into()), - admin: admin.map(|i| i.into()), - freezer: freezer.map(|i| i.into()), - }))?) - } -} - -pub mod trading { - use super::*; - - /// Allows to pay the tips. - pub fn pay_tips(tips: BoundedVec) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::PayTips { tips }))?) - } - - /// Set (or reset) the price for an item. - pub fn price(collection: CollectionId, item: ItemId, price: Option) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::SetPrice { collection, item, price }))?) - } - - /// Allows to buy an item if it's up for sale. - pub fn buy_item(collection: CollectionId, item: ItemId, bid_price: Balance) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::BuyItem { collection, item, bid_price }))?) - } - - pub mod swaps { - use super::*; - - /// Register a new atomic swap, declaring an intention to send an `item` in exchange for - /// `desired_item` from origin to target on the current chain. - pub fn create_swap( - offered_collection: CollectionId, - offered_item: ItemId, - desired_collection: CollectionId, - maybe_desired_item: Option, - maybe_price: Option, - duration: BlockNumber, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::CreateSwap { - offered_collection, - offered_item, - desired_collection, - maybe_desired_item, - maybe_price, - duration, - }))?) - } - - /// Cancel an atomic swap. - pub fn cancel_swap(offered_collection: CollectionId, offered_item: ItemId) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::CancelSwap { - offered_collection, - offered_item, - }))?) - } - - /// Claim an atomic swap. - pub fn claim_swap( - send_collection: CollectionId, - send_item: ItemId, - receive_collection: CollectionId, - receive_item: ItemId, - ) -> Result<()> { - Ok(dispatch(RuntimeCall::Nfts(NftCalls::ClaimSwap { - send_collection, - send_item, - receive_collection, - receive_item, - }))?) - } - } -} - -#[derive(Encode)] -pub(crate) enum NftCalls { - #[codec(index = 0)] - Create { admin: MultiAddress, config: CollectionConfig }, - #[codec(index = 2)] - Destroy { collection: CollectionId }, - #[codec(index = 3)] - Mint { - collection: CollectionId, - item: ItemId, - mint_to: MultiAddress, - witness_data: Option<()>, - }, - #[codec(index = 5)] - Burn { collection: CollectionId, item: ItemId }, - #[codec(index = 6)] - Transfer { collection: CollectionId, item: ItemId, dest: MultiAddress }, - #[codec(index = 7)] - Redeposit { collection: CollectionId, items: Vec }, - #[codec(index = 8)] - LockItemTransfer { collection: CollectionId, item: ItemId }, - #[codec(index = 9)] - UnlockItemTransfer { collection: CollectionId, item: ItemId }, - #[codec(index = 10)] - LockCollection { collection: CollectionId, lock_settings: CollectionSettings }, - #[codec(index = 11)] - TransferOwnership { collection: CollectionId, new_owner: MultiAddress }, - #[codec(index = 12)] - SetTeam { - collection: CollectionId, - issuer: Option>, - admin: Option>, - freezer: Option>, - }, - #[codec(index = 15)] - ApproveTransfer { - collection: CollectionId, - item: ItemId, - delegate: MultiAddress, - maybe_deadline: Option, - }, - #[codec(index = 16)] - CancelApproval { collection: CollectionId, item: ItemId, delegate: MultiAddress }, - #[codec(index = 17)] - ClearAllTransferApprovals { collection: CollectionId, item: ItemId }, - #[codec(index = 18)] - LockItemProperties { - collection: CollectionId, - item: ItemId, - lock_metadata: bool, - lock_attributes: bool, - }, - #[codec(index = 19)] - SetAttribute { - collection: CollectionId, - maybe_item: Option, - namespace: AttributeNamespace, - key: BoundedVec, - value: BoundedVec, - }, - #[codec(index = 21)] - ClearAttribute { - collection: CollectionId, - maybe_item: Option, - namespace: AttributeNamespace, - key: BoundedVec, - }, - #[codec(index = 22)] - ApproveItemAttributes { - collection: CollectionId, - item: ItemId, - delegate: MultiAddress, - }, - #[codec(index = 23)] - CancelItemAttributesApproval { - collection: CollectionId, - item: ItemId, - delegate: MultiAddress, - }, - #[codec(index = 24)] - SetMetadata { collection: CollectionId, item: ItemId, data: BoundedVec }, - #[codec(index = 25)] - ClearMetadata { collection: CollectionId, item: ItemId }, - #[codec(index = 26)] - SetCollectionMetadata { collection: CollectionId, data: BoundedVec }, - #[codec(index = 27)] - ClearCollectionMetadata { collection: CollectionId }, - #[codec(index = 28)] - SetAcceptOwnership { collection: CollectionId, maybe_collection: Option }, - #[codec(index = 29)] - SetCollectionMaxSupply { collection: CollectionId, max_supply: u32 }, - #[codec(index = 30)] - UpdateMintSettings { collection: CollectionId, mint_settings: MintSettings }, - #[codec(index = 31)] - SetPrice { collection: CollectionId, item: ItemId, price: Option }, - #[codec(index = 32)] - BuyItem { collection: CollectionId, item: ItemId, bid_price: Balance }, - #[codec(index = 33)] - PayTips { tips: BoundedVec }, - #[codec(index = 34)] - CreateSwap { - offered_collection: CollectionId, - offered_item: ItemId, - desired_collection: CollectionId, - maybe_desired_item: Option, - maybe_price: Option, - duration: BlockNumber, - }, - #[codec(index = 35)] - CancelSwap { offered_collection: CollectionId, offered_item: ItemId }, - #[codec(index = 36)] - ClaimSwap { - send_collection: CollectionId, - send_item: ItemId, - receive_collection: CollectionId, - receive_item: ItemId, - }, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum Error { - /// The signing account has no permission to do the operation. - NoPermission, - /// The given item ID is unknown. - UnknownCollection, - /// The item ID has already been used for an item. - AlreadyExists, - /// The approval had a deadline that expired, so the approval isn't valid anymore. - ApprovalExpired, - /// The owner turned out to be different to what was expected. - WrongOwner, - /// The witness data given does not match the current state of the chain. - BadWitness, - /// Collection ID is already taken. - CollectionIdInUse, - /// Items within that collection are non-transferable. - ItemsNonTransferable, - /// The provided account is not a delegate. - NotDelegate, - /// The delegate turned out to be different to what was expected. - WrongDelegate, - /// No approval exists that would allow the transfer. - Unapproved, - /// The named owner has not signed ownership acceptance of the collection. - Unaccepted, - /// The item is locked (non-transferable). - ItemLocked, - /// Item's attributes are locked. - LockedItemAttributes, - /// Collection's attributes are locked. - LockedCollectionAttributes, - /// Item's metadata is locked. - LockedItemMetadata, - /// Collection's metadata is locked. - LockedCollectionMetadata, - /// All items have been minted. - MaxSupplyReached, - /// The max supply is locked and can't be changed. - MaxSupplyLocked, - /// The provided max supply is less than the number of items a collection already has. - MaxSupplyTooSmall, - /// The given item ID is unknown. - UnknownItem, - /// Swap doesn't exist. - UnknownSwap, - /// The given item has no metadata set. - MetadataNotFound, - /// The provided attribute can't be found. - AttributeNotFound, - /// Item is not for sale. - NotForSale, - /// The provided bid is too low. - BidTooLow, - /// The item has reached its approval limit. - ReachedApprovalLimit, - /// The deadline has already expired. - DeadlineExpired, - /// The duration provided should be less than or equal to `MaxDeadlineDuration`. - WrongDuration, - /// The method is disabled by system settings. - MethodDisabled, - /// The provided setting can't be set. - WrongSetting, - /// Item's config already exists and should be equal to the provided one. - InconsistentItemConfig, - /// Config for a collection or an item can't be found. - NoConfig, - /// Some roles were not cleared. - RolesNotCleared, - /// Mint has not started yet. - MintNotStarted, - /// Mint has already ended. - MintEnded, - /// The provided Item was already used for claiming. - AlreadyClaimed, - /// The provided data is incorrect. - IncorrectData, - /// The extrinsic was sent by the wrong origin. - WrongOrigin, - /// The provided signature is incorrect. - WrongSignature, - /// The provided metadata might be too long. - IncorrectMetadata, - /// Can't set more attributes per one call. - MaxAttributesLimitReached, - /// The provided namespace isn't supported in this call. - WrongNamespace, - /// Can't delete non-empty collections. - CollectionNotEmpty, - /// The witness data should be provided. - WitnessRequired, -} - -impl TryFrom for Error { - type Error = PopApiError; - - fn try_from(status_code: u32) -> core::result::Result { - use Error::*; - match status_code { - 0 => Ok(NoPermission), - 1 => Ok(UnknownCollection), - 2 => Ok(AlreadyExists), - 3 => Ok(ApprovalExpired), - 4 => Ok(WrongOwner), - 5 => Ok(BadWitness), - 6 => Ok(CollectionIdInUse), - 7 => Ok(ItemsNonTransferable), - 8 => Ok(NotDelegate), - 9 => Ok(WrongDelegate), - 10 => Ok(Unapproved), - 11 => Ok(Unaccepted), - 12 => Ok(ItemLocked), - 13 => Ok(LockedItemAttributes), - 14 => Ok(LockedCollectionAttributes), - 15 => Ok(LockedItemMetadata), - 16 => Ok(LockedCollectionMetadata), - 17 => Ok(MaxSupplyReached), - 18 => Ok(MaxSupplyLocked), - 19 => Ok(MaxSupplyTooSmall), - 20 => Ok(UnknownItem), - 21 => Ok(UnknownSwap), - 22 => Ok(MetadataNotFound), - 23 => Ok(AttributeNotFound), - 24 => Ok(NotForSale), - 25 => Ok(BidTooLow), - 26 => Ok(ReachedApprovalLimit), - 27 => Ok(DeadlineExpired), - 28 => Ok(WrongDuration), - 29 => Ok(MethodDisabled), - 30 => Ok(WrongSetting), - 31 => Ok(InconsistentItemConfig), - 32 => Ok(NoConfig), - 33 => Ok(RolesNotCleared), - 34 => Ok(MintNotStarted), - 35 => Ok(MintEnded), - 36 => Ok(AlreadyClaimed), - 37 => Ok(IncorrectData), - 38 => Ok(WrongOrigin), - 39 => Ok(WrongSignature), - 40 => Ok(IncorrectMetadata), - 41 => Ok(MaxAttributesLimitReached), - 42 => Ok(WrongNamespace), - 43 => Ok(CollectionNotEmpty), - 44 => Ok(WitnessRequired), - _ => Err(UnknownStatusCode(status_code)), - } - } -} - -impl From for Error { - fn from(error: PopApiError) -> Self { - match error { - PopApiError::Nfts(e) => e, - _ => panic!("expected nfts error"), - } - } -} - -// Local implementations of pallet-nfts types -mod types { - use super::*; - use crate::{ - primitives::{CollectionId, ItemId}, - Balance, BlockNumber, - }; - pub use enumflags2::{bitflags, BitFlags}; - use scale::{Decode, EncodeLike, MaxEncodedLen}; - use scale_info::{build::Fields, meta_type, prelude::vec, Path, Type, TypeInfo, TypeParameter}; - - /// Attribute namespaces for non-fungible tokens. - #[derive(Encode)] - pub enum AttributeNamespace { - /// An attribute was set by the pallet. - Pallet, - /// An attribute was set by collection's owner. - CollectionOwner, - /// An attribute was set by item's owner. - ItemOwner, - /// An attribute was set by pre-approved account. - Account(AccountId), - } - - /// Collection's configuration. - #[derive(Encode)] - pub struct CollectionConfig { - /// Collection's settings. - pub settings: CollectionSettings, - /// Collection's max supply. - pub max_supply: Option, - /// Default settings each item will get during the mint. - pub mint_settings: MintSettings, - } - - /// Information about a collection. - #[derive(Decode, Debug, Encode, Eq, PartialEq)] - pub struct CollectionDetails { - /// Collection's owner. - pub owner: AccountId, - /// The total balance deposited by the owner for all the storage data associated with this - /// collection. Used by `destroy`. - pub owner_deposit: Balance, - /// The total number of outstanding items of this collection. - pub items: u32, - /// The total number of outstanding item metadata of this collection. - pub item_metadatas: u32, - /// The total number of outstanding item configs of this collection. - pub item_configs: u32, - /// The total number of attributes for this collection. - pub attributes: u32, - } - - /// Wrapper type for `BitFlags` that implements `Codec`. - pub struct CollectionSettings(pub BitFlags); - - impl_codec_bitflags!(CollectionSettings, u64, CollectionSetting); - - /// Support for up to 64 user-enabled features on a collection. - #[bitflags] - #[repr(u64)] - #[derive(Copy, Clone, Encode, TypeInfo)] - pub enum CollectionSetting { - /// Items in this collection are transferable. - TransferableItems, - /// The metadata of this collection can be modified. - UnlockedMetadata, - /// Attributes of this collection can be modified. - UnlockedAttributes, - /// The supply of this collection can be modified. - UnlockedMaxSupply, - /// When this isn't set then the deposit is required to hold the items of this collection. - DepositRequired, - } - - /// Information concerning the ownership of a single unique item. - #[derive(Decode, Debug, Encode, Eq, PartialEq)] - pub struct ItemDetails { - /// The owner of this item. - pub owner: AccountId, - /// The approved transferrer of this item, if one is set. - pub approvals: BoundedBTreeMap, ApprovalsLimit>, - /// The amount held in the pallet's default account for this item. Free-hold items will - /// have this as zero. - pub deposit: Balance, - } - - /// Support for up to 64 user-enabled features on an item. - #[bitflags] - #[repr(u64)] - #[derive(Copy, Clone, Encode, TypeInfo)] - pub enum ItemSetting { - /// This item is transferable. - Transferable, - /// The metadata of this item can be modified. - UnlockedMetadata, - /// Attributes of this item can be modified. - UnlockedAttributes, - } - - /// Wrapper type for `BitFlags` that implements `Codec`. - pub struct ItemSettings(pub BitFlags); - - impl_codec_bitflags!(ItemSettings, u64, ItemSetting); - - /// Information about the tip. - #[derive(Encode)] - pub struct ItemTip { - /// The collection of the item. - pub(super) collection: CollectionId, - /// An item of which the tip is sent for. - pub(super) item: ItemId, - /// A sender of the tip. - pub(super) receiver: AccountId, - /// An amount the sender is willing to tip. - pub(super) amount: Balance, - } - - /// Holds the information about minting. - #[derive(Encode)] - pub struct MintSettings { - /// Whether anyone can mint or if minters are restricted to some subset. - pub mint_type: MintType, - /// An optional price per mint. - pub price: Option, - /// When the mint starts. - pub start_block: Option, - /// When the mint ends. - pub end_block: Option, - /// Default settings each item will get during the mint. - pub default_item_settings: ItemSettings, - } - - /// Mint type. Can the NFT be created by anyone, or only the creator of the collection, - /// or only by wallets that already hold an NFT from a certain collection? - /// The ownership of a privately minted NFT is still publicly visible. - #[derive(Encode)] - pub enum MintType { - /// Only an `Issuer` could mint items. - Issuer, - /// Anyone could mint items. - Public, - /// Only holders of items in specified collection could mint new items. - HolderOf(CollectionId), - } - - /// Holds the details about the price. - #[derive(Encode)] - pub struct PriceWithDirection { - /// An amount. - pub(super) amount: Balance, - /// A direction (send or receive). - pub(super) direction: PriceDirection, - } - - /// Specifies whether the tokens will be sent or received. - #[derive(Encode)] - pub enum PriceDirection { - /// Tokens will be sent. - Send, - /// Tokens will be received. - Receive, - } - - macro_rules! impl_codec_bitflags { - ($wrapper:ty, $size:ty, $bitflag_enum:ty) => { - impl MaxEncodedLen for $wrapper { - fn max_encoded_len() -> usize { - <$size>::max_encoded_len() - } - } - impl Encode for $wrapper { - fn using_encoded R>(&self, f: F) -> R { - self.0.bits().using_encoded(f) - } - } - impl EncodeLike for $wrapper {} - impl Decode for $wrapper { - fn decode( - input: &mut I, - ) -> core::result::Result { - let field = <$size>::decode(input)?; - Ok(Self(BitFlags::from_bits(field as $size).map_err(|_| "invalid value")?)) - } - } - - impl TypeInfo for $wrapper { - type Identity = Self; - - fn type_info() -> Type { - Type::builder() - .path(Path::new("BitFlags", module_path!())) - .type_params(vec![TypeParameter::new( - "T", - Some(meta_type::<$bitflag_enum>()), - )]) - .composite( - Fields::unnamed() - .field(|f| f.ty::<$size>().type_name(stringify!($bitflag_enum))), - ) - } - } - }; - } - pub(crate) use impl_codec_bitflags; -} diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 5cbd6d6c..e7d55ffe 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -1,21 +1,17 @@ [package] name = "pop-primitives" +description = "Primitives crate for Pop" license = "GPL-3.0-only" version = "0.0.0" edition = "2021" [dependencies] -bounded-collections = { version = "0.1", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.10", default-features = false, features = ["derive"], optional = true } +codec.workspace = true +scale-info.workspace = true [features] default = ["std"] std = [ - "bounded-collections/std", - "scale/std", + "codec/std", "scale-info/std", -] -assets = [] -cross-chain = [] -nfts = [] +] \ No newline at end of file diff --git a/primitives/README.md b/primitives/README.md new file mode 100644 index 00000000..ded7918a --- /dev/null +++ b/primitives/README.md @@ -0,0 +1 @@ +Reserved crate for pop-primitives. \ No newline at end of file diff --git a/primitives/src/cross_chain.rs b/primitives/src/cross_chain.rs deleted file mode 100644 index 381e6a61..00000000 --- a/primitives/src/cross_chain.rs +++ /dev/null @@ -1,19 +0,0 @@ -use scale::{Decode, Encode, MaxEncodedLen}; - -#[derive(Encode, Decode, Debug, MaxEncodedLen)] -pub enum CrossChainMessage { - Relay(RelayChainMessage), -} - -#[derive(Encode, Decode, Debug, MaxEncodedLen)] -pub enum RelayChainMessage { - // Rococo index: https://github.com/paritytech/polkadot-sdk/blob/629506ce061db76d31d4f7a81f4a497752b27259/polkadot/runtime/rococo/src/lib.rs#L1423 - #[codec(index = 66)] - OnDemand(OnDemand), -} - -#[derive(Encode, Decode, Debug, MaxEncodedLen)] -pub enum OnDemand { - #[codec(index = 1)] - PlaceOrderKeepAlive { max_amount: u128, para_id: u32 }, -} diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 376b440d..a51661ea 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -1,37 +1,13 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -pub use bounded_collections::{BoundedBTreeMap, BoundedBTreeSet, BoundedVec}; -use scale::{Decode, Encode, MaxEncodedLen}; +use codec::{Decode, Encode}; #[cfg(feature = "std")] use scale_info::TypeInfo; pub use v0::error; -#[cfg(feature = "cross-chain")] -pub mod cross_chain; -pub mod storage_keys; - -/// An opaque 32-byte cryptographic identifier. -#[derive(Encode, Decode, Debug, MaxEncodedLen, Eq, PartialEq)] -#[cfg_attr(feature = "std", derive(TypeInfo))] -pub struct AccountId(pub [u8; 32]); - /// Identifier for the class of asset. pub type AssetId = u32; -#[cfg(feature = "nfts")] -pub mod nfts { - use bounded_collections::ConstU32; - - /// Id used for identifying non-fungible collections. - pub type CollectionId = u32; - /// Id used for identifying non-fungible items. - pub type ItemId = u32; - /// The maximum length of an attribute key. - pub type KeyLimit = ConstU32<64>; - /// The maximum approvals an item could have. - pub type ApprovalsLimit = ConstU32<20>; -} - pub mod v0 { use super::*; pub mod error { @@ -102,7 +78,7 @@ pub mod v0 { } /// Description of what went wrong when trying to complete an operation on a token. - #[derive(Encode, Decode, Clone, Debug, MaxEncodedLen, Eq, PartialEq, Ord, PartialOrd)] + #[derive(Encode, Decode, Debug, Eq, PartialEq)] #[cfg_attr(feature = "std", derive(TypeInfo))] pub enum TokenError { /// Funds are unavailable. diff --git a/primitives/src/storage_keys.rs b/primitives/src/storage_keys.rs deleted file mode 100644 index e42dbca0..00000000 --- a/primitives/src/storage_keys.rs +++ /dev/null @@ -1,56 +0,0 @@ -#[cfg(feature = "nfts")] -use super::nfts::*; -use super::*; - -#[derive(Encode, Decode, Debug, MaxEncodedLen)] -pub enum RuntimeStateKeys { - #[cfg(feature = "cross-chain")] - #[codec(index = 1)] - ParachainSystem(ParachainSystemKeys), - #[cfg(feature = "nfts")] - #[codec(index = 50)] - Nfts(NftsKeys), - #[cfg(feature = "assets")] - #[codec(index = 52)] - Assets(AssetsKeys), -} - -#[cfg(feature = "cross-chain")] -#[derive(Encode, Decode, Debug, MaxEncodedLen)] -pub enum ParachainSystemKeys { - /// Get the last relay chain block number seen by the parachain. - LastRelayChainBlockNumber, -} - -// https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/nfts/src/impl_nonfungibles.rs -#[cfg(feature = "nfts")] -#[derive(Encode, Decode, Debug, MaxEncodedLen)] -pub enum NftsKeys { - // Get the details of a collection. - Collection(CollectionId), - /// Get the owner of the collection, if the collection exists. - CollectionOwner(CollectionId), - // Get the details of an item. - Item(CollectionId, ItemId), - /// Get the owner of the item, if the item exists. - Owner(CollectionId, ItemId), - /// Get the attribute value of `item` of `collection` corresponding to `key`. - Attribute(CollectionId, ItemId, BoundedVec), - /// Get the system attribute value of `item` of `collection` corresponding to `key` - SystemAttribute(CollectionId, Option, BoundedVec), - /// Get the attribute value of `item` of `collection` corresponding to `key`. - CollectionAttribute(CollectionId, BoundedVec), -} - -/// The required input for state queries in pallet assets. -#[cfg(feature = "assets")] -#[derive(Encode, Decode, Debug, MaxEncodedLen)] -pub enum AssetsKeys { - TotalSupply(AssetId), - BalanceOf(AssetId, AccountId), - Allowance(AssetId, AccountId, AccountId), - TokenName(AssetId), - TokenSymbol(AssetId), - TokenDecimals(AssetId), - // AssetExists(AssetId), -} diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index 70e6e9c9..455a86fd 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -22,8 +22,9 @@ scale-info.workspace = true smallvec.workspace = true # Local -pop-primitives = { workspace = true, features = ["assets", "cross-chain", "nfts"] } -pop-runtime-common = { workspace = true, default-features = false } +pop-primitives.workspace = true +pop-runtime-common.workspace = true +pallet-api.workspace = true # Substrate frame-benchmarking.workspace = true @@ -89,7 +90,6 @@ parachain-info.workspace = true [dev-dependencies] env_logger = "0.11.2" -enumflags2 = "0.7.9" hex = "0.4.3" rand = "0.8.5" @@ -119,6 +119,7 @@ std = [ "pallet-balances/std", "pallet-collator-selection/std", "pallet-contracts/std", + "pallet-api/std", "pallet-message-queue/std", "pallet-multisig/std", "pallet-nft-fractionalization/std", @@ -169,6 +170,7 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", + "pallet-api/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-contracts/runtime-benchmarks", diff --git a/runtime/devnet/src/config/api.rs b/runtime/devnet/src/config/api.rs new file mode 100644 index 00000000..ae179e4a --- /dev/null +++ b/runtime/devnet/src/config/api.rs @@ -0,0 +1,34 @@ +use crate::{config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall}; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::traits::Contains; + +/// A query of runtime state. +#[derive(Encode, Decode, Debug, MaxEncodedLen)] +#[repr(u8)] +pub enum RuntimeRead { + /// Fungible token queries. + #[codec(index = 150)] + Fungibles(fungibles::Read), +} + +impl fungibles::Config for Runtime { + type AssetsInstance = TrustBackedAssetsInstance; + type WeightInfo = fungibles::weights::SubstrateWeight; +} + +/// A type to identify allowed calls to the Runtime from contracts. Used by Pop API +pub struct AllowedApiCalls; + +impl Contains for AllowedApiCalls { + fn contains(c: &RuntimeCall) -> bool { + use fungibles::Call as FungiblesCall; + matches!( + c, + RuntimeCall::Fungibles( + FungiblesCall::transfer { .. } + | FungiblesCall::approve { .. } + | FungiblesCall::increase_allowance { .. } + ) + ) + } +} diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 2c8ea952..78aed8b5 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -1,7 +1,3 @@ -use crate::{ - deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, - RuntimeHoldReason, DAYS, EXISTENTIAL_DEPOSIT, UNIT, -}; use frame_support::{ parameter_types, traits::{AsEnsureOriginWithArg, ConstU32}, @@ -12,6 +8,11 @@ use pallet_nfts::PalletFeatures; use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId, Signature}; use sp_runtime::traits::Verify; +use crate::{ + deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, + RuntimeHoldReason, DAYS, EXISTENTIAL_DEPOSIT, UNIT, +}; + /// We allow root to execute privileged asset operations. pub type AssetsForceOrigin = EnsureRoot; diff --git a/runtime/devnet/src/config/mod.rs b/runtime/devnet/src/config/mod.rs index e0aaa3a1..f62ffa76 100644 --- a/runtime/devnet/src/config/mod.rs +++ b/runtime/devnet/src/config/mod.rs @@ -1,3 +1,4 @@ +pub(crate) mod api; pub mod assets; mod contracts; mod proxy; diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index d2bd63e7..3aed89df 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -1,61 +1,42 @@ -use codec::{Compact, Decode, Encode}; -use cumulus_pallet_parachain_system::RelaychainDataProvider; -use frame_support::traits::{Contains, OriginTrait}; +mod v0; + +use crate::{ + config::{ + api::{AllowedApiCalls, RuntimeRead}, + assets::TrustBackedAssetsInstance, + }, + fungibles::{ + self, + Read::{self, *}, + }, + AccountId, RuntimeCall, RuntimeOrigin, +}; +use codec::{Decode, Encode}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, - traits::{ - fungibles::{approvals::Inspect as ApprovalInspect, metadata::Inspect as MetadataInspect}, - nonfungibles_v2::Inspect as NonFungiblesInspect, - }, + traits::{Contains, OriginTrait}, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, Environment, Ext, InitState, RetVal, }; +use pop_primitives::AssetId; use sp_core::crypto::UncheckedFrom; -use sp_runtime::{ - traits::{BlockNumberProvider, Dispatchable}, - DispatchError, MultiAddress, -}; -use sp_std::{boxed::Box, vec::Vec}; -use xcm::{ - latest::{prelude::*, OriginKind::SovereignAccount}, - VersionedXcm, -}; - -use crate::{ - config::assets::TrustBackedAssetsInstance, AccountId, AllowedApiCalls, Balance, Runtime, - RuntimeCall, RuntimeOrigin, UNIT, -}; -use pop_primitives::{ - cross_chain::CrossChainMessage, - nfts::{CollectionId, ItemId}, - storage_keys::{ - AssetsKeys::{self, *}, - NftsKeys, ParachainSystemKeys, RuntimeStateKeys, - }, - AssetId, -}; - -mod v0; +use sp_runtime::{traits::Dispatchable, DispatchError}; +use sp_std::vec::Vec; const LOG_TARGET: &str = "pop-api::extension"; -// Versions: -const V0: u8 = 0; type ContractSchedule = ::Schedule; #[derive(Default)] pub struct PopApiExtension; -// TODO: check removal or simplification of trait bounds. impl ChainExtension for PopApiExtension where T: pallet_contracts::Config - + pallet_xcm::Config + pallet_assets::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config + + fungibles::Config + frame_system::Config< RuntimeOrigin = RuntimeOrigin, AccountId = AccountId, @@ -102,8 +83,6 @@ where FuncId::ReadState => { read_state::(&mut env, version, pallet_index, call_index, params) }, - // TODO - FuncId::SendXcm => send_xcm::(&mut env), } }, Err(e) => Err(e), @@ -121,7 +100,7 @@ fn dispatch( version: u8, pallet_index: u8, call_index: u8, - params: Vec, + mut params: Vec, ) -> Result<(), DispatchError> where T: frame_system::Config, @@ -129,10 +108,19 @@ where E: Ext, { const LOG_PREFIX: &str = " dispatch |"; - let call = construct_call(version, pallet_index, call_index, params)?; + + // Prefix params with version, pallet, index to simplify decoding. + params.insert(0, version); + params.insert(1, pallet_index); + params.insert(2, call_index); + let call = ::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + // Contract is the origin by default. let origin: RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); - dispatch_call::(env, call, origin, LOG_PREFIX) + match call { + VersionedDispatch::V0(call) => dispatch_call::(env, call, origin, LOG_PREFIX), + } } fn dispatch_call( @@ -165,79 +153,33 @@ where } } -fn construct_call( - version: u8, - pallet_index: u8, - call_index: u8, - params: Vec, -) -> Result { - match pallet_index { - index if index == super::Assets::index() as u8 => { - let call = versioned_construct_assets_call(version, call_index, params)?; - Ok(RuntimeCall::Assets(call)) - }, - _ => Err(DispatchError::Other("UnknownFunctionId")), - } -} - -fn construct_key( - version: u8, - pallet_index: u8, - call_index: u8, - params: Vec, -) -> Result { - match pallet_index { - 52 => { - let key = versioned_construct_assets_key(version, call_index, params)?; - Ok(RuntimeStateKeys::Assets(key)) - }, - _ => Err(DispatchError::Other("UnknownFunctionId")), - } -} - -fn versioned_construct_assets_call( - version: u8, - call_index: u8, - params: Vec, -) -> Result, DispatchError> { - match version { - V0 => v0::assets::construct_assets_call(call_index, params), - _ => Err(DispatchError::Other("UnknownFunctionId")), - } -} - -fn versioned_construct_assets_key( - version: u8, - call_index: u8, - params: Vec, -) -> Result { - match version { - V0 => v0::assets::construct_assets_key(call_index, params), - _ => Err(DispatchError::Other("UnknownFunctionId")), - } -} - fn read_state( env: &mut Environment, version: u8, pallet_index: u8, call_index: u8, - params: Vec, + mut params: Vec, ) -> Result<(), DispatchError> where T: pallet_contracts::Config + pallet_assets::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config + + fungibles::Config + frame_system::Config, E: Ext, { const LOG_PREFIX: &str = " read_state |"; - let key = construct_key(version, pallet_index, call_index, params)?; + + // Prefix params with version, pallet, index to simplify decoding. + params.insert(0, version); + params.insert(1, pallet_index); + params.insert(2, call_index); + let key = >::decode(&mut ¶ms[..]) + .map_err(|_| DispatchError::Other("DecodingFailed"))?; + let result = match key { - RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, env), - RuntimeStateKeys::ParachainSystem(key) => read_parachain_system_state::(key, env), - RuntimeStateKeys::Assets(key) => read_assets_state::(key, env), + VersionedStateRead::V0(key) => match key { + RuntimeRead::Fungibles(key) => read_fungibles_state::(key, env), + }, }? .encode(); log::trace!( @@ -247,48 +189,20 @@ where env.write(&result, false, None) } -fn send_xcm(env: &mut Environment) -> Result<(), DispatchError> -where - T: pallet_contracts::Config - + frame_system::Config< - RuntimeOrigin = RuntimeOrigin, - AccountId = AccountId, - RuntimeCall = RuntimeCall, - >, - E: Ext, -{ - const LOG_PREFIX: &str = " send_xcm |"; - // Read the input as CrossChainMessage. - let xc_call: CrossChainMessage = env.read_as::()?; - // Determine the call to dispatch. - let (dest, message) = match xc_call { - CrossChainMessage::Relay(message) => { - let dest = Location::parent().into_versioned(); - let assets: Asset = (Here, 10 * UNIT).into(); - let beneficiary: Location = - AccountId32 { id: (env.ext().address().clone()).into(), network: None }.into(); - let message = Xcm::builder() - .withdraw_asset(assets.clone().into()) - .buy_execution(assets.clone(), Unlimited) - .transact( - SovereignAccount, - Weight::from_parts(250_000_000, 10_000), - message.encode().into(), - ) - .refund_surplus() - .deposit_asset(assets.into(), beneficiary) - .build(); - (dest, message) - }, - }; - // TODO: revisit to replace with signed contract origin - let origin: RuntimeOrigin = RawOrigin::Root.into(); - // Generate runtime call to dispatch. - let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::send { - dest: Box::new(dest), - message: Box::new(VersionedXcm::V4(message)), - }); - dispatch_call::(env, call, origin, LOG_PREFIX) +/// Wrapper to enable versioning of runtime state reads. +#[derive(Decode, Debug)] +enum VersionedStateRead { + /// Version zero of state reads. + #[codec(index = 0)] + V0(RuntimeRead), +} + +/// Wrapper to enable versioning of runtime calls. +#[derive(Decode, Debug)] +enum VersionedDispatch { + /// Version zero of dispatch calls. + #[codec(index = 0)] + V0(RuntimeCall), } // Converts a `DispatchError` to a `u32` status code based on the version of the API the contract uses. @@ -331,7 +245,7 @@ pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { // - Represents the second level of nesting in `DOUBLE_NESTED_ERRORS`. // - Byte 3: // - Unused or represents further nested information. - 0 => v0::error::handle_unknown_error(&mut encoded_error), + 0 => v0::handle_unknown_error(&mut encoded_error), _ => encoded_error = [254, 0, 0, 0], } u32::from_le_bytes(encoded_error) @@ -350,7 +264,6 @@ pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { pub enum FuncId { Dispatch, ReadState, - SendXcm, } impl TryFrom for FuncId { @@ -364,7 +277,6 @@ impl TryFrom for FuncId { let id = match func_id { 0 => Self::Dispatch, 1 => Self::ReadState, - 2 => Self::SendXcm, _ => { return Err(DispatchError::Other("UnknownFuncId")); }, @@ -373,122 +285,27 @@ impl TryFrom for FuncId { } } -fn read_parachain_system_state( - key: ParachainSystemKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + cumulus_pallet_parachain_system::Config, - E: Ext, -{ - match key { - ParachainSystemKeys::LastRelayChainBlockNumber => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(RelaychainDataProvider::::current_block_number().encode()) - }, - } -} - -fn read_nfts_state( - key: NftsKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + pallet_nfts::Config, - E: Ext, -{ - match key { - NftsKeys::Collection(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Collection::::get(collection).encode()) - }, - NftsKeys::CollectionOwner(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_owner(collection).encode()) - }, - NftsKeys::Item(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Item::::get(collection, item).encode()) - }, - NftsKeys::Owner(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::owner(collection, item).encode()) - }, - NftsKeys::Attribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::attribute(&collection, &item, &key).encode()) - }, - // NftsKeys::CustomAttribute(account, collection, item, key) => { - // env.charge_weight(T::DbWeight::get().reads(1_u64))?; - // Ok(pallet_nfts::Pallet::::custom_attribute(&account, &collection, &item, &key) - // .encode()) - // }, - NftsKeys::SystemAttribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::system_attribute(&collection, item.as_ref(), &key) - .encode()) - }, - NftsKeys::CollectionAttribute(collection, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_attribute(&collection, &key).encode()) - }, - } -} - -fn read_assets_state( - key: AssetsKeys, +fn read_fungibles_state( + key: Read, env: &mut Environment, ) -> Result, DispatchError> where T: pallet_contracts::Config - + pallet_assets::Config, + + pallet_assets::Config + + fungibles::Config, E: Ext, T: frame_system::Config, { + env.charge_weight(T::DbWeight::get().reads(1_u64))?; match key { - TotalSupply(id) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_assets::Pallet::::total_supply(id).encode()) - }, - BalanceOf(id, owner) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_assets::Pallet::::balance(id, &owner.0.into()) - .encode()) - }, - Allowance(id, owner, spender) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_assets::Pallet::::allowance( - id, - &owner.0.into(), - &spender.0.into(), - ) - .encode()) - }, - TokenName(id) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok( as MetadataInspect< - AccountId, - >>::name(id) - .encode()) + TotalSupply(id) => Ok(fungibles::Pallet::::total_supply(id).encode()), + BalanceOf { id, owner } => Ok(fungibles::Pallet::::balance_of(id, &owner).encode()), + Allowance { id, owner, spender } => { + Ok(fungibles::Pallet::::allowance(id, &owner, &spender).encode()) }, - TokenSymbol(id) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok( as MetadataInspect< - AccountId, - >>::symbol(id) - .encode()) - }, - TokenDecimals(id) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok( as MetadataInspect< - AccountId, - >>::decimals(id) - .encode()) - }, - // AssetsKeys::AssetExists(id) => { - // env.charge_weight(T::DbWeight::get().reads(1_u64))?; - // Ok(pallet_assets::Pallet::::asset_exists(id).encode()) - // }, + TokenName(id) => Ok(fungibles::Pallet::::token_name(id).encode()), + TokenSymbol(id) => Ok(fungibles::Pallet::::token_symbol(id).encode()), + TokenDecimals(id) => Ok(fungibles::Pallet::::token_decimals(id).encode()), } } @@ -497,6 +314,7 @@ mod tests { use super::*; use crate::{Assets, Runtime, System}; use sp_runtime::BuildStorage; + // Test ensuring `func_id()` and `ext_id()` work as expected, i.e. extracting the first two // bytes and the last two bytes, respectively, from a 4 byte array. #[test] @@ -673,501 +491,3 @@ mod tests { }); } } -// use enumflags2::BitFlags; -// use pallet_nfts::{CollectionConfig, CollectionSetting, CollectionSettings, MintSettings}; -// use parachains_common::CollectionId; -// { -// // NFT helper functions -// fn collection_config_from_disabled_settings( -// settings: BitFlags, -// ) -> CollectionConfig { -// CollectionConfig { -// settings: CollectionSettings::from_disabled(settings), -// max_supply: None, -// mint_settings: MintSettings::default(), -// } -// } -// -// fn default_collection_config() -> CollectionConfig { -// collection_config_from_disabled_settings(CollectionSetting::DepositRequired.into()) -// } -// -// #[test] -// #[ignore] -// fn dispatch_balance_transfer_from_contract_works() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// -// let (wasm_binary, _) = load_wasm_module::( -// "../../pop-api/examples/balance-transfer/target/ink/balance_transfer.wasm", -// ) -// .unwrap(); -// -// let init_value = 100 * UNIT; -// -// let result = Contracts::bare_instantiate( -// ALICE, -// init_value, -// GAS_LIMIT, -// None, -// Code::Upload(wasm_binary), -// function_selector("new"), -// vec![], -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// ) -// .result -// .unwrap(); -// -// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); -// -// let addr = result.account_id; -// -// let function = function_selector("transfer_through_runtime"); -// let value_to_send: u128 = 10 * UNIT; -// let params = [function, BOB.encode(), value_to_send.encode()].concat(); -// -// let bob_balance_before = Balances::free_balance(&BOB); -// assert_eq!(bob_balance_before, INITIAL_AMOUNT); -// -// let result = Contracts::bare_call( -// ALICE, -// addr.clone(), -// 0, -// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), -// None, -// params, -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// pallet_contracts::Determinism::Enforced, -// ); -// -// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { -// log::debug!( -// "Contract debug buffer - {:?}", -// String::from_utf8(result.debug_message.clone()) -// ); -// log::debug!("result: {:?}", result); -// } -// -// // check for revert -// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); -// -// let bob_balance_after = Balances::free_balance(&BOB); -// assert_eq!(bob_balance_before + value_to_send, bob_balance_after); -// }); -// } -// -// // Create a test for tesing create_nft_collection -// #[test] -// #[ignore] -// fn dispatch_nfts_create_nft_collection() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// -// let (wasm_binary, _) = load_wasm_module::( -// "../../pop-api/examples/nfts/target/ink/pop_api_nft_example.wasm", -// ) -// .unwrap(); -// -// let init_value = 100 * UNIT; -// -// let result = Contracts::bare_instantiate( -// ALICE, -// init_value, -// GAS_LIMIT, -// None, -// Code::Upload(wasm_binary), -// function_selector("new"), -// vec![], -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// ) -// .result -// .unwrap(); -// -// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); -// -// let addr = result.account_id; -// -// let function = function_selector("create_nft_collection"); -// -// let params = [function].concat(); -// -// let result = Contracts::bare_call( -// ALICE, -// addr.clone(), -// 0, -// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), -// None, -// params, -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// pallet_contracts::Determinism::Enforced, -// ); -// -// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { -// log::debug!( -// "Contract debug buffer - {:?}", -// String::from_utf8(result.debug_message.clone()) -// ); -// log::debug!("result: {:?}", result); -// } -// -// // check that the nft collection was created -// assert_eq!(Nfts::collection_owner(0), Some(addr.clone().into())); -// -// // test reading the collection -// let function = function_selector("read_collection"); -// -// let params = [function, 0.encode()].concat(); -// -// let result = Contracts::bare_call( -// ALICE, -// addr.clone(), -// 0, -// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), -// None, -// params, -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// pallet_contracts::Determinism::Enforced, -// ); -// -// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { -// log::debug!( -// "Contract debug buffer - {:?}", -// String::from_utf8(result.debug_message.clone()) -// ); -// log::debug!("result: {:?}", result); -// } -// -// // assert that the collection was read successfully -// assert_eq!(result.result.clone().unwrap().data, vec![1, 1]); -// }); -// } -// -// #[test] -// #[ignore] -// fn dispatch_nfts_mint_from_contract_works() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// -// let (wasm_binary, _) = -// load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") -// .unwrap(); -// -// let init_value = 100; -// -// let result = Contracts::bare_instantiate( -// ALICE, -// init_value, -// GAS_LIMIT, -// None, -// Code::Upload(wasm_binary), -// function_selector("new"), -// vec![], -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// ) -// .result -// .unwrap(); -// -// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); -// -// let addr = result.account_id; -// -// let collection_id: u32 = 0; -// let item_id: u32 = 1; -// -// // create nft collection with contract as owner -// assert_eq!( -// Nfts::force_create( -// RuntimeOrigin::root(), -// addr.clone().into(), -// default_collection_config() -// ), -// Ok(()) -// ); -// -// assert_eq!(Nfts::collection_owner(collection_id), Some(addr.clone().into())); -// // assert that the item does not exist yet -// assert_eq!(Nfts::owner(collection_id, item_id), None); -// -// let function = function_selector("mint_through_runtime"); -// -// let params = -// [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); -// -// let result = Contracts::bare_call( -// ALICE, -// addr.clone(), -// 0, -// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), -// None, -// params, -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// pallet_contracts::Determinism::Enforced, -// ); -// -// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { -// log::debug!( -// "Contract debug buffer - {:?}", -// String::from_utf8(result.debug_message.clone()) -// ); -// log::debug!("result: {:?}", result); -// } -// -// // check for revert -// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); -// -// assert_eq!(Nfts::owner(collection_id, item_id), Some(BOB.into())); -// }); -// } -// -// #[test] -// #[ignore] -// fn nfts_mint_surfaces_error() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// -// let (wasm_binary, _) = -// load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") -// .unwrap(); -// -// let init_value = 100; -// -// let result = Contracts::bare_instantiate( -// ALICE, -// init_value, -// GAS_LIMIT, -// None, -// Code::Upload(wasm_binary), -// function_selector("new"), -// vec![], -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// ) -// .result -// .unwrap(); -// -// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); -// -// let addr = result.account_id; -// -// let collection_id: u32 = 0; -// let item_id: u32 = 1; -// -// let function = function_selector("mint_through_runtime"); -// -// let params = -// [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); -// -// let result = Contracts::bare_call( -// ALICE, -// addr.clone(), -// 0, -// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), -// None, -// params, -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// pallet_contracts::Determinism::Enforced, -// ); -// -// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { -// log::debug!( -// "Contract debug buffer - {:?}", -// String::from_utf8(result.debug_message.clone()) -// ); -// log::debug!("result: {:?}", result); -// } -// -// // check for revert with expected error -// let result = result.result.unwrap(); -// assert!(result.did_revert()); -// }); -// } -// -// #[test] -// #[ignore] -// fn reading_last_relay_chain_block_number_works() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// -// let (wasm_binary, _) = load_wasm_module::( -// "../../pop-api/examples/read-runtime-state/target/ink/read_relay_blocknumber.wasm", -// ) -// .unwrap(); -// -// let init_value = 100; -// -// let contract = Contracts::bare_instantiate( -// ALICE, -// init_value, -// GAS_LIMIT, -// None, -// Code::Upload(wasm_binary), -// function_selector("new"), -// vec![], -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// ) -// .result -// .unwrap(); -// -// assert!(!contract.result.did_revert(), "deploying contract reverted {:?}", contract); -// -// let addr = contract.account_id; -// -// let function = function_selector("read_relay_block_number"); -// let params = [function].concat(); -// -// let result = Contracts::bare_call( -// ALICE, -// addr.clone(), -// 0, -// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), -// None, -// params, -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::UnsafeCollect, -// pallet_contracts::Determinism::Relaxed, -// ); -// -// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { -// log::debug!( -// "Contract debug buffer - {:?}", -// String::from_utf8(result.debug_message.clone()) -// ); -// log::debug!("result: {:?}", result); -// } -// -// // check for revert -// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); -// }); -// } -// -// #[test] -// #[ignore] -// fn place_spot_order_from_contract_works() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// -// let (wasm_binary, _) = load_wasm_module::( -// "../../pop-api/examples/place-spot-order/target/ink/spot_order.wasm", -// ) -// .unwrap(); -// -// let init_value = 100 * UNIT; -// -// let result = Contracts::bare_instantiate( -// ALICE, -// init_value, -// GAS_LIMIT, -// None, -// Code::Upload(wasm_binary), -// function_selector("new"), -// vec![], -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// ) -// .result -// .unwrap(); -// -// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); -// -// let addr = result.account_id; -// -// let function = function_selector("place_spot_order"); -// -// let max_amount = 1 * UNIT; -// let para_id = 2000; -// -// let params = [function, max_amount.encode(), para_id.encode()].concat(); -// -// let result = Contracts::bare_call( -// ALICE, -// addr.clone(), -// 0, -// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), -// None, -// params, -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// pallet_contracts::Determinism::Enforced, -// ); -// -// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { -// log::debug!( -// "Contract debug buffer - {:?}", -// String::from_utf8(result.debug_message.clone()) -// ); -// log::debug!("result: {:?}", result); -// } -// -// // check for revert -// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); -// }); -// } -// -// #[test] -// #[ignore] -// fn allow_call_filter_blocks_call() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// -// let (wasm_binary, _) = load_wasm_module::( -// "../../tests/contracts/filtered-call/target/ink/pop_api_filtered_call.wasm", -// ) -// .unwrap(); -// -// let init_value = 100 * UNIT; -// -// let result = Contracts::bare_instantiate( -// ALICE, -// init_value, -// GAS_LIMIT, -// None, -// Code::Upload(wasm_binary), -// function_selector("new"), -// vec![], -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// ) -// .result -// .unwrap(); -// -// assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); -// -// let addr = result.account_id; -// -// let function = function_selector("get_filtered"); -// let params = [function].concat(); -// -// let result = Contracts::bare_call( -// ALICE, -// addr.clone(), -// 0, -// Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), -// None, -// params, -// DEBUG_OUTPUT, -// pallet_contracts::CollectEvents::Skip, -// pallet_contracts::Determinism::Enforced, -// ); -// -// if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { -// log::debug!( -// "Contract debug buffer - {:?}", -// String::from_utf8(result.debug_message.clone()) -// ); -// log::debug!("filtered result: {:?}", result); -// } -// -// // check for revert -// assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); -// }); -// } -// } diff --git a/runtime/devnet/src/extensions/v0/error.rs b/runtime/devnet/src/extensions/v0.rs similarity index 100% rename from runtime/devnet/src/extensions/v0/error.rs rename to runtime/devnet/src/extensions/v0.rs diff --git a/runtime/devnet/src/extensions/v0/assets.rs b/runtime/devnet/src/extensions/v0/assets.rs deleted file mode 100644 index c6b15b4e..00000000 --- a/runtime/devnet/src/extensions/v0/assets.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::extensions::{ - AccountId as AccountId32, AssetId, - AssetsKeys::{self, *}, - Balance, Compact, Decode, DispatchError, MultiAddress, Runtime, TrustBackedAssetsInstance, -}; -use pop_primitives::AccountId; -use sp_std::vec::Vec; - -pub(crate) fn construct_assets_key( - call_index: u8, - params: Vec, -) -> Result { - match call_index { - 0 => { - let id = ::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; - Ok(TotalSupply(id)) - }, - 1 => { - let (id, owner) = <(AssetId, AccountId)>::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; - Ok(BalanceOf(id, owner)) - }, - 2 => { - let (id, owner, spender) = <(AssetId, AccountId, AccountId)>::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; - Ok(Allowance(id, owner, spender)) - }, - 3 => { - let id = ::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; - Ok(TokenName(id)) - }, - 4 => { - let id = ::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; - Ok(TokenSymbol(id)) - }, - 5 => { - let id = ::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; - Ok(TokenDecimals(id)) - }, - // other calls - _ => Err(DispatchError::Other("UnknownFunctionId")), - } -} - -pub(crate) fn construct_assets_call( - call_index: u8, - params: Vec, -) -> Result, DispatchError> { - match call_index { - 9 => { - let (id, target, amount) = <(AssetId, AccountId32, Balance)>::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; - Ok(pallet_assets::Call::::transfer_keep_alive { - id: Compact(id), - target: MultiAddress::Id(target), - amount, - }) - }, - 22 => { - let (id, delegate, amount) = - <(AssetId, AccountId32, Balance)>::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; - Ok(pallet_assets::Call::::approve_transfer { - id: Compact(id), - delegate: MultiAddress::Id(delegate), - amount, - }) - }, - // other calls - _ => Err(DispatchError::Other("UnknownFunctionId")), - } -} diff --git a/runtime/devnet/src/extensions/v0/mod.rs b/runtime/devnet/src/extensions/v0/mod.rs deleted file mode 100644 index 6406e08f..00000000 --- a/runtime/devnet/src/extensions/v0/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub(crate) mod assets; -pub(crate) mod error; diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 9ab64043..23895310 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -73,6 +73,8 @@ use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; // XCM Imports use xcm::latest::prelude::BodyId; +pub(crate) use pallet_api::fungibles; + /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. pub type AccountId = <::Signer as IdentifyAccount>::AccountId; @@ -250,82 +252,6 @@ impl Contains for FilteredCalls { } } -/// A type to identify allowed calls to the Runtime from contracts. Used by Pop API -pub struct AllowedApiCalls; -impl Contains for crate::AllowedApiCalls { - fn contains(c: &RuntimeCall) -> bool { - use config::assets::AssetsCall; - use pallet_nfts::Call as NftsCall; - matches!( - c, - RuntimeCall::Balances(BalancesCall::transfer_keep_alive { .. }) - | RuntimeCall::Assets( - AssetsCall::create { .. } - | AssetsCall::start_destroy { .. } - | AssetsCall::destroy_accounts { .. } - | AssetsCall::destroy_approvals { .. } - | AssetsCall::finish_destroy { .. } - | AssetsCall::mint { .. } - | AssetsCall::burn { .. } - | AssetsCall::transfer { .. } - | AssetsCall::transfer_keep_alive { .. } - | AssetsCall::force_transfer { .. } - | AssetsCall::freeze { .. } - | AssetsCall::thaw { .. } - | AssetsCall::freeze_asset { .. } - | AssetsCall::thaw_asset { .. } - | AssetsCall::transfer_ownership { .. } - | AssetsCall::set_team { .. } - | AssetsCall::set_metadata { .. } - | AssetsCall::clear_metadata { .. } - | AssetsCall::approve_transfer { .. } - | AssetsCall::cancel_approval { .. } - | AssetsCall::force_cancel_approval { .. } - | AssetsCall::transfer_approved { .. } - | AssetsCall::touch { .. } - | AssetsCall::refund { .. } - | AssetsCall::set_min_balance { .. } - | AssetsCall::touch_other { .. } - | AssetsCall::refund_other { .. } - | AssetsCall::block { .. } - ) | RuntimeCall::Nfts( - NftsCall::create { .. } - | NftsCall::destroy { .. } - | NftsCall::mint { .. } - | NftsCall::burn { .. } - | NftsCall::transfer { .. } - | NftsCall::redeposit { .. } - | NftsCall::lock_item_transfer { .. } - | NftsCall::unlock_item_transfer { .. } - | NftsCall::lock_collection { .. } - | NftsCall::transfer_ownership { .. } - | NftsCall::set_team { .. } - | NftsCall::approve_transfer { .. } - | NftsCall::cancel_approval { .. } - | NftsCall::clear_all_transfer_approvals { .. } - | NftsCall::lock_item_properties { .. } - | NftsCall::set_attribute { .. } - | NftsCall::clear_attribute { .. } - | NftsCall::approve_item_attributes { .. } - | NftsCall::cancel_item_attributes_approval { .. } - | NftsCall::set_metadata { .. } - | NftsCall::clear_metadata { .. } - | NftsCall::set_collection_metadata { .. } - | NftsCall::clear_collection_metadata { .. } - | NftsCall::set_accept_ownership { .. } - | NftsCall::set_collection_max_supply { .. } - | NftsCall::update_mint_settings { .. } - | NftsCall::set_price { .. } - | NftsCall::buy_item { .. } - | NftsCall::pay_tips { .. } - | NftsCall::create_swap { .. } - | NftsCall::cancel_swap { .. } - | NftsCall::claim_swap { .. } - ) - ) - } -} - /// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from /// [`ParaChainDefaultConfig`](`struct@frame_system::config_preludes::ParaChainDefaultConfig`), /// but overridden as needed. @@ -663,6 +589,9 @@ construct_runtime!( Nfts: pallet_nfts = 50, NftFractionalization: pallet_nft_fractionalization = 51, Assets: pallet_assets:: = 52, + + // Pop API + Fungibles: fungibles = 150, } ); @@ -670,6 +599,7 @@ construct_runtime!( mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] + [pallet_api::fungibles, Fungibles] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] @@ -1030,3 +960,22 @@ cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, } + +#[cfg(test)] +mod tests { + use crate::Runtime; + use std::any::TypeId; + + // Ensures that the account id lookup does not perform any state reads. When this changes, + // `pallet_api::fungibles` dispatchables need to be re-evaluated. + #[test] + fn test_lookup_config() { + type ExpectedLookup = sp_runtime::traits::AccountIdLookup; + type ConfigLookup = ::Lookup; + + let expected_type_id = TypeId::of::(); + let config_type_id = TypeId::of::(); + + assert_eq!(config_type_id, expected_type_id); + } +} diff --git a/runtime/testnet/Cargo.toml b/runtime/testnet/Cargo.toml index b04c3102..51cab6d6 100644 --- a/runtime/testnet/Cargo.toml +++ b/runtime/testnet/Cargo.toml @@ -22,8 +22,8 @@ scale-info.workspace = true smallvec.workspace = true # Local -pop-primitives = { workspace = true, features = ["nfts", "cross-chain"] } -pop-runtime-common = { workspace = true, default-features = false } +pop-primitives.workspace = true +pop-runtime-common.workspace = true # Substrate frame-benchmarking.workspace = true @@ -90,7 +90,6 @@ parachain-info.workspace = true [dev-dependencies] env_logger = "0.11.2" hex = "0.4.3" -enumflags2 = "0.7.9" [features] default = ["std"] diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index bcb0f835..a6e309f9 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -1,22 +1,13 @@ -use cumulus_pallet_parachain_system::RelaychainDataProvider; +use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, - traits::nonfungibles_v2::Inspect, - traits::{Contains, OriginTrait}, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, }; -use pop_primitives::{ - nfts::{CollectionId, ItemId}, - storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, -}; use sp_core::crypto::UncheckedFrom; -use sp_runtime::{ - traits::{BlockNumberProvider, Dispatchable}, - DispatchError, -}; +use sp_runtime::{traits::Dispatchable, DispatchError}; use sp_std::vec::Vec; use crate::{AccountId, AllowedApiCalls, RuntimeCall, RuntimeOrigin}; @@ -31,9 +22,6 @@ pub struct PopApiExtension; impl ChainExtension for PopApiExtension where T: pallet_contracts::Config - + pallet_xcm::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config + frame_system::Config< RuntimeOrigin = RuntimeOrigin, AccountId = AccountId, @@ -44,7 +32,6 @@ where fn call(&mut self, env: Environment) -> Result where E: Ext, - T::AccountId: UncheckedFrom + AsRef<[u8]>, { log::debug!(target:LOG_TARGET, " extension called "); match v0::FuncId::try_from(env.func_id())? { @@ -101,8 +88,6 @@ fn dispatch_call( log_prefix: &str, ) -> Result<(), DispatchError> where - T: frame_system::Config, - RuntimeOrigin: From>, E: Ext, { let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; @@ -157,8 +142,7 @@ where fn dispatch(env: Environment) -> Result<(), DispatchError> where - T: pallet_contracts::Config - + frame_system::Config, + T: pallet_contracts::Config, RuntimeOrigin: From>, E: Ext, { @@ -180,10 +164,7 @@ where fn read_state(env: Environment) -> Result<(), DispatchError> where - T: pallet_contracts::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config - + frame_system::Config, + T: pallet_contracts::Config, E: Ext, { const LOG_PREFIX: &str = " read_state |"; @@ -199,16 +180,9 @@ where log::debug!(target:LOG_TARGET, "{} charged weight: {:?}", LOG_PREFIX, charged_weight); - let key: RuntimeStateKeys = env.read_as()?; - - let result = match key { - RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, &mut env), - RuntimeStateKeys::ParachainSystem(key) => { - read_parachain_system_state::(key, &mut env) - }, - _ => Ok(Vec::default()), - }? - .encode(); + // TODO: always returning an empty vec. Chainextension will be refactored into one for both + // runtimes before pop api implementation gets merged into main. + let result = Vec::::default().encode(); log::trace!( target:LOG_TARGET, @@ -219,521 +193,3 @@ where DispatchError::Other("unable to write results to contract memory") }) } - -fn read_parachain_system_state( - key: ParachainSystemKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + cumulus_pallet_parachain_system::Config, - E: Ext, -{ - match key { - ParachainSystemKeys::LastRelayChainBlockNumber => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(RelaychainDataProvider::::current_block_number().encode()) - }, - } -} - -fn read_nfts_state( - key: NftsKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + pallet_nfts::Config, - E: Ext, -{ - match key { - NftsKeys::Collection(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Collection::::get(collection).encode()) - }, - NftsKeys::CollectionOwner(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_owner(collection).encode()) - }, - NftsKeys::Item(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Item::::get(collection, item).encode()) - }, - NftsKeys::Owner(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::owner(collection, item).encode()) - }, - NftsKeys::Attribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::attribute(&collection, &item, &key).encode()) - }, - // NftsKeys::CustomAttribute(account, collection, item, key) => { - // env.charge_weight(T::DbWeight::get().reads(1_u64))?; - // Ok(pallet_nfts::Pallet::::custom_attribute(&account, &collection, &item, &key) - // .encode()) - // }, - NftsKeys::SystemAttribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::system_attribute(&collection, item.as_ref(), &key) - .encode()) - }, - NftsKeys::CollectionAttribute(collection, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_attribute(&collection, &key).encode()) - }, - } -} - -#[cfg(test)] -mod tests { - pub use super::*; - pub use crate::*; - use enumflags2::BitFlags; - pub use pallet_contracts::Code; - use pallet_nfts::{CollectionConfig, CollectionSetting, CollectionSettings, MintSettings}; - use parachains_common::CollectionId; - pub use sp_runtime::{traits::Hash, AccountId32}; - - const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; - - const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); - const BOB: AccountId32 = AccountId32::new([2_u8; 32]); - const INITIAL_AMOUNT: u128 = 100_000 * UNIT; - const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); - - fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default() - .build_storage() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INITIAL_AMOUNT), (BOB, INITIAL_AMOUNT)], - } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } - - fn load_wasm_module(path: &str) -> std::io::Result<(Vec, ::Output)> - where - T: frame_system::Config, - { - let wasm_binary = std::fs::read(path)?; - let code_hash = T::Hashing::hash(&wasm_binary); - Ok((wasm_binary, code_hash)) - } - - fn function_selector(name: &str) -> Vec { - let hash = sp_io::hashing::blake2_256(name.as_bytes()); - [hash[0..4].to_vec()].concat() - } - - // NFT helper functions - fn collection_config_from_disabled_settings( - settings: BitFlags, - ) -> CollectionConfig { - CollectionConfig { - settings: CollectionSettings::from_disabled(settings), - max_supply: None, - mint_settings: MintSettings::default(), - } - } - - fn default_collection_config() -> CollectionConfig { - collection_config_from_disabled_settings(CollectionSetting::DepositRequired.into()) - } - - #[test] - #[ignore] - fn dispatch_balance_transfer_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/balance-transfer/target/ink/balance_transfer.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("transfer_through_runtime"); - let value_to_send: u128 = 10 * UNIT; - let params = [function, BOB.encode(), value_to_send.encode()].concat(); - - let bob_balance_before = Balances::free_balance(&BOB); - assert_eq!(bob_balance_before, INITIAL_AMOUNT); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - let bob_balance_after = Balances::free_balance(&BOB); - assert_eq!(bob_balance_before + value_to_send, bob_balance_after); - }); - } - - #[test] - #[ignore] - fn dispatch_nfts_mint_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = - load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let collection_id: u32 = 0; - let item_id: u32 = 1; - - // create nft collection with contract as owner - assert_eq!( - Nfts::force_create( - RuntimeOrigin::root(), - addr.clone().into(), - default_collection_config() - ), - Ok(()) - ); - - assert_eq!(Nfts::collection_owner(collection_id), Some(addr.clone().into())); - // assert that the item does not exist yet - assert_eq!(Nfts::owner(collection_id, item_id), None); - - let function = function_selector("mint_through_runtime"); - - let params = - [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - assert_eq!(Nfts::owner(collection_id, item_id), Some(BOB.into())); - }); - } - - #[test] - #[ignore] - fn nfts_mint_surfaces_error() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = - load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let collection_id: u32 = 0; - let item_id: u32 = 1; - - let function = function_selector("mint_through_runtime"); - - let params = - [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert with expected error - let result = result.result.unwrap(); - assert!(result.did_revert()); - }); - } - - #[test] - #[ignore] - fn reading_last_relay_chain_block_number_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/read-runtime-state/target/ink/read_relay_blocknumber.wasm", - ) - .unwrap(); - - let init_value = 100; - - let contract = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!contract.result.did_revert(), "deploying contract reverted {:?}", contract); - - let addr = contract.account_id; - - let function = function_selector("read_relay_block_number"); - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::UnsafeCollect, - pallet_contracts::Determinism::Relaxed, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } - - #[test] - #[ignore] - fn place_spot_order_from_contract_fails() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/place-spot-order/target/ink/spot_order.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("place_spot_order"); - - let max_amount = 1 * UNIT; - let para_id = 2000; - - let params = [function, max_amount.encode(), para_id.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!( - result.result.is_err(), - "Contract execution should have failed - unimplemented runtime call!" - ); - }); - } - - #[test] - #[ignore] - fn allow_call_filter_blocks_call() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../tests/contracts/filtered-call/target/ink/pop_api_filtered_call.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("get_filtered"); - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("filtered result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } -} diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index c4178011..5573ef18 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -252,45 +252,8 @@ impl Contains for FilteredCalls { /// A type to identify allowed calls to the Runtime from contracts. Used by Pop API pub struct AllowedApiCalls; impl Contains for AllowedApiCalls { - fn contains(c: &RuntimeCall) -> bool { - use pallet_nfts::Call as NftsCall; - matches!( - c, - RuntimeCall::Balances(BalancesCall::transfer_keep_alive { .. }) - | RuntimeCall::Nfts( - NftsCall::create { .. } - | NftsCall::destroy { .. } - | NftsCall::mint { .. } | NftsCall::burn { .. } - | NftsCall::transfer { .. } - | NftsCall::redeposit { .. } - | NftsCall::lock_item_transfer { .. } - | NftsCall::unlock_item_transfer { .. } - | NftsCall::lock_collection { .. } - | NftsCall::transfer_ownership { .. } - | NftsCall::set_team { .. } - | NftsCall::approve_transfer { .. } - | NftsCall::cancel_approval { .. } - | NftsCall::clear_all_transfer_approvals { .. } - | NftsCall::lock_item_properties { .. } - | NftsCall::set_attribute { .. } - | NftsCall::clear_attribute { .. } - | NftsCall::approve_item_attributes { .. } - | NftsCall::cancel_item_attributes_approval { .. } - | NftsCall::set_metadata { .. } - | NftsCall::clear_metadata { .. } - | NftsCall::set_collection_metadata { .. } - | NftsCall::clear_collection_metadata { .. } - | NftsCall::set_accept_ownership { .. } - | NftsCall::set_collection_max_supply { .. } - | NftsCall::update_mint_settings { .. } - | NftsCall::set_price { .. } - | NftsCall::buy_item { .. } - | NftsCall::pay_tips { .. } - | NftsCall::create_swap { .. } - | NftsCall::cancel_swap { .. } - | NftsCall::claim_swap { .. } - ) - ) + fn contains(_c: &RuntimeCall) -> bool { + false } } diff --git a/scripts/pallet-weights-template.hbs b/scripts/pallet-weights-template.hbs new file mode 100644 index 00000000..9e1e5a46 --- /dev/null +++ b/scripts/pallet-weights-template.hbs @@ -0,0 +1,122 @@ +{{header}} +//! Autogenerated weights for `{{pallet}}` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}} +//! DATE: {{date}}, STEPS: `{{cmd.steps}}`, REPEAT: `{{cmd.repeat}}`, LOW RANGE: `{{cmd.lowest_range_values}}`, HIGH RANGE: `{{cmd.highest_range_values}}` +//! WORST CASE MAP SIZE: `{{cmd.worst_case_map_values}}` +//! HOSTNAME: `R0GUE`, CPU: `{{cpuname}}` +//! WASM-EXECUTION: `{{cmd.wasm_execution}}`, CHAIN: `{{cmd.chain}}`, DB CACHE: `{{cmd.db_cache}}` + +// Executed Command: +{{#each args as |arg|}} +// {{arg}} +{{/each}} + +#![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}}`. +pub trait WeightInfo { + {{#each benchmarks as |benchmark|}} + fn {{benchmark.name~}} + ( + {{~#each benchmark.components as |c| ~}} + {{c.name}}: u32, {{/each~}} + ) -> Weight; + {{/each}} +} + +/// Weights for `{{pallet}}` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +{{#if (eq pallet "frame_system")}} +impl WeightInfo for SubstrateWeight { +{{else}} +impl WeightInfo for SubstrateWeight { +{{/if}} + {{#each benchmarks as |benchmark|}} + {{#each benchmark.comments as |comment|}} + /// {{comment}} + {{/each}} + {{#each benchmark.component_ranges as |range|}} + /// The range of component `{{range.name}}` is `[{{range.min}}, {{range.max}}]`. + {{/each}} + fn {{benchmark.name~}} + ( + {{~#each benchmark.components as |c| ~}} + {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} + ) -> Weight { + // Proof Size summary in bytes: + // Measured: `{{benchmark.base_recorded_proof_size}}{{#each benchmark.component_recorded_proof_size as |cp|}} + {{cp.name}} * ({{cp.slope}} ±{{underscore cp.error}}){{/each}}` + // Estimated: `{{benchmark.base_calculated_proof_size}}{{#each benchmark.component_calculated_proof_size as |cp|}} + {{cp.name}} * ({{cp.slope}} ±{{underscore cp.error}}){{/each}}` + // Minimum execution time: {{underscore benchmark.min_execution_time}}_000 picoseconds. + Weight::from_parts({{underscore benchmark.base_weight}}, {{benchmark.base_calculated_proof_size}}) + {{#each benchmark.component_weight as |cw|}} + // Standard Error: {{underscore cw.error}} + .saturating_add(Weight::from_parts({{underscore cw.slope}}, 0).saturating_mul({{cw.name}}.into())) + {{/each}} + {{#if (ne benchmark.base_reads "0")}} + .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}}_u64)) + {{/if}} + {{#each benchmark.component_reads as |cr|}} + .saturating_add(T::DbWeight::get().reads(({{cr.slope}}_u64).saturating_mul({{cr.name}}.into()))) + {{/each}} + {{#if (ne benchmark.base_writes "0")}} + .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}}_u64)) + {{/if}} + {{#each benchmark.component_writes as |cw|}} + .saturating_add(T::DbWeight::get().writes(({{cw.slope}}_u64).saturating_mul({{cw.name}}.into()))) + {{/each}} + {{#each benchmark.component_calculated_proof_size as |cp|}} + .saturating_add(Weight::from_parts(0, {{cp.slope}}).saturating_mul({{cp.name}}.into())) + {{/each}} + } + {{/each}} +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + {{#each benchmarks as |benchmark|}} + {{#each benchmark.comments as |comment|}} + /// {{comment}} + {{/each}} + {{#each benchmark.component_ranges as |range|}} + /// The range of component `{{range.name}}` is `[{{range.min}}, {{range.max}}]`. + {{/each}} + fn {{benchmark.name~}} + ( + {{~#each benchmark.components as |c| ~}} + {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} + ) -> Weight { + // Proof Size summary in bytes: + // Measured: `{{benchmark.base_recorded_proof_size}}{{#each benchmark.component_recorded_proof_size as |cp|}} + {{cp.name}} * ({{cp.slope}} ±{{underscore cp.error}}){{/each}}` + // Estimated: `{{benchmark.base_calculated_proof_size}}{{#each benchmark.component_calculated_proof_size as |cp|}} + {{cp.name}} * ({{cp.slope}} ±{{underscore cp.error}}){{/each}}` + // Minimum execution time: {{underscore benchmark.min_execution_time}}_000 picoseconds. + Weight::from_parts({{underscore benchmark.base_weight}}, {{benchmark.base_calculated_proof_size}}) + {{#each benchmark.component_weight as |cw|}} + // Standard Error: {{underscore cw.error}} + .saturating_add(Weight::from_parts({{underscore cw.slope}}, 0).saturating_mul({{cw.name}}.into())) + {{/each}} + {{#if (ne benchmark.base_reads "0")}} + .saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}}_u64)) + {{/if}} + {{#each benchmark.component_reads as |cr|}} + .saturating_add(RocksDbWeight::get().reads(({{cr.slope}}_u64).saturating_mul({{cr.name}}.into()))) + {{/each}} + {{#if (ne benchmark.base_writes "0")}} + .saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}}_u64)) + {{/if}} + {{#each benchmark.component_writes as |cw|}} + .saturating_add(RocksDbWeight::get().writes(({{cw.slope}}_u64).saturating_mul({{cw.name}}.into()))) + {{/each}} + {{#each benchmark.component_calculated_proof_size as |cp|}} + .saturating_add(Weight::from_parts(0, {{cp.slope}}).saturating_mul({{cp.name}}.into())) + {{/each}} + } + {{/each}} +} + From 4e4512ef091a9c6322eb17e697b2180c0e210f22 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Fri, 26 Jul 2024 17:45:43 +0700 Subject: [PATCH 029/161] refactor: streamline error from the decoded method by returning `Result` (#130) --- .../integration-tests/src/local_fungibles.rs | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs index c62f0713..6de57ca4 100644 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -8,11 +8,9 @@ use pop_primitives::error::{ const ASSET_ID: AssetId = 1; const CONTRACT: &str = "contracts/fungibles/target/ink/fungibles.wasm"; -fn decoded(result: ExecReturnValue) -> T { - match ::decode(&mut &result.data[2..]) { - Ok(value) => value, - Err(_) => panic!("\nTest failed by trying to decode `{:?}` into `T`\n", result), - } +fn decoded(result: ExecReturnValue) -> Result { + ::decode(&mut &result.data[2..]) + .map_err(|_| format!("\nTest failed by trying to decode `{:?}` into `T`\n", result)) } // Call total_supply contract message. @@ -20,7 +18,7 @@ fn total_supply(addr: AccountId32, asset_id: AssetId) -> Balance { let function = function_selector("total_supply"); let params = [function, asset_id.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::(result).unwrap() } // Call balance_of contract message. @@ -28,7 +26,7 @@ fn balance_of(addr: AccountId32, asset_id: AssetId, owner: AccountId32) -> Balan let function = function_selector("balance_of"); let params = [function, asset_id.encode(), owner.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::(result).unwrap() } // Call allowance contract message. @@ -41,7 +39,7 @@ fn allowance( let function = function_selector("allowance"); let params = [function, asset_id.encode(), owner.encode(), spender.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::(result).unwrap() } // Call token_name contract message. @@ -49,7 +47,7 @@ fn token_name(addr: AccountId32, asset_id: AssetId) -> Vec { let function = function_selector("token_name"); let params = [function, asset_id.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::>(result) + decoded::>(result).unwrap() } // Call token_symbol contract message. @@ -57,7 +55,7 @@ fn token_symbol(addr: AccountId32, asset_id: AssetId) -> Vec { let function = function_selector("token_symbol"); let params = [function, asset_id.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::>(result) + decoded::>(result).unwrap() } // Call token_decimals contract message. @@ -65,7 +63,7 @@ fn token_decimals(addr: AccountId32, asset_id: AssetId) -> u8 { let function = function_selector("token_decimals"); let params = [function, asset_id.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::(result).unwrap() } fn transfer( @@ -327,7 +325,7 @@ fn transfer_works() { // Asset does not exist. assert_eq!( decoded::(transfer(addr.clone(), 1, BOB, amount,)), - Module { index: 52, error: 3 }, + Ok(Module { index: 52, error: 3 }), ); // Create asset with Alice as owner and mint `amount` to contract address. let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); @@ -335,18 +333,18 @@ fn transfer_works() { freeze_asset(ALICE, asset); assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount,)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); thaw_asset(ALICE, asset); // Not enough balance. assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), - Module { index: 52, error: 0 }, + Ok(Module { index: 52, error: 0 }), ); // Not enough balance due to ED. assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 0 }, + Ok(Module { index: 52, error: 0 }), ); // Successful transfer. let balance_before_transfer = Assets::balance(asset, &BOB); @@ -357,13 +355,13 @@ fn transfer_works() { // Transfer asset to account that does not exist. assert_eq!( decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), - Token(CannotCreate) + Ok(Token(CannotCreate)) ); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(ALICE, asset); assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); }); } @@ -377,10 +375,13 @@ fn approve_works() { // Asset does not exist. assert_eq!( decoded::(approve(addr.clone(), 0, BOB, amount)), - Module { index: 52, error: 3 }, + Ok(Module { index: 52, error: 3 }), ); let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); - assert_eq!(decoded::(approve(addr.clone(), asset, BOB, amount)), ConsumerRemaining); + assert_eq!( + decoded::(approve(addr.clone(), asset, BOB, amount)), + Ok(ConsumerRemaining) + ); let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); // Create asset with Alice as owner and mint `amount` to contract address. @@ -389,7 +390,7 @@ fn approve_works() { freeze_asset(ALICE, asset); assert_eq!( decoded::(approve(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); thaw_asset(ALICE, asset); // Successful approvals: @@ -403,7 +404,7 @@ fn approve_works() { start_destroy_asset(ALICE, asset); assert_eq!( decoded::(approve(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); }); } @@ -417,12 +418,12 @@ fn increase_allowance_works() { // Asset does not exist. assert_eq!( decoded::(increase_allowance(addr.clone(), 0, BOB, amount)), - Module { index: 52, error: 3 }, + Ok(Module { index: 52, error: 3 }), ); let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); assert_eq!( decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - ConsumerRemaining + Ok(ConsumerRemaining) ); let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); @@ -432,7 +433,7 @@ fn increase_allowance_works() { freeze_asset(ALICE, asset); assert_eq!( decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); thaw_asset(ALICE, asset); // Successful approvals: @@ -452,7 +453,7 @@ fn increase_allowance_works() { start_destroy_asset(ALICE, asset); assert_eq!( decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); }); } @@ -530,7 +531,7 @@ fn token_metadata_works() { // // Minting can only be done by the owner. // assert_eq!( // decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), -// Module { index: 52, error: 2 }, +// Ok(Module { index: 52, error: 2 }), // ); // // Minimum balance of an asset can not be zero. // assert_eq!( @@ -542,7 +543,7 @@ fn token_metadata_works() { // freeze_asset(addr.clone(), asset); // assert_eq!( // decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), -// Module { index: 52, error: 16 }, +// Ok(Module { index: 52, error: 16 }), // ); // thaw_asset(addr.clone(), asset); // // Successful mint. @@ -567,7 +568,7 @@ fn token_metadata_works() { // start_destroy_asset(addr.clone(), asset); // assert_eq!( // decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), -// Module { index: 52, error: 16 }, +// Ok(Module { index: 52, error: 16 }), // ); // }); // } @@ -582,27 +583,27 @@ fn token_metadata_works() { // // No balance to pay for fees. // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), -// Module { index: 10, error: 2 }, +// Ok(Module { index: 10, error: 2 }), // ); // // Instantiate a contract without balance (relay token). // let addr = instantiate(CONTRACT, 100, vec![2]); // // No balance to pay the deposit. // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), -// Module { index: 10, error: 2 }, +// Ok(Module { index: 10, error: 2 }), // ); // // Instantiate a contract with balance. // let addr = // instantiate(CONTRACT, INIT_VALUE, vec![1]); // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, BOB, 0)), -// Module { index: 52, error: 7 }, +// Ok(Module { index: 52, error: 7 }), // ); // create_asset(ALICE, ASSET_ID, 1); // // Asset ID is already taken. // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), -// Module { index: 52, error: 5 }, +// Ok(Module { index: 52, error: 5 }), // ); // // The minimal balance for an asset must be non zero. // let new_asset = 2; From 027cb85d9d6c97942500a75f528088f9c2402210 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Sat, 27 Jul 2024 00:16:18 +0700 Subject: [PATCH 030/161] refactor: build chain extension method (#121) Co-authored-by: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Co-authored-by: Daanvdplas --- pop-api/src/lib.rs | 18 ++++++++++++++ pop-api/src/v0/assets/fungibles.rs | 38 +++++++++++++++++++++--------- pop-api/src/v0/assets/mod.rs | 1 + pop-api/src/v0/mod.rs | 26 +++++++++++++++++++- 4 files changed, 71 insertions(+), 12 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index a984bb9e..9bf9d50b 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,5 +1,7 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] +use ink::env::chain_extension::{ChainExtensionMethod, FromStatusCode}; + use constants::DECODING_FAILED; use ink::env::chain_extension::FromStatusCode; #[cfg(feature = "assets")] @@ -27,6 +29,22 @@ mod constants { pub(crate) const FUNGIBLES: u8 = 150; } +/// Helper method to build `ChainExtensionMethod`. +/// +/// Parameters: +/// - 'version': The version of the chain extension +/// - 'function': The ID of the function +/// - 'module': The index of the runtime module +/// - 'dispatchable': The index of the module dispatchable functions +fn build_extension_method( + version: u8, + function: u8, + module: u8, + dispatchable: u8, +) -> ChainExtensionMethod<(), (), (), false> { + ChainExtensionMethod::build(u32::from_le_bytes([version, function, module, dispatchable])) +} + /// Represents a status code returned by the runtime. /// /// `StatusCode` encapsulates a `u32` value that indicates the status of an operation performed diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 42373cd7..68ce76b8 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -9,6 +9,22 @@ use crate::{ use constants::*; pub use metadata::*; +/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0` +/// +/// Parameters: +/// - 'dispatchable': The index of the module dispatchable functions +fn build_dispatch(dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { + crate::v0::build_dispatch(FUNGIBLES, dispatchable) +} + +/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0`` +/// +/// Parameters: +/// - 'state_query': The index of the runtime state query +fn build_read_state(state_query: u8) -> ChainExtensionMethod<(), (), (), false> { + crate::v0::build_read_state(FUNGIBLES, state_query) +} + /// Local Fungibles: /// 1. PSP-22 Interface /// 2. PSP-22 Metadata Interface @@ -60,7 +76,7 @@ mod constants { /// The total supply of the token, or an error if the operation fails. #[inline] pub fn total_supply(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOTAL_SUPPLY])) + build_read_state(TOTAL_SUPPLY) .input::() .output::>, true>() .handle_error_code::() @@ -79,7 +95,7 @@ pub fn total_supply(id: AssetId) -> Result { /// The balance of the specified account, or an error if the operation fails. #[inline] pub fn balance_of(id: AssetId, owner: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, BALANCE_OF])) + build_read_state(BALANCE_OF) .input::<(AssetId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -99,7 +115,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { /// The remaining allowance, or an error if the operation fails. #[inline] pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, ALLOWANCE])) + build_read_state(ALLOWANCE) .input::<(AssetId, AccountId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -119,7 +135,7 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, TRANSFER])) + build_dispatch(TRANSFER) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -140,7 +156,7 @@ pub fn transfer(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { /// Returns `Ok(())` if successful, or an error if the transfer fails. #[inline] pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, TRANSFER_FROM])) + build_dispatch(TRANSFER_FROM) .input::<(AssetId, AccountId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -158,7 +174,7 @@ pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, amount: Balanc /// Returns `Ok(())` if successful, or an error if the approval fails. #[inline] pub fn approve(id: AssetId, spender: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, APPROVE])) + build_dispatch(APPROVE) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -176,7 +192,7 @@ pub fn approve(id: AssetId, spender: AccountId, amount: Balance) -> Result<()> { /// Returns `Ok(())` if successful, or an error if the operation fails. #[inline] pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, INCREASE_ALLOWANCE])) + build_dispatch(INCREASE_ALLOWANCE) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -194,7 +210,7 @@ pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re /// Returns `Ok(())` if successful, or an error if the operation fails. #[inline] pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, DECREASE_ALLOWANCE])) + build_dispatch(DECREASE_ALLOWANCE) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -212,7 +228,7 @@ pub mod metadata { /// The name of the token as a byte vector, or an error if the operation fails. #[inline] pub fn token_name(id: AssetId) -> Result> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOKEN_NAME])) + build_read_state(TOKEN_NAME) .input::() .output::>, true>() .handle_error_code::() @@ -229,7 +245,7 @@ pub mod metadata { /// The symbol of the token as a byte vector, or an error if the operation fails. #[inline] pub fn token_symbol(id: AssetId) -> Result> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOKEN_SYMBOL])) + build_read_state(TOKEN_SYMBOL) .input::() .output::>, true>() .handle_error_code::() @@ -246,7 +262,7 @@ pub mod metadata { /// The number of decimals of the token as a byte vector, or an error if the operation fails. #[inline] pub fn token_decimals(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOKEN_DECIMALS])) + build_read_state(TOKEN_DECIMALS) .input::() .output::>, true>() .handle_error_code::() diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 197db710..c68c0181 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,2 +1,3 @@ #[cfg(feature = "fungibles")] pub mod fungibles; + diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 1c3642e1..0fd06c89 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -1,4 +1,10 @@ -use crate::{primitives::error::Error, StatusCode}; +use crate::{ + build_extension_method, + constants::{DISPATCH, READ_STATE}, + primitives::error::Error, + StatusCode, +}; +use ink::env::chain_extension::ChainExtensionMethod; #[cfg(feature = "assets")] pub mod assets; @@ -10,3 +16,21 @@ impl From for Error { value.0.into() } } + +/// Helper method to build a dispatch call `ChainExtensionMethod` +/// +/// Parameters: +/// - 'module': The index of the runtime module +/// - 'dispatchable': The index of the module dispatchable functions +fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method(V0, DISPATCH, module, dispatchable) +} + +/// Helper method to build a dispatch call `ChainExtensionMethod` +/// +/// Parameters: +/// - 'module': The index of the runtime module +/// - 'state_query': The index of the runtime state query +fn build_read_state(module: u8, state_query: u8) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method(V0, READ_STATE, module, state_query) +} From 30ff91ad13346b6931561a25917e89019dd3373c Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Sat, 27 Jul 2024 08:52:26 +0700 Subject: [PATCH 031/161] fix: clean up imports (#135) --- pop-api/src/lib.rs | 2 +- pop-api/src/v0/assets/fungibles.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 9bf9d50b..efa7ecb2 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,6 +1,6 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::env::chain_extension::{ChainExtensionMethod, FromStatusCode}; +use ink::env::chain_extension::ChainExtensionMethod; use constants::DECODING_FAILED; use ink::env::chain_extension::FromStatusCode; diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 68ce76b8..374b6e88 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,7 +1,7 @@ use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec, scale::Decode}; use crate::{ - constants::{ASSETS, BALANCES, DECODING_FAILED, DISPATCH, FUNGIBLES, READ_STATE}, + constants::{ASSETS, BALANCES, DECODING_FAILED, FUNGIBLES}, primitives::{AccountId, AssetId, Balance}, v0::V0, Result, StatusCode, From 9820e7fc0c8568cf1efad813b7464d09c13e676f Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Sun, 28 Jul 2024 12:07:55 +0200 Subject: [PATCH 032/161] refactor: remove read state encoding (#122) Co-authored-by: Frank Bell --- pallets/api/src/fungibles/mod.rs | 78 ++++++++----------------- pallets/api/src/fungibles/tests.rs | 20 ++++--- pop-api/src/lib.rs | 4 +- pop-api/src/v0/assets/fungibles.rs | 20 ++----- pop-api/src/v0/assets/mod.rs | 1 - runtime/devnet/src/config/api.rs | 35 ++++++++---- runtime/devnet/src/extensions/mod.rs | 85 ++++++++++++---------------- runtime/devnet/src/extensions/v0.rs | 4 +- 8 files changed, 106 insertions(+), 141 deletions(-) diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index cd34664a..32f9af67 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -180,61 +180,33 @@ pub mod pallet { } impl Pallet { - /// Returns the total token supply for a given asset ID. + /// Reads fungible asset state based on the provided value. /// - /// # Parameters - /// * `id` - The ID of the asset. - pub fn total_supply(id: AssetIdOf) -> BalanceOf { - AssetsOf::::total_supply(id) - } - - /// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if - /// the account is non-existent. + /// This function matches the value to determine the type of state query and returns the + /// encoded result. /// - /// # Parameters - /// * `id` - The ID of the asset. - /// * `owner` - The account whose balance is being queried. - pub fn balance_of(id: AssetIdOf, owner: &AccountIdOf) -> BalanceOf { - AssetsOf::::balance(id, owner) - } - - /// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given - /// asset ID. Returns `0` if no allowance has been set. - /// - /// # Parameters - /// * `id` - The ID of the asset. - /// * `owner` - The account that owns the tokens. - /// * `spender` - The account that is allowed to spend the tokens. - pub fn allowance( - id: AssetIdOf, - owner: &AccountIdOf, - spender: &AccountIdOf, - ) -> BalanceOf { - AssetsOf::::allowance(id, owner, spender) - } - - /// Returns the token name for a given asset ID. - /// - /// # Parameters - /// * `id` - The ID of the asset. - pub fn token_name(id: AssetIdOf) -> Vec { - as MetadataInspect>>::name(id) - } - - /// Returns the token symbol for a given asset ID. - /// - /// # Parameters - /// * `id` - The ID of the asset. - pub fn token_symbol(id: AssetIdOf) -> Vec { - as MetadataInspect>>::symbol(id) - } - - /// Returns the token decimals for a given asset ID. - /// - /// # Parameters - /// * `id` - The ID of the asset. - pub fn token_decimals(id: AssetIdOf) -> u8 { - as MetadataInspect>>::decimals(id) + /// # Parameter + /// * `value` - An instance of `Read`, which specifies the type of state query and + /// the associated parameters. + pub fn read_state(value: Read) -> Vec { + use Read::*; + + match value { + TotalSupply(id) => AssetsOf::::total_supply(id).encode(), + BalanceOf { id, owner } => AssetsOf::::balance(id, owner).encode(), + Allowance { id, owner, spender } => { + AssetsOf::::allowance(id, &owner, &spender).encode() + }, + TokenName(id) => { + as MetadataInspect>>::name(id).encode() + }, + TokenSymbol(id) => { + as MetadataInspect>>::symbol(id).encode() + }, + TokenDecimals(id) => { + as MetadataInspect>>::decimals(id).encode() + }, + } } } } diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index dbfa0b34..c8de1020 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -1,4 +1,5 @@ -use crate::mock::*; +use crate::{fungibles::Read::*, mock::*}; +use codec::Encode; use frame_support::{ assert_ok, traits::fungibles::{approvals::Inspect, metadata::Inspect as MetadataInspect}, @@ -60,7 +61,7 @@ fn increase_allowance_works() { fn total_supply_works() { new_test_ext().execute_with(|| { create_asset_and_mint_to(ALICE, ASSET, ALICE, 100); - assert_eq!(Assets::total_supply(ASSET), Fungibles::total_supply(ASSET)); + assert_eq!(Assets::total_supply(ASSET).encode(), Fungibles::read_state(TotalSupply(ASSET))); }); } @@ -68,7 +69,10 @@ fn total_supply_works() { fn balance_of_works() { new_test_ext().execute_with(|| { create_asset_and_mint_to(ALICE, ASSET, ALICE, 100); - assert_eq!(Assets::balance(ASSET, ALICE), Fungibles::balance_of(ASSET, &ALICE)); + assert_eq!( + Assets::balance(ASSET, ALICE).encode(), + Fungibles::read_state(BalanceOf { id: ASSET, owner: ALICE }) + ); }); } @@ -77,8 +81,8 @@ fn allowance_works() { new_test_ext().execute_with(|| { create_asset_mint_and_approve(ALICE, ASSET, BOB, 100, ALICE, 50); assert_eq!( - Assets::allowance(ASSET, &ALICE, &BOB), - Fungibles::allowance(ASSET, &ALICE, &BOB) + Assets::allowance(ASSET, &ALICE, &BOB).encode(), + Fungibles::read_state(Allowance { id: ASSET, owner: ALICE, spender: BOB }) ); }); } @@ -90,9 +94,9 @@ fn token_metadata_works() { let symbol: Vec = vec![21, 22, 23]; let decimals: u8 = 69; create_asset_and_set_metadata(ALICE, ASSET, name.clone(), symbol.clone(), decimals); - assert_eq!(Assets::name(ASSET), Fungibles::token_name(ASSET)); - assert_eq!(Assets::symbol(ASSET), Fungibles::token_symbol(ASSET)); - assert_eq!(Assets::decimals(ASSET), Fungibles::token_decimals(ASSET)); + assert_eq!(Assets::name(ASSET).encode(), Fungibles::read_state(TokenName(ASSET))); + assert_eq!(Assets::symbol(ASSET).encode(), Fungibles::read_state(TokenSymbol(ASSET))); + assert_eq!(Assets::decimals(ASSET).encode(), Fungibles::read_state(TokenDecimals(ASSET))); }); } diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index efa7ecb2..7fcfc85b 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,9 +1,7 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::env::chain_extension::ChainExtensionMethod; - use constants::DECODING_FAILED; -use ink::env::chain_extension::FromStatusCode; +use ink::env::chain_extension::{ChainExtensionMethod, FromStatusCode}; #[cfg(feature = "assets")] pub use v0::assets; diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 374b6e88..0712a80b 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,12 +1,10 @@ -use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec, scale::Decode}; - use crate::{ - constants::{ASSETS, BALANCES, DECODING_FAILED, FUNGIBLES}, + constants::{ASSETS, BALANCES, FUNGIBLES}, primitives::{AccountId, AssetId, Balance}, - v0::V0, Result, StatusCode, }; use constants::*; +use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec}; pub use metadata::*; /// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0` @@ -78,10 +76,9 @@ mod constants { pub fn total_supply(id: AssetId) -> Result { build_read_state(TOTAL_SUPPLY) .input::() - .output::>, true>() + .output::, true>() .handle_error_code::() .call(&(id)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } /// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if @@ -97,10 +94,9 @@ pub fn total_supply(id: AssetId) -> Result { pub fn balance_of(id: AssetId, owner: AccountId) -> Result { build_read_state(BALANCE_OF) .input::<(AssetId, AccountId)>() - .output::>, true>() + .output::, true>() .handle_error_code::() .call(&(id, owner)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } /// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given @@ -117,10 +113,9 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { build_read_state(ALLOWANCE) .input::<(AssetId, AccountId, AccountId)>() - .output::>, true>() + .output::, true>() .handle_error_code::() .call(&(id, owner, spender)) - .and_then(|v| Balance::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } /// Transfers `value` amount of tokens from the caller's account to account `to`, with additional @@ -233,7 +228,6 @@ pub mod metadata { .output::>, true>() .handle_error_code::() .call(&(id)) - .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } /// Returns the token symbol for a given asset ID. @@ -250,7 +244,6 @@ pub mod metadata { .output::>, true>() .handle_error_code::() .call(&(id)) - .and_then(|v| >::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } /// Returns the token decimals for a given asset ID. @@ -264,10 +257,9 @@ pub mod metadata { pub fn token_decimals(id: AssetId) -> Result { build_read_state(TOKEN_DECIMALS) .input::() - .output::>, true>() + .output::, true>() .handle_error_code::() .call(&(id)) - .and_then(|v| ::decode(&mut &v[..]).map_err(|_e| StatusCode(DECODING_FAILED))) } } diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index c68c0181..197db710 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,3 +1,2 @@ #[cfg(feature = "fungibles")] pub mod fungibles; - diff --git a/runtime/devnet/src/config/api.rs b/runtime/devnet/src/config/api.rs index ae179e4a..884128f2 100644 --- a/runtime/devnet/src/config/api.rs +++ b/runtime/devnet/src/config/api.rs @@ -11,24 +11,37 @@ pub enum RuntimeRead { Fungibles(fungibles::Read), } -impl fungibles::Config for Runtime { - type AssetsInstance = TrustBackedAssetsInstance; - type WeightInfo = fungibles::weights::SubstrateWeight; -} - -/// A type to identify allowed calls to the Runtime from contracts. Used by Pop API +/// A type to identify allowed calls to the Runtime from the API. pub struct AllowedApiCalls; impl Contains for AllowedApiCalls { + /// Allowed runtime calls from the API. fn contains(c: &RuntimeCall) -> bool { - use fungibles::Call as FungiblesCall; + use fungibles::Call::*; + matches!( + c, + RuntimeCall::Fungibles(transfer { .. } | approve { .. } | increase_allowance { .. }) + ) + } +} + +impl Contains> for AllowedApiCalls { + /// Allowed state queries from the API. + fn contains(c: &RuntimeRead) -> bool { + use fungibles::Read::*; matches!( c, - RuntimeCall::Fungibles( - FungiblesCall::transfer { .. } - | FungiblesCall::approve { .. } - | FungiblesCall::increase_allowance { .. } + RuntimeRead::Fungibles( + TotalSupply(..) + | BalanceOf { .. } | Allowance { .. } + | TokenName(..) | TokenSymbol(..) + | TokenDecimals(..) ) ) } } + +impl fungibles::Config for Runtime { + type AssetsInstance = TrustBackedAssetsInstance; + type WeightInfo = fungibles::weights::SubstrateWeight; +} diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs index 3aed89df..d3bbdd0b 100644 --- a/runtime/devnet/src/extensions/mod.rs +++ b/runtime/devnet/src/extensions/mod.rs @@ -5,10 +5,7 @@ use crate::{ api::{AllowedApiCalls, RuntimeRead}, assets::TrustBackedAssetsInstance, }, - fungibles::{ - self, - Read::{self, *}, - }, + fungibles::{self}, AccountId, RuntimeCall, RuntimeOrigin, }; use codec::{Decode, Encode}; @@ -26,6 +23,14 @@ use sp_runtime::{traits::Dispatchable, DispatchError}; use sp_std::vec::Vec; const LOG_TARGET: &str = "pop-api::extension"; +const DECODING_FAILED_ERROR: DispatchError = DispatchError::Other("DecodingFailed"); +// TODO: issue #93, we can also encode the `pop_primitives::Error::UnknownCall` which means we do use +// `Error` in the runtime and it should stay in primitives. Perhaps issue #91 will also influence +// here. Should be looked at together. +const DECODING_FAILED_ERROR_ENCODED: [u8; 4] = [255u8, 0, 0, 0]; +const UNKNOWN_CALL_ERROR: DispatchError = DispatchError::Other("UnknownCall"); +// TODO: see above. +const UNKNOWN_CALL_ERROR_ENCODED: [u8; 4] = [254u8, 0, 0, 0]; type ContractSchedule = ::Schedule; @@ -113,8 +118,7 @@ where params.insert(0, version); params.insert(1, pallet_index); params.insert(2, call_index); - let call = ::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; + let call = ::decode(&mut ¶ms[..]).map_err(|_| DECODING_FAILED_ERROR)?; // Contract is the origin by default. let origin: RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); @@ -169,19 +173,24 @@ where { const LOG_PREFIX: &str = " read_state |"; - // Prefix params with version, pallet, index to simplify decoding. + // Prefix params with version, pallet, index to simplify decoding, and decode parameters for + // reading state. params.insert(0, version); params.insert(1, pallet_index); params.insert(2, call_index); - let key = >::decode(&mut ¶ms[..]) - .map_err(|_| DispatchError::Other("DecodingFailed"))?; + let read = + >::decode(&mut ¶ms[..]).map_err(|_| DECODING_FAILED_ERROR)?; - let result = match key { - VersionedStateRead::V0(key) => match key { - RuntimeRead::Fungibles(key) => read_fungibles_state::(key, env), + // Charge weight for doing one storage read. + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + let result = match read { + VersionedStateRead::V0(read) => { + ensure!(AllowedApiCalls::contains(&read), UNKNOWN_CALL_ERROR); + match read { + RuntimeRead::Fungibles(key) => fungibles::Pallet::::read_state(key), + } }, - }? - .encode(); + }; log::trace!( target:LOG_TARGET, "{} result: {:?}.", LOG_PREFIX, result @@ -218,16 +227,18 @@ enum VersionedDispatch { // - `error`: The `DispatchError` encountered during contract execution. // - `version`: The version of the chain extension, used to determine the known errors. pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { - // "UnknownFunctionId" and "DecodingFailed" are mapped to specific errors in the API and will - // never change. - let mut encoded_error = match error { - DispatchError::Other("UnknownFunctionId") => Vec::from([254u8, 0, 0, 0]), - DispatchError::Other("DecodingFailed") => Vec::from([255u8, 0, 0, 0]), - _ => error.encode(), + let mut encoded_error: [u8; 4] = match error { + // "UnknownCall" and "DecodingFailed" are mapped to specific errors in the API and will + // never change. + UNKNOWN_CALL_ERROR => UNKNOWN_CALL_ERROR_ENCODED, + DECODING_FAILED_ERROR => DECODING_FAILED_ERROR_ENCODED, + _ => { + let mut encoded_error = error.encode(); + // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). + encoded_error.resize(4, 0); + encoded_error.try_into().expect("qed, resized to 4 bytes line above") + }, }; - // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). - encoded_error.resize(4, 0); - let mut encoded_error = encoded_error.try_into().expect("qed, resized to 4 bytes line above"); match version { // If an unknown variant of the `DispatchError` is detected the error needs to be converted // into the encoded value of `Error::Other`. This conversion is performed by shifting the bytes one @@ -246,7 +257,7 @@ pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { // - Byte 3: // - Unused or represents further nested information. 0 => v0::handle_unknown_error(&mut encoded_error), - _ => encoded_error = [254, 0, 0, 0], + _ => encoded_error = UNKNOWN_CALL_ERROR_ENCODED, } u32::from_le_bytes(encoded_error) } @@ -278,37 +289,13 @@ impl TryFrom for FuncId { 0 => Self::Dispatch, 1 => Self::ReadState, _ => { - return Err(DispatchError::Other("UnknownFuncId")); + return Err(UNKNOWN_CALL_ERROR); }, }; Ok(id) } } -fn read_fungibles_state( - key: Read, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config - + pallet_assets::Config - + fungibles::Config, - E: Ext, - T: frame_system::Config, -{ - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - match key { - TotalSupply(id) => Ok(fungibles::Pallet::::total_supply(id).encode()), - BalanceOf { id, owner } => Ok(fungibles::Pallet::::balance_of(id, &owner).encode()), - Allowance { id, owner, spender } => { - Ok(fungibles::Pallet::::allowance(id, &owner, &spender).encode()) - }, - TokenName(id) => Ok(fungibles::Pallet::::token_name(id).encode()), - TokenSymbol(id) => Ok(fungibles::Pallet::::token_symbol(id).encode()), - TokenDecimals(id) => Ok(fungibles::Pallet::::token_decimals(id).encode()), - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/runtime/devnet/src/extensions/v0.rs b/runtime/devnet/src/extensions/v0.rs index b26668f7..72760323 100644 --- a/runtime/devnet/src/extensions/v0.rs +++ b/runtime/devnet/src/extensions/v0.rs @@ -76,7 +76,7 @@ mod tests { DispatchError::Other(""), (Other { dispatch_error_index: 0, error_index: 0, error: 0 }), ), - (DispatchError::Other("UnknownFunctionId"), UnknownCall), + (DispatchError::Other("UnknownCall"), UnknownCall), (DispatchError::Other("DecodingFailed"), DecodingFailed), (DispatchError::CannotLookup, CannotLookup), (DispatchError::BadOrigin, BadOrigin), @@ -120,7 +120,7 @@ mod tests { DispatchError::Other("Random"), (Other { dispatch_error_index: 0, error_index: 0, error: 0 }), ), - (DispatchError::Other("UnknownFunctionId"), UnknownCall), + (DispatchError::Other("UnknownCall"), UnknownCall), (DispatchError::Other("DecodingFailed"), DecodingFailed), ]; for (dispatch_error, expected) in test_cases { From 5ac5a9a520dea12f8d8c14e1bd7cfeb57a3ec7bd Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:12:25 +0700 Subject: [PATCH 033/161] feat: transfer_from and decrease_allowance (#134) Co-authored-by: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> --- pallets/api/src/fungibles/mod.rs | 80 ++++++++++-- pallets/api/src/fungibles/tests.rs | 37 ++++++ pallets/api/src/mock.rs | 3 +- .../integration-tests/src/local_fungibles.rs | 115 +++++++++++++++++- runtime/devnet/src/config/api.rs | 7 +- 5 files changed, 228 insertions(+), 14 deletions(-) diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index 32f9af67..9fb444f8 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -110,6 +110,28 @@ pub mod pallet { AssetsOf::::transfer_keep_alive(origin, id.into(), target, amount) } + /// Transfers `value` amount of tokens from the delegated account approved by the `owner` to + /// account `to`, with additional `data` in unspecified format. + /// + /// # Parameters + /// * `id` - The ID of the asset. + /// * `owner` - The account from which the asset balance will be withdrawn. + /// * `to` - The recipient account. + /// * `value` - The number of tokens to transfer. + #[pallet::call_index(4)] + #[pallet::weight(AssetsWeightInfoOf::::transfer_approved())] + pub fn transfer_from( + origin: OriginFor, + id: AssetIdOf, + owner: AccountIdOf, + target: AccountIdOf, + amount: BalanceOf, + ) -> DispatchResult { + let owner = T::Lookup::unlookup(owner); + let target = T::Lookup::unlookup(target); + AssetsOf::::transfer_approved(origin, id.into(), owner, target, amount) + } + /// Approves an account to spend a specified number of tokens on behalf of the caller. /// /// # Parameters @@ -124,17 +146,15 @@ pub mod pallet { spender: AccountIdOf, value: BalanceOf, ) -> DispatchResultWithPostInfo { - let weight = |approve: u32, cancel: u32| -> Weight { - ::WeightInfo::approve(cancel, approve) - }; - let who = ensure_signed(origin.clone()).map_err(|e| e.with_weight(weight(0, 0)))?; + let who = ensure_signed(origin.clone()) + .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; let current_allowance = AssetsOf::::allowance(id.clone(), &who, &spender); let spender = T::Lookup::unlookup(spender); let id: AssetIdParameterOf = id.into(); // If the new value is equal to the current allowance, do nothing. let return_weight = if value == current_allowance { - weight(0, 0) + Self::weight_approve(0, 0) } // If the new value is greater than the current allowance, approve the difference // because `approve_transfer` works additively (see `pallet-assets`). @@ -145,17 +165,17 @@ pub mod pallet { spender, value.saturating_sub(current_allowance), ) - .map_err(|e| e.with_weight(weight(1, 0)))?; - weight(1, 0) + .map_err(|e| e.with_weight(Self::weight_approve(1, 0)))?; + Self::weight_approve(1, 0) } else { // If the new value is less than the current allowance, cancel the approval and set the new value AssetsOf::::cancel_approval(origin.clone(), id.clone(), spender.clone()) - .map_err(|e| e.with_weight(weight(0, 1)))?; + .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; if value.is_zero() { - return Ok(Some(weight(0, 1)).into()); + return Ok(Some(Self::weight_approve(0, 1)).into()); } AssetsOf::::approve_transfer(origin, id, spender, value)?; - weight(1, 1) + Self::weight_approve(1, 1) }; Ok(Some(return_weight).into()) } @@ -177,6 +197,42 @@ pub mod pallet { let spender = T::Lookup::unlookup(spender); AssetsOf::::approve_transfer(origin, id.into(), spender, value) } + + /// Decreases the allowance of a spender. + /// + /// # Parameters + /// * `id` - The ID of the asset. + /// * `spender` - The account that is allowed to spend the tokens. + /// * `value` - The number of tokens to decrease the allowance by. + #[pallet::call_index(7)] + #[pallet::weight(::WeightInfo::approve(1, 1))] + pub fn decrease_allowance( + origin: OriginFor, + id: AssetIdOf, + spender: AccountIdOf, + value: BalanceOf, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin.clone()) + .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; + let mut current_allowance = AssetsOf::::allowance(id.clone(), &who, &spender); + let spender = T::Lookup::unlookup(spender); + let id: AssetIdParameterOf = id.into(); + + if value.is_zero() { + return Ok(Some(Self::weight_approve(0, 0)).into()); + } + + current_allowance.saturating_reduce(value); + // Cancel the aproval and set the new value if `current_allowance` is more than zero. + AssetsOf::::cancel_approval(origin.clone(), id.clone(), spender.clone()) + .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; + + if current_allowance.is_zero() { + return Ok(Some(Self::weight_approve(0, 1)).into()); + } + AssetsOf::::approve_transfer(origin, id, spender, current_allowance)?; + Ok(().into()) + } } impl Pallet { @@ -208,5 +264,9 @@ pub mod pallet { }, } } + + pub fn weight_approve(approve: u32, cancel: u32) -> Weight { + ::WeightInfo::approve(cancel, approve) + } } } diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index c8de1020..4377fc83 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -19,6 +19,43 @@ fn transfer_works() { }); } +#[test] +fn transfer_from_works() { + new_test_ext().execute_with(|| { + let amount: Balance = 100 * UNIT; + // Approve CHARLIE to transfer up to `amount` to BOB. + create_asset_mint_and_approve(ALICE, ASSET, ALICE, amount * 2, CHARLIE, amount / 2); + let transferred = amount / 2; + // Successfully call transfer from. + let alice_balance_before_transfer = Assets::balance(ASSET, &ALICE); + let balance_before_transfer = Assets::balance(ASSET, &BOB); + assert_ok!(Fungibles::transfer_from(signed(CHARLIE), ASSET, ALICE, BOB, transferred)); + let alice_balance_after_transfer = Assets::balance(ASSET, &ALICE); + let balance_after_transfer = Assets::balance(ASSET, &BOB); + // Check that BOB receives the `amount` and ALICE `amount` is spent successfully by CHARLIE. + assert_eq!(balance_after_transfer, balance_before_transfer + transferred); + assert_eq!(alice_balance_after_transfer, alice_balance_before_transfer - transferred); + }); +} + +#[test] +fn decrease_allowance_works() { + new_test_ext().execute_with(|| { + let amount: Balance = 100 * UNIT; + create_asset_mint_and_approve(ALICE, ASSET, ALICE, amount, BOB, amount); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); + // Owner balance is not changed if decreased by zero. + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, 0)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); + // Decrease allowance successfully. + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, amount / 2 - 1 * UNIT)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount / 2 + 1 * UNIT); + // Saturating if current allowance is decreased more than the owner balance. + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, amount)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), 0); + }); +} + // Non-additive, sets new value. #[test] fn approve_works() { diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index f5d155ef..b20e2635 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -103,6 +103,7 @@ impl crate::fungibles::Config for Test { pub(crate) const ALICE: AccountId = 1; pub(crate) const BOB: AccountId = 2; +pub(crate) const CHARLIE: AccountId = 3; pub(crate) const INIT_AMOUNT: Balance = 100_000_000 * UNIT; pub(crate) const UNIT: Balance = 10_000_000_000; @@ -112,7 +113,7 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { .expect("Frame system builds valid default genesis config"); pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT)], + balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)], } .assimilate_storage(&mut t) .expect("Pallet balances storage can be assimilated"); diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs index 6de57ca4..15a644ad 100644 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -78,6 +78,22 @@ fn transfer( result } +fn transfer_from( + addr: AccountId32, + asset_id: AssetId, + from: AccountId32, + to: AccountId32, + value: Balance, +) -> ExecReturnValue { + let function = function_selector("transfer_from"); + let data: Vec = vec![]; + let params = + [function, asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()] + .concat(); + let result = bare_call(addr, params, 0).expect("should work"); + result +} + fn approve( addr: AccountId32, asset_id: AssetId, @@ -102,6 +118,18 @@ fn increase_allowance( result } +fn decrease_allowance( + addr: AccountId32, + asset_id: AssetId, + spender: AccountId32, + value: Balance, +) -> ExecReturnValue { + let function = function_selector("decrease_allowance"); + let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + result +} + // fn asset_exists(addr: AccountId32, asset_id: AssetId) -> bool { // let function = function_selector("asset_exists"); // let params = [function, asset_id.encode()].concat(); @@ -171,14 +199,15 @@ fn create_asset_mint_and_approve( mint: Balance, spender: AccountId32, approve: Balance, -) { - create_asset_and_mint_to(owner.clone(), asset_id, to.clone(), mint); +) -> AssetId { + let asset = create_asset_and_mint_to(owner.clone(), asset_id, to.clone(), mint); assert_ok!(Assets::approve_transfer( RuntimeOrigin::signed(to.into()), asset_id.into(), spender.into(), approve, )); + asset } // Freeze an asset. @@ -366,6 +395,52 @@ fn transfer_works() { }); } +#[test] +fn transfer_from_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let amount: Balance = 100 * UNIT; + + // Asset does not exist. + assert_eq!( + decoded::(transfer_from(addr.clone(), 1, ALICE, BOB, amount / 2)), + Ok(Module { index: 52, error: 3 }), + ); + // Create asset with Alice as owner and mint `amount` to contract address. + let asset = create_asset_and_mint_to(ALICE, 1, ALICE, amount); + // Unapproved transfer. + assert_eq!( + decoded::(transfer_from(addr.clone(), asset, ALICE, BOB, amount / 2)), + Ok(Module { index: 52, error: 10 }) + ); + assert_ok!(Assets::approve_transfer( + RuntimeOrigin::signed(ALICE.into()), + asset.into(), + addr.clone().into(), + amount + 1 * UNIT, + )); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(ALICE, asset); + assert_eq!( + decoded::(transfer_from(addr.clone(), asset, ALICE, BOB, amount)), + Ok(Module { index: 52, error: 16 }), + ); + thaw_asset(ALICE, asset); + // Not enough balance. + assert_eq!( + decoded::(transfer_from(addr.clone(), asset, ALICE, BOB, amount + 1 * UNIT,)), + Ok(Module { index: 52, error: 0 }), + ); + // Successful transfer. + let balance_before_transfer = Assets::balance(asset, &BOB); + let result = transfer_from(addr.clone(), asset, ALICE, BOB, amount / 2); + assert!(!result.did_revert(), "Contract reverted!"); + let balance_after_transfer = Assets::balance(asset, &BOB); + assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2); + }); +} + #[test] fn approve_works() { new_test_ext().execute_with(|| { @@ -458,6 +533,42 @@ fn increase_allowance_works() { }); } +#[test] +fn decrease_allowance_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let amount: Balance = 100 * UNIT; + // Asset does not exist. + assert_eq!( + decoded::(decrease_allowance(addr.clone(), 0, BOB, amount)), + Ok(Module { index: 52, error: 3 }), + ); + // Create asset and mint to the address contract, delegate Bob to spend the `amount`. + let asset = + create_asset_mint_and_approve(addr.clone(), 0, addr.clone(), amount, BOB, amount); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(addr.clone(), asset); + assert_eq!( + decoded::(decrease_allowance(addr.clone(), asset, BOB, amount)), + Ok(Module { index: 52, error: 16 }), + ); + thaw_asset(addr.clone(), asset); + // Successfully decrease allowance. + let bob_allowance_before = Assets::allowance(asset, &addr, &BOB); + let result = decrease_allowance(addr.clone(), 0, BOB, amount / 2 - 1 * UNIT); + assert!(!result.did_revert(), "Contract reverted!"); + let bob_allowance_after = Assets::allowance(asset, &addr, &BOB); + assert_eq!(bob_allowance_before - bob_allowance_after, amount / 2 - 1 * UNIT); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(addr.clone(), asset); + assert_eq!( + decoded::(decrease_allowance(addr.clone(), asset, BOB, amount)), + Ok(Module { index: 52, error: 16 }), + ); + }); +} + /// 2. PSP-22 Metadata Interface: /// - token_name /// - token_symbol diff --git a/runtime/devnet/src/config/api.rs b/runtime/devnet/src/config/api.rs index 884128f2..b3932a79 100644 --- a/runtime/devnet/src/config/api.rs +++ b/runtime/devnet/src/config/api.rs @@ -20,7 +20,12 @@ impl Contains for AllowedApiCalls { use fungibles::Call::*; matches!( c, - RuntimeCall::Fungibles(transfer { .. } | approve { .. } | increase_allowance { .. }) + RuntimeCall::Fungibles( + transfer { .. } + | transfer_from { .. } + | approve { .. } | increase_allowance { .. } + | decrease_allowance { .. } + ) ) } } From d8ac5bd433b04359c45987ca5c3d0e78855c59a8 Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:45:07 +0200 Subject: [PATCH 034/161] refactor: api integration tests (#133) Co-authored-by: Frank Bell --- pallets/api/src/fungibles/mod.rs | 222 ++++-- pallets/api/src/fungibles/tests.rs | 129 ++- pop-api/examples/balance-transfer/lib.rs | 3 +- pop-api/examples/nfts/lib.rs | 49 +- pop-api/examples/place-spot-order/lib.rs | 14 +- pop-api/examples/read-runtime-state/lib.rs | 55 +- .../integration-tests/contracts/.gitignore | 9 + .../create_token_in_constructor/Cargo.toml | 21 + .../create_token_in_constructor/lib.rs | 46 ++ .../contracts/fungibles/lib.rs | 100 +-- .../integration-tests/src/fungibles/mod.rs | 546 +++++++++++++ .../integration-tests/src/fungibles/utils.rs | 360 +++++++++ pop-api/integration-tests/src/lib.rs | 2 +- .../integration-tests/src/local_fungibles.rs | 738 ------------------ pop-api/src/lib.rs | 18 +- pop-api/src/v0/assets/fungibles.rs | 344 ++++---- runtime/devnet/src/config/api.rs | 6 +- 17 files changed, 1559 insertions(+), 1103 deletions(-) create mode 100755 pop-api/integration-tests/contracts/.gitignore create mode 100755 pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml create mode 100755 pop-api/integration-tests/contracts/create_token_in_constructor/lib.rs create mode 100644 pop-api/integration-tests/src/fungibles/mod.rs create mode 100644 pop-api/integration-tests/src/fungibles/utils.rs delete mode 100644 pop-api/integration-tests/src/local_fungibles.rs diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index 9fb444f8..eefad0e1 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -28,6 +28,7 @@ type BalanceOf = > as Inspect< #[frame_support::pallet] pub mod pallet { use super::*; + use core::cmp::Ordering::*; use frame_support::{ dispatch::{DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo}, pallet_prelude::*, @@ -75,6 +76,9 @@ pub mod pallet { /// Token decimals for a given asset ID. #[codec(index = 10)] TokenDecimals(AssetIdOf), + /// Check if token with a given asset ID exists. + #[codec(index = 18)] + AssetExists(AssetIdOf), } /// Configure the pallet by specifying the parameters and types on which it depends. @@ -95,49 +99,49 @@ pub mod pallet { /// `data` in unspecified format. /// /// # Parameters - /// * `id` - The ID of the asset. - /// * `to` - The recipient account. - /// * `value` - The number of tokens to transfer. + /// - `id` - The ID of the asset. + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. #[pallet::call_index(3)] #[pallet::weight(AssetsWeightInfoOf::::transfer_keep_alive())] pub fn transfer( origin: OriginFor, id: AssetIdOf, - target: AccountIdOf, - amount: BalanceOf, + to: AccountIdOf, + value: BalanceOf, ) -> DispatchResult { - let target = T::Lookup::unlookup(target); - AssetsOf::::transfer_keep_alive(origin, id.into(), target, amount) + let to = T::Lookup::unlookup(to); + AssetsOf::::transfer_keep_alive(origin, id.into(), to, value) } - /// Transfers `value` amount of tokens from the delegated account approved by the `owner` to - /// account `to`, with additional `data` in unspecified format. + /// Transfers `value` amount tokens on behalf of `from` to account `to` with additional `data` + /// in unspecified format. /// /// # Parameters - /// * `id` - The ID of the asset. - /// * `owner` - The account from which the asset balance will be withdrawn. - /// * `to` - The recipient account. - /// * `value` - The number of tokens to transfer. + /// - `id` - The ID of the asset. + /// - `owner` - The account from which the asset balance will be withdrawn. + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. #[pallet::call_index(4)] #[pallet::weight(AssetsWeightInfoOf::::transfer_approved())] pub fn transfer_from( origin: OriginFor, id: AssetIdOf, - owner: AccountIdOf, - target: AccountIdOf, - amount: BalanceOf, + from: AccountIdOf, + to: AccountIdOf, + value: BalanceOf, ) -> DispatchResult { - let owner = T::Lookup::unlookup(owner); - let target = T::Lookup::unlookup(target); - AssetsOf::::transfer_approved(origin, id.into(), owner, target, amount) + let from = T::Lookup::unlookup(from); + let to = T::Lookup::unlookup(to); + AssetsOf::::transfer_approved(origin, id.into(), from, to, value) } /// Approves an account to spend a specified number of tokens on behalf of the caller. /// /// # Parameters - /// * `id` - The ID of the asset. - /// * `spender` - The account that is allowed to spend the tokens. - /// * `value` - The number of tokens to approve. + /// - `id` - The ID of the asset. + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to approve. #[pallet::call_index(5)] #[pallet::weight(::WeightInfo::approve(1, 1))] pub fn approve( @@ -152,30 +156,32 @@ pub mod pallet { let spender = T::Lookup::unlookup(spender); let id: AssetIdParameterOf = id.into(); - // If the new value is equal to the current allowance, do nothing. - let return_weight = if value == current_allowance { - Self::weight_approve(0, 0) - } - // If the new value is greater than the current allowance, approve the difference - // because `approve_transfer` works additively (see `pallet-assets`). - else if value > current_allowance { - AssetsOf::::approve_transfer( - origin, - id, - spender, - value.saturating_sub(current_allowance), - ) - .map_err(|e| e.with_weight(Self::weight_approve(1, 0)))?; - Self::weight_approve(1, 0) - } else { - // If the new value is less than the current allowance, cancel the approval and set the new value - AssetsOf::::cancel_approval(origin.clone(), id.clone(), spender.clone()) - .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; - if value.is_zero() { - return Ok(Some(Self::weight_approve(0, 1)).into()); - } - AssetsOf::::approve_transfer(origin, id, spender, value)?; - Self::weight_approve(1, 1) + let return_weight = match value.cmp(¤t_allowance) { + // If the new value is equal to the current allowance, do nothing. + Equal => Self::weight_approve(0, 0), + // If the new value is greater than the current allowance, approve the difference + // because `approve_transfer` works additively (see `pallet-assets`). + Greater => { + AssetsOf::::approve_transfer( + origin, + id, + spender, + value.saturating_sub(current_allowance), + ) + .map_err(|e| e.with_weight(Self::weight_approve(1, 0)))?; + Self::weight_approve(1, 0) + }, + // If the new value is less than the current allowance, cancel the approval and + // set the new value. + Less => { + AssetsOf::::cancel_approval(origin.clone(), id.clone(), spender.clone()) + .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; + if value.is_zero() { + return Ok(Some(Self::weight_approve(0, 1)).into()); + } + AssetsOf::::approve_transfer(origin, id, spender, value)?; + Self::weight_approve(1, 1) + }, }; Ok(Some(return_weight).into()) } @@ -183,9 +189,9 @@ pub mod pallet { /// Increases the allowance of a spender. /// /// # Parameters - /// * `id` - The ID of the asset. - /// * `spender` - The account that is allowed to spend the tokens. - /// * `value` - The number of tokens to increase the allowance by. + /// - `id` - The ID of the asset. + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to increase the allowance by. #[pallet::call_index(6)] #[pallet::weight(AssetsWeightInfoOf::::approve_transfer())] pub fn increase_allowance( @@ -201,9 +207,9 @@ pub mod pallet { /// Decreases the allowance of a spender. /// /// # Parameters - /// * `id` - The ID of the asset. - /// * `spender` - The account that is allowed to spend the tokens. - /// * `value` - The number of tokens to decrease the allowance by. + /// - `id` - The ID of the asset. + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to decrease the allowance by. #[pallet::call_index(7)] #[pallet::weight(::WeightInfo::approve(1, 1))] pub fn decrease_allowance( @@ -214,25 +220,118 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin.clone()) .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; - let mut current_allowance = AssetsOf::::allowance(id.clone(), &who, &spender); + let current_allowance = AssetsOf::::allowance(id.clone(), &who, &spender); let spender = T::Lookup::unlookup(spender); let id: AssetIdParameterOf = id.into(); if value.is_zero() { return Ok(Some(Self::weight_approve(0, 0)).into()); } - - current_allowance.saturating_reduce(value); - // Cancel the aproval and set the new value if `current_allowance` is more than zero. + // Cancel the aproval and set the new value if `new_allowance` is more than zero. AssetsOf::::cancel_approval(origin.clone(), id.clone(), spender.clone()) .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; - - if current_allowance.is_zero() { + let new_allowance = current_allowance.saturating_sub(value); + if new_allowance.is_zero() { return Ok(Some(Self::weight_approve(0, 1)).into()); } - AssetsOf::::approve_transfer(origin, id, spender, current_allowance)?; + AssetsOf::::approve_transfer(origin, id, spender, new_allowance)?; Ok(().into()) } + + /// Create a new token with a given asset ID. + /// + /// # Parameters + /// - `id` - The ID of the asset. + /// - `admin` - The account that will administer the asset. + /// - `min_balance` - The minimum balance required for accounts holding this asset. + #[pallet::call_index(11)] + #[pallet::weight(AssetsWeightInfoOf::::create())] + pub fn create( + origin: OriginFor, + id: AssetIdOf, + admin: AccountIdOf, + min_balance: BalanceOf, + ) -> DispatchResult { + let admin = T::Lookup::unlookup(admin); + AssetsOf::::create(origin, id.into(), admin, min_balance) + } + + /// Start the process of destroying a token with a given asset ID. + /// + /// # Parameters + /// - `id` - The ID of the asset. + #[pallet::call_index(12)] + #[pallet::weight(AssetsWeightInfoOf::::start_destroy())] + pub fn start_destroy(origin: OriginFor, id: AssetIdOf) -> DispatchResult { + AssetsOf::::start_destroy(origin, id.into()) + } + + /// Set the metadata for a token with a given asset ID. + /// + /// # Parameters + /// - `id`: The identifier of the asset to update. + /// - `name`: The user friendly name of this asset. Limited in length by + /// `pallet_assets::Config::StringLimit`. + /// - `symbol`: The exchange symbol for this asset. Limited in length by + /// `pallet_assets::Config::StringLimit`. + /// - `decimals`: The number of decimals this asset uses to represent one unit. + #[pallet::call_index(16)] + #[pallet::weight(AssetsWeightInfoOf::::set_metadata(name.len() as u32, symbol.len() as u32))] + pub fn set_metadata( + origin: OriginFor, + id: AssetIdOf, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> DispatchResult { + AssetsOf::::set_metadata(origin, id.into(), name, symbol, decimals) + } + + /// Clear the metadata for a token with a given asset ID. + /// + /// # Parameters + /// - `id` - The ID of the asset. + #[pallet::call_index(17)] + #[pallet::weight(AssetsWeightInfoOf::::clear_metadata())] + pub fn clear_metadata(origin: OriginFor, id: AssetIdOf) -> DispatchResult { + AssetsOf::::clear_metadata(origin, id.into()) + } + + /// Creates `value` amount tokens and assigns them to `account`, increasing the total supply. + /// + /// # Parameters + /// - `id` - The ID of the asset. + /// - `account` - The account to be credited with the created tokens. + /// - `value` - The number of tokens to mint. + #[pallet::call_index(19)] + #[pallet::weight(AssetsWeightInfoOf::::mint())] + pub fn mint( + origin: OriginFor, + id: AssetIdOf, + account: AccountIdOf, + value: BalanceOf, + ) -> DispatchResult { + let account = T::Lookup::unlookup(account); + AssetsOf::::mint(origin, id.into(), account, value) + } + + /// Destroys `value` amount tokens from `account`, reducing the total supply. + /// + /// # Parameters + /// - `id` - The ID of the asset. + /// - `account` - The account from which the tokens will be destroyed. + /// - `value` - The number of tokens to destroy. + #[pallet::call_index(20)] + #[pallet::weight(AssetsWeightInfoOf::::burn())] + pub fn burn( + origin: OriginFor, + id: AssetIdOf, + account: AccountIdOf, + value: BalanceOf, + ) -> DispatchResult { + let account = T::Lookup::unlookup(account); + AssetsOf::::burn(origin, id.into(), account, value) + } } impl Pallet { @@ -242,8 +341,8 @@ pub mod pallet { /// encoded result. /// /// # Parameter - /// * `value` - An instance of `Read`, which specifies the type of state query and - /// the associated parameters. + /// - `value` - An instance of `Read`, which specifies the type of state query and + /// the associated parameters. pub fn read_state(value: Read) -> Vec { use Read::*; @@ -262,6 +361,7 @@ pub mod pallet { TokenDecimals(id) => { as MetadataInspect>>::decimals(id).encode() }, + AssetExists(id) => AssetsOf::::asset_exists(id).encode(), } } diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index 4377fc83..d6cc87e0 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -2,7 +2,9 @@ use crate::{fungibles::Read::*, mock::*}; use codec::Encode; use frame_support::{ assert_ok, - traits::fungibles::{approvals::Inspect, metadata::Inspect as MetadataInspect}, + traits::fungibles::{ + approvals::Inspect as ApprovalInspect, metadata::Inspect as MetadataInspect, Inspect, + }, }; const ASSET: u32 = 42; @@ -38,24 +40,6 @@ fn transfer_from_works() { }); } -#[test] -fn decrease_allowance_works() { - new_test_ext().execute_with(|| { - let amount: Balance = 100 * UNIT; - create_asset_mint_and_approve(ALICE, ASSET, ALICE, amount, BOB, amount); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); - // Owner balance is not changed if decreased by zero. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, 0)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); - // Decrease allowance successfully. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, amount / 2 - 1 * UNIT)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount / 2 + 1 * UNIT); - // Saturating if current allowance is decreased more than the owner balance. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, amount)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), 0); - }); -} - // Non-additive, sets new value. #[test] fn approve_works() { @@ -94,6 +78,99 @@ fn increase_allowance_works() { }); } +#[test] +fn decrease_allowance_works() { + new_test_ext().execute_with(|| { + let amount: Balance = 100 * UNIT; + create_asset_mint_and_approve(ALICE, ASSET, ALICE, amount, BOB, amount); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); + // Owner balance is not changed if decreased by zero. + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, 0)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); + // Decrease allowance successfully. + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, amount / 2 - 1 * UNIT)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount / 2 + 1 * UNIT); + // Saturating if current allowance is decreased more than the owner balance. + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, amount)); + assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), 0); + }); +} + +#[test] +fn create_works() { + new_test_ext().execute_with(|| { + assert!(!Assets::asset_exists(ASSET)); + assert_ok!(Fungibles::create(signed(ALICE), ASSET, ALICE, 100)); + assert!(Assets::asset_exists(ASSET)); + }); +} + +#[test] +fn start_destroy_works() { + new_test_ext().execute_with(|| { + create_asset(ALICE, ASSET); + assert_ok!(Fungibles::start_destroy(signed(ALICE), ASSET)); + }); +} + +#[test] +fn set_metadata_works() { + new_test_ext().execute_with(|| { + let name = vec![42]; + let symbol = vec![42]; + let decimals = 42; + create_asset(ALICE, ASSET); + assert_ok!(Fungibles::set_metadata( + signed(ALICE), + ASSET, + name.clone(), + symbol.clone(), + decimals + )); + assert_eq!(Assets::name(ASSET), name); + assert_eq!(Assets::symbol(ASSET), symbol); + assert_eq!(Assets::decimals(ASSET), decimals); + }); +} + +#[test] +fn clear_metadata_works() { + new_test_ext().execute_with(|| { + let name = vec![42]; + let symbol = vec![42]; + let decimals = 42; + create_asset_and_set_metadata(ALICE, ASSET, name, symbol, decimals); + assert_ok!(Fungibles::clear_metadata(signed(ALICE), ASSET)); + assert_eq!(Assets::name(ASSET), Vec::::new()); + assert_eq!(Assets::symbol(ASSET), Vec::::new()); + assert_eq!(Assets::decimals(ASSET), 0u8); + }); +} + +#[test] +fn mint_works() { + new_test_ext().execute_with(|| { + let amount: Balance = 100 * UNIT; + create_asset(ALICE, ASSET); + let balance_before_mint = Assets::balance(ASSET, &BOB); + assert_ok!(Fungibles::mint(signed(ALICE), ASSET, BOB, amount)); + let balance_after_mint = Assets::balance(ASSET, &BOB); + assert_eq!(balance_after_mint, balance_before_mint + amount); + }); +} + +#[test] +fn burn_works() { + new_test_ext().execute_with(|| { + let amount: Balance = 100 * UNIT; + create_asset_and_mint_to(ALICE, ASSET, BOB, amount); + let balance_before_burn = Assets::balance(ASSET, &BOB); + assert_ok!(Fungibles::burn(signed(ALICE), ASSET, BOB, amount)); + let balance_after_burn = Assets::balance(ASSET, &BOB); + assert_eq!(balance_after_burn, balance_before_burn - amount); + }); +} + #[test] fn total_supply_works() { new_test_ext().execute_with(|| { @@ -137,12 +214,20 @@ fn token_metadata_works() { }); } +#[test] +fn asset_exists_works() { + new_test_ext().execute_with(|| { + create_asset(ALICE, ASSET); + assert_eq!(Assets::asset_exists(ASSET).encode(), Fungibles::read_state(AssetExists(ASSET))); + }); +} + fn signed(account: AccountId) -> RuntimeOrigin { RuntimeOrigin::signed(account) } -fn create_asset(owner: AccountId, asset_id: AssetId, min_balance: Balance) { - assert_ok!(Assets::create(signed(owner), asset_id, owner, min_balance)); +fn create_asset(owner: AccountId, asset_id: AssetId) { + assert_ok!(Assets::create(signed(owner), asset_id, owner, 1)); } fn mint_asset(owner: AccountId, asset_id: AssetId, to: AccountId, value: Balance) { @@ -150,7 +235,7 @@ fn mint_asset(owner: AccountId, asset_id: AssetId, to: AccountId, value: Balance } fn create_asset_and_mint_to(owner: AccountId, asset_id: AssetId, to: AccountId, value: Balance) { - create_asset(owner, asset_id, 1); + create_asset(owner, asset_id); mint_asset(owner, asset_id, to, value) } diff --git a/pop-api/examples/balance-transfer/lib.rs b/pop-api/examples/balance-transfer/lib.rs index 328a818b..d36dfa53 100755 --- a/pop-api/examples/balance-transfer/lib.rs +++ b/pop-api/examples/balance-transfer/lib.rs @@ -1,3 +1,4 @@ +// DEPRECATED #![cfg_attr(not(feature = "std"), no_std, no_main)] use pop_api::balances::*; @@ -131,4 +132,4 @@ mod balance_transfer { Ok(()) } } -} \ No newline at end of file +} diff --git a/pop-api/examples/nfts/lib.rs b/pop-api/examples/nfts/lib.rs index d47140e7..7920c179 100755 --- a/pop-api/examples/nfts/lib.rs +++ b/pop-api/examples/nfts/lib.rs @@ -1,3 +1,4 @@ +// DEPRECATED #![cfg_attr(not(feature = "std"), no_std, no_main)] use pop_api::nfts::*; @@ -33,27 +34,29 @@ mod nfts { } #[ink(message)] - pub fn create_nft_collection( &self ) -> Result<(), ContractError>{ + pub fn create_nft_collection(&self) -> Result<(), ContractError> { ink::env::debug_println!("Nfts::create_nft_collection: collection creation started."); - let admin = Self::env().caller(); - let item_settings = ItemSettings(BitFlags::from(ItemSetting::Transferable)); - - let mint_settings = MintSettings { - mint_type: MintType::Issuer, - price: Some(0), - start_block: Some(0), - end_block: Some(0), - default_item_settings: item_settings, - }; - - let config = CollectionConfig { - settings: CollectionSettings(BitFlags::from(CollectionSetting::TransferableItems)), - max_supply: None, - mint_settings, - }; - pop_api::nfts::create(admin, config)?; - ink::env::debug_println!("Nfts::create_nft_collection: collection created successfully."); - Ok(()) + let admin = Self::env().caller(); + let item_settings = ItemSettings(BitFlags::from(ItemSetting::Transferable)); + + let mint_settings = MintSettings { + mint_type: MintType::Issuer, + price: Some(0), + start_block: Some(0), + end_block: Some(0), + default_item_settings: item_settings, + }; + + let config = CollectionConfig { + settings: CollectionSettings(BitFlags::from(CollectionSetting::TransferableItems)), + max_supply: None, + mint_settings, + }; + pop_api::nfts::create(admin, config)?; + ink::env::debug_println!( + "Nfts::create_nft_collection: collection created successfully." + ); + Ok(()) } #[ink(message)] @@ -82,9 +85,7 @@ mod nfts { // check owner match owner(collection_id, item_id)? { Some(owner) if owner == receiver => { - ink::env::debug_println!( - "Nfts::mint success: minted item belongs to receiver" - ); + ink::env::debug_println!("Nfts::mint success: minted item belongs to receiver"); }, _ => { return Err(ContractError::NotOwner); @@ -113,4 +114,4 @@ mod nfts { Nfts::new(); } } -} \ No newline at end of file +} diff --git a/pop-api/examples/place-spot-order/lib.rs b/pop-api/examples/place-spot-order/lib.rs index f5e34f7f..669b9190 100755 --- a/pop-api/examples/place-spot-order/lib.rs +++ b/pop-api/examples/place-spot-order/lib.rs @@ -1,3 +1,4 @@ +// DEPRECATED #![cfg_attr(not(feature = "std"), no_std, no_main)] #[ink::contract(env = pop_api::Environment)] @@ -15,11 +16,7 @@ mod spot_order { } #[ink(message)] - pub fn place_spot_order( - &mut self, - max_amount: Balance, - para_id: u32, - ) { + pub fn place_spot_order(&mut self, max_amount: Balance, para_id: u32) { ink::env::debug_println!( "SpotOrder::place_spot_order: max_amount {:?} para_id: {:?} ", max_amount, @@ -28,10 +25,7 @@ mod spot_order { #[allow(unused_variables)] let res = pop_api::cross_chain::coretime::place_spot_order(max_amount, para_id); - ink::env::debug_println!( - "SpotOrder::place_spot_order: res {:?} ", - res, - ); + ink::env::debug_println!("SpotOrder::place_spot_order: res {:?} ", res,); ink::env::debug_println!("SpotOrder::place_spot_order end"); } @@ -46,4 +40,4 @@ mod spot_order { SpotOrder::new(); } } -} \ No newline at end of file +} diff --git a/pop-api/examples/read-runtime-state/lib.rs b/pop-api/examples/read-runtime-state/lib.rs index 05a44108..60ef70f0 100755 --- a/pop-api/examples/read-runtime-state/lib.rs +++ b/pop-api/examples/read-runtime-state/lib.rs @@ -1,35 +1,36 @@ +// DEPRECATED #![cfg_attr(not(feature = "std"), no_std, no_main)] #[ink::contract(env = pop_api::Environment)] mod read_relay_blocknumber { - use pop_api::primitives::storage_keys::{ - ParachainSystemKeys::LastRelayChainBlockNumber, RuntimeStateKeys::ParachainSystem, - }; + use pop_api::primitives::storage_keys::{ + ParachainSystemKeys::LastRelayChainBlockNumber, RuntimeStateKeys::ParachainSystem, + }; - #[ink(event)] - pub struct RelayBlockNumberRead { - value: BlockNumber, - } + #[ink(event)] + pub struct RelayBlockNumberRead { + value: BlockNumber, + } - #[ink(storage)] - #[derive(Default)] - pub struct ReadRelayBlockNumber; + #[ink(storage)] + #[derive(Default)] + pub struct ReadRelayBlockNumber; - impl ReadRelayBlockNumber { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("ReadRelayBlockNumber::new"); - Default::default() - } + impl ReadRelayBlockNumber { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("ReadRelayBlockNumber::new"); + Default::default() + } - #[ink(message)] - pub fn read_relay_block_number(&self) { - let result = - pop_api::state::read::(ParachainSystem(LastRelayChainBlockNumber)); - ink::env::debug_println!("Last relay block number read by contract: {:?}", result); - self.env().emit_event(RelayBlockNumberRead { - value: result.expect("Failed to read relay block number."), - }); - } - } -} \ No newline at end of file + #[ink(message)] + pub fn read_relay_block_number(&self) { + let result = + pop_api::state::read::(ParachainSystem(LastRelayChainBlockNumber)); + ink::env::debug_println!("Last relay block number read by contract: {:?}", result); + self.env().emit_event(RelayBlockNumberRead { + value: result.expect("Failed to read relay block number."), + }); + } + } +} diff --git a/pop-api/integration-tests/contracts/.gitignore b/pop-api/integration-tests/contracts/.gitignore new file mode 100755 index 00000000..d60800c8 --- /dev/null +++ b/pop-api/integration-tests/contracts/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +**/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +**/Cargo.lock diff --git a/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml b/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml new file mode 100755 index 00000000..2c202715 --- /dev/null +++ b/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "create_token_in_constructor" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { version = "5.0.0", default-features = false } +pop-api = { path = "../../..", default-features = false, features = ["fungibles"] } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "pop-api/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/pop-api/integration-tests/contracts/create_token_in_constructor/lib.rs b/pop-api/integration-tests/contracts/create_token_in_constructor/lib.rs new file mode 100755 index 00000000..e9e5d127 --- /dev/null +++ b/pop-api/integration-tests/contracts/create_token_in_constructor/lib.rs @@ -0,0 +1,46 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +use ink::prelude::vec::Vec; +use pop_api::{ + assets::fungibles::{self as api}, + primitives::AssetId, + StatusCode, +}; + +pub type Result = core::result::Result; + +#[ink::contract] +mod create_token_in_constructor { + use super::*; + + #[ink(storage)] + pub struct Fungible { + id: AssetId, + } + + impl Fungible { + #[ink(constructor, payable)] + pub fn new(id: AssetId, min_balance: Balance) -> Result { + let contract = Self { id }; + // AccountId of the contract which will be set to the owner of the fungible token. + let owner = contract.env().account_id(); + api::create(id, owner, min_balance)?; + Ok(contract) + } + + #[ink(message)] + pub fn asset_exists(&self) -> Result { + api::asset_exists(self.id) + } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[ink::test] + fn default_works() { + PopApiFungiblesExample::new(); + } + } +} diff --git a/pop-api/integration-tests/contracts/fungibles/lib.rs b/pop-api/integration-tests/contracts/fungibles/lib.rs index 1b42fec4..239d3a2d 100755 --- a/pop-api/integration-tests/contracts/fungibles/lib.rs +++ b/pop-api/integration-tests/contracts/fungibles/lib.rs @@ -122,55 +122,57 @@ mod fungibles { api::token_decimals(id) } - // 3. Asset Management: - // - create - // - start_destroy - // - destroy_accounts - // - destroy_approvals - // - finish_destroy - // - set_metadata - // - clear_metadata - - // #[ink(message)] - // pub fn create(&self, id: AssetId, admin: AccountId, min_balance: Balance) -> Result<()> { - // ink::env::debug_println!( - // "PopApiFungiblesExample::create: id: {:?} admin: {:?} min_balance: {:?}", - // id, - // admin, - // min_balance, - // ); - // let result = api::create(id, admin, min_balance); - // ink::env::debug_println!("Result: {:?}", result); - // result.map_err(|e| e.into()) - // result - // } - - // #[ink(message)] - // pub fn set_metadata( - // &self, - // id: AssetId, - // name: Vec, - // symbol: Vec, - // decimals: u8, - // ) -> Result<()> { - // ink::env::debug_println!( - // "PopApiFungiblesExample::set_metadata: id: {:?} name: {:?} symbol: {:?}, decimals: {:?}", - // id, - // name, - // symbol, - // decimals, - // ); - // let result = api::set_metadata(id, name, symbol, decimals); - // ink::env::debug_println!("Result: {:?}", result); - // // result.map_err(|e| e.into()) - // result - // } - // - // #[ink(message)] - // pub fn asset_exists(&self, id: AssetId) -> Result { - // // api::asset_exists(id).map_err(|e| e.into()) - // api::asset_exists(id) - // } + /// 3. Asset Management: + /// - create + /// - start_destroy + /// - set_metadata + /// - clear_metadata + /// - asset_exists + + #[ink(message)] + pub fn create(&self, id: AssetId, admin: AccountId, min_balance: Balance) -> Result<()> { + api::create(id, admin, min_balance) + } + + #[ink(message)] + pub fn start_destroy(&self, id: AssetId) -> Result<()> { + api::start_destroy(id) + } + + #[ink(message)] + pub fn set_metadata( + &self, + id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()> { + api::set_metadata(id, name, symbol, decimals) + } + + #[ink(message)] + pub fn clear_metadata(&self, id: AssetId) -> Result<()> { + api::clear_metadata(id) + } + + #[ink(message)] + pub fn asset_exists(&self, id: AssetId) -> Result { + api::asset_exists(id) + } + + /// 4. PSP-22 Mintable & Burnable Interface: + /// - mint + /// - burn + + #[ink(message)] + pub fn mint(&self, id: AssetId, account: AccountId, amount: Balance) -> Result<()> { + api::mint(id, account, amount) + } + + #[ink(message)] + pub fn burn(&self, id: AssetId, account: AccountId, amount: Balance) -> Result<()> { + api::burn(id, account, amount) + } } #[cfg(test)] diff --git a/pop-api/integration-tests/src/fungibles/mod.rs b/pop-api/integration-tests/src/fungibles/mod.rs new file mode 100644 index 00000000..0ca7d4f9 --- /dev/null +++ b/pop-api/integration-tests/src/fungibles/mod.rs @@ -0,0 +1,546 @@ +use super::*; +use pop_primitives::error::{ + ArithmeticError::*, + Error::{self, *}, + TokenError::*, +}; +use utils::*; + +mod utils; + +const ASSET_ID: AssetId = 1; +const CONTRACT: &str = "contracts/fungibles/target/ink/fungibles.wasm"; + +/// 1. PSP-22 Interface: +/// - total_supply +/// - balance_of +/// - allowance +/// - transfer +/// - transfer_from +/// - approve +/// - increase_allowance +/// - decrease_allowance + +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + // No tokens in circulation. + assert_eq!(total_supply(addr.clone(), ASSET_ID), Ok(Assets::total_supply(ASSET_ID))); + assert_eq!(total_supply(addr.clone(), ASSET_ID), Ok(0)); + + // Tokens in circulation. + create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); + assert_eq!(total_supply(addr.clone(), ASSET_ID), Ok(Assets::total_supply(ASSET_ID))); + assert_eq!(total_supply(addr, ASSET_ID), Ok(100)); + }); +} + +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + // No tokens in circulation. + assert_eq!(balance_of(addr.clone(), ASSET_ID, BOB), Ok(Assets::balance(ASSET_ID, BOB))); + assert_eq!(balance_of(addr.clone(), ASSET_ID, BOB), Ok(0)); + + // Tokens in circulation. + create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); + assert_eq!(balance_of(addr.clone(), ASSET_ID, BOB), Ok(Assets::balance(ASSET_ID, BOB))); + assert_eq!(balance_of(addr, ASSET_ID, BOB), Ok(100)); + }); +} + +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + // No tokens in circulation. + assert_eq!( + allowance(addr.clone(), ASSET_ID, BOB, ALICE), + Ok(Assets::allowance(ASSET_ID, &BOB, &ALICE)) + ); + assert_eq!(allowance(addr.clone(), ASSET_ID, BOB, ALICE), Ok(0)); + + // Tokens in circulation. + create_asset_mint_and_approve(addr.clone(), ASSET_ID, BOB, 100, ALICE, 50); + assert_eq!( + allowance(addr.clone(), ASSET_ID, BOB, ALICE), + Ok(Assets::allowance(ASSET_ID, &BOB, &ALICE)) + ); + assert_eq!(allowance(addr, ASSET_ID, BOB, ALICE), Ok(50)); + }); +} + +#[test] +fn transfer_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let amount: Balance = 100 * UNIT; + + // Asset does not exist. + assert_eq!(transfer(addr.clone(), 1, BOB, amount), Err(Module { index: 52, error: 3 })); + // Create asset with Alice as owner and mint `amount` to contract address. + let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(ALICE, asset); + assert_eq!( + transfer(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: 16 }) + ); + thaw_asset(ALICE, asset); + // Not enough balance. + assert_eq!( + transfer(addr.clone(), asset, BOB, amount + 1 * UNIT), + Err(Module { index: 52, error: 0 }) + ); + // Not enough balance due to ED. + assert_eq!(transfer(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 0 })); + // Successful transfer. + let balance_before_transfer = Assets::balance(asset, &BOB); + assert_ok!(transfer(addr.clone(), asset, BOB, amount / 2)); + let balance_after_transfer = Assets::balance(asset, &BOB); + assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2); + // Transfer asset to account that does not exist. + assert_eq!(transfer(addr.clone(), asset, FERDIE, amount / 4), Err(Token(CannotCreate))); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(ALICE, asset); + assert_eq!( + transfer(addr.clone(), asset, BOB, amount / 4), + Err(Module { index: 52, error: 16 }) + ); + }); +} + +#[test] +fn transfer_from_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let amount: Balance = 100 * UNIT; + + // Asset does not exist. + assert_eq!( + transfer_from(addr.clone(), 1, ALICE, BOB, amount / 2), + Err(Module { index: 52, error: 3 }), + ); + // Create asset with Alice as owner and mint `amount` to contract address. + let asset = create_asset_and_mint_to(ALICE, 1, ALICE, amount); + // Unapproved transfer. + assert_eq!( + transfer_from(addr.clone(), asset, ALICE, BOB, amount / 2), + Err(Module { index: 52, error: 10 }) + ); + assert_ok!(Assets::approve_transfer( + RuntimeOrigin::signed(ALICE.into()), + asset.into(), + addr.clone().into(), + amount + 1 * UNIT, + )); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(ALICE, asset); + assert_eq!( + transfer_from(addr.clone(), asset, ALICE, BOB, amount), + Err(Module { index: 52, error: 16 }), + ); + thaw_asset(ALICE, asset); + // Not enough balance. + assert_eq!( + transfer_from(addr.clone(), asset, ALICE, BOB, amount + 1 * UNIT), + Err(Module { index: 52, error: 0 }), + ); + // Successful transfer. + let balance_before_transfer = Assets::balance(asset, &BOB); + assert_ok!(transfer_from(addr.clone(), asset, ALICE, BOB, amount / 2)); + let balance_after_transfer = Assets::balance(asset, &BOB); + assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2); + }); +} + +#[test] +fn approve_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, 0, vec![]); + let amount: Balance = 100 * UNIT; + + // Asset does not exist. + assert_eq!(approve(addr.clone(), 0, BOB, amount), Err(Module { index: 52, error: 3 })); + let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); + assert_eq!(approve(addr.clone(), asset, BOB, amount), Err(ConsumerRemaining)); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); + // Create asset with Alice as owner and mint `amount` to contract address. + let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(ALICE, asset); + assert_eq!(approve(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + thaw_asset(ALICE, asset); + // Successful approvals: + assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); + assert_ok!(approve(addr.clone(), asset, BOB, amount)); + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount); + // Non-additive, sets new value. + assert_ok!(approve(addr.clone(), asset, BOB, amount / 2)); + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount / 2); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(ALICE, asset); + assert_eq!(approve(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + }); +} + +#[test] +fn increase_allowance_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let amount: Balance = 100 * UNIT; + // Instantiate a contract without balance - test `ConsumerRemaining. + let addr = instantiate(CONTRACT, 0, vec![]); + // Asset does not exist. + assert_eq!( + increase_allowance(addr.clone(), 0, BOB, amount), + Err(Module { index: 52, error: 3 }) + ); + let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); + assert_eq!(increase_allowance(addr.clone(), asset, BOB, amount), Err(ConsumerRemaining)); + + // Instantiate a contract with balance. + let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); + // Create asset with Alice as owner and mint `amount` to contract address. + let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(ALICE, asset); + assert_eq!( + increase_allowance(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: 16 }) + ); + thaw_asset(ALICE, asset); + // Successful approvals: + assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); + assert_ok!(increase_allowance(addr.clone(), asset, BOB, amount)); + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount); + // Additive. + assert_ok!(increase_allowance(addr.clone(), asset, BOB, amount)); + assert_eq!(Assets::allowance(asset, &addr, &BOB), amount * 2); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(ALICE, asset); + assert_eq!( + increase_allowance(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: 16 }) + ); + }); +} + +#[test] +fn decrease_allowance_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let amount: Balance = 100 * UNIT; + + // Asset does not exist. + assert_eq!( + decrease_allowance(addr.clone(), 0, BOB, amount), + Err(Module { index: 52, error: 3 }), + ); + // Create asset and mint `amount` to contract address, then approve Bob to spend `amount`. + let asset = + create_asset_mint_and_approve(addr.clone(), 0, addr.clone(), amount, BOB, amount); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(addr.clone(), asset); + assert_eq!( + decrease_allowance(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: 16 }), + ); + thaw_asset(addr.clone(), asset); + // Successfully decrease allowance. + let allowance_before = Assets::allowance(asset, &addr, &BOB); + assert_ok!(decrease_allowance(addr.clone(), 0, BOB, amount / 2 - 1 * UNIT)); + let allowance_after = Assets::allowance(asset, &addr, &BOB); + assert_eq!(allowance_before - allowance_after, amount / 2 - 1 * UNIT); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(addr.clone(), asset); + assert_eq!( + decrease_allowance(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: 16 }), + ); + }); +} + +/// 2. PSP-22 Metadata Interface: +/// - token_name +/// - token_symbol +/// - token_decimals + +#[test] +fn token_metadata_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let name: Vec = vec![11, 12, 13]; + let symbol: Vec = vec![21, 22, 23]; + let decimals: u8 = 69; + + // Token does not exist. + assert_eq!(token_name(addr.clone(), ASSET_ID), Ok(token_name_asset(ASSET_ID))); + assert_eq!(token_name(addr.clone(), ASSET_ID), Ok(Vec::::new())); + assert_eq!(token_symbol(addr.clone(), ASSET_ID), Ok(token_symbol_asset(ASSET_ID))); + assert_eq!(token_symbol(addr.clone(), ASSET_ID), Ok(Vec::::new())); + assert_eq!(token_decimals(addr.clone(), ASSET_ID), Ok(token_decimals_asset(ASSET_ID))); + assert_eq!(token_decimals(addr.clone(), ASSET_ID), Ok(0)); + // Create Token. + create_asset_and_set_metadata( + addr.clone(), + ASSET_ID, + name.clone(), + symbol.clone(), + decimals, + ); + assert_eq!(token_name(addr.clone(), ASSET_ID), Ok(token_name_asset(ASSET_ID))); + assert_eq!(token_name(addr.clone(), ASSET_ID), Ok(name)); + assert_eq!(token_symbol(addr.clone(), ASSET_ID), Ok(token_symbol_asset(ASSET_ID))); + assert_eq!(token_symbol(addr.clone(), ASSET_ID), Ok(symbol)); + assert_eq!(token_decimals(addr.clone(), ASSET_ID), Ok(token_decimals_asset(ASSET_ID))); + assert_eq!(token_decimals(addr.clone(), ASSET_ID), Ok(decimals)); + }); +} + +/// 3. Asset Management: +/// - create +/// - start_destroy +/// - set_metadata +/// - clear_metadata +/// - asset_exists + +#[test] +fn create_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + // Instantiate a contract without balance for fees. + let addr = instantiate(CONTRACT, 0, vec![0]); + // No balance to pay for fees. + assert_eq!( + create(addr.clone(), ASSET_ID, addr.clone(), 1), + Err(Module { index: 10, error: 2 }), + ); + + // Instantiate a contract without balance for deposit. + let addr = instantiate(CONTRACT, 100, vec![1]); + // No balance to pay the deposit. + assert_eq!( + create(addr.clone(), ASSET_ID, addr.clone(), 1), + Err(Module { index: 10, error: 2 }), + ); + + // Instantiate a contract with enough balance. + let addr = instantiate(CONTRACT, INIT_VALUE, vec![2]); + assert_eq!(create(addr.clone(), ASSET_ID, BOB, 0), Err(Module { index: 52, error: 7 }),); + // The minimal balance for an asset must be non zero. + assert_eq!(create(addr.clone(), ASSET_ID, BOB, 0), Err(Module { index: 52, error: 7 }),); + // Create asset successfully. + assert_ok!(create(addr.clone(), ASSET_ID, BOB, 1)); + // Asset ID is already taken. + assert_eq!(create(addr.clone(), ASSET_ID, BOB, 1), Err(Module { index: 52, error: 5 }),); + }); +} + +// Testing a contract that creates an asset in the constructor. +#[test] +fn instantiate_and_create_fungible_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let contract = + "contracts/create_token_in_constructor/target/ink/create_token_in_constructor.wasm"; + // Asset already exists. + create_asset(ALICE, 0, 1); + assert_eq!( + instantiate_and_create_fungible(contract, 0, 1), + Err(Module { index: 52, error: 5 }) + ); + // Successfully create an asset when instantiating the contract. + assert_ok!(instantiate_and_create_fungible(contract, ASSET_ID, 1)); + assert!(Assets::asset_exists(ASSET_ID)); + }); +} + +#[test] +fn start_destroy_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![2]); + + // Asset does not exist. + assert_eq!(start_destroy(addr.clone(), ASSET_ID), Err(Module { index: 52, error: 3 }),); + // Create assets where contract is not the owner. + let asset = create_asset(ALICE, 0, 1); + // No Permission. + assert_eq!(start_destroy(addr.clone(), asset), Err(Module { index: 52, error: 2 }),); + let asset = create_asset(addr.clone(), ASSET_ID, 1); + assert_ok!(start_destroy(addr.clone(), asset)); + }); +} + +#[test] +fn set_metadata_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let name = vec![42]; + let symbol = vec![42]; + let decimals = 42u8; + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + // Asset does not exist. + assert_eq!( + set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], 0u8), + Err(Module { index: 52, error: 3 }), + ); + // Create assets where contract is not the owner. + let asset = create_asset(ALICE, 0, 1); + // No Permission. + assert_eq!( + set_metadata(addr.clone(), asset, vec![0], vec![0], 0u8), + Err(Module { index: 52, error: 2 }), + ); + let asset = create_asset(addr.clone(), ASSET_ID, 1); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(addr.clone(), asset); + assert_eq!( + set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], 0u8), + Err(Module { index: 52, error: 16 }), + ); + thaw_asset(addr.clone(), asset); + // TODO: calling the below with a vector of length `100_000` errors in pallet contracts + // `OutputBufferTooSmall. Added to security analysis issue #131 to revisit. + // Set bad metadata - too large values. + assert_eq!( + set_metadata(addr.clone(), ASSET_ID, vec![0; 1000], vec![0; 1000], 0u8), + Err(Module { index: 52, error: 9 }), + ); + // Set metadata successfully. + assert_ok!(set_metadata(addr.clone(), ASSET_ID, name, symbol, decimals)); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(addr.clone(), asset); + assert_eq!( + set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], 0), + Err(Module { index: 52, error: 16 }), + ); + }); +} + +#[test] +fn clear_metadata_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let name = vec![42]; + let symbol = vec![42]; + let decimals = 42u8; + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + // Asset does not exist. + assert_eq!(clear_metadata(addr.clone(), 0), Err(Module { index: 52, error: 3 }),); + // Create assets where contract is not the owner. + let asset = create_asset_and_set_metadata(ALICE, 0, vec![0], vec![0], 0); + // No Permission. + assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: 2 }),); + let asset = create_asset(addr.clone(), ASSET_ID, 1); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(addr.clone(), asset); + assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: 16 }),); + thaw_asset(addr.clone(), asset); + // No metadata set. + assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: 3 }),); + set_metadata_asset(addr.clone(), asset, name, symbol, decimals); + // Clear metadata successfully. + assert_ok!(clear_metadata(addr.clone(), ASSET_ID)); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(addr.clone(), asset); + assert_eq!( + set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], decimals), + Err(Module { index: 52, error: 16 }), + ); + }); +} + +#[test] +fn asset_exists_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + // No tokens in circulation. + assert_eq!(asset_exists(addr.clone(), ASSET_ID), Ok(Assets::asset_exists(ASSET_ID))); + + // Tokens in circulation. + create_asset(addr.clone(), ASSET_ID, 1); + assert_eq!(asset_exists(addr.clone(), ASSET_ID), Ok(Assets::asset_exists(ASSET_ID))); + }); +} + +#[test] +fn mint_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let amount: Balance = 100 * UNIT; + + // Asset does not exist. + assert_eq!(mint(addr.clone(), 1, BOB, amount), Err(Token(UnknownAsset))); + let asset = create_asset(ALICE, 1, 1); + // Minting can only be done by the owner. + assert_eq!(mint(addr.clone(), asset, BOB, 1), Err(Module { index: 52, error: 2 })); + let asset = create_asset(addr.clone(), 2, 2); + // Minimum balance of an asset can not be zero. + assert_eq!(mint(addr.clone(), asset, BOB, 1), Err(Token(BelowMinimum))); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(addr.clone(), asset); + assert_eq!(mint(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + thaw_asset(addr.clone(), asset); + // Successful mint. + let balance_before_mint = Assets::balance(asset, &BOB); + assert_ok!(mint(addr.clone(), asset, BOB, amount)); + let balance_after_mint = Assets::balance(asset, &BOB); + assert_eq!(balance_after_mint, balance_before_mint + amount); + // Account can not hold more tokens than Balance::MAX. + assert_eq!(mint(addr.clone(), asset, BOB, Balance::MAX,), Err(Arithmetic(Overflow))); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(addr.clone(), asset); + assert_eq!(mint(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + }); +} + +#[test] +fn burn_works() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let amount: Balance = 100 * UNIT; + + // Asset does not exist. + assert_eq!(burn(addr.clone(), 1, BOB, amount), Err(Module { index: 52, error: 3 })); + let asset = create_asset(ALICE, 1, 1); + // Bob has no tokens and thus pallet assets doesn't know the account. + assert_eq!(burn(addr.clone(), asset, BOB, 1), Err(Module { index: 52, error: 1 })); + // Burning can only be done by the manager. + mint_asset(ALICE, asset, BOB, amount); + assert_eq!(burn(addr.clone(), asset, BOB, 1), Err(Module { index: 52, error: 2 })); + let asset = create_asset_and_mint_to(addr.clone(), 2, BOB, amount); + // Asset is not live, i.e. frozen or being destroyed. + freeze_asset(addr.clone(), asset); + assert_eq!(burn(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + thaw_asset(addr.clone(), asset); + // Successful mint. + let balance_before_burn = Assets::balance(asset, &BOB); + assert_ok!(burn(addr.clone(), asset, BOB, amount)); + let balance_after_burn = Assets::balance(asset, &BOB); + assert_eq!(balance_after_burn, balance_before_burn - amount); + // Asset is not live, i.e. frozen or being destroyed. + start_destroy_asset(addr.clone(), asset); + assert_eq!(burn(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + }); +} diff --git a/pop-api/integration-tests/src/fungibles/utils.rs b/pop-api/integration-tests/src/fungibles/utils.rs new file mode 100644 index 00000000..2f9be65c --- /dev/null +++ b/pop-api/integration-tests/src/fungibles/utils.rs @@ -0,0 +1,360 @@ +use super::*; + +pub(super) fn decoded(result: ExecReturnValue) -> Result { + ::decode(&mut &result.data[1..]).map_err(|_| result) +} + +pub(super) fn total_supply(addr: AccountId32, asset_id: AssetId) -> Result { + let function = function_selector("total_supply"); + let params = [function, asset_id.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn balance_of( + addr: AccountId32, + asset_id: AssetId, + owner: AccountId32, +) -> Result { + let function = function_selector("balance_of"); + let params = [function, asset_id.encode(), owner.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn allowance( + addr: AccountId32, + asset_id: AssetId, + owner: AccountId32, + spender: AccountId32, +) -> Result { + let function = function_selector("allowance"); + let params = [function, asset_id.encode(), owner.encode(), spender.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn token_name(addr: AccountId32, asset_id: AssetId) -> Result, Error> { + let function = function_selector("token_name"); + let params = [function, asset_id.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::, Error>>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn token_symbol(addr: AccountId32, asset_id: AssetId) -> Result, Error> { + let function = function_selector("token_symbol"); + let params = [function, asset_id.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::, Error>>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn token_decimals(addr: AccountId32, asset_id: AssetId) -> Result { + let function = function_selector("token_decimals"); + let params = [function, asset_id.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn asset_exists(addr: AccountId32, asset_id: AssetId) -> Result { + let function = function_selector("asset_exists"); + let params = [function, asset_id.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn transfer( + addr: AccountId32, + asset_id: AssetId, + to: AccountId32, + value: Balance, +) -> Result<(), Error> { + let function = function_selector("transfer"); + let params = [function, asset_id.encode(), to.encode(), value.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn transfer_from( + addr: AccountId32, + asset_id: AssetId, + from: AccountId32, + to: AccountId32, + value: Balance, +) -> Result<(), Error> { + let function = function_selector("transfer_from"); + let data: Vec = vec![]; + let params = + [function, asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()] + .concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn approve( + addr: AccountId32, + asset_id: AssetId, + spender: AccountId32, + value: Balance, +) -> Result<(), Error> { + let function = function_selector("approve"); + let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn increase_allowance( + addr: AccountId32, + asset_id: AssetId, + spender: AccountId32, + value: Balance, +) -> Result<(), Error> { + let function = function_selector("increase_allowance"); + let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn decrease_allowance( + addr: AccountId32, + asset_id: AssetId, + spender: AccountId32, + value: Balance, +) -> Result<(), Error> { + let function = function_selector("decrease_allowance"); + let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn create( + addr: AccountId32, + asset_id: AssetId, + admin: AccountId32, + min_balance: Balance, +) -> Result<(), Error> { + let function = function_selector("create"); + let params = [function, asset_id.encode(), admin.encode(), min_balance.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn start_destroy(addr: AccountId32, asset_id: AssetId) -> Result<(), Error> { + let function = function_selector("start_destroy"); + let params = [function, asset_id.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + match decoded::>(result) { + Ok(x) => x, + Err(result) => panic!("Contract reverted: {:?}", result), + } +} + +pub(super) fn set_metadata( + addr: AccountId32, + asset_id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, +) -> Result<(), Error> { + let function = function_selector("set_metadata"); + let params = + [function, asset_id.encode(), name.encode(), symbol.encode(), decimals.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn clear_metadata(addr: AccountId32, asset_id: AssetId) -> Result<(), Error> { + let function = function_selector("clear_metadata"); + let params = [function, asset_id.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn mint( + addr: AccountId32, + asset_id: AssetId, + account: AccountId32, + amount: Balance, +) -> Result<(), Error> { + let function = function_selector("mint"); + let params = [function, asset_id.encode(), account.encode(), amount.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn burn( + addr: AccountId32, + asset_id: AssetId, + account: AccountId32, + amount: Balance, +) -> Result<(), Error> { + let function = function_selector("burn"); + let params = [function, asset_id.encode(), account.encode(), amount.encode()].concat(); + let result = bare_call(addr, params, 0).expect("should work"); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn create_asset(owner: AccountId32, asset_id: AssetId, min_balance: Balance) -> AssetId { + assert_ok!(Assets::create( + RuntimeOrigin::signed(owner.clone()), + asset_id.into(), + owner.into(), + min_balance + )); + asset_id +} + +pub(super) fn mint_asset( + owner: AccountId32, + asset_id: AssetId, + to: AccountId32, + value: Balance, +) -> AssetId { + assert_ok!(Assets::mint( + RuntimeOrigin::signed(owner.clone()), + asset_id.into(), + to.into(), + value + )); + asset_id +} + +pub(super) fn create_asset_and_mint_to( + owner: AccountId32, + asset_id: AssetId, + to: AccountId32, + value: Balance, +) -> AssetId { + create_asset(owner.clone(), asset_id, 1); + mint_asset(owner, asset_id, to, value) +} + +// Create an asset, mints to, and approves spender. +pub(super) fn create_asset_mint_and_approve( + owner: AccountId32, + asset_id: AssetId, + to: AccountId32, + mint: Balance, + spender: AccountId32, + approve: Balance, +) -> AssetId { + create_asset_and_mint_to(owner.clone(), asset_id, to.clone(), mint); + assert_ok!(Assets::approve_transfer( + RuntimeOrigin::signed(to.into()), + asset_id.into(), + spender.into(), + approve, + )); + asset_id +} + +// Freeze an asset. +pub(super) fn freeze_asset(owner: AccountId32, asset_id: AssetId) { + assert_ok!(Assets::freeze_asset(RuntimeOrigin::signed(owner.into()), asset_id.into())); +} + +// Thaw an asset. +pub(super) fn thaw_asset(owner: AccountId32, asset_id: AssetId) { + assert_ok!(Assets::thaw_asset(RuntimeOrigin::signed(owner.into()), asset_id.into())); +} + +// Start destroying an asset. +pub(super) fn start_destroy_asset(owner: AccountId32, asset_id: AssetId) { + assert_ok!(Assets::start_destroy(RuntimeOrigin::signed(owner.into()), asset_id.into())); +} + +// Create an asset and set metadata. +pub(super) fn create_asset_and_set_metadata( + owner: AccountId32, + asset_id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, +) -> AssetId { + assert_ok!(Assets::create( + RuntimeOrigin::signed(owner.clone()), + asset_id.into(), + owner.clone().into(), + 100 + )); + set_metadata_asset(owner, asset_id, name, symbol, decimals); + asset_id +} + +// Set metadata of an asset. +pub(super) fn set_metadata_asset( + owner: AccountId32, + asset_id: AssetId, + name: Vec, + symbol: Vec, + decimals: u8, +) { + assert_ok!(Assets::set_metadata( + RuntimeOrigin::signed(owner.into()), + asset_id.into(), + name, + symbol, + decimals + )); +} + +pub(super) fn token_name_asset(asset_id: AssetId) -> Vec { + as MetadataInspect>::name( + asset_id, + ) +} + +pub(super) fn token_symbol_asset(asset_id: AssetId) -> Vec { + as MetadataInspect>::symbol( + asset_id, + ) +} + +pub(super) fn token_decimals_asset(asset_id: AssetId) -> u8 { + as MetadataInspect>::decimals( + asset_id, + ) +} + +pub(super) fn instantiate_and_create_fungible( + contract: &str, + asset_id: AssetId, + min_balance: Balance, +) -> Result<(), Error> { + let function = function_selector("new"); + let input = [function, asset_id.encode(), min_balance.encode()].concat(); + let (wasm_binary, _) = + load_wasm_module::(contract).expect("could not read .wasm file"); + let result = Contracts::bare_instantiate( + ALICE, + INIT_VALUE, + GAS_LIMIT, + None, + Code::Upload(wasm_binary), + input, + vec![], + DEBUG_OUTPUT, + CollectEvents::Skip, + ) + .result + .expect("should work") + .result; + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} diff --git a/pop-api/integration-tests/src/lib.rs b/pop-api/integration-tests/src/lib.rs index ea5ccb05..b728fca6 100644 --- a/pop-api/integration-tests/src/lib.rs +++ b/pop-api/integration-tests/src/lib.rs @@ -16,7 +16,7 @@ use pop_runtime_devnet::{ UNIT, }; -mod local_fungibles; +mod fungibles; type AssetId = u32; type Balance = u128; diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs deleted file mode 100644 index 15a644ad..00000000 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ /dev/null @@ -1,738 +0,0 @@ -use super::*; -use pop_primitives::error::{ - ArithmeticError::*, - Error::{self, *}, - TokenError::*, -}; - -const ASSET_ID: AssetId = 1; -const CONTRACT: &str = "contracts/fungibles/target/ink/fungibles.wasm"; - -fn decoded(result: ExecReturnValue) -> Result { - ::decode(&mut &result.data[2..]) - .map_err(|_| format!("\nTest failed by trying to decode `{:?}` into `T`\n", result)) -} - -// Call total_supply contract message. -fn total_supply(addr: AccountId32, asset_id: AssetId) -> Balance { - let function = function_selector("total_supply"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result).unwrap() -} - -// Call balance_of contract message. -fn balance_of(addr: AccountId32, asset_id: AssetId, owner: AccountId32) -> Balance { - let function = function_selector("balance_of"); - let params = [function, asset_id.encode(), owner.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result).unwrap() -} - -// Call allowance contract message. -fn allowance( - addr: AccountId32, - asset_id: AssetId, - owner: AccountId32, - spender: AccountId32, -) -> Balance { - let function = function_selector("allowance"); - let params = [function, asset_id.encode(), owner.encode(), spender.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result).unwrap() -} - -// Call token_name contract message. -fn token_name(addr: AccountId32, asset_id: AssetId) -> Vec { - let function = function_selector("token_name"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - decoded::>(result).unwrap() -} - -// Call token_symbol contract message. -fn token_symbol(addr: AccountId32, asset_id: AssetId) -> Vec { - let function = function_selector("token_symbol"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - decoded::>(result).unwrap() -} - -// Call token_decimals contract message. -fn token_decimals(addr: AccountId32, asset_id: AssetId) -> u8 { - let function = function_selector("token_decimals"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result).unwrap() -} - -fn transfer( - addr: AccountId32, - asset_id: AssetId, - to: AccountId32, - value: Balance, -) -> ExecReturnValue { - let function = function_selector("transfer"); - let params = [function, asset_id.encode(), to.encode(), value.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - result -} - -fn transfer_from( - addr: AccountId32, - asset_id: AssetId, - from: AccountId32, - to: AccountId32, - value: Balance, -) -> ExecReturnValue { - let function = function_selector("transfer_from"); - let data: Vec = vec![]; - let params = - [function, asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()] - .concat(); - let result = bare_call(addr, params, 0).expect("should work"); - result -} - -fn approve( - addr: AccountId32, - asset_id: AssetId, - spender: AccountId32, - value: Balance, -) -> ExecReturnValue { - let function = function_selector("approve"); - let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - result -} - -fn increase_allowance( - addr: AccountId32, - asset_id: AssetId, - spender: AccountId32, - value: Balance, -) -> ExecReturnValue { - let function = function_selector("increase_allowance"); - let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - result -} - -fn decrease_allowance( - addr: AccountId32, - asset_id: AssetId, - spender: AccountId32, - value: Balance, -) -> ExecReturnValue { - let function = function_selector("decrease_allowance"); - let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); - result -} - -// fn asset_exists(addr: AccountId32, asset_id: AssetId) -> bool { -// let function = function_selector("asset_exists"); -// let params = [function, asset_id.encode()].concat(); -// let result = bare_call(addr, params, 0).expect("should work"); -// decoded::(result) -// } -// -// fn create( -// addr: AccountId32, -// asset_id: AssetId, -// admin: AccountId32, -// min_balance: Balance, -// ) -> ExecReturnValue { -// let function = function_selector("create"); -// let params = [function, asset_id.encode(), admin.encode(), min_balance.encode()].concat(); -// bare_call(addr, params, 0).expect("should work") -// } -// -// fn set_metadata( -// addr: AccountId32, -// asset_id: AssetId, -// name: Vec, -// symbol: Vec, -// decimals: u8, -// ) -> ExecReturnValue { -// let function = function_selector("set_metadata"); -// let params = -// [function, asset_id.encode(), name.encode(), symbol.encode(), decimals.encode()].concat(); -// bare_call(addr, params, 0).expect("should work") -// } - -fn create_asset(owner: AccountId32, asset_id: AssetId, min_balance: Balance) -> AssetId { - assert_ok!(Assets::create( - RuntimeOrigin::signed(owner.clone()), - asset_id.into(), - owner.into(), - min_balance - )); - asset_id -} - -fn mint_asset(owner: AccountId32, asset_id: AssetId, to: AccountId32, value: Balance) -> AssetId { - assert_ok!(Assets::mint( - RuntimeOrigin::signed(owner.clone()), - asset_id.into(), - to.into(), - value - )); - asset_id -} - -fn create_asset_and_mint_to( - owner: AccountId32, - asset_id: AssetId, - to: AccountId32, - value: Balance, -) -> AssetId { - create_asset(owner.clone(), asset_id, 1); - mint_asset(owner, asset_id, to, value) -} - -// Create an asset, mints to, and approves spender. -fn create_asset_mint_and_approve( - owner: AccountId32, - asset_id: AssetId, - to: AccountId32, - mint: Balance, - spender: AccountId32, - approve: Balance, -) -> AssetId { - let asset = create_asset_and_mint_to(owner.clone(), asset_id, to.clone(), mint); - assert_ok!(Assets::approve_transfer( - RuntimeOrigin::signed(to.into()), - asset_id.into(), - spender.into(), - approve, - )); - asset -} - -// Freeze an asset. -fn freeze_asset(owner: AccountId32, asset_id: AssetId) { - assert_ok!(Assets::freeze_asset(RuntimeOrigin::signed(owner.into()), asset_id.into())); -} - -// Thaw an asset. -fn thaw_asset(owner: AccountId32, asset_id: AssetId) { - assert_ok!(Assets::thaw_asset(RuntimeOrigin::signed(owner.into()), asset_id.into())); -} - -// Start destroying an asset. -fn start_destroy_asset(owner: AccountId32, asset_id: AssetId) { - assert_ok!(Assets::start_destroy(RuntimeOrigin::signed(owner.into()), asset_id.into())); -} - -// Create an asset and set metadata. -fn create_asset_and_set_metadata( - owner: AccountId32, - asset_id: AssetId, - name: Vec, - symbol: Vec, - decimals: u8, -) { - assert_ok!(Assets::create( - RuntimeOrigin::signed(owner.clone()), - asset_id.into(), - owner.clone().into(), - 100 - )); - set_metadata_asset(owner, asset_id, name, symbol, decimals); -} - -// Set metadata of an asset. -fn set_metadata_asset( - owner: AccountId32, - asset_id: AssetId, - name: Vec, - symbol: Vec, - decimals: u8, -) { - assert_ok!(Assets::set_metadata( - RuntimeOrigin::signed(owner.into()), - asset_id.into(), - name, - symbol, - decimals - )); -} - -fn token_name_asset(asset_id: AssetId) -> Vec { - as MetadataInspect>::name( - asset_id, - ) -} - -fn token_symbol_asset(asset_id: AssetId) -> Vec { - as MetadataInspect>::symbol( - asset_id, - ) -} - -fn token_decimals_asset(asset_id: AssetId) -> u8 { - as MetadataInspect>::decimals( - asset_id, - ) -} - -/// 1. PSP-22 Interface: -/// - total_supply -/// - balance_of -/// - allowance -/// - transfer -/// - transfer_from -/// - approve -/// - increase_allowance -/// - decrease_allowance - -#[test] -fn total_supply_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - - // No tokens in circulation. - assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr.clone(), ASSET_ID)); - assert_eq!(0, total_supply(addr.clone(), ASSET_ID)); - - // Tokens in circulation. - create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); - assert_eq!(Assets::total_supply(ASSET_ID), total_supply(addr.clone(), ASSET_ID)); - assert_eq!(100, total_supply(addr, ASSET_ID)); - }); -} - -#[test] -fn balance_of_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - - // No tokens in circulation. - assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr.clone(), ASSET_ID, BOB)); - assert_eq!(0, balance_of(addr.clone(), ASSET_ID, BOB)); - - // Tokens in circulation. - create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); - assert_eq!(Assets::balance(ASSET_ID, BOB), balance_of(addr.clone(), ASSET_ID, BOB)); - assert_eq!(100, balance_of(addr, ASSET_ID, BOB)); - }); -} - -#[test] -fn allowance_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - - // No tokens in circulation. - assert_eq!( - Assets::allowance(ASSET_ID, &BOB, &ALICE), - allowance(addr.clone(), ASSET_ID, BOB, ALICE) - ); - assert_eq!(0, allowance(addr.clone(), ASSET_ID, BOB, ALICE)); - - // Tokens in circulation. - create_asset_mint_and_approve(addr.clone(), ASSET_ID, BOB, 100, ALICE, 50); - assert_eq!( - Assets::allowance(ASSET_ID, &BOB, &ALICE), - allowance(addr.clone(), ASSET_ID, BOB, ALICE) - ); - assert_eq!(50, allowance(addr, ASSET_ID, BOB, ALICE)); - }); -} - -#[test] -fn transfer_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let amount: Balance = 100 * UNIT; - - // Asset does not exist. - assert_eq!( - decoded::(transfer(addr.clone(), 1, BOB, amount,)), - Ok(Module { index: 52, error: 3 }), - ); - // Create asset with Alice as owner and mint `amount` to contract address. - let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); - // Asset is not live, i.e. frozen or being destroyed. - freeze_asset(ALICE, asset); - assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount,)), - Ok(Module { index: 52, error: 16 }), - ); - thaw_asset(ALICE, asset); - // Not enough balance. - assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), - Ok(Module { index: 52, error: 0 }), - ); - // Not enough balance due to ED. - assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount)), - Ok(Module { index: 52, error: 0 }), - ); - // Successful transfer. - let balance_before_transfer = Assets::balance(asset, &BOB); - let result = transfer(addr.clone(), asset, BOB, amount / 2); - assert!(!result.did_revert(), "Contract reverted!"); - let balance_after_transfer = Assets::balance(asset, &BOB); - assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2); - // Transfer asset to account that does not exist. - assert_eq!( - decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), - Ok(Token(CannotCreate)) - ); - // Asset is not live, i.e. frozen or being destroyed. - start_destroy_asset(ALICE, asset); - assert_eq!( - decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), - Ok(Module { index: 52, error: 16 }), - ); - }); -} - -#[test] -fn transfer_from_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let amount: Balance = 100 * UNIT; - - // Asset does not exist. - assert_eq!( - decoded::(transfer_from(addr.clone(), 1, ALICE, BOB, amount / 2)), - Ok(Module { index: 52, error: 3 }), - ); - // Create asset with Alice as owner and mint `amount` to contract address. - let asset = create_asset_and_mint_to(ALICE, 1, ALICE, amount); - // Unapproved transfer. - assert_eq!( - decoded::(transfer_from(addr.clone(), asset, ALICE, BOB, amount / 2)), - Ok(Module { index: 52, error: 10 }) - ); - assert_ok!(Assets::approve_transfer( - RuntimeOrigin::signed(ALICE.into()), - asset.into(), - addr.clone().into(), - amount + 1 * UNIT, - )); - // Asset is not live, i.e. frozen or being destroyed. - freeze_asset(ALICE, asset); - assert_eq!( - decoded::(transfer_from(addr.clone(), asset, ALICE, BOB, amount)), - Ok(Module { index: 52, error: 16 }), - ); - thaw_asset(ALICE, asset); - // Not enough balance. - assert_eq!( - decoded::(transfer_from(addr.clone(), asset, ALICE, BOB, amount + 1 * UNIT,)), - Ok(Module { index: 52, error: 0 }), - ); - // Successful transfer. - let balance_before_transfer = Assets::balance(asset, &BOB); - let result = transfer_from(addr.clone(), asset, ALICE, BOB, amount / 2); - assert!(!result.did_revert(), "Contract reverted!"); - let balance_after_transfer = Assets::balance(asset, &BOB); - assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2); - }); -} - -#[test] -fn approve_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = instantiate(CONTRACT, 0, vec![]); - let amount: Balance = 100 * UNIT; - // Asset does not exist. - assert_eq!( - decoded::(approve(addr.clone(), 0, BOB, amount)), - Ok(Module { index: 52, error: 3 }), - ); - let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); - assert_eq!( - decoded::(approve(addr.clone(), asset, BOB, amount)), - Ok(ConsumerRemaining) - ); - - let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); - // Create asset with Alice as owner and mint `amount` to contract address. - let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); - // Asset is not live, i.e. frozen or being destroyed. - freeze_asset(ALICE, asset); - assert_eq!( - decoded::(approve(addr.clone(), asset, BOB, amount)), - Ok(Module { index: 52, error: 16 }), - ); - thaw_asset(ALICE, asset); - // Successful approvals: - assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); - assert!(!approve(addr.clone(), asset, BOB, amount).did_revert(), "Contract reverted!"); - assert_eq!(Assets::allowance(asset, &addr, &BOB), amount); - // Non-additive, sets new value. - assert!(!approve(addr.clone(), asset, BOB, amount / 2).did_revert(), "Contract reverted!"); - assert_eq!(Assets::allowance(asset, &addr, &BOB), amount / 2); - // Asset is not live, i.e. frozen or being destroyed. - start_destroy_asset(ALICE, asset); - assert_eq!( - decoded::(approve(addr.clone(), asset, BOB, amount)), - Ok(Module { index: 52, error: 16 }), - ); - }); -} - -#[test] -fn increase_allowance_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = instantiate(CONTRACT, 0, vec![]); - let amount: Balance = 100 * UNIT; - // Asset does not exist. - assert_eq!( - decoded::(increase_allowance(addr.clone(), 0, BOB, amount)), - Ok(Module { index: 52, error: 3 }), - ); - let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); - assert_eq!( - decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - Ok(ConsumerRemaining) - ); - - let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); - // Create asset with Alice as owner and mint `amount` to contract address. - let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); - // Asset is not live, i.e. frozen or being destroyed. - freeze_asset(ALICE, asset); - assert_eq!( - decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - Ok(Module { index: 52, error: 16 }), - ); - thaw_asset(ALICE, asset); - // Successful approvals: - assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); - assert!( - !increase_allowance(addr.clone(), asset, BOB, amount).did_revert(), - "Contract reverted!" - ); - assert_eq!(Assets::allowance(asset, &addr, &BOB), amount); - // Additive. - assert!( - !increase_allowance(addr.clone(), asset, BOB, amount).did_revert(), - "Contract reverted!" - ); - assert_eq!(Assets::allowance(asset, &addr, &BOB), amount * 2); - // Asset is not live, i.e. frozen or being destroyed. - start_destroy_asset(ALICE, asset); - assert_eq!( - decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - Ok(Module { index: 52, error: 16 }), - ); - }); -} - -#[test] -fn decrease_allowance_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let amount: Balance = 100 * UNIT; - // Asset does not exist. - assert_eq!( - decoded::(decrease_allowance(addr.clone(), 0, BOB, amount)), - Ok(Module { index: 52, error: 3 }), - ); - // Create asset and mint to the address contract, delegate Bob to spend the `amount`. - let asset = - create_asset_mint_and_approve(addr.clone(), 0, addr.clone(), amount, BOB, amount); - // Asset is not live, i.e. frozen or being destroyed. - freeze_asset(addr.clone(), asset); - assert_eq!( - decoded::(decrease_allowance(addr.clone(), asset, BOB, amount)), - Ok(Module { index: 52, error: 16 }), - ); - thaw_asset(addr.clone(), asset); - // Successfully decrease allowance. - let bob_allowance_before = Assets::allowance(asset, &addr, &BOB); - let result = decrease_allowance(addr.clone(), 0, BOB, amount / 2 - 1 * UNIT); - assert!(!result.did_revert(), "Contract reverted!"); - let bob_allowance_after = Assets::allowance(asset, &addr, &BOB); - assert_eq!(bob_allowance_before - bob_allowance_after, amount / 2 - 1 * UNIT); - // Asset is not live, i.e. frozen or being destroyed. - start_destroy_asset(addr.clone(), asset); - assert_eq!( - decoded::(decrease_allowance(addr.clone(), asset, BOB, amount)), - Ok(Module { index: 52, error: 16 }), - ); - }); -} - -/// 2. PSP-22 Metadata Interface: -/// - token_name -/// - token_symbol -/// - token_decimals - -#[test] -fn token_metadata_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - - let name: Vec = vec![11, 12, 13]; - let symbol: Vec = vec![21, 22, 23]; - let decimals: u8 = 69; - // Token does not exist. - assert_eq!(token_name_asset(ASSET_ID), token_name(addr.clone(), ASSET_ID)); - assert_eq!(Vec::::new(), token_name(addr.clone(), ASSET_ID)); - assert_eq!(token_symbol_asset(ASSET_ID), token_symbol(addr.clone(), ASSET_ID)); - assert_eq!(Vec::::new(), token_symbol(addr.clone(), ASSET_ID)); - assert_eq!(token_decimals_asset(ASSET_ID), token_decimals(addr.clone(), ASSET_ID)); - assert_eq!(0, token_decimals(addr.clone(), ASSET_ID)); - - create_asset_and_set_metadata( - addr.clone(), - ASSET_ID, - name.clone(), - symbol.clone(), - decimals, - ); - assert_eq!(token_name_asset(ASSET_ID), token_name(addr.clone(), ASSET_ID)); - assert_eq!(name, token_name(addr.clone(), ASSET_ID)); - assert_eq!(token_symbol_asset(ASSET_ID), token_symbol(addr.clone(), ASSET_ID)); - assert_eq!(symbol, token_symbol(addr.clone(), ASSET_ID)); - assert_eq!(token_decimals_asset(ASSET_ID), token_decimals(addr.clone(), ASSET_ID)); - assert_eq!(decimals, token_decimals(addr.clone(), ASSET_ID)); - }); -} - -// #[test] -// #[ignore] -// fn asset_exists_works() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// let addr = -// instantiate(CONTRACT, INIT_VALUE, vec![]); -// -// // No tokens in circulation. -// assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr.clone(), ASSET_ID)); -// -// // Tokens in circulation. -// create_asset(addr.clone(), ASSET_ID, 1); -// assert_eq!(Assets::asset_exists(ASSET_ID), asset_exists(addr, ASSET_ID)); -// }); -// } - -// #[test] -// #[ignore] -// fn mint_works() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// let addr = -// instantiate(CONTRACT, INIT_VALUE, vec![]); -// let amount: Balance = 100 * UNIT; -// -// // Asset does not exist. -// assert_eq!( -// decoded::(transfer_from(addr.clone(), 1, None, Some(BOB), amount, &[0u8])), -// Token(UnknownAsset) -// ); -// let asset = create_asset(ALICE, 1, 2); -// // Minting can only be done by the owner. -// assert_eq!( -// decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), -// Ok(Module { index: 52, error: 2 }), -// ); -// // Minimum balance of an asset can not be zero. -// assert_eq!( -// decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), 1, &[0u8])), -// Token(BelowMinimum) -// ); -// let asset = create_asset(addr.clone(), 2, 2); -// // Asset is not live, i.e. frozen or being destroyed. -// freeze_asset(addr.clone(), asset); -// assert_eq!( -// decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), -// Ok(Module { index: 52, error: 16 }), -// ); -// thaw_asset(addr.clone(), asset); -// // Successful mint. -// let balance_before_mint = Assets::balance(asset, &BOB); -// let result = transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8]); -// assert!(!result.did_revert(), "Contract reverted!"); -// let balance_after_mint = Assets::balance(asset, &BOB); -// assert_eq!(balance_after_mint, balance_before_mint + amount); -// // Can not mint more tokens than Balance::MAX. -// assert_eq!( -// decoded::(transfer_from( -// addr.clone(), -// asset, -// None, -// Some(BOB), -// Balance::MAX, -// &[0u8] -// )), -// Arithmetic(Overflow) -// ); -// // Asset is not live, i.e. frozen or being destroyed. -// start_destroy_asset(addr.clone(), asset); -// assert_eq!( -// decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), -// Ok(Module { index: 52, error: 16 }), -// ); -// }); -// } - -// #[test] -// #[ignore] -// fn create_works() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// // Instantiate a contract without balance (relay token). -// let addr = instantiate(CONTRACT, 0, vec![0]); -// // No balance to pay for fees. -// assert_eq!( -// decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), -// Ok(Module { index: 10, error: 2 }), -// ); -// // Instantiate a contract without balance (relay token). -// let addr = instantiate(CONTRACT, 100, vec![2]); -// // No balance to pay the deposit. -// assert_eq!( -// decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), -// Ok(Module { index: 10, error: 2 }), -// ); -// // Instantiate a contract with balance. -// let addr = -// instantiate(CONTRACT, INIT_VALUE, vec![1]); -// assert_eq!( -// decoded::(create(addr.clone(), ASSET_ID, BOB, 0)), -// Ok(Module { index: 52, error: 7 }), -// ); -// create_asset(ALICE, ASSET_ID, 1); -// // Asset ID is already taken. -// assert_eq!( -// decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), -// Ok(Module { index: 52, error: 5 }), -// ); -// // The minimal balance for an asset must be non zero. -// let new_asset = 2; -// let result = create(addr.clone(), new_asset, BOB, 1); -// assert!(!result.did_revert(), "Contract reverted!"); -// }); -// } - -// #[test] -// #[ignore] -// fn set_metadata_works() { -// new_test_ext().execute_with(|| { -// let _ = env_logger::try_init(); -// let addr = -// instantiate(CONTRACT, INIT_VALUE, vec![]); -// -// create_asset(addr.clone(), ASSET_ID, 1); -// let result = set_metadata(addr.clone(), ASSET_ID, vec![12], vec![12], 12); -// assert!(!result.did_revert(), "Contract reverted!"); -// }); -// } diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 7fcfc85b..78a79f80 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -30,10 +30,10 @@ mod constants { /// Helper method to build `ChainExtensionMethod`. /// /// Parameters: -/// - 'version': The version of the chain extension -/// - 'function': The ID of the function -/// - 'module': The index of the runtime module -/// - 'dispatchable': The index of the module dispatchable functions +/// - 'version': The version of the chain extension. +/// - 'function': The ID of the function. +/// - 'module': The index of the runtime module. +/// - 'dispatchable': The index of the module dispatchable functions. fn build_extension_method( version: u8, function: u8, @@ -45,13 +45,13 @@ fn build_extension_method( /// Represents a status code returned by the runtime. /// -/// `StatusCode` encapsulates a `u32` value that indicates the status of an operation performed -/// by the runtime. It helps to communicate the success or failure of a Pop API call to the contract, +/// `StatusCode` encapsulates a `u32` value that indicates the status of an operation performed by +/// the runtime. It helps to communicate the success or failure of a Pop API call to the contract, /// providing a standardized way to handle errors. /// -/// This status code can be used to determine if an operation succeeded or if it encountered -/// an error. A `StatusCode` of `0` typically indicates success, while any other value represents -/// an error. +/// This status code can be used to determine if an operation succeeded or if it encountered an +/// error. A `StatusCode` of `0` typically indicates success, while any other value represents an +/// error. #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub struct StatusCode(pub u32); diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 0712a80b..8600c439 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -3,22 +3,23 @@ use crate::{ primitives::{AccountId, AssetId, Balance}, Result, StatusCode, }; +pub use asset_management::*; use constants::*; use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec}; pub use metadata::*; -/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0` +/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0`. /// /// Parameters: -/// - 'dispatchable': The index of the module dispatchable functions +/// - 'dispatchable': The index of the module dispatchable functions. fn build_dispatch(dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { crate::v0::build_dispatch(FUNGIBLES, dispatchable) } -/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0`` +/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0`. /// /// Parameters: -/// - 'state_query': The index of the runtime state query +/// - 'state_query': The index of the runtime state query. fn build_read_state(state_query: u8) -> ChainExtensionMethod<(), (), (), false> { crate::v0::build_read_state(FUNGIBLES, state_query) } @@ -27,48 +28,40 @@ fn build_read_state(state_query: u8) -> ChainExtensionMethod<(), (), (), false> /// 1. PSP-22 Interface /// 2. PSP-22 Metadata Interface /// 3. Asset Management +/// 4. PSP-22 Mintable & Burnable Interface mod constants { /// 1. PSP-22 Interface: - /// - total_supply - pub const TOTAL_SUPPLY: u8 = 0; - /// - balance_of - pub const BALANCE_OF: u8 = 1; - /// - allowance - pub const ALLOWANCE: u8 = 2; - /// - transfer + pub(super) const TOTAL_SUPPLY: u8 = 0; + pub(super) const BALANCE_OF: u8 = 1; + pub(super) const ALLOWANCE: u8 = 2; pub(super) const TRANSFER: u8 = 3; - /// - transfer_from pub(super) const TRANSFER_FROM: u8 = 4; - /// - approve pub(super) const APPROVE: u8 = 5; - /// - increase_allowance pub(super) const INCREASE_ALLOWANCE: u8 = 6; - /// - decrease_allowance pub(super) const DECREASE_ALLOWANCE: u8 = 7; /// 2. PSP-22 Metadata Interface: - /// - token_name - pub const TOKEN_NAME: u8 = 8; - /// - token_symbol - pub const TOKEN_SYMBOL: u8 = 9; - /// - token_decimals - pub const TOKEN_DECIMALS: u8 = 10; - - // 3. Asset Management: - // - create - // - start_destroy - // - destroy_accounts - // - destroy_approvals - // - finish_destroy - // - set_metadata - // - clear_metadata + pub(super) const TOKEN_NAME: u8 = 8; + pub(super) const TOKEN_SYMBOL: u8 = 9; + pub(super) const TOKEN_DECIMALS: u8 = 10; + + /// 3. Asset Management: + pub(super) const CREATE: u8 = 11; + pub(super) const START_DESTROY: u8 = 12; + pub(super) const SET_METADATA: u8 = 16; + pub(super) const CLEAR_METADATA: u8 = 17; + pub(super) const ASSET_EXISTS: u8 = 18; + + /// 4. PSP-22 Mintable & Burnable interface: + pub(super) const MINT: u8 = 19; + pub(super) const BURN: u8 = 20; } /// Returns the total token supply for a given asset ID. /// -/// # Arguments -/// * `id` - The ID of the asset. +/// # Parameters +/// - `id` - The ID of the asset. /// /// # Returns /// The total supply of the token, or an error if the operation fails. @@ -84,9 +77,9 @@ pub fn total_supply(id: AssetId) -> Result { /// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if /// the account is non-existent. /// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `owner` - The account whose balance is being queried. +/// # Parameters +/// - `id` - The ID of the asset. +/// - `owner` - The account whose balance is being queried. /// /// # Returns /// The balance of the specified account, or an error if the operation fails. @@ -102,10 +95,10 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { /// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given /// asset ID. Returns `0` if no allowance has been set. /// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `owner` - The account that owns the tokens. -/// * `spender` - The account that is allowed to spend the tokens. +/// # Parameters +/// - `id` - The ID of the asset. +/// - `owner` - The account that owns the tokens. +/// - `spender` - The account that is allowed to spend the tokens. /// /// # Returns /// The remaining allowance, or an error if the operation fails. @@ -121,67 +114,66 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result<()> { +pub fn transfer(id: AssetId, to: AccountId, value: Balance) -> Result<()> { build_dispatch(TRANSFER) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, target, amount)) + .call(&(id, to, value)) } -/// Transfers `value` tokens on behalf of `from` to account `to` with additional `data` -/// in unspecified format. If `from` is equal to `None`, tokens will be minted to account `to`. If -/// `to` is equal to `None`, tokens will be burned from account `from`. +/// Transfers `value` amount tokens on behalf of `from` to account `to` with additional `data` +/// in unspecified format. /// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `from` - The account from which the tokens are transferred. -/// * `to` - The recipient account. -/// * `value` - The number of tokens to transfer. +/// # Parameters +/// - `id` - The ID of the asset. +/// - `from` - The account from which the tokens are transferred. +/// - `to` - The recipient account. +/// - `value` - The number of tokens to transfer. /// /// # Returns /// Returns `Ok(())` if successful, or an error if the transfer fails. #[inline] -pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, amount: Balance) -> Result<()> { +pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { build_dispatch(TRANSFER_FROM) .input::<(AssetId, AccountId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, from, to, amount)) + .call(&(id, from, to, value)) } /// Approves an account to spend a specified number of tokens on behalf of the caller. /// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `spender` - The account that is allowed to spend the tokens. -/// * `value` - The number of tokens to approve. +/// # Parameters +/// - `id` - The ID of the asset. +/// - `spender` - The account that is allowed to spend the tokens. +/// - `value` - The number of tokens to approve. /// /// # Returns /// Returns `Ok(())` if successful, or an error if the approval fails. #[inline] -pub fn approve(id: AssetId, spender: AccountId, amount: Balance) -> Result<()> { +pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(APPROVE) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, spender, amount)) + .call(&(id, spender, value)) } /// Increases the allowance of a spender. /// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `spender` - The account that is allowed to spend the tokens. -/// * `value` - The number of tokens to increase the allowance by. +/// # Parameters +/// - `id` - The ID of the asset. +/// - `spender` - The account that is allowed to spend the tokens. +/// - `value` - The number of tokens to increase the allowance by. /// /// # Returns /// Returns `Ok(())` if successful, or an error if the operation fails. @@ -196,10 +188,10 @@ pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re /// Decreases the allowance of a spender. /// -/// # Arguments -/// * `id` - The ID of the asset. -/// * `spender` - The account that is allowed to spend the tokens. -/// * `value` - The number of tokens to decrease the allowance by. +/// # Parameters +/// - `id` - The ID of the asset. +/// - `spender` - The account that is allowed to spend the tokens. +/// - `value` - The number of tokens to decrease the allowance by. /// /// # Returns /// Returns `Ok(())` if successful, or an error if the operation fails. @@ -212,12 +204,47 @@ pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re .call(&(id, spender, value)) } +/// Creates `value` amount tokens and assigns them to `account`, increasing the total supply. +/// +/// # Parameters +/// - `id` - The ID of the asset. +/// - `account` - The account to be credited with the created tokens. +/// - `value` - The number of tokens to mint. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +pub fn mint(id: AssetId, account: AccountId, value: Balance) -> Result<()> { + build_dispatch(MINT) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, account, value)) +} + +/// Destroys `value` amount tokens from `account`, reducing the total supply. +/// +/// # Parameters +/// - `id` - The ID of the asset. +/// - `account` - The account from which the tokens will be destroyed. +/// - `value` - The number of tokens to destroy. +/// +/// # Returns +/// Returns `Ok(())` if successful, or an error if the operation fails. +pub fn burn(id: AssetId, account: AccountId, value: Balance) -> Result<()> { + build_dispatch(BURN) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, account, value)) +} + pub mod metadata { use super::*; + /// Returns the token name for a given asset ID. /// - /// # Arguments - /// * `id` - The ID of the asset. + /// # Parameters + /// - `id` - The ID of the asset. /// /// # Returns /// The name of the token as a byte vector, or an error if the operation fails. @@ -232,8 +259,8 @@ pub mod metadata { /// Returns the token symbol for a given asset ID. /// - /// # Arguments - /// * `id` - The ID of the asset. + /// # Parameters + /// - `id` - The ID of the asset. /// /// # Returns /// The symbol of the token as a byte vector, or an error if the operation fails. @@ -248,11 +275,11 @@ pub mod metadata { /// Returns the token decimals for a given asset ID. /// - /// # Arguments - /// * `id` - The ID of the asset. + /// # Parameters + /// - `id` - The ID of the asset. /// /// # Returns - /// The number of decimals of the token as a byte vector, or an error if the operation fails. + /// The number of decimals of the token, or an error if the operation fails. #[inline] pub fn token_decimals(id: AssetId) -> Result { build_read_state(TOKEN_DECIMALS) @@ -263,90 +290,87 @@ pub mod metadata { } } -// pub asset_management { -// /// Create a new token with a given asset ID. -// /// -// /// # Arguments -// /// * `id` - The ID of the asset. -// /// * `admin` - The account that will administer the asset. -// /// * `min_balance` - The minimum balance required for accounts holding this asset. -// /// -// /// # Returns -// /// Returns `Ok(())` if successful, or an error if the creation fails. -// pub fn create(id: AssetId, admin: impl Into>, min_balance: Balance) -> Result<()> { -// Ok(()) -// } -// -// /// Start the process of destroying a token with a given asset ID. -// /// -// /// # Arguments -// /// * `id` - The ID of the asset. -// /// -// /// # Returns -// /// Returns `Ok(())` if successful, or an error if the operation fails. -// fn start_destroy(id: AssetId) -> Result<()> { -// Ok(()) -// } -// -// /// Destroy all accounts associated with a token with a given asset ID. -// /// -// /// # Arguments -// /// * `id` - The ID of the asset. -// /// -// /// # Returns -// /// Returns `Ok(())` if successful, or an error if the operation fails. -// fn destroy_accounts(id: AssetId) -> Result<()> { -// Ok(()) -// } -// -// /// Destroy all approvals associated with a token with a given asset ID. -// /// -// /// # Arguments -// /// * `id` - The ID of the asset. -// /// -// /// # Returns -// /// Returns `Ok(())` if successful, or an error if the operation fails. -// fn destroy_approvals(id: AssetId) -> Result<()> { -// Ok(()) -// } -// -// /// Complete the process of destroying a token with a given asset ID. -// /// -// /// # Arguments -// /// * `id` - The ID of the asset. -// /// -// /// # Returns -// /// Returns `Ok(())` if successful, or an error if the operation fails. -// fn finish_destroy(id: AssetId) -> Result<()> { -// Ok(()) -// } -// -// /// Set the metadata for a token with a given asset ID. -// /// -// /// # Arguments -// /// * `id` - The ID of the asset. -// /// -// /// # Returns -// /// Returns `Ok(())` if successful, or an error if the operation fails. -// pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { -// Ok(()) -// } -// -// /// Clear the metadata for a token with a given asset ID. -// /// -// /// # Arguments -// /// * `id` - The ID of the asset. -// /// -// /// # Returns -// /// Returns `Ok(())` if successful, or an error if the operation fails. -// fn clear_metadata(id: AssetId) -> Result<()> { -// Ok(()) -// } -// } -// -// pub fn asset_exists(id: AssetId) -> Result { -// assets::asset_exists(id) -// } +pub mod asset_management { + use super::*; + + /// Create a new token with a given asset ID. + /// + /// # Parameters + /// - `id` - The ID of the asset. + /// - `admin` - The account that will administer the asset. + /// - `min_balance` - The minimum balance required for accounts holding this asset. + /// + /// # Returns + /// Returns `Ok(())` if successful, or an error if the creation fails. + pub fn create(id: AssetId, admin: AccountId, min_balance: Balance) -> Result<()> { + build_dispatch(CREATE) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, admin, min_balance)) + } + + /// Start the process of destroying a token with a given asset ID. + /// + /// # Parameters + /// - `id` - The ID of the asset. + /// + /// # Returns + /// Returns `Ok(())` if successful, or an error if the operation fails. + pub fn start_destroy(id: AssetId) -> Result<()> { + build_dispatch(START_DESTROY) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(id)) + } + + /// Set the metadata for a token with a given asset ID. + /// + /// # Parameters + /// - `id`: The identifier of the asset to update. + /// - `name`: The user friendly name of this asset. Limited in length by `StringLimit`. + /// - `symbol`: The exchange symbol for this asset. Limited in length by `StringLimit`. + /// - `decimals`: The number of decimals this asset uses to represent one unit. + /// + /// # Returns + /// Returns `Ok(())` if successful, or an error if the operation fails. + pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { + build_dispatch(SET_METADATA) + .input::<(AssetId, Vec, Vec, u8)>() + .output::, true>() + .handle_error_code::() + .call(&(id, name, symbol, decimals)) + } + + /// Clear the metadata for a token with a given asset ID. + /// + /// # Parameters + /// - `id` - The ID of the asset. + /// + /// # Returns + /// Returns `Ok(())` if successful, or an error if the operation fails. + pub fn clear_metadata(id: AssetId) -> Result<()> { + build_dispatch(CLEAR_METADATA) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(id)) + } + + /// Checks if token with a given asset ID exists. + /// + /// # Parameters + /// - `id` - The ID of the asset. + #[inline] + pub fn asset_exists(id: AssetId) -> Result { + build_read_state(ASSET_EXISTS) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(id)) + } +} /// Represents various errors related to local fungible assets in the Pop API. /// diff --git a/runtime/devnet/src/config/api.rs b/runtime/devnet/src/config/api.rs index b3932a79..bdff6bbb 100644 --- a/runtime/devnet/src/config/api.rs +++ b/runtime/devnet/src/config/api.rs @@ -25,6 +25,10 @@ impl Contains for AllowedApiCalls { | transfer_from { .. } | approve { .. } | increase_allowance { .. } | decrease_allowance { .. } + | create { .. } | set_metadata { .. } + | start_destroy { .. } + | clear_metadata { .. } + | mint { .. } | burn { .. } ) ) } @@ -40,7 +44,7 @@ impl Contains> for AllowedApiCalls { TotalSupply(..) | BalanceOf { .. } | Allowance { .. } | TokenName(..) | TokenSymbol(..) - | TokenDecimals(..) + | TokenDecimals(..) | AssetExists(..) ) ) } From 00c59032b3755d2cf8b3442095876612425116f9 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Fri, 9 Aug 2024 18:37:37 +0700 Subject: [PATCH 035/161] refactor: remove bare_call code duplication in integration test (#168) --- .../integration-tests/src/fungibles/utils.rs | 91 +++++++------------ 1 file changed, 35 insertions(+), 56 deletions(-) diff --git a/pop-api/integration-tests/src/fungibles/utils.rs b/pop-api/integration-tests/src/fungibles/utils.rs index 2f9be65c..33a25f7a 100644 --- a/pop-api/integration-tests/src/fungibles/utils.rs +++ b/pop-api/integration-tests/src/fungibles/utils.rs @@ -1,13 +1,17 @@ use super::*; +fn do_bare_call(function: &str, addr: AccountId32, params: Vec) -> ExecReturnValue { + let function = function_selector(function); + let params = [function, params].concat(); + bare_call(addr, params, 0).expect("should work") +} + pub(super) fn decoded(result: ExecReturnValue) -> Result { ::decode(&mut &result.data[1..]).map_err(|_| result) } pub(super) fn total_supply(addr: AccountId32, asset_id: AssetId) -> Result { - let function = function_selector("total_supply"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let result = do_bare_call("total_supply", addr, asset_id.encode()); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -17,9 +21,8 @@ pub(super) fn balance_of( asset_id: AssetId, owner: AccountId32, ) -> Result { - let function = function_selector("balance_of"); - let params = [function, asset_id.encode(), owner.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), owner.encode()].concat(); + let result = do_bare_call("balance_of", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -30,41 +33,32 @@ pub(super) fn allowance( owner: AccountId32, spender: AccountId32, ) -> Result { - let function = function_selector("allowance"); - let params = [function, asset_id.encode(), owner.encode(), spender.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), owner.encode(), spender.encode()].concat(); + let result = do_bare_call("allowance", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } pub(super) fn token_name(addr: AccountId32, asset_id: AssetId) -> Result, Error> { - let function = function_selector("token_name"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let result = do_bare_call("token_name", addr, asset_id.encode()); decoded::, Error>>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } pub(super) fn token_symbol(addr: AccountId32, asset_id: AssetId) -> Result, Error> { - let function = function_selector("token_symbol"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let result = do_bare_call("token_symbol", addr, asset_id.encode()); decoded::, Error>>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } pub(super) fn token_decimals(addr: AccountId32, asset_id: AssetId) -> Result { - let function = function_selector("token_decimals"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let result = do_bare_call("token_decimals", addr, asset_id.encode()); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } pub(super) fn asset_exists(addr: AccountId32, asset_id: AssetId) -> Result { - let function = function_selector("asset_exists"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let result = do_bare_call("asset_exists", addr, asset_id.encode()); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -75,9 +69,8 @@ pub(super) fn transfer( to: AccountId32, value: Balance, ) -> Result<(), Error> { - let function = function_selector("transfer"); - let params = [function, asset_id.encode(), to.encode(), value.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), to.encode(), value.encode()].concat(); + let result = do_bare_call("transfer", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -89,12 +82,10 @@ pub(super) fn transfer_from( to: AccountId32, value: Balance, ) -> Result<(), Error> { - let function = function_selector("transfer_from"); let data: Vec = vec![]; let params = - [function, asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()] - .concat(); - let result = bare_call(addr, params, 0).expect("should work"); + [asset_id.encode(), from.encode(), to.encode(), value.encode(), data.encode()].concat(); + let result = do_bare_call("transfer_from", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -105,9 +96,8 @@ pub(super) fn approve( spender: AccountId32, value: Balance, ) -> Result<(), Error> { - let function = function_selector("approve"); - let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), spender.encode(), value.encode()].concat(); + let result = do_bare_call("approve", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -118,9 +108,8 @@ pub(super) fn increase_allowance( spender: AccountId32, value: Balance, ) -> Result<(), Error> { - let function = function_selector("increase_allowance"); - let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), spender.encode(), value.encode()].concat(); + let result = do_bare_call("increase_allowance", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -131,9 +120,8 @@ pub(super) fn decrease_allowance( spender: AccountId32, value: Balance, ) -> Result<(), Error> { - let function = function_selector("decrease_allowance"); - let params = [function, asset_id.encode(), spender.encode(), value.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), spender.encode(), value.encode()].concat(); + let result = do_bare_call("decrease_allowance", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -144,17 +132,14 @@ pub(super) fn create( admin: AccountId32, min_balance: Balance, ) -> Result<(), Error> { - let function = function_selector("create"); - let params = [function, asset_id.encode(), admin.encode(), min_balance.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), admin.encode(), min_balance.encode()].concat(); + let result = do_bare_call("create", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } pub(super) fn start_destroy(addr: AccountId32, asset_id: AssetId) -> Result<(), Error> { - let function = function_selector("start_destroy"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let result = do_bare_call("start_destroy", addr, asset_id.encode()); match decoded::>(result) { Ok(x) => x, Err(result) => panic!("Contract reverted: {:?}", result), @@ -168,18 +153,14 @@ pub(super) fn set_metadata( symbol: Vec, decimals: u8, ) -> Result<(), Error> { - let function = function_selector("set_metadata"); - let params = - [function, asset_id.encode(), name.encode(), symbol.encode(), decimals.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), name.encode(), symbol.encode(), decimals.encode()].concat(); + let result = do_bare_call("set_metadata", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } pub(super) fn clear_metadata(addr: AccountId32, asset_id: AssetId) -> Result<(), Error> { - let function = function_selector("clear_metadata"); - let params = [function, asset_id.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let result = do_bare_call("clear_metadata", addr, asset_id.encode()); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -190,9 +171,8 @@ pub(super) fn mint( account: AccountId32, amount: Balance, ) -> Result<(), Error> { - let function = function_selector("mint"); - let params = [function, asset_id.encode(), account.encode(), amount.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), account.encode(), amount.encode()].concat(); + let result = do_bare_call("mint", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } @@ -203,9 +183,8 @@ pub(super) fn burn( account: AccountId32, amount: Balance, ) -> Result<(), Error> { - let function = function_selector("burn"); - let params = [function, asset_id.encode(), account.encode(), amount.encode()].concat(); - let result = bare_call(addr, params, 0).expect("should work"); + let params = [asset_id.encode(), account.encode(), amount.encode()].concat(); + let result = do_bare_call("burn", addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } From 9ebe1621081f0593bf93096bccf86e1a5b761317 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Tue, 13 Aug 2024 10:52:42 +0200 Subject: [PATCH 036/161] fix: compilation --- Cargo.lock | 1621 +++++++++++++++++++++++++++------------------------- 1 file changed, 831 insertions(+), 790 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 982705a3..7f033a20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,11 +23,11 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ - "gimli 0.28.1", + "gimli 0.29.0", ] [[package]] @@ -68,7 +68,7 @@ dependencies = [ "cipher 0.4.4", "ctr", "ghash", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] @@ -77,7 +77,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "once_cell", "version_check", ] @@ -89,7 +89,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom 0.2.12", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "always-assert" @@ -142,47 +142,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -190,9 +191,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "approx" @@ -214,7 +215,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -354,15 +355,15 @@ checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" [[package]] name = "array-bytes" -version = "6.2.2" +version = "6.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f840fb7195bcfc5e17ea40c26e5ce6d5b9ce5d584466e17703209657e459ae0" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" @@ -404,7 +405,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -427,7 +428,7 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "asset-hub-paseo-runtime" version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#e7265b10b28d8b82c3146e72c98895dac2b55729" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" dependencies = [ "assets-common", "bp-asset-hub-paseo", @@ -468,6 +469,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "pallet-uniques", "pallet-utility", + "pallet-vesting", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub-router", @@ -570,27 +572,25 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", - "event-listener 5.2.0", - "event-listener-strategy 0.5.0", + "event-listener-strategy", "futures-core", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] name = "async-executor" -version = "1.8.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" dependencies = [ - "async-lock 3.3.0", "async-task", "concurrent-queue", - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-lite 2.3.0", "slab", ] @@ -629,21 +629,21 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.2" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ - "async-lock 3.3.0", + "async-lock 3.4.0", "cfg-if", "concurrent-queue", "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.6.0", - "rustix 0.38.32", + "polling 3.7.3", + "rustix 0.38.34", "slab", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -657,13 +657,13 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", - "pin-project-lite 0.2.13", + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite 0.2.14", ] [[package]] @@ -690,43 +690,43 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.48.0", ] [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io 2.3.2", - "async-lock 2.8.0", + "async-io 2.3.4", + "async-lock 3.4.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.32", + "rustix 0.38.34", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "async-task" -version = "4.7.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -739,7 +739,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -756,22 +756,22 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ - "addr2line 0.21.0", + "addr2line 0.22.0", "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.32.2", + "object 0.36.3", "rustc-demangle", ] @@ -845,13 +845,13 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "prettyplease 0.2.17", + "prettyplease 0.2.20", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -881,9 +881,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -953,9 +953,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec 0.7.4", @@ -984,18 +984,15 @@ dependencies = [ [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel 2.2.0", - "async-lock 3.3.0", + "async-channel 2.3.1", "async-task", - "fastrand 2.0.2", "futures-io", "futures-lite 2.3.0", "piper", - "tracing", ] [[package]] @@ -1022,7 +1019,7 @@ dependencies = [ [[package]] name = "bp-asset-hub-paseo" version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#e7265b10b28d8b82c3146e72c98895dac2b55729" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" dependencies = [ "frame-support", "sp-std", @@ -1049,7 +1046,7 @@ dependencies = [ [[package]] name = "bp-bridge-hub-paseo" version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#e7265b10b28d8b82c3146e72c98895dac2b55729" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" dependencies = [ "bp-bridge-hub-cumulus", "bp-messages", @@ -1066,9 +1063,9 @@ dependencies = [ [[package]] name = "bp-header-chain" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96157f586811969b3911d26cc79e02b28cfbecf859d96d7c12b6af10b9ea9350" +checksum = "1c4d2c457d5e18a5dbfe47a2ecd01f95036930a4a7ac0f3e47c2843bb067331b" dependencies = [ "bp-runtime", "finality-grandpa", @@ -1278,9 +1275,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-slice-cast" @@ -1296,9 +1293,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" [[package]] name = "byteorder" @@ -1308,9 +1305,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "bzip2-sys" @@ -1335,9 +1332,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] @@ -1359,7 +1356,7 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", - "semver 1.0.22", + "semver 1.0.23", "serde", "serde_json", "thiserror", @@ -1367,9 +1364,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.90" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" dependencies = [ "jobserver", "libc", @@ -1386,9 +1383,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" dependencies = [ "smallvec", ] @@ -1441,16 +1438,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -1497,9 +1494,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -1508,9 +1505,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" dependencies = [ "clap_builder", "clap_derive", @@ -1518,9 +1515,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -1531,21 +1528,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "coarsetime" @@ -1570,39 +1567,39 @@ dependencies = [ [[package]] name = "color-print" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a858372ff14bab9b1b30ea504f2a4bc534582aee3e42ba2d41d2a7baba63d5d" +checksum = "1ee543c60ff3888934877a5671f45494dd27ed4ba25c6670b9a7576b7ed7a8c0" dependencies = [ "color-print-proc-macro", ] [[package]] name = "color-print-proc-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e37866456a721d0a404439a1adae37a31be4e0055590d053dfe6981e05003f" +checksum = "77ff1a80c5f3cb1ca7c06ffdd71b6a6dd6d8f896c42141fbd43f50ed28dcdb93" dependencies = [ "nom", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.74", ] [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "comfy-table" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" +checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" dependencies = [ - "strum 0.25.0", - "strum_macros 0.25.3", + "strum 0.26.3", + "strum_macros 0.26.4", "unicode-width", ] @@ -1614,9 +1611,9 @@ checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -1655,7 +1652,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "once_cell", "tiny-keccak", ] @@ -1696,9 +1693,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core2" @@ -1730,9 +1727,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -1837,9 +1834,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -1874,9 +1871,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1892,7 +1889,7 @@ checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.4.1", "zeroize", ] @@ -1924,17 +1921,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ "generic-array 0.14.7", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] name = "crypto-mac" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ "generic-array 0.14.7", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] @@ -1975,7 +1972,7 @@ dependencies = [ "cumulus-primitives-core", "futures", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-overseer", @@ -2088,7 +2085,7 @@ dependencies = [ "futures", "futures-timer", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-primitives", "polkadot-parachain-primitives", "polkadot-primitives", @@ -2252,7 +2249,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -2444,13 +2441,13 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7718fe298d567adc44fae3dd7024418d6eff08264041e4b0544d1892861cd6" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-trait", "cumulus-primitives-core", "cumulus-relay-chain-interface", "cumulus-relay-chain-rpc-interface", "futures", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-availability-recovery", "polkadot-collator-protocol", "polkadot-core-primitives", @@ -2544,24 +2541,23 @@ dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", - "subtle 2.5.0", + "subtle 2.4.1", "zeroize", ] [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", - "subtle 2.5.0", + "subtle 2.4.1", "zeroize", ] @@ -2573,7 +2569,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -2591,9 +2587,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dc7287237dd438b926a81a1a5605dad33d286870e5eee2db17bf2bcd9e92a" +checksum = "273dcfd3acd4e1e276af13ed2a43eea7001318823e7a726a6b3ed39b4acc0b82" dependencies = [ "cc", "cxxbridge-flags", @@ -2603,9 +2599,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47c6c8ad7c1a10d3ef0fe3ff6733f4db0d78f08ef0b13121543163ef327058b" +checksum = "d8b2766fbd92be34e9ed143898fce6c572dc009de39506ed6903e5a05b68914e" dependencies = [ "cc", "codespan-reporting", @@ -2613,37 +2609,37 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "cxxbridge-flags" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "701a1ac7a697e249cdd8dc026d7a7dafbfd0dbcd8bd24ec55889f2bc13dd6287" +checksum = "839fcd5e43464614ffaa989eaf1c139ef1f0c51672a1ed08023307fa1b909ccd" [[package]] name = "cxxbridge-macro" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b404f596046b0bb2d903a9c786b875a126261b52b7c3a64bbb66382c41c771df" +checksum = "4b2c1c1776b986979be68bb2285da855f8d8a35851a769fca8740df7c3d07877" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "data-encoding-macro" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" +checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -2651,9 +2647,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" +checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f" dependencies = [ "data-encoding", "syn 1.0.109", @@ -2661,9 +2657,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -2722,20 +2718,20 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.74", ] [[package]] @@ -2771,7 +2767,7 @@ dependencies = [ "block-buffer 0.10.4", "const-oid", "crypto-common", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] @@ -2818,13 +2814,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -2848,9 +2844,9 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.55", + "syn 2.0.74", "termcolor", - "toml 0.8.12", + "toml 0.8.19", "walkdir", ] @@ -2862,9 +2858,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "downcast-rs" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dtoa" @@ -2929,12 +2925,12 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", "rand_core 0.6.4", "serde", "sha2 0.10.8", - "subtle 2.5.0", + "subtle 2.4.1", "zeroize", ] @@ -2958,9 +2954,9 @@ version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "rand_core 0.6.4", "sha2 0.10.8", @@ -2969,9 +2965,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -2988,7 +2984,7 @@ dependencies = [ "pkcs8", "rand_core 0.6.4", "sec1", - "subtle 2.5.0", + "subtle 2.4.1", "zeroize", ] @@ -3045,40 +3041,40 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" dependencies = [ "enumflags2_derive", ] [[package]] name = "enumflags2_derive" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "enumn" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ "log", "regex", @@ -3099,9 +3095,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ "anstream", "anstyle", @@ -3124,9 +3120,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3187,49 +3183,28 @@ checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite 0.2.13", -] - -[[package]] -name = "event-listener" -version = "5.2.0" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.13", -] - -[[package]] -name = "event-listener-strategy" -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 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] name = "event-listener-strategy" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 5.2.0", - "pin-project-lite 0.2.13", + "event-listener 5.3.1", + "pin-project-lite 0.2.14", ] [[package]] @@ -3255,16 +3230,17 @@ dependencies = [ [[package]] name = "expander" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e83c02035136f1592a47964ea60c05a50e4ed8b5892cfac197063850898d4d" +checksum = "e2c470c71d91ecbd179935b24170459e926382eaaa86b590b78814e180d8a8e2" dependencies = [ "blake2 0.10.6", + "file-guard", "fs-err", - "prettier-please", + "prettyplease 0.2.20", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -3284,9 +3260,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fatality" @@ -3306,7 +3282,7 @@ checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", "indexmap 1.9.3", - "proc-macro-crate 1.3.1", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 1.0.109", @@ -3330,14 +3306,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] name = "fiat-crypto" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" +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" @@ -3351,14 +3337,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -3373,7 +3359,7 @@ dependencies = [ "log", "num-traits", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "scale-info", ] @@ -3397,9 +3383,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "libz-sys", @@ -3478,7 +3464,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efe02c96362e3c7308cdea7545859f767194a1f3f00928f0e1357f4b8a0b3b2c" dependencies = [ "Inflector", - "array-bytes 6.2.2", + "array-bytes 6.2.3", "chrono", "clap", "comfy-table", @@ -3529,7 +3515,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -3587,7 +3573,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bb1eec9eb46d3e016c95b2fa875118c04609f2150013c56a894cae00581e265" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "docify", "frame-support", "frame-system", @@ -3627,7 +3613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e52c84b611d2049d9253f83a62ab0f093e4be5c42a7ef42ea5bb16d6611e32" dependencies = [ "aquamarine", - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bitflags 1.3.2", "docify", "environmental", @@ -3671,7 +3657,7 @@ dependencies = [ "Inflector", "cfg-expr", "derive-syn-parse 0.1.5", - "expander 2.1.0", + "expander 2.2.1", "frame-support-procedural-tools", "itertools 0.10.5", "macro_magic", @@ -3679,7 +3665,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -3692,7 +3678,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -3703,7 +3689,7 @@ checksum = "68672b9ec6fe72d259d3879dc212c5e42e977588cdac830c76f54d9f492aeb58" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -3791,7 +3777,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f9df8a11882c4e3335eb2d18a0137c505d9ca927470b0cac9c6f0ae07d28f7" dependencies = [ - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.48.0", ] @@ -3861,7 +3847,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "waker-fn", ] @@ -3871,11 +3857,11 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-core", "futures-io", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -3886,7 +3872,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -3931,7 +3917,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "pin-utils", "slab", ] @@ -3988,9 +3974,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -4030,9 +4016,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "glob" @@ -4048,7 +4034,7 @@ checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] @@ -4063,7 +4049,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.6", + "indexmap 2.3.0", "slab", "tokio", "tokio-util", @@ -4119,9 +4105,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", "allocator-api2", @@ -4134,7 +4120,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -4155,6 +4141,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -4192,7 +4184,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ - "crypto-mac 0.11.0", + "crypto-mac 0.11.1", "digest 0.9.0", ] @@ -4255,7 +4247,7 @@ checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", ] [[package]] @@ -4266,9 +4258,9 @@ checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -4284,9 +4276,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -4298,8 +4290,8 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.13", - "socket2 0.5.6", + "pin-project-lite 0.2.14", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -4316,7 +4308,7 @@ dependencies = [ "http", "hyper", "log", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-native-certs", "tokio", "tokio-rustls", @@ -4333,7 +4325,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -4382,7 +4374,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" dependencies = [ - "async-io 2.3.2", + "async-io 2.3.4", "core-foundation", "fnv", "futures", @@ -4446,18 +4438,18 @@ dependencies = [ [[package]] name = "include_dir" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" dependencies = [ "include_dir_macros", ] [[package]] name = "include_dir_macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" dependencies = [ "proc-macro2", "quote", @@ -4476,12 +4468,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -4514,9 +4506,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -4574,7 +4566,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -4591,7 +4583,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.6", + "socket2 0.5.7", "widestring", "windows-sys 0.48.0", "winreg", @@ -4609,7 +4601,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "windows-sys 0.52.0", ] @@ -4623,6 +4615,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.10.5" @@ -4641,26 +4639,35 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -4715,7 +4722,7 @@ dependencies = [ "futures-util", "hyper", "jsonrpsee-types", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "rustc-hash", "serde", @@ -4753,7 +4760,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29110019693a4fa2dbda04876499d098fa16d70eba06b1e6e2b3f1b251419515" dependencies = [ "heck 0.4.1", - "proc-macro-crate 1.3.1", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 1.0.109", @@ -4853,7 +4860,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7a85fe66f9ff9cd74e169fdd2c94c6e1e74c412c99a73b4df3200b5d3760b2" dependencies = [ "kvdb", - "parking_lot 0.12.1", + "parking_lot 0.12.3", ] [[package]] @@ -4864,7 +4871,7 @@ checksum = "b644c70b92285f66bfc2032922a79000ea30af7bc2ab31902992a5dcb9b434f6" dependencies = [ "kvdb", "num_cpus", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "regex", "rocksdb", "smallvec", @@ -4872,9 +4879,9 @@ dependencies = [ [[package]] name = "landlock" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1530c5b973eeed4ac216af7e24baf5737645a6272e361f1fb95710678b67d9cc" +checksum = "9baa9eeb6e315942429397e617a190f4fdc696ef1ee0342939d641029cbb4ea7" dependencies = [ "enumflags2", "libc", @@ -4883,9 +4890,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -4895,18 +4902,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -4924,7 +4931,7 @@ dependencies = [ "bytes", "futures", "futures-timer", - "getrandom 0.2.12", + "getrandom 0.2.15", "instant", "libp2p-allow-block-list", "libp2p-connection-limits", @@ -4989,7 +4996,7 @@ dependencies = [ "multihash 0.17.0", "multistream-select", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "quick-protobuf", "rand", @@ -5009,7 +5016,7 @@ dependencies = [ "futures", "libp2p-core", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "smallvec", "trust-dns-resolver", ] @@ -5171,7 +5178,7 @@ dependencies = [ "libp2p-identity", "libp2p-tls", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "quinn-proto", "rand", "rustls 0.20.9", @@ -5287,7 +5294,7 @@ dependencies = [ "futures-rustls", "libp2p-core", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "quicksink", "rw-stream-sink", "soketto", @@ -5310,13 +5317,13 @@ dependencies = [ [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.3", ] [[package]] @@ -5361,7 +5368,7 @@ checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" dependencies = [ "crunchy", "digest 0.9.0", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] @@ -5384,9 +5391,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.16" +version = "1.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" +checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647" dependencies = [ "cc", "pkg-config", @@ -5440,9 +5447,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lioness" @@ -5458,9 +5465,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -5468,9 +5475,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" @@ -5507,9 +5514,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.24.0" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +checksum = "958b4caa893816eea05507c20cfe47574a43d9a697138a7872990bba8a0ece68" dependencies = [ "libc", "lz4-sys", @@ -5517,9 +5524,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.4" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "109de74d5d2353660401699a4174a4ff23fcc649caf553df71933c7fb45ad868" dependencies = [ "cc", "libc", @@ -5536,50 +5543,50 @@ dependencies = [ [[package]] name = "macro_magic" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e03844fc635e92f3a0067e25fa4bf3e3dbf3f2927bf3aa01bb7bc8f1c428949d" +checksum = "cc33f9f0351468d26fbc53d9ce00a096c8522ecb42f19b50f34f2c422f76d21d" dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "macro_magic_core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "468155613a44cfd825f1fb0ffa532b018253920d404e6fca1e8d43155198a46d" +checksum = "1687dc887e42f352865a393acae7cf79d98fab6351cde1f58e9e057da89bf150" dependencies = [ "const-random", - "derive-syn-parse 0.1.5", + "derive-syn-parse 0.2.0", "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "macro_magic_core_macros" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" +checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "macro_magic_macros" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" +checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -5620,9 +5627,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matrixmultiply" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" dependencies = [ "autocfg", "rawpointer", @@ -5630,9 +5637,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memfd" @@ -5640,7 +5647,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.32", + "rustix 0.38.34", ] [[package]] @@ -5710,22 +5717,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi 0.3.9", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -5739,16 +5747,16 @@ dependencies = [ "bitflags 1.3.2", "blake2 0.10.6", "c2-chacha", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "either", "hashlink", "lioness", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "rand_chacha 0.3.1", "rand_distr", - "subtle 2.5.0", + "subtle 2.4.1", "thiserror", "zeroize", ] @@ -5857,7 +5865,7 @@ dependencies = [ "blake3", "core2", "digest 0.10.7", - "multihash-derive 0.8.0", + "multihash-derive 0.8.1", "sha2 0.10.8", "sha3", "unsigned-varint", @@ -5871,7 +5879,7 @@ checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" dependencies = [ "core2", "digest 0.10.7", - "multihash-derive 0.8.0", + "multihash-derive 0.8.1", "sha2 0.10.8", "unsigned-varint", ] @@ -5908,16 +5916,16 @@ dependencies = [ [[package]] name = "multihash-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" +checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 1.1.3", "proc-macro-error", "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -5933,16 +5941,16 @@ dependencies = [ [[package]] name = "multihash-derive-impl" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38685e08adb338659871ecfc6ee47ba9b22dcc8abcf6975d379cc49145c3040" +checksum = "3958713ce794e12f7c6326fac9aa274c68d74c4881dd37b3e2662b8a2046bb19" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 2.0.0", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", - "synstructure", + "syn 2.0.74", + "synstructure 0.13.1", ] [[package]] @@ -5967,9 +5975,9 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.4" +version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4541eb06dce09c0241ebbaab7102f0a01a0c8994afed2e5d0d66775016e25ac2" +checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" dependencies = [ "approx", "matrixmultiply", @@ -5983,13 +5991,13 @@ dependencies = [ [[package]] name = "nalgebra-macros" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.74", ] [[package]] @@ -6062,9 +6070,9 @@ dependencies = [ [[package]] name = "netlink-sys" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307" dependencies = [ "bytes", "futures", @@ -6090,7 +6098,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "libc", ] @@ -6131,20 +6139,19 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -6176,11 +6183,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -6188,9 +6194,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -6202,7 +6208,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -6226,9 +6232,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -6274,9 +6280,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchestra" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2356622ffdfe72362a45a1e5e87bb113b8327e596e39b91f11f0ef4395c8da79" +checksum = "92829eef0328a3d1cd22a02c0e51deb92a5362df3e7d21a4e9bdc38934694e66" dependencies = [ "async-trait", "dyn-clonable", @@ -6291,15 +6297,15 @@ dependencies = [ [[package]] name = "orchestra-proc-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eedb646674596266dc9bb2b5c7eea7c36b32ecc7777eba0d510196972d72c4fd" +checksum = "1344346d5af32c95bbddea91b18a88cc83eac394192d20ef2fc4c40a74332355" dependencies = [ - "expander 2.1.0", - "indexmap 2.2.6", + "expander 2.2.1", + "indexmap 2.3.0", "itertools 0.11.0", "petgraph", - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -6560,7 +6566,7 @@ version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d334f24d3c0c016d16aa87d069485847d622e8ebebace18ec5cf56609ca3a67" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "binary-merkle-tree", "frame-support", "frame-system", @@ -6802,7 +6808,7 @@ checksum = "3163c6bc21b55a0ccb74c546ba784d9c9e69beb9240c059d28a3052f4cbce509" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -7470,7 +7476,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -7849,7 +7855,7 @@ dependencies = [ "log", "lz4", "memmap2 0.5.10", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "siphasher", "snap", @@ -7901,7 +7907,7 @@ dependencies = [ "impl-trait-for-tuples", "lru 0.8.1", "parity-util-mem-derive", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "primitive-types", "smallvec", "winapi", @@ -7915,7 +7921,7 @@ checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -7943,12 +7949,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", + "parking_lot_core 0.9.10", ] [[package]] @@ -7967,15 +7973,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -7987,7 +7993,7 @@ checksum = "7924d1d0ad836f665c9065e26d016c673ece3993f30d340068b16f282afc1156" [[package]] name = "paseo-runtime" version = "1.2.5" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#e7265b10b28d8b82c3146e72c98895dac2b55729" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" dependencies = [ "binary-merkle-tree", "frame-benchmarking", @@ -8082,7 +8088,7 @@ dependencies = [ [[package]] name = "paseo-runtime-constants" version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#e7265b10b28d8b82c3146e72c98895dac2b55729" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" dependencies = [ "frame-support", "polkadot-primitives", @@ -8096,9 +8102,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbkdf2" @@ -8106,7 +8112,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" dependencies = [ - "crypto-mac 0.11.0", + "crypto-mac 0.11.1", ] [[package]] @@ -8141,9 +8147,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.8" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -8152,9 +8158,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.8" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -8162,22 +8168,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.8" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "pest_meta" -version = "2.7.8" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -8186,12 +8192,12 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.3.0", ] [[package]] @@ -8211,7 +8217,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -8222,9 +8228,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -8234,12 +8240,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-io", ] @@ -8259,12 +8265,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" - [[package]] name = "polkadot-approval-distribution" version = "8.0.0" @@ -8426,7 +8426,7 @@ dependencies = [ "fatality", "futures", "futures-timer", - "indexmap 2.2.6", + "indexmap 2.3.0", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -8492,7 +8492,7 @@ dependencies = [ "fatality", "futures", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-subsystem", @@ -8753,7 +8753,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3bbb1b5f4b966f21a0336e94c0a0222958d2f3cba451da1157af271d07f9748" dependencies = [ "always-assert", - "array-bytes 6.2.2", + "array-bytes 6.2.3", "blake3", "cfg-if", "futures", @@ -8851,7 +8851,7 @@ dependencies = [ "log", "mick-jaeger", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-primitives", "polkadot-primitives", "sc-network", @@ -8984,7 +8984,7 @@ dependencies = [ "kvdb", "parity-db", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "polkadot-node-jaeger", "polkadot-node-metrics", @@ -9015,7 +9015,7 @@ dependencies = [ "futures", "futures-timer", "orchestra", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -9250,7 +9250,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "parity-db", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "polkadot-approval-distribution", "polkadot-availability-bitfield-distribution", "polkadot-availability-distribution", @@ -9353,7 +9353,7 @@ dependencies = [ "fatality", "futures", "futures-timer", - "indexmap 2.2.6", + "indexmap 2.3.0", "parity-scale-codec", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -9391,7 +9391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6380dbe1fb03ecc74ad55d841cfc75480222d153ba69ddcb00977866cbdabdb8" dependencies = [ "polkavm-derive-impl", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -9403,7 +9403,7 @@ dependencies = [ "polkavm-common", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -9418,23 +9418,23 @@ dependencies = [ "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "windows-sys 0.48.0", ] [[package]] name = "polling" -version = "3.6.0" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi", - "pin-project-lite 0.2.13", - "rustix 0.38.32", + "hermit-abi 0.4.0", + "pin-project-lite 0.2.14", + "rustix 0.38.34", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -9557,7 +9557,7 @@ dependencies = [ "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-utility", - "env_logger 0.11.3", + "env_logger 0.11.5", "frame-benchmarking", "frame-executive", "frame-support", @@ -9631,7 +9631,7 @@ dependencies = [ "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-utility", - "env_logger 0.11.3", + "env_logger 0.11.5", "frame-benchmarking", "frame-executive", "frame-support", @@ -9693,9 +9693,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "powerfmt" @@ -9705,9 +9705,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "predicates" @@ -9725,35 +9728,25 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" dependencies = [ "predicates-core", "termtree", ] -[[package]] -name = "prettier-please" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3" -dependencies = [ - "proc-macro2", - "syn 2.0.55", -] - [[package]] name = "prettyplease" -version = "0.1.11" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28f53e8b192565862cf99343194579a022eb9c7dd3a8d03134734803c7b3125" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" dependencies = [ "proc-macro2", "syn 1.0.109", @@ -9761,12 +9754,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -9802,12 +9795,21 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "thiserror", + "toml 0.5.11", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +dependencies = [ + "toml_edit 0.20.7", ] [[package]] @@ -9851,29 +9853,29 @@ checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if", "fnv", "lazy_static", "memchr", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "thiserror", ] @@ -9885,7 +9887,7 @@ checksum = "5d6fa99d535dd930d1249e6c79cb3c2915f9172a540fe2b02a4c8f9ca954721e" dependencies = [ "dtoa", "itoa", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "prometheus-client-derive-encode", ] @@ -9897,7 +9899,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -9912,12 +9914,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.12.3", + "prost-derive 0.12.6", ] [[package]] @@ -9933,7 +9935,7 @@ dependencies = [ "log", "multimap", "petgraph", - "prettyplease 0.1.11", + "prettyplease 0.1.25", "prost 0.11.9", "prost-types", "regex", @@ -9957,15 +9959,15 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -10045,9 +10047,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -10104,7 +10106,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", ] [[package]] @@ -10175,20 +10177,20 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "libredox", "thiserror", ] @@ -10207,22 +10209,22 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -10239,14 +10241,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -10260,13 +10262,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.4", ] [[package]] @@ -10277,9 +10279,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "resolv-conf" @@ -10298,7 +10300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac 0.12.1", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] @@ -10324,7 +10326,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.12", + "getrandom 0.2.15", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -10519,9 +10521,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -10541,7 +10543,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.22", + "semver 1.0.23", ] [[package]] @@ -10583,14 +10585,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] @@ -10608,9 +10610,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring 0.17.8", @@ -10651,9 +10653,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ruzstd" @@ -10679,15 +10681,15 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safe_arch" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354" +checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" dependencies = [ "bytemuck", ] @@ -10728,7 +10730,7 @@ dependencies = [ "multihash 0.18.1", "multihash-codetable", "parity-scale-codec", - "prost 0.12.3", + "prost 0.12.6", "prost-build", "rand", "sc-client-api", @@ -10788,7 +10790,7 @@ version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f73880050f8b04fed7f6301279ef3899df13a3891bd06156d56f9a1c50fefba" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "docify", "log", "memmap2 0.9.4", @@ -10818,7 +10820,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -10827,7 +10829,7 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a284c10ea92b1fe789b9f0e5815d393f3a1e3bf6a4adaa884f24e36143b83b" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bip39", "chrono", "clap", @@ -10873,7 +10875,7 @@ dependencies = [ "futures", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-executor", "sc-transaction-pool-api", "sc-utils", @@ -10905,7 +10907,7 @@ dependencies = [ "log", "parity-db", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-state-db", "schnellru", @@ -10930,7 +10932,7 @@ dependencies = [ "libp2p-identity", "log", "mockall", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-utils", "serde", @@ -10988,7 +10990,7 @@ dependencies = [ "num-rational", "num-traits", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-consensus", "sc-consensus-epochs", @@ -11040,14 +11042,14 @@ version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9ce3ee15eff7fa642791966d427f185184df3c7f4e58893705f3e7781da8ef5" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-channel 1.9.0", "async-trait", "fnv", "futures", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-consensus", "sc-network", @@ -11081,7 +11083,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-consensus-beefy", "sc-rpc", "serde", @@ -11112,7 +11114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ae91e5b5a120be4d13a59eaf94fd85d7c7af528482b8e21d861fa1167df3083" dependencies = [ "ahash 0.8.11", - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-trait", "dyn-clone", "finality-grandpa", @@ -11121,7 +11123,7 @@ dependencies = [ "futures-timer", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "sc-block-builder", "sc-chain-spec", @@ -11201,7 +11203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa2ac6c356538d67987bbb867e11a12a84ba87250c70fd50005b6d74f570a4f7" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-executor-common", "sc-executor-wasmtime", "schnellru", @@ -11240,7 +11242,7 @@ dependencies = [ "cfg-if", "libc", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rustix 0.36.17", "sc-allocator", "sc-executor-common", @@ -11273,8 +11275,8 @@ version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cc4f6a558dd23e3bae2e9f195da822465258b9aaf211c34360d7f6efb944e54" dependencies = [ - "array-bytes 6.2.2", - "parking_lot 0.12.1", + "array-bytes 6.2.3", + "parking_lot 0.12.3", "serde_json", "sp-application-crypto", "sp-core", @@ -11299,7 +11301,7 @@ dependencies = [ "mixnet", "multiaddr", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-network", "sc-transaction-pool-api", @@ -11318,7 +11320,7 @@ version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f231c7d5e749ec428b4cfa669d759ae76cd3da4f50d7352a2d711acdc7532891" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-channel 1.9.0", "async-trait", "asynchronous-codec", @@ -11333,7 +11335,7 @@ dependencies = [ "log", "mockall", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "partial_sort", "pin-project", "rand", @@ -11367,7 +11369,7 @@ dependencies = [ "futures", "libp2p-identity", "log", - "prost 0.12.3", + "prost 0.12.6", "prost-build", "sc-client-api", "sc-network", @@ -11421,13 +11423,13 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84ef0b212c775f58e0304ec09166089f6b09afddf559b7c2b5702933b3be4" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-channel 1.9.0", "futures", "libp2p-identity", "log", "parity-scale-codec", - "prost 0.12.3", + "prost 0.12.6", "prost-build", "sc-client-api", "sc-network", @@ -11443,7 +11445,7 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aa9377059deece4e7d419d9ec456f657268c0c603e1cf98df4a920f6da83461" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "async-channel 1.9.0", "async-trait", "fork-tree", @@ -11453,7 +11455,7 @@ dependencies = [ "log", "mockall", "parity-scale-codec", - "prost 0.12.3", + "prost 0.12.6", "prost-build", "sc-client-api", "sc-consensus", @@ -11480,7 +11482,7 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16c9cad4baf348725bd82eadcd1747fc112ec49c76b863755ce79c588fa73fe4" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "futures", "libp2p", "log", @@ -11500,7 +11502,7 @@ version = "30.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aee89f2abd406356bfd688bd7a51155dc963259e4b752bb85d1f8a061a194fd" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bytes", "fnv", "futures", @@ -11512,7 +11514,7 @@ dependencies = [ "num_cpus", "once_cell", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "sc-client-api", "sc-network", @@ -11549,7 +11551,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -11615,14 +11617,14 @@ version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7f10275c62296a785f6e2ac716521e3b6e0fae470416fdf86491cbbfcc2e23d" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "futures", "futures-util", "hex", "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-chain-spec", "sc-client-api", "sc-rpc", @@ -11654,7 +11656,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "sc-chain-spec", @@ -11712,7 +11714,7 @@ checksum = "aa842052c41ad379eaecdfddc0d5c953d57e311ae688233f68f461b91d38da0a" dependencies = [ "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sp-core", ] @@ -11782,7 +11784,7 @@ dependencies = [ "futures", "libp2p", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "sc-utils", @@ -11805,7 +11807,7 @@ dependencies = [ "libc", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "regex", "rustc-hash", "sc-client-api", @@ -11832,7 +11834,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -11847,7 +11849,7 @@ dependencies = [ "linked-hash-map", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-transaction-pool-api", "sc-utils", @@ -11891,16 +11893,16 @@ dependencies = [ "futures-timer", "lazy_static", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "prometheus", "sp-arithmetic", ] [[package]] name = "scale-info" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "788745a868b0e751750388f4e6546eb921ef714a4317fa6954f7cde114eb2eb7" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "bitvec", "cfg-if", @@ -11912,11 +11914,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc2f4e8bc344b9fc3d5f74f72c2e55bfc38d28dc2ebc69c194a3df424e4d9ac" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -11933,9 +11935,9 @@ dependencies = [ [[package]] name = "schnellru" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" dependencies = [ "ahash 0.8.11", "cfg-if", @@ -11967,13 +11969,13 @@ dependencies = [ "aead", "arrayref", "arrayvec 0.7.4", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "getrandom_or_panic", "merlin", "rand_core 0.6.4", "serde_bytes", "sha2 0.10.8", - "subtle 2.5.0", + "subtle 2.4.1", "zeroize", ] @@ -12009,7 +12011,7 @@ dependencies = [ "der", "generic-array 0.14.7", "pkcs8", - "subtle 2.5.0", + "subtle 2.4.1", "zeroize", ] @@ -12051,11 +12053,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -12064,9 +12066,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -12083,9 +12085,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -12098,9 +12100,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" dependencies = [ "serde_derive", ] @@ -12116,40 +12118,41 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -12229,9 +12232,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -12353,7 +12356,7 @@ dependencies = [ "fnv", "futures-lite 1.13.0", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "hmac 0.12.1", "itertools 0.11.0", @@ -12402,13 +12405,13 @@ dependencies = [ "futures-channel", "futures-lite 1.13.0", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "itertools 0.11.0", "log", "lru 0.11.1", "no-std-net", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "rand_chacha 0.3.1", @@ -12436,12 +12439,12 @@ dependencies = [ "aes-gcm", "blake2 0.10.6", "chacha20poly1305", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "ring 0.17.8", "rustc_version", "sha2 0.10.8", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] @@ -12456,9 +12459,9 @@ dependencies = [ [[package]] name = "snowbridge-beacon-primitives" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a73ef707257064bc4ecce8323cdb7c30e8ecd1ce74aa89a6e82e81fa8b9970" +checksum = "5404af73550b39022e08e5500b30fba627e109a56407b7e80b08da2305b11bfe" dependencies = [ "byte-slice-cast", "frame-support", @@ -12481,9 +12484,9 @@ dependencies = [ [[package]] name = "snowbridge-core" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3e2e3b94bfcfc8f363e21a6c5a1d3c67eb4592ada672c868a3236ad1dd563b" +checksum = "aed4ebefed4c40b9c00e9adf5f02ab2760a7a2dad8bf05110c0013a7a59f4097" dependencies = [ "ethabi-decode", "frame-support", @@ -12577,9 +12580,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -12632,11 +12635,11 @@ checksum = "0301e2f77afb450fbf2b093f8b324c7ad88cc82e5e69bd5dc8658a1f068b2a96" dependencies = [ "Inflector", "blake2 0.10.6", - "expander 2.1.0", + "expander 2.2.1", "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -12703,7 +12706,7 @@ dependencies = [ "futures", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "schnellru", "sp-api", "sp-consensus", @@ -12826,7 +12829,7 @@ version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c33c7a1568175250628567d50c4e1c54a6ac5bc1190413b9be29a9e810cbe73" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bip39", "bitflags 1.3.2", "blake2 0.10.6", @@ -12843,7 +12846,7 @@ dependencies = [ "log", "merlin", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "paste", "primitive-types", "rand", @@ -12888,7 +12891,7 @@ checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -12898,7 +12901,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "722cbecdbf5b94578137dbd07feb51e95f7de221be0c1ff4dcfe0bb4cd986929" dependencies = [ "kvdb", - "parking_lot 0.12.1", + "parking_lot 0.12.3", ] [[package]] @@ -12909,7 +12912,7 @@ checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -12995,7 +12998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444f2d53968b1ce5e908882710ff1f3873fcf3e95f59d57432daf685bbacb959" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sp-core", "sp-externalities", "thiserror", @@ -13154,11 +13157,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfaf6e85b2ec12a4b99cd6d8d57d083e30c94b7f1b0d8f93547121495aae6f0c" dependencies = [ "Inflector", - "expander 2.1.0", + "expander 2.2.1", "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -13201,7 +13204,7 @@ dependencies = [ "hash-db", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "smallvec", "sp-core", @@ -13221,7 +13224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "309a9ae4e8134bbed8ffc510cf4d461a4a651f9250b556de782cedd876abe1ff" dependencies = [ "aes-gcm", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519-dalek", "hkdf", "parity-scale-codec", @@ -13325,7 +13328,7 @@ dependencies = [ "memory-db", "nohash-hasher", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "scale-info", "schnellru", @@ -13365,7 +13368,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -13496,7 +13499,7 @@ version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48fa328b87de3466bc38cc9a07244c42c647b7755b81115e1dfeb47cc13fc6e6" dependencies = [ - "array-bytes 6.2.2", + "array-bytes 6.2.3", "bounded-collections", "derivative", "environmental", @@ -13597,15 +13600,15 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "keccak", - "subtle 2.5.0", + "subtle 2.4.1", "zeroize", ] [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -13618,9 +13621,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.25.0" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" [[package]] name = "strum_macros" @@ -13637,15 +13640,15 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -13746,7 +13749,7 @@ dependencies = [ "sp-maybe-compressed-blob", "strum 0.24.1", "tempfile", - "toml 0.8.12", + "toml 0.8.19", "walkdir", "wasm-opt", ] @@ -13759,9 +13762,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "subtle" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "subtle-ng" @@ -13782,9 +13785,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.55" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", @@ -13803,6 +13806,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.74", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -13827,7 +13841,7 @@ dependencies = [ [[package]] name = "system-parachains-constants" version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#e7265b10b28d8b82c3146e72c98895dac2b55729" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" dependencies = [ "frame-support", "parachains-common", @@ -13846,20 +13860,21 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", - "fastrand 2.0.2", - "rustix 0.38.32", - "windows-sys 0.52.0", + "fastrand 2.1.0", + "once_cell", + "rustix 0.38.34", + "windows-sys 0.59.0", ] [[package]] @@ -13877,7 +13892,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.48.0", ] @@ -13889,9 +13904,9 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] @@ -13913,18 +13928,18 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -13988,9 +14003,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -14009,9 +14024,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -14028,9 +14043,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -14043,32 +14058,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", - "parking_lot 0.12.1", - "pin-project-lite 0.2.13", + "parking_lot 0.12.3", + "pin-project-lite 0.2.14", "signal-hook-registry", - "socket2 0.5.6", + "socket2 0.5.7", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -14088,7 +14102,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", + "rustls 0.21.12", "tokio", ] @@ -14099,24 +14113,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tokio", "tokio-util", ] [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tokio", - "tracing", ] [[package]] @@ -14130,32 +14143,32 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.12" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.9", + "toml_edit 0.22.20", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "toml_datetime", "winnow 0.5.40", ] @@ -14166,22 +14179,22 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.18", ] [[package]] @@ -14193,7 +14206,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tower-layer", "tower-service", "tracing", @@ -14205,14 +14218,14 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "futures-core", "futures-util", "http", "http-body", "http-range-header", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tower-layer", "tower-service", ] @@ -14236,7 +14249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.14", "tracing-attributes", "tracing-core", ] @@ -14249,7 +14262,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -14290,11 +14303,11 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f074568687ffdfd0adb6005aa8d1d96840197f2c159f80471285f08694cf0ce" dependencies = [ - "expander 2.1.0", + "expander 2.2.1", "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -14427,7 +14440,7 @@ dependencies = [ "ipconfig", "lazy_static", "lru-cache", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "resolv-conf", "smallvec", "thiserror", @@ -14544,9 +14557,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -14561,7 +14574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", - "subtle 2.5.0", + "subtle 2.4.1", ] [[package]] @@ -14590,9 +14603,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna 0.5.0", @@ -14601,9 +14614,9 @@ dependencies = [ [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" @@ -14619,9 +14632,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "void" @@ -14631,9 +14644,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "w3f-bls" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7335e4c132c28cc43caef6adb339789e599e39adbe78da0c4d547fad48cbc331" +checksum = "9c5da5fa2c6afa2c9158eaa7cd9aee249765eb32b5fb0c63ad8b9e79336a47ec" dependencies = [ "ark-bls12-377", "ark-bls12-381", @@ -14655,9 +14668,9 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "walkdir" @@ -14701,34 +14714,35 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -14738,9 +14752,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -14748,22 +14762,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-instrument" @@ -14776,9 +14790,9 @@ dependencies = [ [[package]] name = "wasm-opt" -version = "0.116.0" +version = "0.116.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc942673e7684671f0c5708fc18993569d184265fd5223bb51fc8e5b9b6cfd52" +checksum = "2fd87a4c135535ffed86123b6fb0f0a5a0bc89e50416c942c5f0662c645f679c" dependencies = [ "anyhow", "libc", @@ -14872,9 +14886,9 @@ dependencies = [ [[package]] name = "wasmparser-nostd" -version = "0.100.1" +version = "0.100.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" dependencies = [ "indexmap-nostd", ] @@ -15076,9 +15090,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -15105,15 +15119,16 @@ dependencies = [ [[package]] name = "westend-runtime" -version = "8.0.0" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2a5cebb4c678a0d1291bb21f9d44ddebceae044b0fb5200fa3bed108a31595" +checksum = "b4aa5580861b05668a6af845aa271c4f699a2fc26646d524e5b0d9375fb0647e" dependencies = [ "binary-merkle-tree", "bitvec", "frame-benchmarking", "frame-election-provider-support", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -15236,14 +15251,14 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.32", + "rustix 0.38.34", ] [[package]] name = "wide" -version = "0.7.15" +version = "0.7.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89beec544f246e679fc25490e3f8e08003bc4bf612068f325120dad4cea02c1c" +checksum = "b828f995bf1e9622031f8009f8481a85406ce1f4d4588ff746d872043e855690" dependencies = [ "bytemuck", "safe_arch", @@ -15251,9 +15266,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" [[package]] name = "winapi" @@ -15273,11 +15288,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -15292,7 +15307,7 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ - "windows-core", + "windows-core 0.51.1", "windows-targets 0.48.5", ] @@ -15305,6 +15320,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -15329,7 +15353,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "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", ] [[package]] @@ -15364,17 +15397,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "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", ] [[package]] @@ -15391,9 +15425,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -15409,9 +15443,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -15427,9 +15461,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -15445,9 +15485,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -15463,9 +15503,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -15481,9 +15521,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -15499,9 +15539,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -15514,9 +15554,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -15557,7 +15597,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "serde", "zeroize", @@ -15625,7 +15665,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -15637,7 +15677,7 @@ dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "static_assertions", ] @@ -15653,29 +15693,30 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -15688,7 +15729,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.74", ] [[package]] @@ -15731,9 +15772,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", From 545bd334dac38a1b7bf28e5be6c7de7822672c8a Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Tue, 13 Aug 2024 13:33:12 +0200 Subject: [PATCH 037/161] fix: try-runtime error --- runtime/devnet/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index 5f83d991..87dce79e 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -202,6 +202,7 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "frame-try-runtime/try-runtime", + "pallet-api/try-runtime", "pallet-aura/try-runtime", "pallet-authorship/try-runtime", "pallet-assets/try-runtime", @@ -224,4 +225,4 @@ try-runtime = [ "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", -] \ No newline at end of file +] From 99d0f6d76aaac6d366ae62a68983ea0878840685 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Tue, 13 Aug 2024 23:00:33 +0700 Subject: [PATCH 038/161] refactor: generic extension crate to de-duplicate code between runtimes (#163) --- Cargo.lock | 17 + Cargo.toml | 26 +- extension/Cargo.toml | 51 ++ extension/src/lib.rs | 323 ++++++++++++ extension/src/tests.rs | 135 +++++ .../src/extensions => extension/src}/v0.rs | 4 +- runtime/devnet/Cargo.toml | 2 + runtime/devnet/src/config/api.rs | 57 ++- runtime/devnet/src/config/contracts.rs | 7 +- runtime/devnet/src/extensions/mod.rs | 480 ------------------ runtime/devnet/src/lib.rs | 1 - 11 files changed, 583 insertions(+), 520 deletions(-) create mode 100644 extension/Cargo.toml create mode 100644 extension/src/lib.rs create mode 100644 extension/src/tests.rs rename {runtime/devnet/src/extensions => extension/src}/v0.rs (98%) delete mode 100644 runtime/devnet/src/extensions/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 7f033a20..78e5e1d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9460,6 +9460,22 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "pop-chain-extension" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "log", + "pallet-contracts", + "parity-scale-codec", + "pop-primitives", + "rand", + "sp-core", + "sp-runtime", + "sp-std", +] + [[package]] name = "pop-node" version = "0.1.0-alpha" @@ -9594,6 +9610,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-runtime-common", + "pop-chain-extension", "pop-primitives", "pop-runtime-common", "rand", diff --git a/Cargo.toml b/Cargo.toml index d082e838..f037f6b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,18 +23,19 @@ members = [ "pallets/*", "primitives", ] -exclude = [ - "pop-api", - "tests/contracts" -] +exclude = ["pop-api", "tests/contracts"] resolver = "2" [workspace.dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ + "derive", +] } hex-literal = "0.4.1" log = { version = "0.4.20", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = [ + "derive", +] } smallvec = "1.11.0" serde = "1.0.195" clap = { version = "4.4.18", features = ["derive"] } @@ -52,7 +53,8 @@ substrate-build-script-utils = "11.0.0" # Local pallet-api = { path = "pallets/api", default-features = false } -pop-runtime-devnet = { path = "runtime/devnet", default-features = true } # default-features=true required for `-p pop-node` builds +pop-chain-extension = { path = "./extension", default-features = false } +pop-runtime-devnet = { path = "runtime/devnet", default-features = true } # default-features=true required for `-p pop-node` builds pop-runtime-testnet = { path = "runtime/testnet", default-features = true } # default-features=true required for `-p pop-node` builds pop-runtime-common = { path = "runtime/common", default-features = false } pop-primitives = { path = "./primitives", default-features = false } @@ -82,7 +84,9 @@ frame-system = { version = "29.0.0", default-features = false } frame-system-benchmarking = { version = "29.0.0", default-features = false } frame-system-rpc-runtime-api = { version = "27.0.0", default-features = false } frame-try-runtime = { version = "0.35.0", default-features = false } -pallet-aura = { version = "28.0.0", default-features = false, features = ["experimental"] } +pallet-aura = { version = "28.0.0", default-features = false, features = [ + "experimental", +] } pallet-authorship = { version = "29.0.0", default-features = false } pallet-assets = { version = "30.0.0", default-features = false } pallet-balances = { version = "29.0.2", default-features = false } @@ -139,7 +143,9 @@ xcm-executor = { package = "staging-xcm-executor", version = "8.0.2", default-fe # Cumulus asset-test-utils = { version = "8.0.1", default-features = false } cumulus-pallet-aura-ext = { version = "0.8.0", default-features = false } -cumulus-pallet-parachain-system = { version = "0.8.1", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { version = "0.8.1", default-features = false, features = [ + "parameterized-consensus-hook", +] } cumulus-pallet-session-benchmarking = { version = "10.0.0", default-features = false } cumulus-pallet-xcm = { version = "0.8.0", default-features = false } cumulus-pallet-xcmp-queue = { version = "0.8.0", default-features = false } @@ -163,4 +169,4 @@ cumulus-client-service = "0.8.0" # Paseo asset-hub-paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } -paseo-runtime-constants = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } \ No newline at end of file +paseo-runtime-constants = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } diff --git a/extension/Cargo.toml b/extension/Cargo.toml new file mode 100644 index 00000000..03b4221a --- /dev/null +++ b/extension/Cargo.toml @@ -0,0 +1,51 @@ +[package] +name = "pop-chain-extension" +version = "0.1.0" +authors.workspace = true +description.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +edition.workspace = true +publish = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec.workspace = true +log.workspace = true + +# Local +pop-primitives.workspace = true + +# Substrate +frame-support.workspace = true +frame-system.workspace = true +pallet-contracts.workspace = true +sp-core.workspace = true +sp-runtime.workspace = true +sp-std.workspace = true + +[dev-dependencies] +rand = "0.8.5" + +[features] +default = ["std"] +std = [ + "log/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "pallet-contracts/std", + "pop-primitives/std", + "sp-runtime/std", + "sp-core/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-contracts/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] diff --git a/extension/src/lib.rs b/extension/src/lib.rs new file mode 100644 index 00000000..582f346c --- /dev/null +++ b/extension/src/lib.rs @@ -0,0 +1,323 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(test)] +mod tests; +mod v0; + +use codec::Encode; +use frame_support::{ + dispatch::{GetDispatchInfo, PostDispatchInfo}, + pallet_prelude::*, + traits::OriginTrait, +}; +use frame_system::RawOrigin; +use pallet_contracts::chain_extension::{ + BufInBufOutState, ChainExtension, Environment, Ext, InitState, RetVal, +}; +use sp_core::crypto::UncheckedFrom; +use sp_runtime::{traits::Dispatchable, DispatchError}; +use sp_std::vec::Vec; + +/// Logging target for categorizing messages from the Pop API extension module. +const LOG_TARGET: &str = "pop-api::extension"; + +const DECODING_FAILED_ERROR: DispatchError = DispatchError::Other("DecodingFailed"); +// TODO: issue #93, we can also encode the `pop_primitives::Error::UnknownCall` which means we do use +// `Error` in the runtime and it should stay in primitives. Perhaps issue #91 will also influence +// here. Should be looked at together. +const DECODING_FAILED_ERROR_ENCODED: [u8; 4] = [255u8, 0, 0, 0]; +const UNKNOWN_CALL_ERROR: DispatchError = DispatchError::Other("UnknownCall"); +// TODO: see above. +const UNKNOWN_CALL_ERROR_ENCODED: [u8; 4] = [254u8, 0, 0, 0]; + +type ContractSchedule = ::Schedule; + +/// Type of the state reader. +pub trait ReadState { + /// Query of the state read operations. + type StateQuery: Decode; + + /// Check if a state query is allowed. + fn contains(c: &Self::StateQuery) -> bool; + + /// Reads state using the provided query, returning the result as a byte vector. + fn read(read: Self::StateQuery) -> Vec; + + /// Decodes parameters into state query. + fn decode(params: &mut &[u8]) -> Result { + decode_checked(params) + } +} + +/// Type of the dispatch call filter. +pub trait CallFilter { + /// Query of the dispatch calls operations. + type Call: Decode; + + /// Check if runtime call is allowed. + fn contains(t: &Self::Call) -> bool; +} + +/// Pop API chain extension. +#[derive(Default)] +pub struct ApiExtension(PhantomData); + +impl ChainExtension for ApiExtension +where + T: pallet_contracts::Config + + frame_system::Config< + RuntimeCall: GetDispatchInfo + Dispatchable, + >, + T::AccountId: UncheckedFrom + AsRef<[u8]>, + // Bound the type by the two traits which need to be implemented by the runtime. + I: ReadState + CallFilter::RuntimeCall> + 'static, +{ + fn call>( + &mut self, + env: Environment, + ) -> Result { + log::debug!(target:LOG_TARGET, " extension called "); + let mut env = env.buf_in_buf_out(); + // Charge weight for making a call from a contract to the runtime. + // `debug_message` weight is a good approximation of the additional overhead of going + // from contract layer to substrate layer. + // reference: https://github.com/paritytech/ink-examples/blob/b8d2caa52cf4691e0ddd7c919e4462311deb5ad0/psp22-extension/runtime/psp22-extension-example.rs#L236 + let contract_host_weight = ContractSchedule::::get().host_fn_weights; + env.charge_weight(contract_host_weight.debug_message)?; + + let (version, function_id, pallet_index, call_index) = extract_env(&env); + + let result = match FuncId::try_from(function_id) { + // Read encoded parameters from buffer and calculate weight for reading `len` bytes`. + Ok(function_id) => { + // reference: https://github.com/paritytech/polkadot-sdk/blob/117a9433dac88d5ac00c058c9b39c511d47749d2/substrate/frame/contracts/src/wasm/runtime.rs#L267 + let len = env.in_len(); + env.charge_weight(contract_host_weight.return_per_byte.saturating_mul(len.into()))?; + let params = env.read(len)?; + match function_id { + FuncId::Dispatch => { + dispatch::(&mut env, version, pallet_index, call_index, params) + }, + FuncId::ReadState => { + read_state::(&mut env, version, pallet_index, call_index, params) + }, + } + }, + Err(e) => Err(e), + }; + + match result { + Ok(_) => Ok(RetVal::Converging(0)), + Err(e) => Ok(RetVal::Converging(convert_to_status_code(e, version))), + } + } +} + +/// Extract (version, function_id, pallet_index, call_index) from the payload bytes. +fn extract_env>(env: &Environment) -> (u8, u8, u8, u8) { + // Extract version and function_id from first two bytes. + let (version, function_id) = { + let bytes = env.func_id().to_le_bytes(); + (bytes[0], bytes[1]) + }; + // Extract pallet index and call / key index from last two bytes. + let (pallet_index, call_index) = { + let bytes = env.ext_id().to_le_bytes(); + (bytes[0], bytes[1]) + }; + + (version, function_id, pallet_index, call_index) +} + +fn read_state, StateReader: ReadState>( + env: &mut Environment, + version: u8, + pallet_index: u8, + call_index: u8, + mut params: Vec, +) -> Result<(), DispatchError> { + const LOG_PREFIX: &str = " read_state |"; + + // Prefix params with version, pallet, index to simplify decoding. + params.insert(0, version); + params.insert(1, pallet_index); + params.insert(2, call_index); + let (mut encoded_version, mut encoded_read) = (¶ms[..1], ¶ms[1..]); + let version = decode_checked::(&mut encoded_version)?; + + // Charge weight for doing one storage read. + env.charge_weight(T::DbWeight::get().reads(1_u64))?; + let result = match version { + VersionedStateRead::V0 => { + let read = StateReader::decode(&mut encoded_read)?; + ensure!(StateReader::contains(&read), UNKNOWN_CALL_ERROR); + StateReader::read(read) + }, + }; + log::trace!( + target:LOG_TARGET, + "{} result: {:?}.", LOG_PREFIX, result + ); + env.write(&result, false, None) +} + +fn dispatch( + env: &mut Environment, + version: u8, + pallet_index: u8, + call_index: u8, + mut params: Vec, +) -> Result<(), DispatchError> +where + T: frame_system::Config< + RuntimeCall: GetDispatchInfo + Dispatchable, + >, + E: Ext, + Filter: CallFilter::RuntimeCall> + 'static, +{ + const LOG_PREFIX: &str = " dispatch |"; + + // Prefix params with version, pallet, index to simplify decoding. + params.insert(0, version); + params.insert(1, pallet_index); + params.insert(2, call_index); + let call = decode_checked::>(&mut ¶ms[..])?; + // Contract is the origin by default. + let origin: T::RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); + match call { + VersionedDispatch::V0(call) => dispatch_call::(env, call, origin, LOG_PREFIX), + } +} + +/// Helper method to decode the byte data to a provided type and throws error if failed. +fn decode_checked(params: &mut &[u8]) -> Result { + T::decode(params).map_err(|_| DECODING_FAILED_ERROR) +} + +fn dispatch_call( + env: &mut Environment, + call: T::RuntimeCall, + mut origin: T::RuntimeOrigin, + log_prefix: &str, +) -> Result<(), DispatchError> +where + T: frame_system::Config< + RuntimeCall: GetDispatchInfo + Dispatchable, + >, + E: Ext, + Filter: CallFilter::RuntimeCall> + 'static, +{ + let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; + log::debug!(target:LOG_TARGET, "{} Inputted RuntimeCall: {:?}", log_prefix, call); + origin.add_filter(Filter::contains); + match call.dispatch(origin) { + Ok(info) => { + log::debug!(target:LOG_TARGET, "{} success, actual weight: {:?}", log_prefix, info.actual_weight); + // Refund weight if the actual weight is less than the charged weight. + if let Some(actual_weight) = info.actual_weight { + env.adjust_weight(charged_dispatch_weight, actual_weight); + } + Ok(()) + }, + Err(err) => { + log::debug!(target:LOG_TARGET, "{} failed: error: {:?}", log_prefix, err.error); + Err(err.error) + }, + } +} + +/// Wrapper to enable versioning of runtime state reads. +#[derive(Decode, Debug)] +enum VersionedStateRead { + /// Version zero of state reads. + #[codec(index = 0)] + V0, +} + +/// Wrapper to enable versioning of runtime calls. +#[derive(Decode, Debug)] +enum VersionedDispatch { + /// Version zero of dispatch calls. + #[codec(index = 0)] + V0(RuntimeCall), +} + +/// Function identifiers used in the Pop API. +/// +/// The `FuncId` specifies the available functions that can be called through the Pop API. Each +/// variant corresponds to a specific functionality provided by the API, facilitating the +/// interaction between smart contracts and the runtime. +#[derive(Debug)] +pub enum FuncId { + /// Represents a function call to dispatch a runtime call. + Dispatch, + /// Represents a function call to read the state from the runtime. + ReadState, +} + +impl TryFrom for FuncId { + type Error = DispatchError; + + /// Attempts to convert a `u8` value to its corresponding `FuncId` variant. + /// + /// If the `u8` value does not match any known function identifier, it returns a + /// `DispatchError::Other` indicating an unknown function ID. + fn try_from(func_id: u8) -> Result { + let id = match func_id { + 0 => Self::Dispatch, + 1 => Self::ReadState, + _ => { + return Err(UNKNOWN_CALL_ERROR); + }, + }; + Ok(id) + } +} + +/// Converts a `DispatchError` to a `u32` status code based on the version of the API the contract uses. +/// The contract calling the chain extension can convert the status code to the descriptive `Error`. +/// +/// For `Error` see `pop_primitives::::error::Error`. +/// +/// The error encoding can vary per version, allowing for flexible and backward-compatible error handling. +/// As a result, contracts maintain compatibility across different versions of the runtime. +/// +/// # Parameters +/// +/// - `error`: The `DispatchError` encountered during contract execution. +/// - `version`: The version of the chain extension, used to determine the known errors. +pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { + let mut encoded_error: [u8; 4] = match error { + // "UnknownCall" and "DecodingFailed" are mapped to specific errors in the API and will + // never change. + UNKNOWN_CALL_ERROR => UNKNOWN_CALL_ERROR_ENCODED, + DECODING_FAILED_ERROR => DECODING_FAILED_ERROR_ENCODED, + _ => { + let mut encoded_error = error.encode(); + // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). + encoded_error.resize(4, 0); + encoded_error.try_into().expect("qed, resized to 4 bytes line above") + }, + }; + match version { + // If an unknown variant of the `DispatchError` is detected the error needs to be converted + // into the encoded value of `Error::Other`. This conversion is performed by shifting the bytes one + // position forward (discarding the last byte as it is not used) and setting the first byte to the + // encoded value of `Other` (0u8). This ensures the error is correctly categorized as an `Other` + // variant which provides all the necessary information to debug which error occurred in the runtime. + // + // Byte layout explanation: + // - Byte 0: index of the variant within `Error` + // - Byte 1: + // - Must be zero for `UNIT_ERRORS`. + // - Represents the nested error in `SINGLE_NESTED_ERRORS`. + // - Represents the first level of nesting in `DOUBLE_NESTED_ERRORS`. + // - Byte 2: + // - Represents the second level of nesting in `DOUBLE_NESTED_ERRORS`. + // - Byte 3: + // - Unused or represents further nested information. + 0 => v0::handle_unknown_error(&mut encoded_error), + _ => encoded_error = UNKNOWN_CALL_ERROR_ENCODED, + } + u32::from_le_bytes(encoded_error) +} diff --git a/extension/src/tests.rs b/extension/src/tests.rs new file mode 100644 index 00000000..a47feef9 --- /dev/null +++ b/extension/src/tests.rs @@ -0,0 +1,135 @@ +use codec::{Decode, Encode}; + +// Test ensuring `func_id()` and `ext_id()` work as expected, i.e. extracting the first two +// bytes and the last two bytes, respectively, from a 4 byte array. +#[test] +fn test_byte_extraction() { + use rand::Rng; + + // Helper functions + fn func_id(id: u32) -> u16 { + (id & 0x0000FFFF) as u16 + } + fn ext_id(id: u32) -> u16 { + (id >> 16) as u16 + } + + // Number of test iterations + let test_iterations = 1_000_000; + + // Create a random number generator + let mut rng = rand::thread_rng(); + + // Run the test for a large number of random 4-byte arrays + for _ in 0..test_iterations { + // Generate a random 4-byte array + let bytes: [u8; 4] = rng.gen(); + + // Convert the 4-byte array to a u32 value + let value = u32::from_le_bytes(bytes); + + // Extract the first two bytes (least significant 2 bytes) + let first_two_bytes = func_id(value); + + // Extract the last two bytes (most significant 2 bytes) + let last_two_bytes = ext_id(value); + + // Check if the first two bytes match the expected value + assert_eq!([bytes[0], bytes[1]], first_two_bytes.to_le_bytes()); + + // Check if the last two bytes match the expected value + assert_eq!([bytes[2], bytes[3]], last_two_bytes.to_le_bytes()); + } +} + +// Test showing all the different type of variants and its encoding. +#[test] +fn encoding_of_enum() { + #[derive(Debug, PartialEq, Encode, Decode)] + enum ComprehensiveEnum { + SimpleVariant, + DataVariant(u8), + NamedFields { w: u8 }, + NestedEnum(InnerEnum), + OptionVariant(Option), + VecVariant(Vec), + TupleVariant(u8, u8), + NestedStructVariant(NestedStruct), + NestedEnumStructVariant(NestedEnumStruct), + } + + #[derive(Debug, PartialEq, Encode, Decode)] + enum InnerEnum { + A, + B { inner_data: u8 }, + C(u8), + } + + #[derive(Debug, PartialEq, Encode, Decode)] + struct NestedStruct { + x: u8, + y: u8, + } + + #[derive(Debug, PartialEq, Encode, Decode)] + struct NestedEnumStruct { + inner_enum: InnerEnum, + } + + // Creating each possible variant for an enum. + let enum_simple = ComprehensiveEnum::SimpleVariant; + let enum_data = ComprehensiveEnum::DataVariant(42); + let enum_named = ComprehensiveEnum::NamedFields { w: 42 }; + let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 }); + let enum_option = ComprehensiveEnum::OptionVariant(Some(42)); + let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]); + let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42); + let enum_nested_struct = ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 }); + let enum_nested_enum_struct = ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { + inner_enum: InnerEnum::C(42), + }); + + // Encode and print each variant individually to see their encoded values. + println!("{:?} -> {:?}", enum_simple, enum_simple.encode()); + println!("{:?} -> {:?}", enum_data, enum_data.encode()); + println!("{:?} -> {:?}", enum_named, enum_named.encode()); + println!("{:?} -> {:?}", enum_nested, enum_nested.encode()); + println!("{:?} -> {:?}", enum_option, enum_option.encode()); + println!("{:?} -> {:?}", enum_vec, enum_vec.encode()); + println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode()); + println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode()); + println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); +} + +#[test] +fn encoding_decoding_dispatch_error() { + use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; + + let error = DispatchError::Module(ModuleError { + index: 255, + error: [2, 0, 0, 0], + message: Some("error message"), + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); + assert_eq!( + decoded, + // `message` is skipped for encoding. + DispatchError::Module(ModuleError { index: 255, error: [2, 0, 0, 0], message: None }) + ); + + // Example DispatchError::Token + let error = DispatchError::Token(TokenError::UnknownAsset); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![7, 4]); + assert_eq!(decoded, error); + + // Example DispatchError::Arithmetic + let error = DispatchError::Arithmetic(ArithmeticError::Overflow); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![8, 1]); + assert_eq!(decoded, error); +} diff --git a/runtime/devnet/src/extensions/v0.rs b/extension/src/v0.rs similarity index 98% rename from runtime/devnet/src/extensions/v0.rs rename to extension/src/v0.rs index 72760323..4c3536a4 100644 --- a/runtime/devnet/src/extensions/v0.rs +++ b/extension/src/v0.rs @@ -1,5 +1,5 @@ #[cfg(test)] -use crate::extensions::convert_to_status_code; +use crate::convert_to_status_code; pub(crate) fn handle_unknown_error(encoded_error: &mut [u8; 4]) { let unknown = match encoded_error[0] { @@ -106,7 +106,7 @@ mod tests { (DispatchError::RootNotAllowed, RootNotAllowed), ]; for (dispatch_error, expected) in test_cases { - let status_code = crate::extensions::convert_to_status_code(dispatch_error, 0); + let status_code = crate::convert_to_status_code(dispatch_error, 0); let error: Error = status_code.into(); assert_eq!(error, expected); } diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index 87dce79e..995af269 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -22,6 +22,7 @@ scale-info.workspace = true smallvec.workspace = true # Local +pop-chain-extension.workspace = true pop-primitives.workspace = true pop-runtime-common.workspace = true pallet-api.workspace = true @@ -139,6 +140,7 @@ std = [ "parachains-common/std", "polkadot-parachain-primitives/std", "polkadot-runtime-common/std", + "pop-chain-extension/std", "pop-primitives/std", "scale-info/std", "sp-api/std", diff --git a/runtime/devnet/src/config/api.rs b/runtime/devnet/src/config/api.rs index bdff6bbb..5f234cd4 100644 --- a/runtime/devnet/src/config/api.rs +++ b/runtime/devnet/src/config/api.rs @@ -1,22 +1,47 @@ use crate::{config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall}; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::traits::Contains; +use pop_chain_extension::{CallFilter, ReadState}; +use sp_std::vec::Vec; /// A query of runtime state. #[derive(Encode, Decode, Debug, MaxEncodedLen)] #[repr(u8)] -pub enum RuntimeRead { +pub enum RuntimeRead { /// Fungible token queries. #[codec(index = 150)] - Fungibles(fungibles::Read), + Fungibles(fungibles::Read), } -/// A type to identify allowed calls to the Runtime from the API. -pub struct AllowedApiCalls; +/// A struct that implement requirements for the Pop API chain extension. +#[derive(Default)] +pub struct Extension; +impl ReadState for Extension { + type StateQuery = RuntimeRead; -impl Contains for AllowedApiCalls { - /// Allowed runtime calls from the API. - fn contains(c: &RuntimeCall) -> bool { + fn contains(c: &Self::StateQuery) -> bool { + use fungibles::Read::*; + matches!( + c, + RuntimeRead::Fungibles( + TotalSupply(..) + | BalanceOf { .. } | Allowance { .. } + | TokenName(..) | TokenSymbol(..) + | TokenDecimals(..) | AssetExists(..) + ) + ) + } + + fn read(read: RuntimeRead) -> Vec { + match read { + RuntimeRead::Fungibles(key) => fungibles::Pallet::read_state(key), + } + } +} + +impl CallFilter for Extension { + type Call = RuntimeCall; + + fn contains(c: &Self::Call) -> bool { use fungibles::Call::*; matches!( c, @@ -34,22 +59,6 @@ impl Contains for AllowedApiCalls { } } -impl Contains> for AllowedApiCalls { - /// Allowed state queries from the API. - fn contains(c: &RuntimeRead) -> bool { - use fungibles::Read::*; - matches!( - c, - RuntimeRead::Fungibles( - TotalSupply(..) - | BalanceOf { .. } | Allowance { .. } - | TokenName(..) | TokenSymbol(..) - | TokenDecimals(..) | AssetExists(..) - ) - ) - } -} - impl fungibles::Config for Runtime { type AssetsInstance = TrustBackedAssetsInstance; type WeightInfo = fungibles::weights::SubstrateWeight; diff --git a/runtime/devnet/src/config/contracts.rs b/runtime/devnet/src/config/contracts.rs index 36d62f7f..5dc613b5 100644 --- a/runtime/devnet/src/config/contracts.rs +++ b/runtime/devnet/src/config/contracts.rs @@ -1,6 +1,7 @@ +use super::api::Extension; use crate::{ - deposit, extensions, Balance, Balances, BalancesCall, Perbill, Runtime, RuntimeCall, - RuntimeEvent, RuntimeHoldReason, Timestamp, + deposit, Balance, Balances, BalancesCall, Perbill, Runtime, RuntimeCall, RuntimeEvent, + RuntimeHoldReason, Timestamp, }; use frame_support::{ parameter_types, @@ -63,7 +64,7 @@ impl pallet_contracts::Config for Runtime { type CallStack = [pallet_contracts::Frame; 23]; type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; - type ChainExtension = extensions::PopApiExtension; + type ChainExtension = pop_chain_extension::ApiExtension; type Schedule = Schedule; type AddressGenerator = pallet_contracts::DefaultAddressGenerator; // This node is geared towards development and testing of contracts. diff --git a/runtime/devnet/src/extensions/mod.rs b/runtime/devnet/src/extensions/mod.rs deleted file mode 100644 index d3bbdd0b..00000000 --- a/runtime/devnet/src/extensions/mod.rs +++ /dev/null @@ -1,480 +0,0 @@ -mod v0; - -use crate::{ - config::{ - api::{AllowedApiCalls, RuntimeRead}, - assets::TrustBackedAssetsInstance, - }, - fungibles::{self}, - AccountId, RuntimeCall, RuntimeOrigin, -}; -use codec::{Decode, Encode}; -use frame_support::{ - dispatch::{GetDispatchInfo, RawOrigin}, - pallet_prelude::*, - traits::{Contains, OriginTrait}, -}; -use pallet_contracts::chain_extension::{ - BufInBufOutState, ChainExtension, Environment, Ext, InitState, RetVal, -}; -use pop_primitives::AssetId; -use sp_core::crypto::UncheckedFrom; -use sp_runtime::{traits::Dispatchable, DispatchError}; -use sp_std::vec::Vec; - -const LOG_TARGET: &str = "pop-api::extension"; -const DECODING_FAILED_ERROR: DispatchError = DispatchError::Other("DecodingFailed"); -// TODO: issue #93, we can also encode the `pop_primitives::Error::UnknownCall` which means we do use -// `Error` in the runtime and it should stay in primitives. Perhaps issue #91 will also influence -// here. Should be looked at together. -const DECODING_FAILED_ERROR_ENCODED: [u8; 4] = [255u8, 0, 0, 0]; -const UNKNOWN_CALL_ERROR: DispatchError = DispatchError::Other("UnknownCall"); -// TODO: see above. -const UNKNOWN_CALL_ERROR_ENCODED: [u8; 4] = [254u8, 0, 0, 0]; - -type ContractSchedule = ::Schedule; - -#[derive(Default)] -pub struct PopApiExtension; - -impl ChainExtension for PopApiExtension -where - T: pallet_contracts::Config - + pallet_assets::Config - + fungibles::Config - + frame_system::Config< - RuntimeOrigin = RuntimeOrigin, - AccountId = AccountId, - RuntimeCall = RuntimeCall, - >, - T::AccountId: UncheckedFrom + AsRef<[u8]>, -{ - fn call(&mut self, env: Environment) -> Result - where - E: Ext, - { - log::debug!(target:LOG_TARGET, " extension called "); - let mut env = env.buf_in_buf_out(); - // Charge weight for making a call from a contract to the runtime. - // `debug_message` weight is a good approximation of the additional overhead of going - // from contract layer to substrate layer. - // reference: https://github.com/paritytech/ink-examples/blob/b8d2caa52cf4691e0ddd7c919e4462311deb5ad0/psp22-extension/runtime/psp22-extension-example.rs#L236 - let contract_host_weight = ContractSchedule::::get().host_fn_weights; - env.charge_weight(contract_host_weight.debug_message)?; - - // Extract version and function_id from first two bytes. - let (version, function_id) = { - let bytes = env.func_id().to_le_bytes(); - (bytes[0], bytes[1]) - }; - // Extract pallet index and call / key index from last two bytes. - let (pallet_index, call_index) = { - let bytes = env.ext_id().to_le_bytes(); - (bytes[0], bytes[1]) - }; - - let result = match FuncId::try_from(function_id) { - Ok(function_id) => { - // Read encoded parameters from buffer and calculate weight for reading `len` bytes`. - // reference: https://github.com/paritytech/polkadot-sdk/blob/117a9433dac88d5ac00c058c9b39c511d47749d2/substrate/frame/contracts/src/wasm/runtime.rs#L267 - let len = env.in_len(); - env.charge_weight(contract_host_weight.return_per_byte.saturating_mul(len.into()))?; - let params = env.read(len)?; - log::debug!(target: LOG_TARGET, "Read input successfully"); - match function_id { - FuncId::Dispatch => { - dispatch::(&mut env, version, pallet_index, call_index, params) - }, - FuncId::ReadState => { - read_state::(&mut env, version, pallet_index, call_index, params) - }, - } - }, - Err(e) => Err(e), - }; - - match result { - Ok(_) => Ok(RetVal::Converging(0)), - Err(e) => Ok(RetVal::Converging(convert_to_status_code(e, version))), - } - } -} - -fn dispatch( - env: &mut Environment, - version: u8, - pallet_index: u8, - call_index: u8, - mut params: Vec, -) -> Result<(), DispatchError> -where - T: frame_system::Config, - RuntimeOrigin: From>, - E: Ext, -{ - const LOG_PREFIX: &str = " dispatch |"; - - // Prefix params with version, pallet, index to simplify decoding. - params.insert(0, version); - params.insert(1, pallet_index); - params.insert(2, call_index); - let call = ::decode(&mut ¶ms[..]).map_err(|_| DECODING_FAILED_ERROR)?; - - // Contract is the origin by default. - let origin: RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); - match call { - VersionedDispatch::V0(call) => dispatch_call::(env, call, origin, LOG_PREFIX), - } -} - -fn dispatch_call( - env: &mut Environment, - call: RuntimeCall, - mut origin: RuntimeOrigin, - log_prefix: &str, -) -> Result<(), DispatchError> -where - T: frame_system::Config, - RuntimeOrigin: From>, - E: Ext, -{ - let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; - log::debug!(target:LOG_TARGET, "{} Inputted RuntimeCall: {:?}", log_prefix, call); - origin.add_filter(AllowedApiCalls::contains); - match call.dispatch(origin) { - Ok(info) => { - log::debug!(target:LOG_TARGET, "{} success, actual weight: {:?}", log_prefix, info.actual_weight); - // Refund weight if the actual weight is less than the charged weight. - if let Some(actual_weight) = info.actual_weight { - env.adjust_weight(charged_dispatch_weight, actual_weight); - } - Ok(()) - }, - Err(err) => { - log::debug!(target:LOG_TARGET, "{} failed: error: {:?}", log_prefix, err.error); - Err(err.error) - }, - } -} - -fn read_state( - env: &mut Environment, - version: u8, - pallet_index: u8, - call_index: u8, - mut params: Vec, -) -> Result<(), DispatchError> -where - T: pallet_contracts::Config - + pallet_assets::Config - + fungibles::Config - + frame_system::Config, - E: Ext, -{ - const LOG_PREFIX: &str = " read_state |"; - - // Prefix params with version, pallet, index to simplify decoding, and decode parameters for - // reading state. - params.insert(0, version); - params.insert(1, pallet_index); - params.insert(2, call_index); - let read = - >::decode(&mut ¶ms[..]).map_err(|_| DECODING_FAILED_ERROR)?; - - // Charge weight for doing one storage read. - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - let result = match read { - VersionedStateRead::V0(read) => { - ensure!(AllowedApiCalls::contains(&read), UNKNOWN_CALL_ERROR); - match read { - RuntimeRead::Fungibles(key) => fungibles::Pallet::::read_state(key), - } - }, - }; - log::trace!( - target:LOG_TARGET, - "{} result: {:?}.", LOG_PREFIX, result - ); - env.write(&result, false, None) -} - -/// Wrapper to enable versioning of runtime state reads. -#[derive(Decode, Debug)] -enum VersionedStateRead { - /// Version zero of state reads. - #[codec(index = 0)] - V0(RuntimeRead), -} - -/// Wrapper to enable versioning of runtime calls. -#[derive(Decode, Debug)] -enum VersionedDispatch { - /// Version zero of dispatch calls. - #[codec(index = 0)] - V0(RuntimeCall), -} - -// Converts a `DispatchError` to a `u32` status code based on the version of the API the contract uses. -// The contract calling the chain extension can convert the status code to the descriptive `Error`. -// -// For `Error` see `pop_primitives::::error::Error`. -// -// The error encoding can vary per version, allowing for flexible and backward-compatible error handling. -// As a result, contracts maintain compatibility across different versions of the runtime. -// -// # Parameters -// -// - `error`: The `DispatchError` encountered during contract execution. -// - `version`: The version of the chain extension, used to determine the known errors. -pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { - let mut encoded_error: [u8; 4] = match error { - // "UnknownCall" and "DecodingFailed" are mapped to specific errors in the API and will - // never change. - UNKNOWN_CALL_ERROR => UNKNOWN_CALL_ERROR_ENCODED, - DECODING_FAILED_ERROR => DECODING_FAILED_ERROR_ENCODED, - _ => { - let mut encoded_error = error.encode(); - // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). - encoded_error.resize(4, 0); - encoded_error.try_into().expect("qed, resized to 4 bytes line above") - }, - }; - match version { - // If an unknown variant of the `DispatchError` is detected the error needs to be converted - // into the encoded value of `Error::Other`. This conversion is performed by shifting the bytes one - // position forward (discarding the last byte as it is not used) and setting the first byte to the - // encoded value of `Other` (0u8). This ensures the error is correctly categorized as an `Other` - // variant which provides all the necessary information to debug which error occurred in the runtime. - // - // Byte layout explanation: - // - Byte 0: index of the variant within `Error` - // - Byte 1: - // - Must be zero for `UNIT_ERRORS`. - // - Represents the nested error in `SINGLE_NESTED_ERRORS`. - // - Represents the first level of nesting in `DOUBLE_NESTED_ERRORS`. - // - Byte 2: - // - Represents the second level of nesting in `DOUBLE_NESTED_ERRORS`. - // - Byte 3: - // - Unused or represents further nested information. - 0 => v0::handle_unknown_error(&mut encoded_error), - _ => encoded_error = UNKNOWN_CALL_ERROR_ENCODED, - } - u32::from_le_bytes(encoded_error) -} - -/// Function identifiers used in the Pop API. -/// -/// The `FuncId` specifies the available functions that can be called through the Pop API. Each -/// variant corresponds to a specific functionality provided by the API, facilitating the -/// interaction between smart contracts and the runtime. -/// -/// - `Dispatch`: Represents a function call to dispatch a runtime call. -/// - `ReadState`: Represents a function call to read the state from the runtime. -/// - `SendXcm`: Represents a function call to send an XCM message. -#[derive(Debug)] -pub enum FuncId { - Dispatch, - ReadState, -} - -impl TryFrom for FuncId { - type Error = DispatchError; - - /// Attempts to convert a `u8` value to its corresponding `FuncId` variant. - /// - /// If the `u8` value does not match any known function identifier, it returns a - /// `DispatchError::Other` indicating an unknown function ID. - fn try_from(func_id: u8) -> Result { - let id = match func_id { - 0 => Self::Dispatch, - 1 => Self::ReadState, - _ => { - return Err(UNKNOWN_CALL_ERROR); - }, - }; - Ok(id) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{Assets, Runtime, System}; - use sp_runtime::BuildStorage; - - // Test ensuring `func_id()` and `ext_id()` work as expected, i.e. extracting the first two - // bytes and the last two bytes, respectively, from a 4 byte array. - #[test] - fn test_byte_extraction() { - use rand::Rng; - - // Helper functions - fn func_id(id: u32) -> u16 { - (id & 0x0000FFFF) as u16 - } - fn ext_id(id: u32) -> u16 { - (id >> 16) as u16 - } - - // Number of test iterations - let test_iterations = 1_000_000; - - // Create a random number generator - let mut rng = rand::thread_rng(); - - // Run the test for a large number of random 4-byte arrays - for _ in 0..test_iterations { - // Generate a random 4-byte array - let bytes: [u8; 4] = rng.gen(); - - // Convert the 4-byte array to a u32 value - let value = u32::from_le_bytes(bytes); - - // Extract the first two bytes (least significant 2 bytes) - let first_two_bytes = func_id(value); - - // Extract the last two bytes (most significant 2 bytes) - let last_two_bytes = ext_id(value); - - // Check if the first two bytes match the expected value - assert_eq!([bytes[0], bytes[1]], first_two_bytes.to_le_bytes()); - - // Check if the last two bytes match the expected value - assert_eq!([bytes[2], bytes[3]], last_two_bytes.to_le_bytes()); - } - } - - // Test showing all the different type of variants and its encoding. - #[test] - fn encoding_of_enum() { - #[derive(Debug, PartialEq, Encode, Decode)] - enum ComprehensiveEnum { - SimpleVariant, - DataVariant(u8), - NamedFields { w: u8 }, - NestedEnum(InnerEnum), - OptionVariant(Option), - VecVariant(Vec), - TupleVariant(u8, u8), - NestedStructVariant(NestedStruct), - NestedEnumStructVariant(NestedEnumStruct), - } - - #[derive(Debug, PartialEq, Encode, Decode)] - enum InnerEnum { - A, - B { inner_data: u8 }, - C(u8), - } - - #[derive(Debug, PartialEq, Encode, Decode)] - struct NestedStruct { - x: u8, - y: u8, - } - - #[derive(Debug, PartialEq, Encode, Decode)] - struct NestedEnumStruct { - inner_enum: InnerEnum, - } - - // Creating each possible variant for an enum. - let enum_simple = ComprehensiveEnum::SimpleVariant; - let enum_data = ComprehensiveEnum::DataVariant(42); - let enum_named = ComprehensiveEnum::NamedFields { w: 42 }; - let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 }); - let enum_option = ComprehensiveEnum::OptionVariant(Some(42)); - let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]); - let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42); - let enum_nested_struct = - ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 }); - let enum_nested_enum_struct = - ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { - inner_enum: InnerEnum::C(42), - }); - - // Encode and print each variant individually to see their encoded values. - println!("{:?} -> {:?}", enum_simple, enum_simple.encode()); - println!("{:?} -> {:?}", enum_data, enum_data.encode()); - println!("{:?} -> {:?}", enum_named, enum_named.encode()); - println!("{:?} -> {:?}", enum_nested, enum_nested.encode()); - println!("{:?} -> {:?}", enum_option, enum_option.encode()); - println!("{:?} -> {:?}", enum_vec, enum_vec.encode()); - println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode()); - println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode()); - println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); - } - - fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::::default() - .build_storage() - .expect("Frame system builds valid default genesis config"); - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } - - #[test] - fn encoding_decoding_dispatch_error() { - use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; - - new_test_ext().execute_with(|| { - let error = DispatchError::Module(ModuleError { - index: 255, - error: [2, 0, 0, 0], - message: Some("error message"), - }); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); - assert_eq!( - decoded, - // `message` is skipped for encoding. - DispatchError::Module(ModuleError { - index: 255, - error: [2, 0, 0, 0], - message: None - }) - ); - - // Example pallet assets Error into ModuleError. - let index = <::PalletInfo as frame_support::traits::PalletInfo>::index::< - Assets, - >() - .expect("Every active module has an index in the runtime; qed") as u8; - let mut error = - pallet_assets::Error::NotFrozen::.encode(); - error.resize(MAX_MODULE_ERROR_ENCODED_SIZE, 0); - let error = DispatchError::Module(ModuleError { - index, - error: TryInto::try_into(error).expect("should work"), - message: None, - }); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 52, 18, 0, 0, 0]); - assert_eq!( - decoded, - DispatchError::Module(ModuleError { - index: 52, - error: [18, 0, 0, 0], - message: None - }) - ); - - // Example DispatchError::Token - let error = DispatchError::Token(TokenError::UnknownAsset); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![7, 4]); - assert_eq!(decoded, error); - - // Example DispatchError::Arithmetic - let error = DispatchError::Arithmetic(ArithmeticError::Overflow); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![8, 1]); - assert_eq!(decoded, error); - }); - } -} diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 130fbb9a..4256ac01 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -8,7 +8,6 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); // Public due to integration tests crate. pub mod config; -mod extensions; mod weights; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; From 8b4f595fc745804301162a5ed5845837ee524601 Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Wed, 14 Aug 2024 10:00:49 +0200 Subject: [PATCH 039/161] feat: api events (#153) Co-authored-by: Frank Bell --- pallets/api/src/fungibles/mod.rs | 182 +++++++++++++++++++------ pallets/api/src/fungibles/tests.rs | 211 ++++++++++++++++++----------- pallets/api/src/mock.rs | 1 + pop-api/src/v0/assets/fungibles.rs | 85 ++++++++++++ runtime/devnet/src/config/api.rs | 5 +- 5 files changed, 359 insertions(+), 125 deletions(-) diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index eefad0e1..7aa9ac00 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -84,6 +84,8 @@ pub mod pallet { /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] pub trait Config: frame_system::Config + pallet_assets::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// The instance of pallet assets it is tightly coupled to. type AssetsInstance; /// Weight information for dispatchables in this pallet. @@ -93,6 +95,43 @@ pub mod pallet { #[pallet::pallet] pub struct Pallet(_); + /// The events that can be emitted. + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Event emitted when allowance by `owner` to `spender` changes. + Approval { + /// The ID of the asset. + id: AssetIdOf, + /// Account providing allowance. + owner: AccountIdOf, + /// Allowance beneficiary. + spender: AccountIdOf, + /// New allowance amount. + value: BalanceOf, + }, + /// Event emitted when transfer of tokens occurs. + Transfer { + /// The ID of the asset. + id: AssetIdOf, + /// Transfer sender. `None` in case of minting new tokens. + from: Option>, + /// Transfer recipient. `None` in case of burning tokens. + to: Option>, + /// Amount of tokens transferred (or minted/burned). + value: BalanceOf, + }, + /// Event emitted when a token class is created. + Create { + /// The ID of the asset. + id: AssetIdOf, + /// Creator of the asset. + creator: AccountIdOf, + /// Admin of the asset. + admin: AccountIdOf, + }, + } + #[pallet::call] impl Pallet { /// Transfers `value` amount of tokens from the caller's account to account `to`, with additional @@ -110,8 +149,15 @@ pub mod pallet { to: AccountIdOf, value: BalanceOf, ) -> DispatchResult { - let to = T::Lookup::unlookup(to); - AssetsOf::::transfer_keep_alive(origin, id.into(), to, value) + AssetsOf::::transfer_keep_alive( + origin.clone(), + id.clone().into(), + T::Lookup::unlookup(to.clone()), + value, + )?; + let from = ensure_signed(origin)?; + Self::deposit_event(Event::Transfer { id, from: Some(from), to: Some(to), value }); + Ok(()) } /// Transfers `value` amount tokens on behalf of `from` to account `to` with additional `data` @@ -119,7 +165,7 @@ pub mod pallet { /// /// # Parameters /// - `id` - The ID of the asset. - /// - `owner` - The account from which the asset balance will be withdrawn. + /// - `from` - The account from which the asset balance will be withdrawn. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[pallet::call_index(4)] @@ -131,9 +177,15 @@ pub mod pallet { to: AccountIdOf, value: BalanceOf, ) -> DispatchResult { - let from = T::Lookup::unlookup(from); - let to = T::Lookup::unlookup(to); - AssetsOf::::transfer_approved(origin, id.into(), from, to, value) + AssetsOf::::transfer_approved( + origin, + id.clone().into(), + T::Lookup::unlookup(from.clone()), + T::Lookup::unlookup(to.clone()), + value, + )?; + Self::deposit_event(Event::Transfer { id, from: Some(from), to: Some(to), value }); + Ok(()) } /// Approves an account to spend a specified number of tokens on behalf of the caller. @@ -150,13 +202,11 @@ pub mod pallet { spender: AccountIdOf, value: BalanceOf, ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin.clone()) + let owner = ensure_signed(origin.clone()) .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; - let current_allowance = AssetsOf::::allowance(id.clone(), &who, &spender); - let spender = T::Lookup::unlookup(spender); - let id: AssetIdParameterOf = id.into(); + let current_allowance = AssetsOf::::allowance(id.clone(), &owner, &spender); - let return_weight = match value.cmp(¤t_allowance) { + let weight = match value.cmp(¤t_allowance) { // If the new value is equal to the current allowance, do nothing. Equal => Self::weight_approve(0, 0), // If the new value is greater than the current allowance, approve the difference @@ -164,8 +214,8 @@ pub mod pallet { Greater => { AssetsOf::::approve_transfer( origin, - id, - spender, + id.clone().into(), + T::Lookup::unlookup(spender.clone()), value.saturating_sub(current_allowance), ) .map_err(|e| e.with_weight(Self::weight_approve(1, 0)))?; @@ -174,16 +224,24 @@ pub mod pallet { // If the new value is less than the current allowance, cancel the approval and // set the new value. Less => { - AssetsOf::::cancel_approval(origin.clone(), id.clone(), spender.clone()) - .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; + let id_param: AssetIdParameterOf = id.clone().into(); + let spender_source = T::Lookup::unlookup(spender.clone()); + AssetsOf::::cancel_approval( + origin.clone(), + id_param.clone(), + spender_source.clone(), + ) + .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; if value.is_zero() { - return Ok(Some(Self::weight_approve(0, 1)).into()); + Self::weight_approve(0, 1) + } else { + AssetsOf::::approve_transfer(origin, id_param, spender_source, value)?; + Self::weight_approve(1, 1) } - AssetsOf::::approve_transfer(origin, id, spender, value)?; - Self::weight_approve(1, 1) }, }; - Ok(Some(return_weight).into()) + Self::deposit_event(Event::Approval { id, owner, spender, value }); + Ok(Some(weight).into()) } /// Increases the allowance of a spender. @@ -193,15 +251,25 @@ pub mod pallet { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[pallet::call_index(6)] - #[pallet::weight(AssetsWeightInfoOf::::approve_transfer())] + #[pallet::weight(::WeightInfo::approve(1, 0))] pub fn increase_allowance( origin: OriginFor, id: AssetIdOf, spender: AccountIdOf, value: BalanceOf, - ) -> DispatchResult { - let spender = T::Lookup::unlookup(spender); - AssetsOf::::approve_transfer(origin, id.into(), spender, value) + ) -> DispatchResultWithPostInfo { + let owner = ensure_signed(origin.clone()) + .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; + AssetsOf::::approve_transfer( + origin, + id.clone().into(), + T::Lookup::unlookup(spender.clone()), + value, + ) + .map_err(|e| e.with_weight(AssetsWeightInfoOf::::approve_transfer()))?; + let value = AssetsOf::::allowance(id.clone(), &owner, &spender); + Self::deposit_event(Event::Approval { id, owner, spender, value }); + Ok(().into()) } /// Decreases the allowance of a spender. @@ -218,24 +286,31 @@ pub mod pallet { spender: AccountIdOf, value: BalanceOf, ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin.clone()) + let owner = ensure_signed(origin.clone()) .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; - let current_allowance = AssetsOf::::allowance(id.clone(), &who, &spender); - let spender = T::Lookup::unlookup(spender); - let id: AssetIdParameterOf = id.into(); - if value.is_zero() { return Ok(Some(Self::weight_approve(0, 0)).into()); } - // Cancel the aproval and set the new value if `new_allowance` is more than zero. - AssetsOf::::cancel_approval(origin.clone(), id.clone(), spender.clone()) - .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; + let current_allowance = AssetsOf::::allowance(id.clone(), &owner, &spender); + let spender_source = T::Lookup::unlookup(spender.clone()); + let id_param: AssetIdParameterOf = id.clone().into(); + + // Cancel the approval and set the new value if `new_allowance` is more than zero. + AssetsOf::::cancel_approval( + origin.clone(), + id_param.clone(), + spender_source.clone(), + ) + .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; let new_allowance = current_allowance.saturating_sub(value); - if new_allowance.is_zero() { - return Ok(Some(Self::weight_approve(0, 1)).into()); - } - AssetsOf::::approve_transfer(origin, id, spender, new_allowance)?; - Ok(().into()) + let weight = if new_allowance.is_zero() { + Self::weight_approve(0, 1) + } else { + AssetsOf::::approve_transfer(origin, id_param, spender_source, new_allowance)?; + Self::weight_approve(1, 1) + }; + Self::deposit_event(Event::Approval { id, owner, spender, value: new_allowance }); + Ok(Some(weight).into()) } /// Create a new token with a given asset ID. @@ -252,8 +327,15 @@ pub mod pallet { admin: AccountIdOf, min_balance: BalanceOf, ) -> DispatchResult { - let admin = T::Lookup::unlookup(admin); - AssetsOf::::create(origin, id.into(), admin, min_balance) + let creator = ensure_signed(origin.clone())?; + AssetsOf::::create( + origin, + id.clone().into(), + T::Lookup::unlookup(admin.clone()), + min_balance, + )?; + Self::deposit_event(Event::Create { id, creator, admin }); + Ok(()) } /// Start the process of destroying a token with a given asset ID. @@ -297,7 +379,7 @@ pub mod pallet { AssetsOf::::clear_metadata(origin, id.into()) } - /// Creates `value` amount tokens and assigns them to `account`, increasing the total supply. + /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. /// /// # Parameters /// - `id` - The ID of the asset. @@ -311,11 +393,17 @@ pub mod pallet { account: AccountIdOf, value: BalanceOf, ) -> DispatchResult { - let account = T::Lookup::unlookup(account); - AssetsOf::::mint(origin, id.into(), account, value) + AssetsOf::::mint( + origin, + id.clone().into(), + T::Lookup::unlookup(account.clone()), + value, + )?; + Self::deposit_event(Event::Transfer { id, from: None, to: Some(account), value }); + Ok(()) } - /// Destroys `value` amount tokens from `account`, reducing the total supply. + /// Destroys `value` amount of tokens from `account`, reducing the total supply. /// /// # Parameters /// - `id` - The ID of the asset. @@ -329,8 +417,14 @@ pub mod pallet { account: AccountIdOf, value: BalanceOf, ) -> DispatchResult { - let account = T::Lookup::unlookup(account); - AssetsOf::::burn(origin, id.into(), account, value) + AssetsOf::::burn( + origin, + id.clone().into(), + T::Lookup::unlookup(account.clone()), + value, + )?; + Self::deposit_event(Event::Transfer { id, from: Some(account), to: None, value }); + Ok(()) } } diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index d6cc87e0..ca2a85c9 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -2,6 +2,7 @@ use crate::{fungibles::Read::*, mock::*}; use codec::Encode; use frame_support::{ assert_ok, + sp_runtime::traits::Zero, traits::fungibles::{ approvals::Inspect as ApprovalInspect, metadata::Inspect as MetadataInspect, Inspect, }, @@ -9,34 +10,45 @@ use frame_support::{ const ASSET: u32 = 42; +type Event = crate::fungibles::Event; + #[test] fn transfer_works() { new_test_ext().execute_with(|| { - let amount: Balance = 100 * UNIT; - create_asset_and_mint_to(ALICE, ASSET, ALICE, amount); - let balance_before_transfer = Assets::balance(ASSET, &BOB); - assert_ok!(Fungibles::transfer(signed(ALICE), ASSET, BOB, amount / 2)); - let balance_after_transfer = Assets::balance(ASSET, &BOB); - assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2); + let value: Balance = 100 * UNIT; + let id = ASSET; + let from = Some(ALICE); + let to = Some(BOB); + + create_asset_and_mint_to(ALICE, id, ALICE, value * 2); + let balance_before_transfer = Assets::balance(id, &BOB); + assert_ok!(Fungibles::transfer(signed(ALICE), id, BOB, value)); + let balance_after_transfer = Assets::balance(id, &BOB); + assert_eq!(balance_after_transfer, balance_before_transfer + value); + System::assert_last_event(Event::Transfer { id, from, to, value }.into()); }); } #[test] fn transfer_from_works() { new_test_ext().execute_with(|| { - let amount: Balance = 100 * UNIT; - // Approve CHARLIE to transfer up to `amount` to BOB. - create_asset_mint_and_approve(ALICE, ASSET, ALICE, amount * 2, CHARLIE, amount / 2); - let transferred = amount / 2; + let value: Balance = 100 * UNIT; + let id = ASSET; + let from = Some(ALICE); + let to = Some(BOB); + + // Approve CHARLIE to transfer up to `value` to BOB. + create_asset_mint_and_approve(ALICE, id, ALICE, value * 2, CHARLIE, value); // Successfully call transfer from. - let alice_balance_before_transfer = Assets::balance(ASSET, &ALICE); - let balance_before_transfer = Assets::balance(ASSET, &BOB); - assert_ok!(Fungibles::transfer_from(signed(CHARLIE), ASSET, ALICE, BOB, transferred)); - let alice_balance_after_transfer = Assets::balance(ASSET, &ALICE); - let balance_after_transfer = Assets::balance(ASSET, &BOB); - // Check that BOB receives the `amount` and ALICE `amount` is spent successfully by CHARLIE. - assert_eq!(balance_after_transfer, balance_before_transfer + transferred); - assert_eq!(alice_balance_after_transfer, alice_balance_before_transfer - transferred); + let alice_balance_before_transfer = Assets::balance(id, &ALICE); + let bob_balance_before_transfer = Assets::balance(id, &BOB); + assert_ok!(Fungibles::transfer_from(signed(CHARLIE), id, ALICE, BOB, value)); + let alice_balance_after_transfer = Assets::balance(id, &ALICE); + let bob_balance_after_transfer = Assets::balance(id, &BOB); + // Check that BOB receives the `value` and ALICE `amount` is spent successfully by CHARLIE. + assert_eq!(bob_balance_after_transfer, bob_balance_before_transfer + value); + assert_eq!(alice_balance_after_transfer, alice_balance_before_transfer - value); + System::assert_last_event(Event::Transfer { id, from, to, value }.into()); }); } @@ -44,130 +56,169 @@ fn transfer_from_works() { #[test] fn approve_works() { new_test_ext().execute_with(|| { - let amount: Balance = 100 * UNIT; - create_asset_and_mint_to(ALICE, ASSET, ALICE, amount); - assert_eq!(0, Assets::allowance(ASSET, &ALICE, &BOB)); - assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, amount)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); - // Approves an amount to spend that is lower than the current allowance. - assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, amount / 2)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount / 2); - // Approves an amount to spend that is higher than the current allowance. - assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, amount * 2)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount * 2); - // Approves an amount to spend that is equal to the current allowance. - assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, amount * 2)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount * 2); + let value: Balance = 100 * UNIT; + let id = ASSET; + let owner = ALICE; + let spender = BOB; + + create_asset_and_mint_to(ALICE, id, ALICE, value); + assert_eq!(0, Assets::allowance(id, &ALICE, &BOB)); + assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, value)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), value); + System::assert_last_event(Event::Approval { id, owner, spender, value }.into()); + // Approves an value to spend that is lower than the current allowance. + assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, value / 2)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), value / 2); + System::assert_last_event(Event::Approval { id, owner, spender, value: value / 2 }.into()); + // Approves an value to spend that is higher than the current allowance. + assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, value * 2)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), value * 2); + System::assert_last_event(Event::Approval { id, owner, spender, value: value * 2 }.into()); + // Approves an value to spend that is equal to the current allowance. + assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, value * 2)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), value * 2); + System::assert_last_event(Event::Approval { id, owner, spender, value: value * 2 }.into()); // Sets allowance to zero. - assert_ok!(Fungibles::approve(signed(ALICE), ASSET, BOB, 0)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), 0); + assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, 0)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), 0); + System::assert_last_event(Event::Approval { id, owner, spender, value: 0 }.into()); }); } #[test] fn increase_allowance_works() { new_test_ext().execute_with(|| { - let amount: Balance = 100 * UNIT; - create_asset_and_mint_to(ALICE, ASSET, ALICE, amount); - assert_eq!(0, Assets::allowance(ASSET, &ALICE, &BOB)); - assert_ok!(Fungibles::increase_allowance(signed(ALICE), ASSET, BOB, amount)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); + let value: Balance = 100 * UNIT; + let id = ASSET; + let owner = ALICE; + let spender = BOB; + + create_asset_and_mint_to(ALICE, id, ALICE, value); + assert_eq!(0, Assets::allowance(id, &ALICE, &BOB)); + assert_ok!(Fungibles::increase_allowance(signed(ALICE), id, BOB, value)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), value); + System::assert_last_event(Event::Approval { id, owner, spender, value }.into()); // Additive. - assert_ok!(Fungibles::increase_allowance(signed(ALICE), ASSET, BOB, amount)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount * 2); + assert_ok!(Fungibles::increase_allowance(signed(ALICE), id, BOB, value)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), value * 2); + System::assert_last_event(Event::Approval { id, owner, spender, value: value * 2 }.into()); }); } #[test] fn decrease_allowance_works() { new_test_ext().execute_with(|| { - let amount: Balance = 100 * UNIT; - create_asset_mint_and_approve(ALICE, ASSET, ALICE, amount, BOB, amount); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); + let value: Balance = 100 * UNIT; + let id = ASSET; + let owner = ALICE; + let spender = BOB; + + create_asset_mint_and_approve(ALICE, id, ALICE, value, BOB, value); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), value); // Owner balance is not changed if decreased by zero. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, 0)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount); + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), id, BOB, 0)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), value); // Decrease allowance successfully. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, amount / 2 - 1 * UNIT)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), amount / 2 + 1 * UNIT); + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), id, BOB, value / 2)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), value / 2); + System::assert_last_event(Event::Approval { id, owner, spender, value: value / 2 }.into()); // Saturating if current allowance is decreased more than the owner balance. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), ASSET, BOB, amount)); - assert_eq!(Assets::allowance(ASSET, &ALICE, &BOB), 0); + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), id, BOB, value)); + assert_eq!(Assets::allowance(id, &ALICE, &BOB), 0); + System::assert_last_event(Event::Approval { id, owner, spender, value: 0 }.into()); }); } #[test] fn create_works() { new_test_ext().execute_with(|| { - assert!(!Assets::asset_exists(ASSET)); - assert_ok!(Fungibles::create(signed(ALICE), ASSET, ALICE, 100)); - assert!(Assets::asset_exists(ASSET)); + let id = ASSET; + let creator = ALICE; + let admin = ALICE; + + assert!(!Assets::asset_exists(id)); + assert_ok!(Fungibles::create(signed(creator), id, admin, 100)); + assert!(Assets::asset_exists(id)); + System::assert_last_event(Event::Create { id, creator, admin }.into()); }); } #[test] fn start_destroy_works() { new_test_ext().execute_with(|| { - create_asset(ALICE, ASSET); - assert_ok!(Fungibles::start_destroy(signed(ALICE), ASSET)); + let id = ASSET; + + create_asset(ALICE, id); + assert_ok!(Fungibles::start_destroy(signed(ALICE), id)); }); } #[test] fn set_metadata_works() { new_test_ext().execute_with(|| { + let id = ASSET; let name = vec![42]; let symbol = vec![42]; let decimals = 42; - create_asset(ALICE, ASSET); + + create_asset(ALICE, id); assert_ok!(Fungibles::set_metadata( signed(ALICE), - ASSET, + id, name.clone(), symbol.clone(), decimals )); - assert_eq!(Assets::name(ASSET), name); - assert_eq!(Assets::symbol(ASSET), symbol); - assert_eq!(Assets::decimals(ASSET), decimals); + assert_eq!(Assets::name(id), name); + assert_eq!(Assets::symbol(id), symbol); + assert_eq!(Assets::decimals(id), decimals); }); } #[test] fn clear_metadata_works() { new_test_ext().execute_with(|| { - let name = vec![42]; - let symbol = vec![42]; - let decimals = 42; - create_asset_and_set_metadata(ALICE, ASSET, name, symbol, decimals); - assert_ok!(Fungibles::clear_metadata(signed(ALICE), ASSET)); - assert_eq!(Assets::name(ASSET), Vec::::new()); - assert_eq!(Assets::symbol(ASSET), Vec::::new()); - assert_eq!(Assets::decimals(ASSET), 0u8); + let id = ASSET; + + create_asset_and_set_metadata(ALICE, id, vec![42], vec![42], 42); + assert_ok!(Fungibles::clear_metadata(signed(ALICE), id)); + assert!(Assets::name(id).is_empty()); + assert!(Assets::symbol(id).is_empty()); + assert!(Assets::decimals(id).is_zero()); }); } #[test] fn mint_works() { new_test_ext().execute_with(|| { - let amount: Balance = 100 * UNIT; - create_asset(ALICE, ASSET); - let balance_before_mint = Assets::balance(ASSET, &BOB); - assert_ok!(Fungibles::mint(signed(ALICE), ASSET, BOB, amount)); - let balance_after_mint = Assets::balance(ASSET, &BOB); - assert_eq!(balance_after_mint, balance_before_mint + amount); + let value: Balance = 100 * UNIT; + let id = ASSET; + let from = None; + let to = Some(BOB); + + create_asset(ALICE, id); + let balance_before_mint = Assets::balance(id, &BOB); + assert_ok!(Fungibles::mint(signed(ALICE), id, BOB, value)); + let balance_after_mint = Assets::balance(id, &BOB); + assert_eq!(balance_after_mint, balance_before_mint + value); + System::assert_last_event(Event::Transfer { id, from, to, value }.into()); }); } #[test] fn burn_works() { new_test_ext().execute_with(|| { - let amount: Balance = 100 * UNIT; - create_asset_and_mint_to(ALICE, ASSET, BOB, amount); - let balance_before_burn = Assets::balance(ASSET, &BOB); - assert_ok!(Fungibles::burn(signed(ALICE), ASSET, BOB, amount)); - let balance_after_burn = Assets::balance(ASSET, &BOB); - assert_eq!(balance_after_burn, balance_before_burn - amount); + let value: Balance = 100 * UNIT; + let id = ASSET; + let from = Some(BOB); + let to = None; + + create_asset_and_mint_to(ALICE, id, BOB, value); + let balance_before_burn = Assets::balance(id, &BOB); + assert_ok!(Fungibles::burn(signed(ALICE), id, BOB, value)); + let balance_after_burn = Assets::balance(id, &BOB); + assert_eq!(balance_after_burn, balance_before_burn - value); + System::assert_last_event(Event::Transfer { id, from, to, value }.into()); }); } diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index b20e2635..77e17394 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -97,6 +97,7 @@ impl pallet_assets::Config for Test { type BenchmarkHelper = (); } impl crate::fungibles::Config for Test { + type RuntimeEvent = RuntimeEvent; type AssetsInstance = AssetsInstance; type WeightInfo = (); } diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 8600c439..323db2b6 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -58,6 +58,91 @@ mod constants { pub(super) const BURN: u8 = 20; } +/// A set of events for use in smart contracts interacting with the fungibles API. +/// +/// The `Transfer` and `Approval` events conform to the PSP-22 standard. The other events +/// (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. +/// +/// These events are not emitted by the API itself but can be used in your contracts to +/// track asset operations. Be mindful of the costs associated with emitting events. +/// +/// For more details, refer to [ink! events](https://use.ink/basics/events). +pub mod events { + use super::*; + + /// Event emitted when allowance by `owner` to `spender` changes. + #[ink::event] + pub struct Approval { + /// Account providing allowance. + #[ink(topic)] + pub owner: AccountId, + /// Allowance beneficiary. + #[ink(topic)] + pub spender: AccountId, + /// New allowance amount. + pub value: u128, + } + + /// Event emitted when transfer of tokens occurs. + #[ink::event] + pub struct Transfer { + /// Transfer sender. `None` in case of minting new tokens. + #[ink(topic)] + pub from: Option, + /// Transfer recipient. `None` in case of burning tokens. + #[ink(topic)] + pub to: Option, + /// Amount of tokens transferred (or minted/burned). + pub value: u128, + } + + /// Event emitted when a token class is created. + #[ink::event] + pub struct Create { + /// The ID of the asset. + #[ink(topic)] + pub id: AssetId, + /// Creator of the asset. + #[ink(topic)] + pub creator: AccountId, + /// Admin of the asset. + #[ink(topic)] + pub admin: AccountId, + } + + /// Event emitted when a asset is in the process of being destroyed. + #[ink::event] + pub struct StartDestroy { + /// The ID of the asset. + #[ink(topic)] + pub id: AssetId, + } + + /// Event emitted when new metadata is set for an asset. + #[ink::event] + pub struct SetMetadata { + /// The ID of the asset created. + #[ink(topic)] + pub id: AssetId, + /// The name of the asset. + #[ink(topic)] + pub name: Vec, + /// The symbol of the asset. + #[ink(topic)] + pub symbol: Vec, + /// The decimals of the asset. + pub decimals: u8, + } + + /// Event emitted when metadata is cleared for a token. + #[ink::event] + pub struct ClearMetadata { + /// The ID of the asset. + #[ink(topic)] + pub id: AssetId, + } +} + /// Returns the total token supply for a given asset ID. /// /// # Parameters diff --git a/runtime/devnet/src/config/api.rs b/runtime/devnet/src/config/api.rs index 5f234cd4..4a404c99 100644 --- a/runtime/devnet/src/config/api.rs +++ b/runtime/devnet/src/config/api.rs @@ -1,4 +1,6 @@ -use crate::{config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall}; +use crate::{ + config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall, RuntimeEvent, +}; use codec::{Decode, Encode, MaxEncodedLen}; use pop_chain_extension::{CallFilter, ReadState}; use sp_std::vec::Vec; @@ -60,6 +62,7 @@ impl CallFilter for Extension { } impl fungibles::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type AssetsInstance = TrustBackedAssetsInstance; type WeightInfo = fungibles::weights::SubstrateWeight; } From f13b39cb85417830aa7951fab5a29e5b407812f2 Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Fri, 16 Aug 2024 10:27:06 +0200 Subject: [PATCH 040/161] docs: pop api (#190) Co-authored-by: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> --- pop-api/src/lib.rs | 23 +++++--- pop-api/src/v0/assets/fungibles.rs | 91 ++++++++---------------------- pop-api/src/v0/assets/mod.rs | 1 + pop-api/src/v0/mod.rs | 21 +++---- 4 files changed, 53 insertions(+), 83 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 78a79f80..cc785c14 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,3 +1,10 @@ +//! The `pop-api` crate provides an API for smart contracts to interact with the Pop Network runtime. +//! +//! This crate abstracts away complexities to deliver a streamlined developer experience while supporting +//! multiple API versions to ensure backward compatibility. It is designed with a focus on stability, +//! future-proofing, and storage efficiency, allowing developers to easily integrate powerful runtime +//! features into their contracts without unnecessary overhead. + #![cfg_attr(not(feature = "std"), no_std, no_main)] use constants::DECODING_FAILED; @@ -5,7 +12,9 @@ use ink::env::chain_extension::{ChainExtensionMethod, FromStatusCode}; #[cfg(feature = "assets")] pub use v0::assets; +/// Module providing primitives types. pub mod primitives; +/// The first version of the API. pub mod v0; /// A result type used by the API, with the `StatusCode` as the error type. @@ -27,13 +36,13 @@ mod constants { pub(crate) const FUNGIBLES: u8 = 150; } -/// Helper method to build `ChainExtensionMethod`. -/// -/// Parameters: -/// - 'version': The version of the chain extension. -/// - 'function': The ID of the function. -/// - 'module': The index of the runtime module. -/// - 'dispatchable': The index of the module dispatchable functions. +// Helper method to build a dispatch call or a call to read state. +// +// Parameters: +// - 'version': The version of the chain extension. +// - 'function': The ID of the function. +// - 'module': The index of the runtime module. +// - 'dispatchable': The index of the module dispatchable functions. fn build_extension_method( version: u8, function: u8, diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 323db2b6..c881f823 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -1,3 +1,11 @@ +//! The `fungibles` module provides an API for interacting and managing fungible assets on Pop Network. +//! +//! The API includes the following interfaces: +//! 1. PSP-22 +//! 2. PSP-22 Metadata +//! 3. Asset Management +//! 4. PSP-22 Mintable & Burnable + use crate::{ constants::{ASSETS, BALANCES, FUNGIBLES}, primitives::{AccountId, AssetId, Balance}, @@ -8,28 +16,22 @@ use constants::*; use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec}; pub use metadata::*; -/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0`. -/// -/// Parameters: -/// - 'dispatchable': The index of the module dispatchable functions. +// Helper method to build a dispatch call. +// +// Parameters: +// - 'dispatchable': The index of the dispatchable function within the module. fn build_dispatch(dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { crate::v0::build_dispatch(FUNGIBLES, dispatchable) } -/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0`. -/// -/// Parameters: -/// - 'state_query': The index of the runtime state query. +// Helper method to build a call to read state. +// +// Parameters: +// - 'state_query': The index of the runtime state query. fn build_read_state(state_query: u8) -> ChainExtensionMethod<(), (), (), false> { crate::v0::build_read_state(FUNGIBLES, state_query) } -/// Local Fungibles: -/// 1. PSP-22 Interface -/// 2. PSP-22 Metadata Interface -/// 3. Asset Management -/// 4. PSP-22 Mintable & Burnable Interface - mod constants { /// 1. PSP-22 Interface: pub(super) const TOTAL_SUPPLY: u8 = 0; @@ -147,9 +149,6 @@ pub mod events { /// /// # Parameters /// - `id` - The ID of the asset. -/// -/// # Returns -/// The total supply of the token, or an error if the operation fails. #[inline] pub fn total_supply(id: AssetId) -> Result { build_read_state(TOTAL_SUPPLY) @@ -165,9 +164,6 @@ pub fn total_supply(id: AssetId) -> Result { /// # Parameters /// - `id` - The ID of the asset. /// - `owner` - The account whose balance is being queried. -/// -/// # Returns -/// The balance of the specified account, or an error if the operation fails. #[inline] pub fn balance_of(id: AssetId, owner: AccountId) -> Result { build_read_state(BALANCE_OF) @@ -184,9 +180,6 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { /// - `id` - The ID of the asset. /// - `owner` - The account that owns the tokens. /// - `spender` - The account that is allowed to spend the tokens. -/// -/// # Returns -/// The remaining allowance, or an error if the operation fails. #[inline] pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { build_read_state(ALLOWANCE) @@ -203,9 +196,6 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result<()> { build_dispatch(TRANSFER) @@ -223,9 +213,6 @@ pub fn transfer(id: AssetId, to: AccountId, value: Balance) -> Result<()> { /// - `from` - The account from which the tokens are transferred. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the transfer fails. #[inline] pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { build_dispatch(TRANSFER_FROM) @@ -241,9 +228,6 @@ pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance /// - `id` - The ID of the asset. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the approval fails. #[inline] pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(APPROVE) @@ -259,9 +243,6 @@ pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { /// - `id` - The ID of the asset. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. #[inline] pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(INCREASE_ALLOWANCE) @@ -277,9 +258,6 @@ pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re /// - `id` - The ID of the asset. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. #[inline] pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(DECREASE_ALLOWANCE) @@ -295,9 +273,7 @@ pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re /// - `id` - The ID of the asset. /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. +#[inline] pub fn mint(id: AssetId, account: AccountId, value: Balance) -> Result<()> { build_dispatch(MINT) .input::<(AssetId, AccountId, Balance)>() @@ -312,9 +288,7 @@ pub fn mint(id: AssetId, account: AccountId, value: Balance) -> Result<()> { /// - `id` - The ID of the asset. /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. -/// -/// # Returns -/// Returns `Ok(())` if successful, or an error if the operation fails. +#[inline] pub fn burn(id: AssetId, account: AccountId, value: Balance) -> Result<()> { build_dispatch(BURN) .input::<(AssetId, AccountId, Balance)>() @@ -323,6 +297,7 @@ pub fn burn(id: AssetId, account: AccountId, value: Balance) -> Result<()> { .call(&(id, account, value)) } +/// The PSP-22 Metadata interface for querying metadata. pub mod metadata { use super::*; @@ -330,9 +305,6 @@ pub mod metadata { /// /// # Parameters /// - `id` - The ID of the asset. - /// - /// # Returns - /// The name of the token as a byte vector, or an error if the operation fails. #[inline] pub fn token_name(id: AssetId) -> Result> { build_read_state(TOKEN_NAME) @@ -346,9 +318,6 @@ pub mod metadata { /// /// # Parameters /// - `id` - The ID of the asset. - /// - /// # Returns - /// The symbol of the token as a byte vector, or an error if the operation fails. #[inline] pub fn token_symbol(id: AssetId) -> Result> { build_read_state(TOKEN_SYMBOL) @@ -362,9 +331,6 @@ pub mod metadata { /// /// # Parameters /// - `id` - The ID of the asset. - /// - /// # Returns - /// The number of decimals of the token, or an error if the operation fails. #[inline] pub fn token_decimals(id: AssetId) -> Result { build_read_state(TOKEN_DECIMALS) @@ -375,7 +341,8 @@ pub mod metadata { } } -pub mod asset_management { +/// The interface for creating, managing and destroying fungible assets. +pub mod management { use super::*; /// Create a new token with a given asset ID. @@ -384,9 +351,7 @@ pub mod asset_management { /// - `id` - The ID of the asset. /// - `admin` - The account that will administer the asset. /// - `min_balance` - The minimum balance required for accounts holding this asset. - /// - /// # Returns - /// Returns `Ok(())` if successful, or an error if the creation fails. + #[inline] pub fn create(id: AssetId, admin: AccountId, min_balance: Balance) -> Result<()> { build_dispatch(CREATE) .input::<(AssetId, AccountId, Balance)>() @@ -399,9 +364,7 @@ pub mod asset_management { /// /// # Parameters /// - `id` - The ID of the asset. - /// - /// # Returns - /// Returns `Ok(())` if successful, or an error if the operation fails. + #[inline] pub fn start_destroy(id: AssetId) -> Result<()> { build_dispatch(START_DESTROY) .input::() @@ -417,9 +380,7 @@ pub mod asset_management { /// - `name`: The user friendly name of this asset. Limited in length by `StringLimit`. /// - `symbol`: The exchange symbol for this asset. Limited in length by `StringLimit`. /// - `decimals`: The number of decimals this asset uses to represent one unit. - /// - /// # Returns - /// Returns `Ok(())` if successful, or an error if the operation fails. + #[inline] pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { build_dispatch(SET_METADATA) .input::<(AssetId, Vec, Vec, u8)>() @@ -432,9 +393,7 @@ pub mod asset_management { /// /// # Parameters /// - `id` - The ID of the asset. - /// - /// # Returns - /// Returns `Ok(())` if successful, or an error if the operation fails. + #[inline] pub fn clear_metadata(id: AssetId) -> Result<()> { build_dispatch(CLEAR_METADATA) .input::() diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 197db710..2d5ae236 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,2 +1,3 @@ +/// APIs for fungible assets. #[cfg(feature = "fungibles")] pub mod fungibles; diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 0fd06c89..a4824327 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -6,6 +6,7 @@ use crate::{ }; use ink::env::chain_extension::ChainExtensionMethod; +/// APIs for asset-related use cases. #[cfg(feature = "assets")] pub mod assets; @@ -17,20 +18,20 @@ impl From for Error { } } -/// Helper method to build a dispatch call `ChainExtensionMethod` -/// -/// Parameters: -/// - 'module': The index of the runtime module -/// - 'dispatchable': The index of the module dispatchable functions +// Helper method to build a dispatch call. +// +// Parameters: +// - 'module': The index of the runtime module. +// - 'dispatchable': The index of the module dispatchable functions. fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method(V0, DISPATCH, module, dispatchable) } -/// Helper method to build a dispatch call `ChainExtensionMethod` -/// -/// Parameters: -/// - 'module': The index of the runtime module -/// - 'state_query': The index of the runtime state query +// Helper method to build a call to read state. +// +// Parameters: +// - 'module': The index of the runtime module. +// - 'state_query': The index of the runtime state query. fn build_read_state(module: u8, state_query: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method(V0, READ_STATE, module, state_query) } From 7c942847cc6b95c5fa6fef7033ba2978f7fe236d Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Fri, 16 Aug 2024 14:10:46 +0200 Subject: [PATCH 041/161] refactor: extension --- extension/src/lib.rs | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/extension/src/lib.rs b/extension/src/lib.rs index 582f346c..650f73f8 100644 --- a/extension/src/lib.rs +++ b/extension/src/lib.rs @@ -1,9 +1,5 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(test)] -mod tests; -mod v0; - use codec::Encode; use frame_support::{ dispatch::{GetDispatchInfo, PostDispatchInfo}, @@ -18,6 +14,10 @@ use sp_core::crypto::UncheckedFrom; use sp_runtime::{traits::Dispatchable, DispatchError}; use sp_std::vec::Vec; +#[cfg(test)] +mod tests; +mod v0; + /// Logging target for categorizing messages from the Pop API extension module. const LOG_TARGET: &str = "pop-api::extension"; @@ -113,7 +113,7 @@ where } } -/// Extract (version, function_id, pallet_index, call_index) from the payload bytes. +/// Extract discriminators (version, function_id, pallet_index, call_index) from the encoded call. fn extract_env>(env: &Environment) -> (u8, u8, u8, u8) { // Extract version and function_id from first two bytes. let (version, function_id) = { @@ -136,8 +136,6 @@ fn read_state, StateReader: ReadState>( call_index: u8, mut params: Vec, ) -> Result<(), DispatchError> { - const LOG_PREFIX: &str = " read_state |"; - // Prefix params with version, pallet, index to simplify decoding. params.insert(0, version); params.insert(1, pallet_index); @@ -156,7 +154,7 @@ fn read_state, StateReader: ReadState>( }; log::trace!( target:LOG_TARGET, - "{} result: {:?}.", LOG_PREFIX, result + "{} result: {:?}.", " read_state |", result ); env.write(&result, false, None) } @@ -175,8 +173,6 @@ where E: Ext, Filter: CallFilter::RuntimeCall> + 'static, { - const LOG_PREFIX: &str = " dispatch |"; - // Prefix params with version, pallet, index to simplify decoding. params.insert(0, version); params.insert(1, pallet_index); @@ -185,7 +181,7 @@ where // Contract is the origin by default. let origin: T::RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); match call { - VersionedDispatch::V0(call) => dispatch_call::(env, call, origin, LOG_PREFIX), + VersionedDispatch::V0(call) => dispatch_call::(env, call, origin), } } @@ -198,7 +194,6 @@ fn dispatch_call( env: &mut Environment, call: T::RuntimeCall, mut origin: T::RuntimeOrigin, - log_prefix: &str, ) -> Result<(), DispatchError> where T: frame_system::Config< @@ -207,12 +202,14 @@ where E: Ext, Filter: CallFilter::RuntimeCall> + 'static, { + const LOG_PREFIX: &str = " dispatch |"; + let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; - log::debug!(target:LOG_TARGET, "{} Inputted RuntimeCall: {:?}", log_prefix, call); + log::debug!(target:LOG_TARGET, "{} Inputted RuntimeCall: {:?}", LOG_PREFIX, call); origin.add_filter(Filter::contains); match call.dispatch(origin) { Ok(info) => { - log::debug!(target:LOG_TARGET, "{} success, actual weight: {:?}", log_prefix, info.actual_weight); + log::debug!(target:LOG_TARGET, "{} success, actual weight: {:?}", LOG_PREFIX, info.actual_weight); // Refund weight if the actual weight is less than the charged weight. if let Some(actual_weight) = info.actual_weight { env.adjust_weight(charged_dispatch_weight, actual_weight); @@ -220,7 +217,11 @@ where Ok(()) }, Err(err) => { - log::debug!(target:LOG_TARGET, "{} failed: error: {:?}", log_prefix, err.error); + log::debug!(target:LOG_TARGET, "{} failed: error: {:?}", LOG_PREFIX, err.error); + // Refund weight if the actual weight is less than the charged weight. + if let Some(actual_weight) = err.post_info.actual_weight { + env.adjust_weight(charged_dispatch_weight, actual_weight); + } Err(err.error) }, } @@ -275,7 +276,7 @@ impl TryFrom for FuncId { } /// Converts a `DispatchError` to a `u32` status code based on the version of the API the contract uses. -/// The contract calling the chain extension can convert the status code to the descriptive `Error`. +/// The contract calling the chain extension can optionally convert the status code to the descriptive `Error`. /// /// For `Error` see `pop_primitives::::error::Error`. /// From 5934fa8d623462303f032e0a80097eeaf591d62e Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Fri, 16 Aug 2024 14:36:55 +0200 Subject: [PATCH 042/161] fix: remove old api code from deprecated examples --- pop-api/examples/balance-transfer/lib.rs | 2 +- pop-api/examples/nfts/lib.rs | 2 +- pop-api/examples/place-spot-order/lib.rs | 2 +- pop-api/examples/read-runtime-state/lib.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pop-api/examples/balance-transfer/lib.rs b/pop-api/examples/balance-transfer/lib.rs index d36dfa53..e75c15b9 100755 --- a/pop-api/examples/balance-transfer/lib.rs +++ b/pop-api/examples/balance-transfer/lib.rs @@ -15,7 +15,7 @@ impl From for ContractError { } } -#[ink::contract(env = pop_api::Environment)] +#[ink::contract] mod balance_transfer { use super::*; diff --git a/pop-api/examples/nfts/lib.rs b/pop-api/examples/nfts/lib.rs index 7920c179..0cd0f313 100755 --- a/pop-api/examples/nfts/lib.rs +++ b/pop-api/examples/nfts/lib.rs @@ -18,7 +18,7 @@ impl From for ContractError { } } -#[ink::contract(env = pop_api::Environment)] +#[ink::contract] mod nfts { use super::*; diff --git a/pop-api/examples/place-spot-order/lib.rs b/pop-api/examples/place-spot-order/lib.rs index 669b9190..965917d1 100755 --- a/pop-api/examples/place-spot-order/lib.rs +++ b/pop-api/examples/place-spot-order/lib.rs @@ -1,7 +1,7 @@ // DEPRECATED #![cfg_attr(not(feature = "std"), no_std, no_main)] -#[ink::contract(env = pop_api::Environment)] +#[ink::contract] mod spot_order { #[ink(storage)] diff --git a/pop-api/examples/read-runtime-state/lib.rs b/pop-api/examples/read-runtime-state/lib.rs index 60ef70f0..092e9f2f 100755 --- a/pop-api/examples/read-runtime-state/lib.rs +++ b/pop-api/examples/read-runtime-state/lib.rs @@ -1,7 +1,7 @@ // DEPRECATED #![cfg_attr(not(feature = "std"), no_std, no_main)] -#[ink::contract(env = pop_api::Environment)] +#[ink::contract] mod read_relay_blocknumber { use pop_api::primitives::storage_keys::{ ParachainSystemKeys::LastRelayChainBlockNumber, RuntimeStateKeys::ParachainSystem, From f2ef7a184c67a80e14291786360a7b115b837c75 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Fri, 16 Aug 2024 14:59:40 +0200 Subject: [PATCH 043/161] refactor: runtime devnet --- Cargo.lock | 1 - runtime/devnet/Cargo.toml | 1 - runtime/devnet/src/config/mod.rs | 4 ++-- runtime/devnet/src/lib.rs | 4 ++-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78e5e1d1..3407a210 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9613,7 +9613,6 @@ dependencies = [ "pop-chain-extension", "pop-primitives", "pop-runtime-common", - "rand", "scale-info", "smallvec", "sp-api", diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index 995af269..3d2f20d0 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -92,7 +92,6 @@ parachain-info.workspace = true [dev-dependencies] env_logger = "0.11.2" hex = "0.4.3" -rand = "0.8.5" [features] default = ["std"] diff --git a/runtime/devnet/src/config/mod.rs b/runtime/devnet/src/config/mod.rs index f62ffa76..1dcd44da 100644 --- a/runtime/devnet/src/config/mod.rs +++ b/runtime/devnet/src/config/mod.rs @@ -1,5 +1,5 @@ -pub(crate) mod api; -pub mod assets; +mod api; +mod assets; mod contracts; mod proxy; // Public due to integration tests crate. diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 4256ac01..e1ef6c6d 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -72,7 +72,7 @@ use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; // XCM Imports use xcm::latest::prelude::BodyId; -pub(crate) use pallet_api::fungibles; +use pallet_api::fungibles; /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. @@ -590,7 +590,7 @@ construct_runtime!( mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] - [pallet_api::fungibles, Fungibles] + [fungibles, Fungibles] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] From b3dd9935cffabc5ccac2a92fe8355822b3275158 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Fri, 16 Aug 2024 15:56:50 +0200 Subject: [PATCH 044/161] refactor: fungibles pallet --- pallets/api/Cargo.toml | 2 +- pallets/api/src/fungibles/mod.rs | 232 +++++++++++++++-------------- pallets/api/src/fungibles/tests.rs | 202 +++++++++++++------------ 3 files changed, 226 insertions(+), 210 deletions(-) diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml index a813a09c..f9a807a3 100644 --- a/pallets/api/Cargo.toml +++ b/pallets/api/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pallet-api" authors.workspace = true -description = "Api pallet, enabling smart(er) contracts with the power of Polkadot" +description = "API pallet, enabling smart(er) contracts with the power of Polkadot" edition.workspace = true license.workspace = true version = "0.1.0" diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index 7aa9ac00..6ff8ac87 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -1,6 +1,11 @@ -/// The fungibles pallet serves as a wrapper around the pallet_assets, offering a streamlined -/// interface for interacting with fungible assets. The goal is to provide a simplified, consistent -/// API that adheres to standards in the smart contract space. +//! The fungibles pallet offers a streamlined interface for interacting with fungible assets. The +//! goal is to provide a simplified, consistent API that adheres to standards in the smart contract +//! space. + +use frame_support::traits::fungibles::{metadata::Inspect as MetadataInspect, Inspect}; +pub use pallet::*; +use pallet_assets::WeightInfo as AssetsWeightInfoTrait; +use weights::WeightInfo; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; @@ -8,11 +13,6 @@ mod benchmarking; mod tests; pub mod weights; -use frame_support::traits::fungibles::{metadata::Inspect as MetadataInspect, Inspect}; -pub use pallet::*; -use pallet_assets::WeightInfo as AssetsWeightInfoTrait; -use weights::WeightInfo; - type AccountIdOf = ::AccountId; type AssetIdOf = > as Inspect< ::AccountId, @@ -41,42 +41,42 @@ pub mod pallet { }; use sp_std::vec::Vec; - /// State reads for the fungibles api with required input. + /// State reads for the fungibles API with required input. #[derive(Encode, Decode, Debug, MaxEncodedLen)] #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { - /// Total token supply for a given asset ID. + /// Total token supply for a specified asset. #[codec(index = 0)] TotalSupply(AssetIdOf), - /// Account balance for a given asset ID. + /// Account balance for a specified `asset` and `owner`. #[codec(index = 1)] BalanceOf { - /// The asset ID. - id: AssetIdOf, - /// The account ID of the owner. + /// The asset. + asset: AssetIdOf, + /// The owner of the asset. owner: AccountIdOf, }, - /// Allowance for a spender approved by an owner, for a given asset ID. + /// Allowance for a `spender` approved by an `owner`, for a specified `asset`. #[codec(index = 2)] Allowance { - /// The asset ID. - id: AssetIdOf, - /// The account ID of the owner. + /// The asset. + asset: AssetIdOf, + /// The owner of the asset. owner: AccountIdOf, - /// The account ID of the spender. + /// The spender with an allowance. spender: AccountIdOf, }, - /// Token name for a given asset ID. + /// Name of the specified asset. #[codec(index = 8)] TokenName(AssetIdOf), - /// Token symbol for a given asset ID. + /// Symbol for the specified asset. #[codec(index = 9)] TokenSymbol(AssetIdOf), - /// Token decimals for a given asset ID. + /// Decimals for the specified asset. #[codec(index = 10)] TokenDecimals(AssetIdOf), - /// Check if token with a given asset ID exists. + /// Check if a specified asset exists. #[codec(index = 18)] AssetExists(AssetIdOf), } @@ -101,70 +101,68 @@ pub mod pallet { pub enum Event { /// Event emitted when allowance by `owner` to `spender` changes. Approval { - /// The ID of the asset. - id: AssetIdOf, - /// Account providing allowance. + /// The asset. + asset: AssetIdOf, + /// The owner providing the allowance. owner: AccountIdOf, - /// Allowance beneficiary. + /// The beneficiary of the allowance. spender: AccountIdOf, - /// New allowance amount. + /// The new allowance amount. value: BalanceOf, }, - /// Event emitted when transfer of tokens occurs. + /// Event emitted when an asset transfer occurs. Transfer { - /// The ID of the asset. - id: AssetIdOf, - /// Transfer sender. `None` in case of minting new tokens. + /// The asset. + asset: AssetIdOf, + /// The source of the transfer. `None` when minting. from: Option>, - /// Transfer recipient. `None` in case of burning tokens. + /// The recipient of the transfer. `None` when burning. to: Option>, - /// Amount of tokens transferred (or minted/burned). + /// The amount transferred (or minted/burned). value: BalanceOf, }, - /// Event emitted when a token class is created. + /// Event emitted when an asset is created. Create { - /// The ID of the asset. + /// The asset identifier. id: AssetIdOf, - /// Creator of the asset. + /// The creator of the asset. creator: AccountIdOf, - /// Admin of the asset. + /// The administrator of the asset. admin: AccountIdOf, }, } #[pallet::call] impl Pallet { - /// Transfers `value` amount of tokens from the caller's account to account `to`, with additional - /// `data` in unspecified format. + /// Transfers `value` amount of tokens from the caller's account to account `to`. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `asset` - The asset to transfer. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[pallet::call_index(3)] #[pallet::weight(AssetsWeightInfoOf::::transfer_keep_alive())] pub fn transfer( origin: OriginFor, - id: AssetIdOf, + asset: AssetIdOf, to: AccountIdOf, value: BalanceOf, ) -> DispatchResult { + let from = ensure_signed(origin.clone())?; AssetsOf::::transfer_keep_alive( - origin.clone(), - id.clone().into(), + origin, + asset.clone().into(), T::Lookup::unlookup(to.clone()), value, )?; - let from = ensure_signed(origin)?; - Self::deposit_event(Event::Transfer { id, from: Some(from), to: Some(to), value }); + Self::deposit_event(Event::Transfer { asset, from: Some(from), to: Some(to), value }); Ok(()) } - /// Transfers `value` amount tokens on behalf of `from` to account `to` with additional `data` - /// in unspecified format. + /// Transfers `value` amount tokens on behalf of `from` to account `to`. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `asset` - The asset to transfer. /// - `from` - The account from which the asset balance will be withdrawn. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. @@ -172,39 +170,39 @@ pub mod pallet { #[pallet::weight(AssetsWeightInfoOf::::transfer_approved())] pub fn transfer_from( origin: OriginFor, - id: AssetIdOf, + asset: AssetIdOf, from: AccountIdOf, to: AccountIdOf, value: BalanceOf, ) -> DispatchResult { AssetsOf::::transfer_approved( origin, - id.clone().into(), + asset.clone().into(), T::Lookup::unlookup(from.clone()), T::Lookup::unlookup(to.clone()), value, )?; - Self::deposit_event(Event::Transfer { id, from: Some(from), to: Some(to), value }); + Self::deposit_event(Event::Transfer { asset, from: Some(from), to: Some(to), value }); Ok(()) } - /// Approves an account to spend a specified number of tokens on behalf of the caller. + /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `asset` - The asset to approve. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[pallet::call_index(5)] #[pallet::weight(::WeightInfo::approve(1, 1))] pub fn approve( origin: OriginFor, - id: AssetIdOf, + asset: AssetIdOf, spender: AccountIdOf, value: BalanceOf, ) -> DispatchResultWithPostInfo { let owner = ensure_signed(origin.clone()) .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; - let current_allowance = AssetsOf::::allowance(id.clone(), &owner, &spender); + let current_allowance = AssetsOf::::allowance(asset.clone(), &owner, &spender); let weight = match value.cmp(¤t_allowance) { // If the new value is equal to the current allowance, do nothing. @@ -214,7 +212,7 @@ pub mod pallet { Greater => { AssetsOf::::approve_transfer( origin, - id.clone().into(), + asset.clone().into(), T::Lookup::unlookup(spender.clone()), value.saturating_sub(current_allowance), ) @@ -224,37 +222,42 @@ pub mod pallet { // If the new value is less than the current allowance, cancel the approval and // set the new value. Less => { - let id_param: AssetIdParameterOf = id.clone().into(); + let asset_param: AssetIdParameterOf = asset.clone().into(); let spender_source = T::Lookup::unlookup(spender.clone()); AssetsOf::::cancel_approval( origin.clone(), - id_param.clone(), + asset_param.clone(), spender_source.clone(), ) .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; if value.is_zero() { Self::weight_approve(0, 1) } else { - AssetsOf::::approve_transfer(origin, id_param, spender_source, value)?; + AssetsOf::::approve_transfer( + origin, + asset_param, + spender_source, + value, + )?; Self::weight_approve(1, 1) } }, }; - Self::deposit_event(Event::Approval { id, owner, spender, value }); + Self::deposit_event(Event::Approval { asset, owner, spender, value }); Ok(Some(weight).into()) } - /// Increases the allowance of a spender. + /// Increases the allowance of `spender` by `value` amount of tokens. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `asset` - The asset to have an allowance increased. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[pallet::call_index(6)] #[pallet::weight(::WeightInfo::approve(1, 0))] pub fn increase_allowance( origin: OriginFor, - id: AssetIdOf, + asset: AssetIdOf, spender: AccountIdOf, value: BalanceOf, ) -> DispatchResultWithPostInfo { @@ -262,27 +265,27 @@ pub mod pallet { .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; AssetsOf::::approve_transfer( origin, - id.clone().into(), + asset.clone().into(), T::Lookup::unlookup(spender.clone()), value, ) .map_err(|e| e.with_weight(AssetsWeightInfoOf::::approve_transfer()))?; - let value = AssetsOf::::allowance(id.clone(), &owner, &spender); - Self::deposit_event(Event::Approval { id, owner, spender, value }); + let value = AssetsOf::::allowance(asset.clone(), &owner, &spender); + Self::deposit_event(Event::Approval { asset, owner, spender, value }); Ok(().into()) } - /// Decreases the allowance of a spender. + /// Decreases the allowance of a `spender` by `value` amount of tokens. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `asset` - The asset to have an allowance decreased. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[pallet::call_index(7)] #[pallet::weight(::WeightInfo::approve(1, 1))] pub fn decrease_allowance( origin: OriginFor, - id: AssetIdOf, + asset: AssetIdOf, spender: AccountIdOf, value: BalanceOf, ) -> DispatchResultWithPostInfo { @@ -291,14 +294,14 @@ pub mod pallet { if value.is_zero() { return Ok(Some(Self::weight_approve(0, 0)).into()); } - let current_allowance = AssetsOf::::allowance(id.clone(), &owner, &spender); + let current_allowance = AssetsOf::::allowance(asset.clone(), &owner, &spender); let spender_source = T::Lookup::unlookup(spender.clone()); - let id_param: AssetIdParameterOf = id.clone().into(); + let asset_param: AssetIdParameterOf = asset.clone().into(); // Cancel the approval and set the new value if `new_allowance` is more than zero. AssetsOf::::cancel_approval( origin.clone(), - id_param.clone(), + asset_param.clone(), spender_source.clone(), ) .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; @@ -306,17 +309,22 @@ pub mod pallet { let weight = if new_allowance.is_zero() { Self::weight_approve(0, 1) } else { - AssetsOf::::approve_transfer(origin, id_param, spender_source, new_allowance)?; + AssetsOf::::approve_transfer( + origin, + asset_param, + spender_source, + new_allowance, + )?; Self::weight_approve(1, 1) }; - Self::deposit_event(Event::Approval { id, owner, spender, value: new_allowance }); + Self::deposit_event(Event::Approval { asset, owner, spender, value: new_allowance }); Ok(Some(weight).into()) } - /// Create a new token with a given asset ID. + /// Create a new token with a given identifier. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `id` - The identifier of the asset. /// - `admin` - The account that will administer the asset. /// - `min_balance` - The minimum balance required for accounts holding this asset. #[pallet::call_index(11)] @@ -338,92 +346,90 @@ pub mod pallet { Ok(()) } - /// Start the process of destroying a token with a given asset ID. + /// Start the process of destroying a token. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `asset` - The asset to be destroyed. #[pallet::call_index(12)] #[pallet::weight(AssetsWeightInfoOf::::start_destroy())] - pub fn start_destroy(origin: OriginFor, id: AssetIdOf) -> DispatchResult { - AssetsOf::::start_destroy(origin, id.into()) + pub fn start_destroy(origin: OriginFor, asset: AssetIdOf) -> DispatchResult { + AssetsOf::::start_destroy(origin, asset.into()) } - /// Set the metadata for a token with a given asset ID. + /// Set the metadata for a token. /// /// # Parameters - /// - `id`: The identifier of the asset to update. - /// - `name`: The user friendly name of this asset. Limited in length by - /// `pallet_assets::Config::StringLimit`. - /// - `symbol`: The exchange symbol for this asset. Limited in length by - /// `pallet_assets::Config::StringLimit`. + /// - `asset`: The asset to update. + /// - `name`: The user friendly name of this asset. + /// - `symbol`: The exchange symbol for this asset. /// - `decimals`: The number of decimals this asset uses to represent one unit. #[pallet::call_index(16)] #[pallet::weight(AssetsWeightInfoOf::::set_metadata(name.len() as u32, symbol.len() as u32))] pub fn set_metadata( origin: OriginFor, - id: AssetIdOf, + asset: AssetIdOf, name: Vec, symbol: Vec, decimals: u8, ) -> DispatchResult { - AssetsOf::::set_metadata(origin, id.into(), name, symbol, decimals) + AssetsOf::::set_metadata(origin, asset.into(), name, symbol, decimals) } - /// Clear the metadata for a token with a given asset ID. + /// Clear the metadata for a token. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `asset` - The asset to update. #[pallet::call_index(17)] #[pallet::weight(AssetsWeightInfoOf::::clear_metadata())] - pub fn clear_metadata(origin: OriginFor, id: AssetIdOf) -> DispatchResult { - AssetsOf::::clear_metadata(origin, id.into()) + pub fn clear_metadata(origin: OriginFor, asset: AssetIdOf) -> DispatchResult { + AssetsOf::::clear_metadata(origin, asset.into()) } /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `asset` - The asset to mint. /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[pallet::call_index(19)] #[pallet::weight(AssetsWeightInfoOf::::mint())] pub fn mint( origin: OriginFor, - id: AssetIdOf, + asset: AssetIdOf, account: AccountIdOf, value: BalanceOf, ) -> DispatchResult { AssetsOf::::mint( origin, - id.clone().into(), + asset.clone().into(), T::Lookup::unlookup(account.clone()), value, )?; - Self::deposit_event(Event::Transfer { id, from: None, to: Some(account), value }); + Self::deposit_event(Event::Transfer { asset, from: None, to: Some(account), value }); Ok(()) } /// Destroys `value` amount of tokens from `account`, reducing the total supply. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `asset` - the asset to burn. /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[pallet::call_index(20)] #[pallet::weight(AssetsWeightInfoOf::::burn())] pub fn burn( origin: OriginFor, - id: AssetIdOf, + asset: AssetIdOf, account: AccountIdOf, value: BalanceOf, ) -> DispatchResult { AssetsOf::::burn( origin, - id.clone().into(), + asset.clone().into(), T::Lookup::unlookup(account.clone()), value, )?; - Self::deposit_event(Event::Transfer { id, from: Some(account), to: None, value }); + Self::deposit_event(Event::Transfer { asset, from: Some(account), to: None, value }); Ok(()) } } @@ -441,25 +447,25 @@ pub mod pallet { use Read::*; match value { - TotalSupply(id) => AssetsOf::::total_supply(id).encode(), - BalanceOf { id, owner } => AssetsOf::::balance(id, owner).encode(), - Allowance { id, owner, spender } => { - AssetsOf::::allowance(id, &owner, &spender).encode() + TotalSupply(asset) => AssetsOf::::total_supply(asset).encode(), + BalanceOf { asset, owner } => AssetsOf::::balance(asset, owner).encode(), + Allowance { asset, owner, spender } => { + AssetsOf::::allowance(asset, &owner, &spender).encode() }, - TokenName(id) => { - as MetadataInspect>>::name(id).encode() + TokenName(asset) => { + as MetadataInspect>>::name(asset).encode() }, - TokenSymbol(id) => { - as MetadataInspect>>::symbol(id).encode() + TokenSymbol(asset) => { + as MetadataInspect>>::symbol(asset).encode() }, - TokenDecimals(id) => { - as MetadataInspect>>::decimals(id).encode() + TokenDecimals(asset) => { + as MetadataInspect>>::decimals(asset).encode() }, - AssetExists(id) => AssetsOf::::asset_exists(id).encode(), + AssetExists(asset) => AssetsOf::::asset_exists(asset).encode(), } } - pub fn weight_approve(approve: u32, cancel: u32) -> Weight { + fn weight_approve(approve: u32, cancel: u32) -> Weight { ::WeightInfo::approve(cancel, approve) } } diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index ca2a85c9..9610139e 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -16,16 +16,16 @@ type Event = crate::fungibles::Event; fn transfer_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let id = ASSET; + let asset = ASSET; let from = Some(ALICE); let to = Some(BOB); - create_asset_and_mint_to(ALICE, id, ALICE, value * 2); - let balance_before_transfer = Assets::balance(id, &BOB); - assert_ok!(Fungibles::transfer(signed(ALICE), id, BOB, value)); - let balance_after_transfer = Assets::balance(id, &BOB); + create_asset_and_mint_to(ALICE, asset, ALICE, value * 2); + let balance_before_transfer = Assets::balance(asset, &BOB); + assert_ok!(Fungibles::transfer(signed(ALICE), asset, BOB, value)); + let balance_after_transfer = Assets::balance(asset, &BOB); assert_eq!(balance_after_transfer, balance_before_transfer + value); - System::assert_last_event(Event::Transfer { id, from, to, value }.into()); + System::assert_last_event(Event::Transfer { asset, from, to, value }.into()); }); } @@ -33,22 +33,22 @@ fn transfer_works() { fn transfer_from_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let id = ASSET; + let asset = ASSET; let from = Some(ALICE); let to = Some(BOB); // Approve CHARLIE to transfer up to `value` to BOB. - create_asset_mint_and_approve(ALICE, id, ALICE, value * 2, CHARLIE, value); + create_asset_mint_and_approve(ALICE, asset, ALICE, value * 2, CHARLIE, value); // Successfully call transfer from. - let alice_balance_before_transfer = Assets::balance(id, &ALICE); - let bob_balance_before_transfer = Assets::balance(id, &BOB); - assert_ok!(Fungibles::transfer_from(signed(CHARLIE), id, ALICE, BOB, value)); - let alice_balance_after_transfer = Assets::balance(id, &ALICE); - let bob_balance_after_transfer = Assets::balance(id, &BOB); + let alice_balance_before_transfer = Assets::balance(asset, &ALICE); + let bob_balance_before_transfer = Assets::balance(asset, &BOB); + assert_ok!(Fungibles::transfer_from(signed(CHARLIE), asset, ALICE, BOB, value)); + let alice_balance_after_transfer = Assets::balance(asset, &ALICE); + let bob_balance_after_transfer = Assets::balance(asset, &BOB); // Check that BOB receives the `value` and ALICE `amount` is spent successfully by CHARLIE. assert_eq!(bob_balance_after_transfer, bob_balance_before_transfer + value); assert_eq!(alice_balance_after_transfer, alice_balance_before_transfer - value); - System::assert_last_event(Event::Transfer { id, from, to, value }.into()); + System::assert_last_event(Event::Transfer { asset, from, to, value }.into()); }); } @@ -57,31 +57,37 @@ fn transfer_from_works() { fn approve_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let id = ASSET; + let asset = ASSET; let owner = ALICE; let spender = BOB; - create_asset_and_mint_to(ALICE, id, ALICE, value); - assert_eq!(0, Assets::allowance(id, &ALICE, &BOB)); - assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, value)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), value); - System::assert_last_event(Event::Approval { id, owner, spender, value }.into()); + create_asset_and_mint_to(ALICE, asset, ALICE, value); + assert_eq!(0, Assets::allowance(asset, &ALICE, &BOB)); + assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, value)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value); + System::assert_last_event(Event::Approval { asset, owner, spender, value }.into()); // Approves an value to spend that is lower than the current allowance. - assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, value / 2)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), value / 2); - System::assert_last_event(Event::Approval { id, owner, spender, value: value / 2 }.into()); + assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, value / 2)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value / 2); + System::assert_last_event( + Event::Approval { asset, owner, spender, value: value / 2 }.into(), + ); // Approves an value to spend that is higher than the current allowance. - assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, value * 2)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), value * 2); - System::assert_last_event(Event::Approval { id, owner, spender, value: value * 2 }.into()); + assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, value * 2)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value * 2); + System::assert_last_event( + Event::Approval { asset, owner, spender, value: value * 2 }.into(), + ); // Approves an value to spend that is equal to the current allowance. - assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, value * 2)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), value * 2); - System::assert_last_event(Event::Approval { id, owner, spender, value: value * 2 }.into()); + assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, value * 2)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value * 2); + System::assert_last_event( + Event::Approval { asset, owner, spender, value: value * 2 }.into(), + ); // Sets allowance to zero. - assert_ok!(Fungibles::approve(signed(ALICE), id, BOB, 0)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), 0); - System::assert_last_event(Event::Approval { id, owner, spender, value: 0 }.into()); + assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, 0)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), 0); + System::assert_last_event(Event::Approval { asset, owner, spender, value: 0 }.into()); }); } @@ -89,19 +95,21 @@ fn approve_works() { fn increase_allowance_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let id = ASSET; + let asset = ASSET; let owner = ALICE; let spender = BOB; - create_asset_and_mint_to(ALICE, id, ALICE, value); - assert_eq!(0, Assets::allowance(id, &ALICE, &BOB)); - assert_ok!(Fungibles::increase_allowance(signed(ALICE), id, BOB, value)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), value); - System::assert_last_event(Event::Approval { id, owner, spender, value }.into()); + create_asset_and_mint_to(ALICE, asset, ALICE, value); + assert_eq!(0, Assets::allowance(asset, &ALICE, &BOB)); + assert_ok!(Fungibles::increase_allowance(signed(ALICE), asset, BOB, value)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value); + System::assert_last_event(Event::Approval { asset, owner, spender, value }.into()); // Additive. - assert_ok!(Fungibles::increase_allowance(signed(ALICE), id, BOB, value)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), value * 2); - System::assert_last_event(Event::Approval { id, owner, spender, value: value * 2 }.into()); + assert_ok!(Fungibles::increase_allowance(signed(ALICE), asset, BOB, value)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value * 2); + System::assert_last_event( + Event::Approval { asset, owner, spender, value: value * 2 }.into(), + ); }); } @@ -109,23 +117,25 @@ fn increase_allowance_works() { fn decrease_allowance_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let id = ASSET; + let asset = ASSET; let owner = ALICE; let spender = BOB; - create_asset_mint_and_approve(ALICE, id, ALICE, value, BOB, value); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), value); + create_asset_mint_and_approve(ALICE, asset, ALICE, value, BOB, value); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value); // Owner balance is not changed if decreased by zero. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), id, BOB, 0)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), value); + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), asset, BOB, 0)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value); // Decrease allowance successfully. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), id, BOB, value / 2)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), value / 2); - System::assert_last_event(Event::Approval { id, owner, spender, value: value / 2 }.into()); + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), asset, BOB, value / 2)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value / 2); + System::assert_last_event( + Event::Approval { asset, owner, spender, value: value / 2 }.into(), + ); // Saturating if current allowance is decreased more than the owner balance. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), id, BOB, value)); - assert_eq!(Assets::allowance(id, &ALICE, &BOB), 0); - System::assert_last_event(Event::Approval { id, owner, spender, value: 0 }.into()); + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), asset, BOB, value)); + assert_eq!(Assets::allowance(asset, &ALICE, &BOB), 0); + System::assert_last_event(Event::Approval { asset, owner, spender, value: 0 }.into()); }); } @@ -146,45 +156,45 @@ fn create_works() { #[test] fn start_destroy_works() { new_test_ext().execute_with(|| { - let id = ASSET; + let asset = ASSET; - create_asset(ALICE, id); - assert_ok!(Fungibles::start_destroy(signed(ALICE), id)); + create_asset(ALICE, asset); + assert_ok!(Fungibles::start_destroy(signed(ALICE), asset)); }); } #[test] fn set_metadata_works() { new_test_ext().execute_with(|| { - let id = ASSET; + let asset = ASSET; let name = vec![42]; let symbol = vec![42]; let decimals = 42; - create_asset(ALICE, id); + create_asset(ALICE, asset); assert_ok!(Fungibles::set_metadata( signed(ALICE), - id, + asset, name.clone(), symbol.clone(), decimals )); - assert_eq!(Assets::name(id), name); - assert_eq!(Assets::symbol(id), symbol); - assert_eq!(Assets::decimals(id), decimals); + assert_eq!(Assets::name(asset), name); + assert_eq!(Assets::symbol(asset), symbol); + assert_eq!(Assets::decimals(asset), decimals); }); } #[test] fn clear_metadata_works() { new_test_ext().execute_with(|| { - let id = ASSET; + let asset = ASSET; - create_asset_and_set_metadata(ALICE, id, vec![42], vec![42], 42); - assert_ok!(Fungibles::clear_metadata(signed(ALICE), id)); - assert!(Assets::name(id).is_empty()); - assert!(Assets::symbol(id).is_empty()); - assert!(Assets::decimals(id).is_zero()); + create_asset_and_set_metadata(ALICE, asset, vec![42], vec![42], 42); + assert_ok!(Fungibles::clear_metadata(signed(ALICE), asset)); + assert!(Assets::name(asset).is_empty()); + assert!(Assets::symbol(asset).is_empty()); + assert!(Assets::decimals(asset).is_zero()); }); } @@ -192,16 +202,16 @@ fn clear_metadata_works() { fn mint_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let id = ASSET; + let asset = ASSET; let from = None; let to = Some(BOB); - create_asset(ALICE, id); - let balance_before_mint = Assets::balance(id, &BOB); - assert_ok!(Fungibles::mint(signed(ALICE), id, BOB, value)); - let balance_after_mint = Assets::balance(id, &BOB); + create_asset(ALICE, asset); + let balance_before_mint = Assets::balance(asset, &BOB); + assert_ok!(Fungibles::mint(signed(ALICE), asset, BOB, value)); + let balance_after_mint = Assets::balance(asset, &BOB); assert_eq!(balance_after_mint, balance_before_mint + value); - System::assert_last_event(Event::Transfer { id, from, to, value }.into()); + System::assert_last_event(Event::Transfer { asset, from, to, value }.into()); }); } @@ -209,16 +219,16 @@ fn mint_works() { fn burn_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let id = ASSET; + let asset = ASSET; let from = Some(BOB); let to = None; - create_asset_and_mint_to(ALICE, id, BOB, value); - let balance_before_burn = Assets::balance(id, &BOB); - assert_ok!(Fungibles::burn(signed(ALICE), id, BOB, value)); - let balance_after_burn = Assets::balance(id, &BOB); + create_asset_and_mint_to(ALICE, asset, BOB, value); + let balance_before_burn = Assets::balance(asset, &BOB); + assert_ok!(Fungibles::burn(signed(ALICE), asset, BOB, value)); + let balance_after_burn = Assets::balance(asset, &BOB); assert_eq!(balance_after_burn, balance_before_burn - value); - System::assert_last_event(Event::Transfer { id, from, to, value }.into()); + System::assert_last_event(Event::Transfer { asset, from, to, value }.into()); }); } @@ -236,7 +246,7 @@ fn balance_of_works() { create_asset_and_mint_to(ALICE, ASSET, ALICE, 100); assert_eq!( Assets::balance(ASSET, ALICE).encode(), - Fungibles::read_state(BalanceOf { id: ASSET, owner: ALICE }) + Fungibles::read_state(BalanceOf { asset: ASSET, owner: ALICE }) ); }); } @@ -247,7 +257,7 @@ fn allowance_works() { create_asset_mint_and_approve(ALICE, ASSET, BOB, 100, ALICE, 50); assert_eq!( Assets::allowance(ASSET, &ALICE, &BOB).encode(), - Fungibles::read_state(Allowance { id: ASSET, owner: ALICE, spender: BOB }) + Fungibles::read_state(Allowance { asset: ASSET, owner: ALICE, spender: BOB }) ); }); } @@ -277,48 +287,48 @@ fn signed(account: AccountId) -> RuntimeOrigin { RuntimeOrigin::signed(account) } -fn create_asset(owner: AccountId, asset_id: AssetId) { - assert_ok!(Assets::create(signed(owner), asset_id, owner, 1)); +fn create_asset(owner: AccountId, asset_asset: AssetId) { + assert_ok!(Assets::create(signed(owner), asset_asset, owner, 1)); } -fn mint_asset(owner: AccountId, asset_id: AssetId, to: AccountId, value: Balance) { - assert_ok!(Assets::mint(signed(owner), asset_id, to, value)); +fn mint_asset(owner: AccountId, asset_asset: AssetId, to: AccountId, value: Balance) { + assert_ok!(Assets::mint(signed(owner), asset_asset, to, value)); } -fn create_asset_and_mint_to(owner: AccountId, asset_id: AssetId, to: AccountId, value: Balance) { - create_asset(owner, asset_id); - mint_asset(owner, asset_id, to, value) +fn create_asset_and_mint_to(owner: AccountId, asset_asset: AssetId, to: AccountId, value: Balance) { + create_asset(owner, asset_asset); + mint_asset(owner, asset_asset, to, value) } fn create_asset_mint_and_approve( owner: AccountId, - asset_id: AssetId, + asset_asset: AssetId, to: AccountId, mint: Balance, spender: AccountId, approve: Balance, ) { - create_asset_and_mint_to(owner, asset_id, to, mint); - assert_ok!(Assets::approve_transfer(signed(to), asset_id, spender, approve,)); + create_asset_and_mint_to(owner, asset_asset, to, mint); + assert_ok!(Assets::approve_transfer(signed(to), asset_asset, spender, approve,)); } fn create_asset_and_set_metadata( owner: AccountId, - asset_id: AssetId, + asset_asset: AssetId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::create(signed(owner), asset_id, owner, 100)); - set_metadata_asset(owner, asset_id, name, symbol, decimals); + assert_ok!(Assets::create(signed(owner), asset_asset, owner, 100)); + set_metadata_asset(owner, asset_asset, name, symbol, decimals); } fn set_metadata_asset( owner: AccountId, - asset_id: AssetId, + asset_asset: AssetId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::set_metadata(signed(owner), asset_id, name, symbol, decimals)); + assert_ok!(Assets::set_metadata(signed(owner), asset_asset, name, symbol, decimals)); } From 08115984fb33da05dbd735532f28bd1f464d99ef Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Mon, 19 Aug 2024 09:29:44 +0200 Subject: [PATCH 045/161] style: fix tests asset_asset parameter --- pallets/api/src/fungibles/tests.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index 9610139e..d881a3c1 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -287,48 +287,48 @@ fn signed(account: AccountId) -> RuntimeOrigin { RuntimeOrigin::signed(account) } -fn create_asset(owner: AccountId, asset_asset: AssetId) { - assert_ok!(Assets::create(signed(owner), asset_asset, owner, 1)); +fn create_asset(owner: AccountId, asset: AssetId) { + assert_ok!(Assets::create(signed(owner), asset, owner, 1)); } -fn mint_asset(owner: AccountId, asset_asset: AssetId, to: AccountId, value: Balance) { - assert_ok!(Assets::mint(signed(owner), asset_asset, to, value)); +fn mint_asset(owner: AccountId, asset: AssetId, to: AccountId, value: Balance) { + assert_ok!(Assets::mint(signed(owner), asset, to, value)); } -fn create_asset_and_mint_to(owner: AccountId, asset_asset: AssetId, to: AccountId, value: Balance) { - create_asset(owner, asset_asset); - mint_asset(owner, asset_asset, to, value) +fn create_asset_and_mint_to(owner: AccountId, asset: AssetId, to: AccountId, value: Balance) { + create_asset(owner, asset); + mint_asset(owner, asset, to, value) } fn create_asset_mint_and_approve( owner: AccountId, - asset_asset: AssetId, + asset: AssetId, to: AccountId, mint: Balance, spender: AccountId, approve: Balance, ) { - create_asset_and_mint_to(owner, asset_asset, to, mint); - assert_ok!(Assets::approve_transfer(signed(to), asset_asset, spender, approve,)); + create_asset_and_mint_to(owner, asset, to, mint); + assert_ok!(Assets::approve_transfer(signed(to), asset, spender, approve,)); } fn create_asset_and_set_metadata( owner: AccountId, - asset_asset: AssetId, + asset: AssetId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::create(signed(owner), asset_asset, owner, 100)); - set_metadata_asset(owner, asset_asset, name, symbol, decimals); + assert_ok!(Assets::create(signed(owner), asset, owner, 100)); + set_metadata_asset(owner, asset, name, symbol, decimals); } fn set_metadata_asset( owner: AccountId, - asset_asset: AssetId, + asset: AssetId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::set_metadata(signed(owner), asset_asset, name, symbol, decimals)); + assert_ok!(Assets::set_metadata(signed(owner), asset, name, symbol, decimals)); } From 6482a437ecd3028a63b307591369b990e3487612 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:06:50 +0700 Subject: [PATCH 046/161] fix: invalid imported crates & crate visibility (#214) --- pop-api/src/v0/assets/fungibles.rs | 2 +- runtime/devnet/src/config/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index c881f823..4f270e6b 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -11,9 +11,9 @@ use crate::{ primitives::{AccountId, AssetId, Balance}, Result, StatusCode, }; -pub use asset_management::*; use constants::*; use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec}; +pub use management::*; pub use metadata::*; // Helper method to build a dispatch call. diff --git a/runtime/devnet/src/config/mod.rs b/runtime/devnet/src/config/mod.rs index 1dcd44da..1ef83bc1 100644 --- a/runtime/devnet/src/config/mod.rs +++ b/runtime/devnet/src/config/mod.rs @@ -1,5 +1,6 @@ mod api; -mod assets; +// Public due to pop api integration tests crate. +pub mod assets; mod contracts; mod proxy; // Public due to integration tests crate. From 1b78c110f3a1a686fa86b5662097b032d2bbd3a2 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Mon, 26 Aug 2024 20:04:08 +0700 Subject: [PATCH 047/161] ci: add CI script for `pop-api` tests and integration tests (#228) Co-authored-by: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> --- .github/workflows/ci.yml | 28 +- Cargo.lock | 945 ++++++++++++++++----------- pop-api/Cargo.toml | 12 +- pop-api/integration-tests/Cargo.toml | 8 +- pop-api/integration-tests/build.rs | 57 ++ 5 files changed, 676 insertions(+), 374 deletions(-) create mode 100644 pop-api/integration-tests/build.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a56a6bfb..283390f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: ci on: push: - branches: [ main ] + branches: [main] pull_request: - types: [ opened, synchronize, reopened, ready_for_review ] + types: [opened, synchronize, reopened, ready_for_review] jobs: lint: @@ -67,6 +67,28 @@ jobs: - name: Run integration tests run: cargo test --release --locked --package integration-tests + api-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: "./.github/actions/init" + + - name: Run tests + working-directory: pop-api + run: cargo test --release --all-features + + api-integration-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: "./.github/actions/init" + + - name: Run integration tests + working-directory: pop-api/integration-tests + run: cargo test --release + coverage: needs: lint runs-on: ubuntu-latest @@ -86,4 +108,4 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} files: codecov.json - fail_ci_if_error: true \ No newline at end of file + fail_ci_if_error: true diff --git a/Cargo.lock b/Cargo.lock index 3407a210..e2a4bbcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,6 +36,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aead" version = "0.5.2" @@ -142,9 +148,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", @@ -157,33 +163,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -215,7 +221,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -361,9 +367,9 @@ checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" [[package]] name = "arrayref" -version = "0.3.8" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" @@ -584,9 +590,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" dependencies = [ "async-task", "concurrent-queue", @@ -629,9 +635,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.4" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" dependencies = [ "async-lock 3.4.0", "cfg-if", @@ -639,11 +645,11 @@ dependencies = [ "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.7.3", + "polling 3.7.2", "rustix 0.38.34", "slab", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -696,11 +702,11 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.10" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" dependencies = [ - "async-io 2.3.4", + "async-io 2.3.3", "async-lock 3.4.0", "atomic-waker", "cfg-if", @@ -709,7 +715,7 @@ dependencies = [ "rustix 0.38.34", "signal-hook-registry", "slab", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -720,13 +726,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -770,8 +776,8 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", - "object 0.36.3", + "miniz_oxide 0.7.3", + "object 0.36.0", "rustc-demangle", ] @@ -851,7 +857,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -881,9 +887,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -953,9 +959,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" dependencies = [ "arrayref", "arrayvec 0.7.4", @@ -1293,9 +1299,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.16.3" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" +checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" [[package]] name = "byteorder" @@ -1305,9 +1311,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bzip2-sys" @@ -1364,12 +1370,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.10" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" dependencies = [ "jobserver", "libc", + "once_cell", ] [[package]] @@ -1447,7 +1454,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -1505,9 +1512,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.15" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -1515,9 +1522,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", @@ -1528,21 +1535,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "coarsetime" @@ -1583,14 +1590,14 @@ dependencies = [ "nom", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "comfy-table" @@ -1598,7 +1605,7 @@ version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" dependencies = [ - "strum 0.26.3", + "strum 0.26.2", "strum_macros 0.26.4", "unicode-width", ] @@ -1693,9 +1700,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 = "core2" @@ -1727,9 +1734,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -2249,7 +2256,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -2569,7 +2576,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -2609,7 +2616,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -2626,7 +2633,7 @@ checksum = "4b2c1c1776b986979be68bb2285da855f8d8a35851a769fca8740df7c3d07877" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -2718,7 +2725,7 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -2731,7 +2738,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -2814,13 +2821,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -2844,9 +2851,9 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.74", + "syn 2.0.66", "termcolor", - "toml 0.8.19", + "toml 0.8.14", "walkdir", ] @@ -2965,9 +2972,9 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elliptic-curve" @@ -3056,18 +3063,18 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] name = "enumn" -version = "0.1.14" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" +checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -3240,7 +3247,7 @@ dependencies = [ "prettyplease 0.2.20", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -3337,14 +3344,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.24" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "libredox", - "windows-sys 0.59.0", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", ] [[package]] @@ -3383,13 +3390,13 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" +checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" dependencies = [ "crc32fast", "libz-sys", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -3515,7 +3522,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -3665,7 +3672,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -3678,7 +3685,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -3689,7 +3696,7 @@ checksum = "68672b9ec6fe72d259d3879dc212c5e42e977588cdac830c76f54d9f492aeb58" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -3872,7 +3879,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -4049,7 +4056,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.3.0", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -4276,9 +4283,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes", "futures-channel", @@ -4325,7 +4332,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core", ] [[package]] @@ -4337,6 +4344,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "idna" version = "0.2.3" @@ -4350,12 +4475,14 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -4374,7 +4501,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" dependencies = [ - "async-io 2.3.4", + "async-io 2.3.3", "core-foundation", "fnv", "futures", @@ -4468,9 +4595,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.3.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -4617,9 +4744,9 @@ dependencies = [ [[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" @@ -4639,15 +4766,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.11" @@ -4656,27 +4774,27 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "jsonrpsee" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "affdc52f7596ccb2d7645231fc6163bb314630c989b64998f3699a28b4d5d4dc" +checksum = "138572befc78a9793240645926f30161f8b4143d2be18d09e44ed9814bd7ee2c" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -4690,9 +4808,9 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b005c793122d03217da09af68ba9383363caa950b90d3436106df8cabce935" +checksum = "5c671353e4adf926799107bd7f5724a06b6bc0a333db442a0843c58640bdd0c1" dependencies = [ "futures-util", "http", @@ -4710,9 +4828,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2327ba8df2fdbd5e897e2b5ed25ce7f299d345b9736b6828814c3dbd1fd47b" +checksum = "f24ea59b037b6b9b0e2ebe2c30a3e782b56bd7c76dcc5d6d70ba55d442af56e3" dependencies = [ "anyhow", "async-lock 2.8.0", @@ -4735,9 +4853,9 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f80c17f62c7653ce767e3d7288b793dfec920f97067ceb189ebdd3570f2bc20" +checksum = "57c7b9f95208927653e7965a98525e7fc641781cab89f0e27c43fa2974405683" dependencies = [ "async-trait", "hyper", @@ -4755,9 +4873,9 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29110019693a4fa2dbda04876499d098fa16d70eba06b1e6e2b3f1b251419515" +checksum = "dcc0eba68ba205452bcb4c7b80a79ddcb3bf36c261a841b239433142db632d24" dependencies = [ "heck 0.4.1", "proc-macro-crate 1.1.3", @@ -4768,9 +4886,9 @@ dependencies = [ [[package]] name = "jsonrpsee-server" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c39a00449c9ef3f50b84fc00fc4acba20ef8f559f07902244abf4c15c5ab9c" +checksum = "a482bc4e25eebd0adb61a3468c722763c381225bd3ec46e926f709df8a8eb548" dependencies = [ "futures-util", "http", @@ -4791,9 +4909,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be0be325642e850ed0bdff426674d2e66b2b7117c9be23a7caef68a2902b7d9" +checksum = "3264e339143fe37ed081953842ee67bfafa99e3b91559bdded6e4abd8fc8535e" dependencies = [ "anyhow", "beef", @@ -4805,9 +4923,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca9cb3933ccae417eb6b08c3448eb1cb46e39834e5b503e395e5e5bd08546c0" +checksum = "6d06eeabbb55f0af8405288390a358ebcceb6e79e1390741e6f152309c4d6076" dependencies = [ "http", "jsonrpsee-client-transport", @@ -4890,9 +5008,9 @@ 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 = "lazycell" @@ -4908,12 +5026,12 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -5321,9 +5439,8 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "libc", - "redox_syscall 0.5.3", ] [[package]] @@ -5391,9 +5508,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.19" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647" +checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" dependencies = [ "cc", "pkg-config", @@ -5463,6 +5580,12 @@ dependencies = [ "keystream", ] +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -5475,9 +5598,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lru" @@ -5514,9 +5637,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.26.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958b4caa893816eea05507c20cfe47574a43d9a697138a7872990bba8a0ece68" +checksum = "d6eab492fe7f8651add23237ea56dbf11b3c4ff762ab83d40a47f11433421f91" dependencies = [ "libc", "lz4-sys", @@ -5524,9 +5647,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.10.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109de74d5d2353660401699a4174a4ff23fcc649caf553df71933c7fb45ad868" +checksum = "e9764018d143cc854c9f17f0b907de70f14393b1f502da6375dce70f00514eb3" dependencies = [ "cc", "libc", @@ -5550,7 +5673,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -5564,7 +5687,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -5575,7 +5698,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -5586,7 +5709,7 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -5627,9 +5750,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[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", @@ -5717,23 +5840,31 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" -version = "1.0.2" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.48.0", ] [[package]] @@ -5949,7 +6080,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", "synstructure 0.13.1", ] @@ -5991,13 +6122,13 @@ dependencies = [ [[package]] name = "nalgebra-macros" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" +checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 1.0.109", ] [[package]] @@ -6098,7 +6229,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "cfg-if", "libc", ] @@ -6139,9 +6270,9 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[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", @@ -6232,9 +6363,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -6302,7 +6433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1344346d5af32c95bbddea91b18a88cc83eac394192d20ef2fc4c40a74332355" dependencies = [ "expander 2.2.1", - "indexmap 2.3.0", + "indexmap 2.2.6", "itertools 0.11.0", "petgraph", "proc-macro-crate 3.1.0", @@ -6808,7 +6939,7 @@ checksum = "3163c6bc21b55a0ccb74c546ba784d9c9e69beb9240c059d28a3052f4cbce509" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -7476,7 +7607,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -7979,9 +8110,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.3", + "redox_syscall 0.5.2", "smallvec", - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -8147,9 +8278,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.11" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -8158,9 +8289,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" dependencies = [ "pest", "pest_generator", @@ -8168,22 +8299,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" dependencies = [ "once_cell", "pest", @@ -8197,7 +8328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.3.0", + "indexmap 2.2.6", ] [[package]] @@ -8217,7 +8348,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -8240,9 +8371,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" dependencies = [ "atomic-waker", "fastrand 2.1.0", @@ -8426,7 +8557,7 @@ dependencies = [ "fatality", "futures", "futures-timer", - "indexmap 2.3.0", + "indexmap 2.2.6", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -9353,7 +9484,7 @@ dependencies = [ "fatality", "futures", "futures-timer", - "indexmap 2.3.0", + "indexmap 2.2.6", "parity-scale-codec", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -9391,7 +9522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6380dbe1fb03ecc74ad55d841cfc75480222d153ba69ddcb00977866cbdabdb8" dependencies = [ "polkavm-derive-impl", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -9403,7 +9534,7 @@ dependencies = [ "polkavm-common", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -9424,9 +9555,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.3" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" dependencies = [ "cfg-if", "concurrent-queue", @@ -9434,7 +9565,7 @@ dependencies = [ "pin-project-lite 0.2.14", "rustix 0.38.34", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -9709,9 +9840,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "powerfmt" @@ -9721,12 +9852,9 @@ 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 = "predicates" @@ -9744,15 +9872,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.8" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" [[package]] name = "predicates-tree" -version = "1.0.11" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" dependencies = [ "predicates-core", "termtree", @@ -9775,7 +9903,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -9869,14 +9997,14 @@ checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -9915,7 +10043,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -9980,10 +10108,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -10193,11 +10321,20 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", ] [[package]] @@ -10240,7 +10377,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -10257,9 +10394,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -10605,7 +10742,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys 0.4.14", @@ -10836,7 +10973,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -11850,7 +11987,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -12069,11 +12206,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.6.0", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -12082,9 +12219,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -12116,9 +12253,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.207" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -12134,41 +12271,40 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.15" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.207" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.124" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", - "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -12655,7 +12791,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -12907,7 +13043,7 @@ checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -12928,7 +13064,7 @@ checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -13177,7 +13313,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -13384,7 +13520,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -13637,9 +13773,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.26.3" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" [[package]] name = "strum_macros" @@ -13664,7 +13800,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -13765,7 +13901,7 @@ dependencies = [ "sp-maybe-compressed-blob", "strum 0.24.1", "tempfile", - "toml 0.8.19", + "toml 0.8.14", "walkdir", "wasm-opt", ] @@ -13801,9 +13937,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.74" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -13830,7 +13966,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -13876,21 +14012,20 @@ 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.12.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand 2.1.0", - "once_cell", "rustix 0.38.34", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -13920,9 +14055,9 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] @@ -13944,18 +14079,18 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -14057,11 +14192,21 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -14074,31 +14219,32 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.2" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", "libc", "mio", + "num_cpus", "parking_lot 0.12.3", "pin-project-lite 0.2.14", "signal-hook-registry", "socket2 0.5.7", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -14159,21 +14305,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.20", + "toml_edit 0.22.14", ] [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -14184,7 +14330,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.2.6", "toml_datetime", "winnow 0.5.40", ] @@ -14195,22 +14341,22 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.2.6", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.18", + "winnow 0.6.13", ] [[package]] @@ -14234,7 +14380,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "bytes", "futures-core", "futures-util", @@ -14278,7 +14424,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -14323,7 +14469,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -14619,15 +14765,27 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.0", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -14648,9 +14806,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[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 = "void" @@ -14730,35 +14888,34 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", - "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -14768,9 +14925,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -14778,22 +14935,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-instrument" @@ -15106,9 +15263,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -15272,9 +15429,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.28" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b828f995bf1e9622031f8009f8481a85406ce1f4d4588ff746d872043e855690" +checksum = "8a040b111774ab63a19ef46bbc149398ab372b4ccdcfd719e9814dbd7dfd76c8" dependencies = [ "bytemuck", "safe_arch", @@ -15304,11 +15461,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]] @@ -15323,7 +15480,7 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ - "windows-core 0.51.1", + "windows-core", "windows-targets 0.48.5", ] @@ -15336,15 +15493,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -15369,16 +15517,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]] @@ -15413,18 +15552,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]] @@ -15441,9 +15580,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" @@ -15459,9 +15598,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" @@ -15477,15 +15616,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" @@ -15501,9 +15640,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" @@ -15519,9 +15658,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" @@ -15537,9 +15676,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" @@ -15555,9 +15694,9 @@ 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" @@ -15570,9 +15709,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" dependencies = [ "memchr", ] @@ -15587,6 +15726,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -15681,7 +15832,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", ] [[package]] @@ -15707,25 +15858,69 @@ dependencies = [ "time", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "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.74", + "syn 2.0.66", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure 0.13.1", ] [[package]] @@ -15745,7 +15940,29 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.66", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", ] [[package]] @@ -15788,9 +16005,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" +version = "2.0.11+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4" dependencies = [ "cc", "pkg-config", diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 9946abf7..05dd9715 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -7,7 +7,11 @@ edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } -sp-io = { version = "31.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } +sp-io = { version = "31.0.0", default-features = false, features = [ + "disable_panic_handler", + "disable_oom", + "disable_allocator", +] } pop-primitives = { path = "../primitives", default-features = false } @@ -18,10 +22,6 @@ crate-type = ["rlib"] [features] default = ["std"] -std = [ - "ink/std", - "pop-primitives/std", - "sp-io/std", -] +std = ["ink/std", "pop-primitives/std", "sp-io/std"] assets = [] fungibles = ["assets"] diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml index cc56630a..7ab2d0fb 100644 --- a/pop-api/integration-tests/Cargo.toml +++ b/pop-api/integration-tests/Cargo.toml @@ -2,10 +2,16 @@ name = "integration-tests" version = "0.1.0" edition = "2021" +build = "build.rs" + +[build-dependencies] +contract-build = "4.1.1" [dev-dependencies] env_logger = "0.11.2" -scale = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ + "derive", +] } frame-support = { version = "29.0.0", default-features = false } frame-system = { version = "29.0.0", default-features = false } pallet-balances = { version = "29.0.2", default-features = false } diff --git a/pop-api/integration-tests/build.rs b/pop-api/integration-tests/build.rs new file mode 100644 index 00000000..5b969a9f --- /dev/null +++ b/pop-api/integration-tests/build.rs @@ -0,0 +1,57 @@ +use contract_build::{ + execute, BuildArtifacts, BuildMode, BuildResult, ExecuteArgs, ManifestPath, OutputType, + Verbosity, +}; +use std::{ + fs, + path::{Path, PathBuf}, + process, +}; + +fn main() { + let contracts_dir = PathBuf::from("./contracts/"); + let contract_dirs = match get_subcontract_directories(&contracts_dir) { + Ok(dirs) => dirs, + Err(e) => { + eprintln!("Failed to read contracts directory: {}", e); + process::exit(1); + }, + }; + + for contract in contract_dirs { + if let Err(e) = build_contract(&contract) { + eprintln!("Failed to build contract {}: {}", contract.display(), e); + process::exit(1); + } + } +} + +// Function to retrieve all subdirectories in a given directory. +fn get_subcontract_directories(contracts_dir: &Path) -> Result, String> { + fs::read_dir(contracts_dir) + .map_err(|e| format!("Could not read directory '{}': {}", contracts_dir.display(), e))? + .filter_map(|entry| match entry { + Ok(entry) if entry.path().is_dir() => Some(Ok(entry.path())), + Ok(_) => None, + Err(e) => Some(Err(format!("Error reading directory entry: {}", e))), + }) + .collect() +} + +// Function to build a contract given its directory. +fn build_contract(contract_dir: &Path) -> Result { + let manifest_path = ManifestPath::new(contract_dir.join("Cargo.toml")).map_err(|e| { + format!("Could not retrieve manifest path for {}: {}", contract_dir.display(), e) + })?; + + let args = ExecuteArgs { + build_artifact: BuildArtifacts::CodeOnly, + build_mode: BuildMode::Debug, + manifest_path, + output_type: OutputType::HumanReadable, + verbosity: Verbosity::Default, + ..Default::default() + }; + + execute(args).map_err(|e| format!("Build failed for {}: {}", contract_dir.display(), e)) +} From 8d1c0850c03da6e0d62181133eeb7ca35a680385 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Mon, 26 Aug 2024 22:40:15 +0700 Subject: [PATCH 048/161] fix: mutable `self` required for dispatchable ink! methods (#235) --- pop-api/examples/fungibles/lib.rs | 10 ++++---- .../contracts/fungibles/lib.rs | 25 +++++++++++-------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 1b42fec4..a6328c37 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -60,13 +60,13 @@ mod fungibles { } #[ink(message)] - pub fn transfer(&self, id: AssetId, to: AccountId, value: Balance) -> Result<()> { + pub fn transfer(&mut self, id: AssetId, to: AccountId, value: Balance) -> Result<()> { api::transfer(id, to, value) } #[ink(message)] pub fn transfer_from( - &self, + &mut self, id: AssetId, from: AccountId, to: AccountId, @@ -78,13 +78,13 @@ mod fungibles { } #[ink(message)] - pub fn approve(&self, id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + pub fn approve(&mut self, id: AssetId, spender: AccountId, value: Balance) -> Result<()> { api::approve(id, spender, value) } #[ink(message)] pub fn increase_allowance( - &self, + &mut self, id: AssetId, spender: AccountId, value: Balance, @@ -94,7 +94,7 @@ mod fungibles { #[ink(message)] pub fn decrease_allowance( - &self, + &mut self, id: AssetId, spender: AccountId, value: Balance, diff --git a/pop-api/integration-tests/contracts/fungibles/lib.rs b/pop-api/integration-tests/contracts/fungibles/lib.rs index 239d3a2d..2b33ce04 100755 --- a/pop-api/integration-tests/contracts/fungibles/lib.rs +++ b/pop-api/integration-tests/contracts/fungibles/lib.rs @@ -60,13 +60,13 @@ mod fungibles { } #[ink(message)] - pub fn transfer(&self, id: AssetId, to: AccountId, value: Balance) -> Result<()> { + pub fn transfer(&mut self, id: AssetId, to: AccountId, value: Balance) -> Result<()> { api::transfer(id, to, value) } #[ink(message)] pub fn transfer_from( - &self, + &mut self, id: AssetId, from: AccountId, to: AccountId, @@ -78,13 +78,13 @@ mod fungibles { } #[ink(message)] - pub fn approve(&self, id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + pub fn approve(&mut self, id: AssetId, spender: AccountId, value: Balance) -> Result<()> { api::approve(id, spender, value) } #[ink(message)] pub fn increase_allowance( - &self, + &mut self, id: AssetId, spender: AccountId, value: Balance, @@ -94,7 +94,7 @@ mod fungibles { #[ink(message)] pub fn decrease_allowance( - &self, + &mut self, id: AssetId, spender: AccountId, value: Balance, @@ -130,18 +130,23 @@ mod fungibles { /// - asset_exists #[ink(message)] - pub fn create(&self, id: AssetId, admin: AccountId, min_balance: Balance) -> Result<()> { + pub fn create( + &mut self, + id: AssetId, + admin: AccountId, + min_balance: Balance, + ) -> Result<()> { api::create(id, admin, min_balance) } #[ink(message)] - pub fn start_destroy(&self, id: AssetId) -> Result<()> { + pub fn start_destroy(&mut self, id: AssetId) -> Result<()> { api::start_destroy(id) } #[ink(message)] pub fn set_metadata( - &self, + &mut self, id: AssetId, name: Vec, symbol: Vec, @@ -165,12 +170,12 @@ mod fungibles { /// - burn #[ink(message)] - pub fn mint(&self, id: AssetId, account: AccountId, amount: Balance) -> Result<()> { + pub fn mint(&mut self, id: AssetId, account: AccountId, amount: Balance) -> Result<()> { api::mint(id, account, amount) } #[ink(message)] - pub fn burn(&self, id: AssetId, account: AccountId, amount: Balance) -> Result<()> { + pub fn burn(&mut self, id: AssetId, account: AccountId, amount: Balance) -> Result<()> { api::burn(id, account, amount) } } From 479dbb0b509e17cd32c050673a9822c4c6527c4d Mon Sep 17 00:00:00 2001 From: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:22:52 +0100 Subject: [PATCH 049/161] refactor: generic extension (#218) Co-authored-by: Tin Chung <56880684+chungquantin@users.noreply.github.com> --- .github/workflows/ci.yml | 8 +- .gitignore | 5 +- Cargo.lock | 524 +++++++++++++++-- Cargo.toml | 6 +- extension/Cargo.toml | 43 +- extension/contract/Cargo.toml | 16 + extension/contract/lib.rs | 51 ++ extension/src/decoding.rs | 297 ++++++++++ extension/src/environment.rs | 193 +++++++ extension/src/functions.rs | 534 ++++++++++++++++++ extension/src/lib.rs | 466 ++++++--------- extension/src/matching.rs | 84 +++ extension/src/mock.rs | 373 ++++++++++++ extension/src/tests.rs | 321 +++++++---- extension/src/v0.rs | 298 ---------- integration-tests/src/lib.rs | 37 +- node/src/command.rs | 5 +- pallets/api/Cargo.toml | 5 + pallets/api/src/extension.rs | 180 ++++++ pallets/api/src/fungibles/mod.rs | 106 +++- pallets/api/src/fungibles/tests.rs | 25 +- pallets/api/src/lib.rs | 25 + pop-api/integration-tests/Cargo.toml | 1 + .../integration-tests/src/fungibles/mod.rs | 127 +++-- pop-api/integration-tests/src/lib.rs | 1 + pop-api/src/v0/assets/fungibles.rs | 27 +- pop-api/src/v0/mod.rs | 2 +- primitives/src/lib.rs | 75 ++- runtime/devnet/src/config/api.rs | 68 --- runtime/devnet/src/config/api/mod.rs | 213 +++++++ runtime/devnet/src/config/api/versioning.rs | 218 +++++++ runtime/devnet/src/config/contracts.rs | 4 +- runtime/devnet/src/config/proxy.rs | 108 ++-- runtime/devnet/src/config/xcm.rs | 4 +- runtime/devnet/src/lib.rs | 8 +- runtime/testnet/src/config/proxy.rs | 108 ++-- runtime/testnet/src/config/xcm.rs | 4 +- runtime/testnet/src/extensions.rs | 2 +- runtime/testnet/src/lib.rs | 8 +- 39 files changed, 3483 insertions(+), 1097 deletions(-) create mode 100755 extension/contract/Cargo.toml create mode 100755 extension/contract/lib.rs create mode 100644 extension/src/decoding.rs create mode 100644 extension/src/environment.rs create mode 100644 extension/src/functions.rs create mode 100644 extension/src/matching.rs create mode 100644 extension/src/mock.rs delete mode 100644 extension/src/v0.rs create mode 100644 pallets/api/src/extension.rs delete mode 100644 runtime/devnet/src/config/api.rs create mode 100644 runtime/devnet/src/config/api/mod.rs create mode 100644 runtime/devnet/src/config/api/versioning.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 283390f3..c8e2b2cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: ci on: push: - branches: [main] + branches: [ main ] pull_request: - types: [opened, synchronize, reopened, ready_for_review] + types: [ opened, synchronize, reopened, ready_for_review ] jobs: lint: @@ -13,7 +13,9 @@ jobs: - uses: actions/checkout@v4 - name: Check formatting - run: cargo +stable fmt --all -- --check + run: | + rustup toolchain install nightly --profile minimal --component rustfmt + cargo +nightly fmt --all -- --check check: needs: lint diff --git a/.gitignore b/.gitignore index 52e0800a..b99b862b 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,7 @@ .idea # Binaries -**/bin/ \ No newline at end of file +**/bin/ + +# Cargo.lock +**/Cargo.lock \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e2a4bbcd..26fb5d46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -805,6 +805,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -1001,6 +1007,50 @@ dependencies = [ "piper", ] +[[package]] +name = "bollard" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aed08d3adb6ebe0eff737115056652670ae290f177759aac19c30456135f94c" +dependencies = [ + "base64 0.22.1", + "bollard-stubs", + "bytes", + "futures-core", + "futures-util", + "hex", + "http 1.1.0", + "http-body-util", + "hyper 1.4.1", + "hyper-named-pipe", + "hyper-util", + "hyperlocal-next", + "log", + "pin-project-lite 0.2.14", + "serde", + "serde_derive", + "serde_json", + "serde_repr", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util", + "tower-service", + "url", + "winapi", +] + +[[package]] +name = "bollard-stubs" +version = "1.44.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709d9aa1c37abb89d40f19f5d0ad6f0d88cb1581264e571c9350fc5bb89cf1c5" +dependencies = [ + "serde", + "serde_repr", + "serde_with", +] + [[package]] name = "bounded-collections" version = "0.2.0" @@ -1368,6 +1418,20 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.23", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cc" version = "1.0.99" @@ -1453,8 +1517,9 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -1599,6 +1664,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "colored" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +dependencies = [ + "lazy_static", + "windows-sys 0.48.0", +] + [[package]] name = "comfy-table" version = "7.1.1" @@ -1682,6 +1757,60 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" +[[package]] +name = "contract-build" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d30f629d8cb26692c4e5f4155e8ab37649f1b2fd0abab64a4c1b3c95c9bcf3df" +dependencies = [ + "anyhow", + "blake2 0.10.6", + "bollard", + "cargo_metadata 0.18.1", + "clap", + "colored", + "contract-metadata", + "crossterm", + "duct", + "heck 0.5.0", + "hex", + "impl-serde", + "parity-scale-codec", + "parity-wasm", + "regex", + "rustc_version", + "semver 1.0.23", + "serde", + "serde_json", + "strum 0.26.2", + "tempfile", + "term_size", + "tokio", + "tokio-stream", + "toml 0.8.14", + "tracing", + "url", + "uzers", + "walkdir", + "wasm-opt", + "which 6.0.3", + "zip", +] + +[[package]] +name = "contract-metadata" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd54ed69476dc2076d6ebda17351babe1c2f33751170877f66719e8129078d3a" +dependencies = [ + "anyhow", + "impl-serde", + "semver 1.0.23", + "serde", + "serde_json", + "url", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -1882,6 +2011,31 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.5.0", + "crossterm_winapi", + "libc", + "mio", + "parking_lot 0.12.3", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -2693,6 +2847,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -2875,6 +3030,18 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" +[[package]] +name = "duct" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + [[package]] name = "dyn-clonable" version = "0.9.0" @@ -4055,7 +4222,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap 2.2.6", "slab", "tokio", @@ -4246,6 +4413,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -4253,7 +4431,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite 0.2.14", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite 0.2.14", ] @@ -4292,8 +4493,8 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -4305,6 +4506,40 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "itoa", + "pin-project-lite 0.2.14", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-named-pipe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" +dependencies = [ + "hex", + "hyper 1.4.1", + "hyper-util", + "pin-project-lite 0.2.14", + "tokio", + "tower-service", + "winapi", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -4312,8 +4547,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.29", "log", "rustls 0.21.12", "rustls-native-certs", @@ -4321,6 +4556,41 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "hyper-util" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", + "pin-project-lite 0.2.14", + "socket2 0.5.7", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "hyperlocal-next" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf569d43fa9848e510358c07b80f4adf34084ddc28c6a4a651ee8474c070dcc" +dependencies = [ + "hex", + "http-body-util", + "hyper 1.4.1", + "hyper-util", + "pin-project-lite 0.2.14", + "tokio", + "tower-service", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -4601,6 +4871,7 @@ checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.5", + "serde", ] [[package]] @@ -4813,7 +5084,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c671353e4adf926799107bd7f5724a06b6bc0a333db442a0843c58640bdd0c1" dependencies = [ "futures-util", - "http", + "http 0.2.12", "jsonrpsee-core", "pin-project", "rustls-native-certs", @@ -4838,7 +5109,7 @@ dependencies = [ "beef", "futures-timer", "futures-util", - "hyper", + "hyper 0.14.29", "jsonrpsee-types", "parking_lot 0.12.3", "rand", @@ -4858,7 +5129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c7b9f95208927653e7965a98525e7fc641781cab89f0e27c43fa2974405683" dependencies = [ "async-trait", - "hyper", + "hyper 0.14.29", "hyper-rustls", "jsonrpsee-core", "jsonrpsee-types", @@ -4891,8 +5162,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a482bc4e25eebd0adb61a3468c722763c381225bd3ec46e926f709df8a8eb548" dependencies = [ "futures-util", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.29", "jsonrpsee-core", "jsonrpsee-types", "route-recognizer", @@ -4927,7 +5198,7 @@ version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d06eeabbb55f0af8405288390a358ebcceb6e79e1390741e6f152309c4d6076" dependencies = [ - "http", + "http 0.2.12", "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", @@ -5031,7 +5302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] @@ -5863,6 +6134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -6451,6 +6723,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "os_pipe" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "pallet-api" version = "0.1.0" @@ -6458,9 +6740,11 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "pallet-assets", "pallet-balances", "parity-scale-codec", + "pop-chain-extension", "scale-info", "sp-core", "sp-io", @@ -8112,7 +8396,7 @@ dependencies = [ "libc", "redox_syscall 0.5.2", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -9595,14 +9879,20 @@ dependencies = [ name = "pop-chain-extension" version = "0.1.0" dependencies = [ + "contract-build", + "env_logger 0.11.5", "frame-support", "frame-system", + "impl-trait-for-tuples", "log", + "pallet-balances", "pallet-contracts", + "pallet-timestamp", "parity-scale-codec", - "pop-primitives", "rand", + "scale-info", "sp-core", + "sp-io", "sp-runtime", "sp-std", ] @@ -10085,7 +10375,7 @@ dependencies = [ "regex", "syn 1.0.109", "tempfile", - "which", + "which 4.4.2", ] [[package]] @@ -11660,7 +11950,7 @@ dependencies = [ "fnv", "futures", "futures-timer", - "hyper", + "hyper 0.14.29", "hyper-rustls", "libp2p", "log", @@ -11754,7 +12044,7 @@ version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "691440bbaddd3bc2675309c965cc75f8bf694f51e0a28039bfc9658299fbc394" dependencies = [ - "http", + "http 0.2.12", "jsonrpsee", "log", "serde_json", @@ -12300,6 +12590,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "serde_spanned" version = "0.6.6" @@ -12309,6 +12610,35 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "time", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -12376,12 +12706,43 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared_child" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -12750,7 +13111,7 @@ dependencies = [ "bytes", "flate2", "futures", - "http", + "http 0.2.12", "httparse", "log", "rand", @@ -13776,6 +14137,9 @@ name = "strum" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros 0.26.4", +] [[package]] name = "strum_macros" @@ -13848,7 +14212,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8fe06b03b8a291c09507c42f92a2c2c10dd3d62975d02c7f64a92d87bfe09b" dependencies = [ - "hyper", + "hyper 0.14.29", "log", "prometheus", "thiserror", @@ -13894,7 +14258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a39a20e17c24ede36b5bd5e7543a4cef8d8a0daf6e1a046dc31832b837a54a0" dependencies = [ "build-helper", - "cargo_metadata", + "cargo_metadata 0.15.4", "console", "filetime", "parity-wasm", @@ -14028,6 +14392,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "term_size" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -14369,6 +14743,7 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite 0.2.14", + "tokio", "tower-layer", "tower-service", "tracing", @@ -14384,8 +14759,8 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "http-range-header", "pin-project-lite 0.2.14", "tower-layer", @@ -14772,6 +15147,7 @@ dependencies = [ "form_urlencoded", "idna 1.0.0", "percent-encoding", + "serde", ] [[package]] @@ -14792,6 +15168,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uzers" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d283dc7e8c901e79e32d077866eaf599156cbf427fffa8289aecc52c5c3f63" +dependencies = [ + "libc", + "log", +] + [[package]] name = "valuable" version = "0.1.0" @@ -15427,6 +15813,18 @@ dependencies = [ "rustix 0.38.34", ] +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix 0.38.34", + "winsafe", +] + [[package]] name = "wide" version = "0.7.24" @@ -15517,7 +15915,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "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", ] [[package]] @@ -15552,18 +15959,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "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", + "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", ] [[package]] @@ -15580,9 +15987,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -15598,9 +16005,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -15616,15 +16023,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -15640,9 +16047,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -15658,9 +16065,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -15676,9 +16083,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -15694,9 +16101,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -15726,6 +16133,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "write16" version = "1.0.0" @@ -15965,6 +16378,17 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/Cargo.toml b/Cargo.toml index f037f6b7..7027423c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ members = [ "pallets/*", "primitives", ] -exclude = ["pop-api", "tests/contracts"] +exclude = ["extension/contract", "pop-api", "tests/contracts"] resolver = "2" @@ -31,7 +31,10 @@ resolver = "2" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } +contract-build = "4.1.1" +env_logger = "0.11.5" hex-literal = "0.4.1" +impl-trait-for-tuples = "0.2.2" log = { version = "0.4.20", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = [ "derive", @@ -41,6 +44,7 @@ serde = "1.0.195" clap = { version = "4.4.18", features = ["derive"] } jsonrpsee = { version = "0.20.3", features = ["server"] } futures = "0.3.28" +rand = "0.8.5" serde_json = "1.0.111" tracing-subscriber = { version = "0.3", default-features = false } subxt = "0.34.0" diff --git a/extension/Cargo.toml b/extension/Cargo.toml index 03b4221a..268365be 100644 --- a/extension/Cargo.toml +++ b/extension/Cargo.toml @@ -14,11 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec.workspace = true +impl-trait-for-tuples.workspace = true log.workspace = true -# Local -pop-primitives.workspace = true - # Substrate frame-support.workspace = true frame-system.workspace = true @@ -28,24 +26,35 @@ sp-runtime.workspace = true sp-std.workspace = true [dev-dependencies] -rand = "0.8.5" +contract-build.workspace = true +env_logger.workspace = true +pallet-balances.workspace = true +pallet-contracts.workspace = true +pallet-timestamp.workspace = true +rand.workspace = true +scale-info.workspace = true +sp-io.workspace = true [features] default = ["std"] std = [ - "log/std", - "codec/std", - "frame-support/std", - "frame-system/std", - "pallet-contracts/std", - "pop-primitives/std", - "sp-runtime/std", - "sp-core/std", - "sp-std/std", + "log/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "pallet-contracts/std", + "pallet-timestamp/std", + "sp-runtime/std", + "sp-core/std", + "sp-io/std", + "sp-std/std", ] runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-contracts/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-contracts/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] diff --git a/extension/contract/Cargo.toml b/extension/contract/Cargo.toml new file mode 100755 index 00000000..97ecabf9 --- /dev/null +++ b/extension/contract/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["R0GUE "] +name = "proxy" +description = "Simple contract for proxying a call to a chain extension." +version = "0.1.0" +edition = "2021" + +[dependencies] +ink = { version = "5.0.0", default-features = false } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = ["ink/std"] diff --git a/extension/contract/lib.rs b/extension/contract/lib.rs new file mode 100755 index 00000000..181ba28c --- /dev/null +++ b/extension/contract/lib.rs @@ -0,0 +1,51 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +use ink::{ + env::chain_extension::{ChainExtensionMethod, FromStatusCode}, + prelude::vec::Vec, +}; + +#[ink::contract] +mod contract { + use super::*; + + // Simple contract for proxying a call to a chain extension. + #[ink(storage)] + #[derive(Default)] + pub struct Proxy; + + impl Proxy { + #[ink(constructor)] + pub fn new() -> Self { + ink::env::debug_println!("Proxy::new()"); + Default::default() + } + + #[ink(message)] + pub fn call(&self, func_id: u32, input: Vec) -> Result, StatusCode> { + ink::env::debug_println!("Proxy::call() func_id={func_id}, input={input:?}"); + ChainExtensionMethod::build(func_id) + .input::>() + .output::, StatusCode>, true>() + .handle_error_code::() + .call(&input) + } + } +} + +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub struct StatusCode(u32); +impl FromStatusCode for StatusCode { + fn from_status_code(status_code: u32) -> Result<(), Self> { + match status_code { + 0 => Ok(()), + _ => Err(StatusCode(status_code)), + } + } +} + +impl From for StatusCode { + fn from(_: ink::scale::Error) -> Self { + StatusCode(u32::MAX) + } +} diff --git a/extension/src/decoding.rs b/extension/src/decoding.rs new file mode 100644 index 00000000..9405aa5b --- /dev/null +++ b/extension/src/decoding.rs @@ -0,0 +1,297 @@ +use super::*; +use sp_runtime::DispatchError; +use sp_std::vec::Vec; + +/// Trait for decoding data read from contract memory. +pub trait Decode { + /// The output type to be decoded. + type Output: codec::Decode; + /// An optional processor, for performing any additional processing on data read from the + /// contract before decoding. + type Processor: Processor>; + /// The error to return if decoding fails. + type Error: Get; + + /// The log target. + const LOG_TARGET: &'static str; + + /// Decodes data read from contract memory. + /// + /// # Parameters + /// - `env` - The current execution environment. + fn decode(env: &mut E) -> Result; +} + +/// Trait for processing a value based on additional information available from the environment. +pub trait Processor { + /// The type of value to be processed. + type Value; + + /// The log target. + const LOG_TARGET: &'static str; + + /// Processes the provided value. + /// + /// # Parameters + /// - `value` - The value to be processed. + /// - `env` - The current execution environment. + fn process(value: Self::Value, env: &impl Environment) -> Self::Value; +} + +/// Default processor implementation which just passes through the value unchanged. +pub struct Identity(PhantomData); +impl Processor for Identity { + type Value = Value; + const LOG_TARGET: &'static str = ""; + + fn process(value: Self::Value, _env: &impl Environment) -> Self::Value { + value + } +} + +/// Default implementation for decoding data read from contract memory. +pub struct Decodes>, L = ()>(PhantomData<(O, W, E, P, L)>); +impl< + Output: codec::Decode, + Weight: WeightInfo, + Error: Get, + ValueProcessor: Processor>, + Logger: LogTarget, + > Decode for Decodes +{ + type Output = Output; + type Processor = ValueProcessor; + type Error = Error; + const LOG_TARGET: &'static str = Logger::LOG_TARGET; + + /// Decodes data read from contract memory. + /// + /// # Parameters + /// - `env` - The current execution environment. + fn decode(env: &mut E) -> Result { + // Charge appropriate weight for copying from contract, based on input length, prior to + // decoding. reference: https://github.com/paritytech/polkadot-sdk/pull/4233/files#:~:text=CopyToContract(len)%20%3D%3E%20T%3A%3AWeightInfo%3A%3Aseal_return(len)%2C + let len = env.in_len(); + let weight = Weight::seal_return(len); + let charged = env.charge_weight(weight)?; + log::debug!(target: Self::LOG_TARGET, "pre-decode weight charged: len={len}, weight={weight}, charged={charged:?}"); + // Read encoded input supplied by contract for buffer. + let mut input = env.read(len)?; + log::debug!(target: Self::LOG_TARGET, "input read: input={input:?}"); + // Perform any additional processing required. Any implementation is expected to charge + // weight as appropriate. + input = Self::Processor::process(input, env); + // Finally decode and return. + Output::decode(&mut &input[..]).map_err(|_| { + log::error!(target: Self::LOG_TARGET, "decoding failed: unable to decode input into output type. input={input:?}"); + Error::get() + }) + } +} + +/// Error to be returned when decoding fails. +pub struct DecodingFailed(PhantomData); +impl Get for DecodingFailed { + fn get() -> DispatchError { + pallet_contracts::Error::::DecodingFailed.into() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + extension::read_from_buffer_weight, + mock::{MockEnvironment, RemoveFirstByte, Test}, + }; + use codec::{Decode as OriginalDecode, Encode}; + use frame_support::assert_ok; + + type EnumDecodes = Decodes, DecodingFailed>; + + #[test] + fn identity_processor_works() { + let env = MockEnvironment::default(); + assert_eq!(Identity::process(42, &env), 42); + assert_eq!(Identity::process(vec![0, 1, 2, 3, 4], &env), vec![0, 1, 2, 3, 4]); + } + + #[test] + fn remove_first_byte_processor_works() { + let env = MockEnvironment::default(); + let result = RemoveFirstByte::process(vec![0, 1, 2, 3, 4], &env); + assert_eq!(result, vec![1, 2, 3, 4]) + } + + #[test] + fn decode_works() { + test_cases().into_iter().for_each(|t| { + let (input, output) = (t.0, t.1); + println!("input: {:?} -> output: {:?}", input, output); + let mut env = MockEnvironment::new(0, input); + // Decode `input` to `output`. + assert_eq!(EnumDecodes::decode(&mut env), Ok(output)); + }); + } + + #[test] + fn decode_charges_weight() { + test_cases().into_iter().for_each(|t| { + let (input, output) = (t.0, t.1); + println!("input: {:?} -> output: {:?}", input, output); + let mut env = MockEnvironment::new(0, input.clone()); + // Decode `input` to `output`. + assert_ok!(EnumDecodes::decode(&mut env)); + // Decode charges weight based on the length of the input. + assert_eq!(env.charged(), read_from_buffer_weight(input.len() as u32)); + }); + } + + #[test] + fn decoding_failed_error_type_works() { + assert_eq!( + DecodingFailed::::get(), + pallet_contracts::Error::::DecodingFailed.into() + ) + } + + #[test] + fn decode_failure_returns_decoding_failed_error() { + let input = vec![100]; + let mut env = MockEnvironment::new(0, input.clone()); + let result = EnumDecodes::decode(&mut env); + assert_eq!(result, Err(pallet_contracts::Error::::DecodingFailed.into())); + } + + #[test] + fn decode_failure_charges_weight() { + let input = vec![100]; + let mut env = MockEnvironment::new(0, input.clone()); + assert!(EnumDecodes::decode(&mut env).is_err()); + // Decode charges weight based on the length of the input, also when decoding fails. + assert_eq!(env.charged(), ContractWeightsOf::::seal_return(input.len() as u32)); + } + + #[derive(Debug, Clone, PartialEq, Encode, OriginalDecode)] + enum ComprehensiveEnum { + SimpleVariant, + DataVariant(u8), + NamedFields { w: u8 }, + NestedEnum(InnerEnum), + OptionVariant(Option), + VecVariant(Vec), + TupleVariant(u8, u8), + NestedStructVariant(NestedStruct), + NestedEnumStructVariant(NestedEnumStruct), + } + + #[derive(Debug, Clone, PartialEq, Encode, OriginalDecode)] + enum InnerEnum { + A, + B { inner_data: u8 }, + C(u8), + } + + #[derive(Debug, Clone, PartialEq, Encode, OriginalDecode)] + struct NestedStruct { + x: u8, + y: u8, + } + + #[derive(Debug, Clone, PartialEq, Encode, OriginalDecode)] + struct NestedEnumStruct { + inner_enum: InnerEnum, + } + + // Creating a set of byte data input and the decoded enum variant. + fn test_cases() -> Vec<(Vec, ComprehensiveEnum)> { + vec![ + (vec![0, 0, 0, 0], ComprehensiveEnum::SimpleVariant), + (vec![1, 42, 0, 0], ComprehensiveEnum::DataVariant(42)), + (vec![2, 42, 0, 0], ComprehensiveEnum::NamedFields { w: 42 }), + (vec![3, 0, 0, 0], ComprehensiveEnum::NestedEnum(InnerEnum::A)), + (vec![3, 1, 42, 0], ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 })), + (vec![3, 2, 42, 0], ComprehensiveEnum::NestedEnum(InnerEnum::C(42))), + (vec![4, 1, 42, 0], ComprehensiveEnum::OptionVariant(Some(42))), + (vec![4, 0, 0, 0], ComprehensiveEnum::OptionVariant(None)), + (vec![5, 12, 1, 2, 3], ComprehensiveEnum::VecVariant(vec![1, 2, 3])), + (vec![5, 16, 1, 2, 3, 4], ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4])), + (vec![5, 20, 1, 2, 3, 4, 5], ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5])), + (vec![6, 42, 43, 0], ComprehensiveEnum::TupleVariant(42, 43)), + ( + vec![7, 42, 43, 0], + ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 43 }), + ), + ( + vec![8, 1, 42, 0], + ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { + inner_enum: InnerEnum::B { inner_data: 42 }, + }), + ), + ] + } + + // Test showing all the different type of variants and its encoding. + #[test] + fn encoding_of_enum() { + // Creating each possible variant for an enum. + let enum_simple = ComprehensiveEnum::SimpleVariant; + let enum_data = ComprehensiveEnum::DataVariant(42); + let enum_named = ComprehensiveEnum::NamedFields { w: 42 }; + let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 }); + let enum_option = ComprehensiveEnum::OptionVariant(Some(42)); + let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]); + let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42); + let enum_nested_struct = + ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 }); + let enum_nested_enum_struct = + ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { + inner_enum: InnerEnum::C(42), + }); + + // Encode and print each variant individually to see their encoded values. + println!("{:?} -> {:?}", enum_simple, enum_simple.encode()); + println!("{:?} -> {:?}", enum_data, enum_data.encode()); + println!("{:?} -> {:?}", enum_named, enum_named.encode()); + println!("{:?} -> {:?}", enum_nested, enum_nested.encode()); + println!("{:?} -> {:?}", enum_option, enum_option.encode()); + println!("{:?} -> {:?}", enum_vec, enum_vec.encode()); + println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode()); + println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode()); + println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); + } + + #[test] + fn encoding_decoding_dispatch_error() { + use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; + + let error = DispatchError::Module(ModuleError { + index: 255, + error: [2, 0, 0, 0], + message: Some("error message"), + }); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + // DispatchError::Module index is 3 + assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); + assert_eq!( + decoded, + // `message` is skipped for encoding. + DispatchError::Module(ModuleError { index: 255, error: [2, 0, 0, 0], message: None }) + ); + + // Example DispatchError::Token + let error = DispatchError::Token(TokenError::UnknownAsset); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![7, 4]); + assert_eq!(decoded, error); + + // Example DispatchError::Arithmetic + let error = DispatchError::Arithmetic(ArithmeticError::Overflow); + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![8, 1]); + assert_eq!(decoded, error); + } +} diff --git a/extension/src/environment.rs b/extension/src/environment.rs new file mode 100644 index 00000000..e5eff083 --- /dev/null +++ b/extension/src/environment.rs @@ -0,0 +1,193 @@ +use crate::AccountIdOf; +use core::fmt::Debug; +use frame_support::pallet_prelude::Weight; +use pallet_contracts::chain_extension::{BufInBufOutState, ChargedAmount, Result, State}; +use sp_std::vec::Vec; + +/// Provides access to the parameters passed to a chain extension and its execution environment. +/// +/// A wrapper trait for `pallet_contracts::chain_extension::Environment`. All comments have been +/// copied solely for consistent developer experience in line with the wrapped type. +pub trait Environment { + /// The account identifier type for the runtime. + type AccountId; + /// The charged weight type. + type ChargedAmount: Debug; + + /// The function id within the `id` passed by a contract. + /// + /// It returns the two least significant bytes of the `id` passed by a contract as the other + /// two bytes represent the chain extension itself (the code which is calling this function). + fn func_id(&self) -> u16; + + /// The chain extension id within the `id` passed by a contract. + /// + /// It returns the two most significant bytes of the `id` passed by a contract which represent + /// the chain extension itself (the code which is calling this function). + fn ext_id(&self) -> u16; + + /// Charge the passed `amount` of weight from the overall limit. + /// + /// It returns `Ok` when there the remaining weight budget is larger than the passed + /// `weight`. It returns `Err` otherwise. In this case the chain extension should + /// abort the execution and pass through the error. + /// + /// The returned value can be used to with [`Self::adjust_weight`]. Other than that + /// it has no purpose. + /// + /// # Note + /// + /// Weight is synonymous with gas in substrate. + fn charge_weight(&mut self, amount: Weight) -> Result; + + /// Adjust a previously charged amount down to its actual amount. + /// + /// This is when a maximum a priori amount was charged and then should be partially + /// refunded to match the actual amount. + fn adjust_weight(&mut self, charged: Self::ChargedAmount, actual_weight: Weight); + + /// Grants access to the execution environment of the current contract call. + /// + /// Consult the functions on the returned type before re-implementing those functions. + // TODO: improve the return type to &mut + fn ext(&mut self) -> impl Ext; +} + +/// A wrapper type for `pallet_contracts::chain_extension::Environment`. +pub(crate) struct Env<'a, 'b, E: pallet_contracts::chain_extension::Ext, S: State>( + pub(crate) pallet_contracts::chain_extension::Environment<'a, 'b, E, S>, +); + +impl<'a, 'b, E: pallet_contracts::chain_extension::Ext, S: State> Environment + for Env<'a, 'b, E, S> +{ + type AccountId = AccountIdOf; + type ChargedAmount = ChargedAmount; + + fn func_id(&self) -> u16 { + self.0.func_id() + } + + fn ext_id(&self) -> u16 { + self.0.ext_id() + } + + fn charge_weight(&mut self, amount: Weight) -> Result { + self.0.charge_weight(amount) + } + + fn adjust_weight(&mut self, charged: Self::ChargedAmount, actual_weight: Weight) { + self.0.adjust_weight(charged, actual_weight) + } + + fn ext(&mut self) -> impl Ext { + ExternalEnvironment(self.0.ext()) + } +} + +/// A state that uses a buffer as input. +/// +/// A wrapper trait for `pallet_contracts::chain_extension::BufIn` related function available on +/// `pallet_contracts::chain_extension::Environment`. All comments have been copied solely for +/// consistent developer experience in line with the wrapped type. +pub trait BufIn { + /// The length of the input as passed in as `input_len`. + /// + /// A chain extension would use this value to calculate the dynamic part of its + /// weight. For example a chain extension that calculates the hash of some passed in + /// bytes would use `in_len` to charge the costs of hashing that amount of bytes. + /// This also subsumes the act of copying those bytes as a benchmarks measures both. + fn in_len(&self) -> u32; + /// Reads `min(max_len, in_len)` from contract memory. + /// + /// This does **not** charge any weight. The caller must make sure that the an + /// appropriate amount of weight is charged **before** reading from contract memory. + /// The reason for that is that usually the costs for reading data and processing + /// said data cannot be separated in a benchmark. Therefore a chain extension would + /// charge the overall costs either using `max_len` (worst case approximation) or using + /// [`in_len()`](Self::in_len). + fn read(&self, max_len: u32) -> Result>; +} + +impl<'a, 'b, E: pallet_contracts::chain_extension::Ext> BufIn for Env<'a, 'b, E, BufInBufOutState> { + fn in_len(&self) -> u32 { + self.0.in_len() + } + + fn read(&self, max_len: u32) -> Result> { + self.0.read(max_len) + } +} + +/// A state that uses a buffer as output. +/// +/// A wrapper trait for `pallet_contracts::chain_extension::BufOut` related function available on +/// `pallet_contracts::chain_extension::Environment`. All comments have been copied solely for +/// consistent developer experience in line with the wrapped type. +pub trait BufOut { + /// Write the supplied buffer to contract memory. + /// + /// If the contract supplied buffer is smaller than the passed `buffer` an `Err` is returned. + /// If `allow_skip` is set to true the contract is allowed to skip the copying of the buffer + /// by supplying the guard value of `pallet-contracts::SENTINEL` as `out_ptr`. The + /// `weight_per_byte` is only charged when the write actually happens and is not skipped or + /// failed due to a too small output buffer. + fn write( + &mut self, + buffer: &[u8], + allow_skip: bool, + weight_per_byte: Option, + ) -> Result<()>; +} + +impl<'a, 'b, E: pallet_contracts::chain_extension::Ext> BufOut + for Env<'a, 'b, E, BufInBufOutState> +{ + fn write( + &mut self, + buffer: &[u8], + allow_skip: bool, + weight_per_byte: Option, + ) -> Result<()> { + self.0.write(buffer, allow_skip, weight_per_byte) + } +} + +/// An interface that provides access to the external environment in which the smart-contract is +/// executed. +/// +/// This interface is specialized to an account of the executing code, so all operations are +/// implicitly performed on that account. +/// +/// A wrapper trait for `pallet_contracts::chain_extension::Ext`. All comments have been copied +/// solely for consistent developer experience in line with the wrapped type. +pub trait Ext { + /// The account identifier type for the runtime. + type AccountId; + + /// Returns a reference to the account id of the current contract. + fn address(&self) -> &Self::AccountId; +} + +impl Ext for () { + type AccountId = (); + + fn address(&self) -> &Self::AccountId { + &() + } +} + +/// A wrapper type for a type implementing `pallet_contracts::chain_extension::Ext`. +pub(crate) struct ExternalEnvironment<'a, T: pallet_contracts::chain_extension::Ext>(&'a mut T); + +impl<'a, E: pallet_contracts::chain_extension::Ext> Ext for ExternalEnvironment<'a, E> { + type AccountId = AccountIdOf; + fn address(&self) -> &Self::AccountId { + self.0.address() + } +} + +#[test] +fn default_ext_works() { + assert_eq!(().address(), &()) +} diff --git a/extension/src/functions.rs b/extension/src/functions.rs new file mode 100644 index 00000000..16ca1f1c --- /dev/null +++ b/extension/src/functions.rs @@ -0,0 +1,534 @@ +use super::*; +use core::fmt::Debug; + +/// A chain extension function. +pub trait Function { + /// The configuration of the contracts module. + type Config: pallet_contracts::Config; + /// Optional error conversion. + type Error: ErrorConverter; + + /// Executes the function. + /// + /// # Parameters + /// - `env` - The current execution environment. + fn execute( + env: &mut (impl Environment> + BufIn + BufOut), + ) -> Result; +} + +/// A function for dispatching a runtime call. +pub struct DispatchCall(PhantomData<(M, C, D, F, E, L)>); +impl< + Matcher: Matches, + Config: pallet_contracts::Config + + frame_system::Config< + RuntimeCall: GetDispatchInfo + Dispatchable, + >, + Decoder: Decode>>, + Filter: Contains> + 'static, + Error: ErrorConverter, + Logger: LogTarget, + > Function for DispatchCall +{ + /// The configuration of the contracts module. + type Config = Config; + /// Optional error conversion. + type Error = Error; + + /// Executes the function. + /// + /// # Parameters + /// - `env` - The current execution environment. + fn execute( + env: &mut (impl Environment + BufIn), + ) -> Result { + // Decode runtime call. + let call = Decoder::decode(env)?.into(); + log::debug!(target: Logger::LOG_TARGET, "decoded: call={call:?}"); + // Charge weight before dispatch. + let dispatch_info = call.get_dispatch_info(); + log::debug!(target: Logger::LOG_TARGET, "pre-dispatch info: dispatch_info={dispatch_info:?}"); + let charged = env.charge_weight(dispatch_info.weight)?; + log::debug!(target: Logger::LOG_TARGET, "pre-dispatch weight charged: charged={charged:?}"); + // Contract is the origin by default. + let origin = RawOrigin::Signed(env.ext().address().clone()); + log::debug!(target: Logger::LOG_TARGET, "contract origin: origin={origin:?}"); + let mut origin: Config::RuntimeOrigin = origin.into(); + // Ensure call allowed. + origin.add_filter(Filter::contains); + // Dispatch call. + let result = call.dispatch(origin); + log::debug!(target: Logger::LOG_TARGET, "dispatched: result={result:?}"); + // Adjust weight. + let weight = frame_support::dispatch::extract_actual_weight(&result, &dispatch_info); + env.adjust_weight(charged, weight); + log::debug!(target: Logger::LOG_TARGET, "weight adjusted: weight={weight:?}"); + match result { + Ok(_) => Ok(Converging(0)), + Err(e) => Error::convert(e.error, env), + } + } +} + +impl Matches for DispatchCall { + fn matches(env: &impl Environment) -> bool { + M::matches(env) + } +} + +/// A function for reading runtime state. +pub struct ReadState::Result>, E = (), L = ()>( + PhantomData<(M, C, R, D, F, RC, E, L)>, +); +impl< + Matcher: Matches, + Config: pallet_contracts::Config, + Read: Readable + Debug, + Decoder: Decode>, + Filter: Contains, + ResultConverter: Converter>>, + Error: ErrorConverter, + Logger: LogTarget, + > Function for ReadState +{ + /// The configuration of the contracts module. + type Config = Config; + /// Optional error conversion. + type Error = Error; + + /// Executes the function. + /// + /// # Parameters + /// - `env` - The current execution environment. + fn execute(env: &mut (impl Environment + BufIn + BufOut)) -> Result { + // Decode runtime state read + let read = Decoder::decode(env)?.into(); + log::debug!(target: Logger::LOG_TARGET, "decoded: read={read:?}"); + // Charge weight before read + let weight = read.weight(); + let charged = env.charge_weight(weight)?; + log::trace!(target: Logger::LOG_TARGET, "pre-read weight charged: weight={weight}, charged={charged:?}"); + // Ensure read allowed + ensure!(Filter::contains(&read), frame_system::Error::::CallFiltered); + let result = read.read(); + log::debug!(target: Logger::LOG_TARGET, "read: result={result:?}"); + // Perform any final conversion. Any implementation is expected to charge weight as + // appropriate. + let result = ResultConverter::convert(result, env).into(); + log::debug!(target: Logger::LOG_TARGET, "converted: result={result:?}"); + // Charge appropriate weight for writing to contract, based on result length. + let weight = ContractWeightsOf::::seal_input(result.len() as u32); + let charged = env.charge_weight(weight)?; + log::trace!(target: Logger::LOG_TARGET, "return result to contract: weight={weight}, charged={charged:?}"); + env.write(&result, false, None)?; // weight charged above + Ok(Converging(0)) + } +} + +impl Matches for ReadState { + fn matches(env: &impl Environment) -> bool { + M::matches(env) + } +} + +/// Trait to be implemented for a type handling a read of runtime state. +pub trait Readable { + /// The corresponding type carrying the result of the runtime state read. + type Result: Debug; + + /// Determines the weight of the read, used to charge the appropriate weight before the read is + /// performed. + fn weight(&self) -> Weight; + + /// Performs the read and returns the result. + fn read(self) -> Self::Result; +} + +/// Trait for converting a value based on additional information available from the environment. +pub trait Converter { + /// The type of value to be converted. + type Source; + /// The target type. + type Target; + /// The log target. + const LOG_TARGET: &'static str; + + /// Converts the provided value. + /// + /// # Parameters + /// - `value` - The value to be converted. + /// - `env` - The current execution environment. + fn convert(value: Self::Source, env: &impl Environment) -> Self::Target; +} + +/// A default converter, for converting (encoding) from some type into a byte array. +pub struct DefaultConverter(PhantomData); +impl>> Converter for DefaultConverter { + type Source = T; + type Target = Vec; + const LOG_TARGET: &'static str = ""; + + fn convert(value: Self::Source, _env: &impl Environment) -> Self::Target { + value.into() + } +} + +/// Trait for error conversion. +pub trait ErrorConverter { + /// The log target. + const LOG_TARGET: &'static str; + + /// Converts the provided error. + /// + /// # Parameters + /// - `error` - The error to be converted. + /// - `env` - The current execution environment. + fn convert(error: DispatchError, env: &impl Environment) -> Result; +} + +impl ErrorConverter for () { + const LOG_TARGET: &'static str = "pop-chain-extension::converters::error"; + + fn convert(error: DispatchError, _env: &impl Environment) -> Result { + Err(error) + } +} + +// Support tuples of at least one function (required for type resolution) and a maximum of ten. +#[impl_trait_for_tuples::impl_for_tuples(1, 10)] +#[tuple_types_custom_trait_bound(Function + Matches)] +impl Function for Tuple { + for_tuples!( where #( Tuple: Function )* ); + type Config = Runtime; + type Error = (); + + fn execute( + env: &mut (impl Environment> + BufIn + BufOut), + ) -> Result { + // Attempts to match a specified extension/function identifier to its corresponding + // function, as configured by the runtime. + for_tuples!( #( + if Tuple::matches(env) { + return Tuple::execute(env) + } + )* ); + + // Otherwise returns error indicating an unmatched request. + log::error!("no function could be matched"); + Err(pallet_contracts::Error::::DecodingFailed.into()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + extension::{read_from_buffer_weight, write_to_contract_weight}, + matching::WithFuncId, + mock::{Noop, NoopFuncId, INVALID_FUNC_ID}, + }; + use codec::Encode; + use frame_support::traits::{Everything, Nothing}; + use frame_system::Call; + use mock::{new_test_ext, Functions, MockEnvironment, RuntimeCall, RuntimeRead, Test}; + use sp_core::ConstU32; + + type FuncId = ConstU32<42>; + + enum AtLeastOneByte {} + impl Contains> for AtLeastOneByte { + fn contains(input: &Vec) -> bool { + input.len() > 0 + } + } + + enum LargerThan100 {} + impl Contains for LargerThan100 { + fn contains(input: &u8) -> bool { + *input > 100 + } + } + + enum MustBeEven {} + impl Contains for MustBeEven { + fn contains(input: &u8) -> bool { + *input % 2 == 0 + } + } + + #[test] + fn contains_works() { + fn contains, T>(input: T, expected: bool) { + assert_eq!(C::contains(&input), expected); + } + contains::(42, true); + contains::>(vec![1, 2, 3, 4], true); + contains::(42, false); + contains::>(vec![1, 2, 3, 4], false); + contains::>(vec![], false); + contains::>(vec![1], true); + contains::>(vec![1, 2, 3, 4], true); + contains::(100, false); + contains::(101, true); + contains::(100, true); + contains::(101, false); + } + + mod dispatch_call { + use super::*; + + type DispatchCall = DispatchCallWithFilter; + type DispatchCallWithFilter = super::DispatchCall< + WithFuncId, + Test, + Decodes, DecodingFailed>, + Filter, + >; + + #[test] + fn dispatch_call_filtering_works() { + let call = + RuntimeCall::System(Call::remark_with_event { remark: "pop".as_bytes().to_vec() }); + let mut env = MockEnvironment::new(FuncId::get(), call.encode()); + let error = frame_system::Error::::CallFiltered.into(); + let expected = <() as ErrorConverter>::convert(error, &mut env).err(); + assert_eq!(DispatchCallWithFilter::::execute(&mut env).err(), expected); + } + + #[test] + fn dispatch_call_filtered_charges_weight() { + let call = + RuntimeCall::System(Call::remark_with_event { remark: "pop".as_bytes().to_vec() }); + let encoded_call = call.encode(); + let mut env = MockEnvironment::new(FuncId::get(), encoded_call.clone()); + assert!(DispatchCallWithFilter::::execute(&mut env).is_err()); + assert_eq!( + env.charged(), + read_from_buffer_weight(encoded_call.len() as u32) + + call.get_dispatch_info().weight + ); + } + + #[test] + fn dispatch_call_works() { + new_test_ext().execute_with(|| { + let call = RuntimeCall::System(Call::remark_with_event { + remark: "pop".as_bytes().to_vec(), + }); + let mut env = MockEnvironment::new(FuncId::get(), call.encode()); + assert!(matches!(DispatchCall::execute(&mut env), Ok(Converging(0)))); + }) + } + + #[test] + fn dispatch_call_returns_error() { + new_test_ext().execute_with(|| { + let call = RuntimeCall::System(Call::set_code { code: "pop".as_bytes().to_vec() }); + let mut env = MockEnvironment::new(FuncId::get(), call.encode()); + let error = DispatchCall::execute(&mut env).err(); + let expected = + <() as ErrorConverter>::convert(DispatchError::BadOrigin, &env).err(); + assert_eq!(error, expected); + }) + } + + #[test] + fn dispatch_call_charges_weight() { + new_test_ext().execute_with(|| { + let call = RuntimeCall::System(Call::remark_with_event { + remark: "pop".as_bytes().to_vec(), + }); + let encoded_call = call.encode(); + let mut env = MockEnvironment::new(FuncId::get(), encoded_call.clone()); + assert!(DispatchCall::execute(&mut env).is_ok()); + assert_eq!( + env.charged(), + read_from_buffer_weight(encoded_call.len() as u32) + + call.get_dispatch_info().weight + ); + }) + } + + #[test] + fn dispatch_call_adjusts_weight() { + new_test_ext().execute_with(|| { + // Attempt to perform non-existent migration with additional weight limit specified. + let weight_limit = Weight::from_parts(123456789, 12345); + let call = RuntimeCall::Contracts(pallet_contracts::Call::migrate { weight_limit }); + let encoded_call = call.encode(); + let mut env = MockEnvironment::new(FuncId::get(), encoded_call.clone()); + let expected: DispatchError = + pallet_contracts::Error::::NoMigrationPerformed.into(); + assert_eq!(DispatchCall::execute(&mut env).err().unwrap(), expected); + assert_eq!( + env.charged(), + read_from_buffer_weight(encoded_call.len() as u32) + + // Weight limit subtracted from pre-dispatch weight charged on failure. + call.get_dispatch_info().weight - + weight_limit + ); + }) + } + + #[test] + fn dispatch_call_with_invalid_input_returns_error() { + // Invalid encoded runtime call. + let input = vec![0, 99]; + let mut env = MockEnvironment::new(FuncId::get(), input.clone()); + let error = pallet_contracts::Error::::DecodingFailed.into(); + let expected = <() as ErrorConverter>::convert(error, &mut env).err(); + assert_eq!(DispatchCall::execute(&mut env).err(), expected); + } + + #[test] + fn dispatch_call_with_invalid_input_charges_weight() { + // Invalid encoded runtime call. + let input = vec![0, 99]; + let mut env = MockEnvironment::new(FuncId::get(), input.clone()); + assert!(DispatchCall::execute(&mut env).is_err()); + assert_eq!(env.charged(), read_from_buffer_weight(input.len() as u32,)); + } + } + + mod read_state { + use super::*; + use crate::mock::{RuntimeResult, UppercaseConverter}; + + type ReadState = ReadStateWithFilter; + type ReadStateWithFilter = super::ReadState< + WithFuncId, + Test, + RuntimeRead, + Decodes, DecodingFailed>, + Filter, + >; + type ReadStateWithResultConverter = super::ReadState< + WithFuncId, + Test, + RuntimeRead, + Decodes, DecodingFailed>, + Everything, + ResultConverter, + >; + + #[test] + fn read_state_filtering_works() { + let read = RuntimeRead::Ping; + let mut env = MockEnvironment::new(FuncId::get(), read.encode()); + let error = frame_system::Error::::CallFiltered.into(); + let expected = <() as ErrorConverter>::convert(error, &mut env).err(); + assert_eq!(ReadStateWithFilter::::execute(&mut env).err(), expected); + } + + #[test] + fn read_state_filtered_charges_weight() { + let read = RuntimeRead::Ping; + let encoded_read = read.encode(); + let mut env = MockEnvironment::new(FuncId::get(), encoded_read.clone()); + assert!(ReadStateWithFilter::::execute(&mut env).is_err()); + assert_eq!( + env.charged(), + read_from_buffer_weight(encoded_read.len() as u32) + read.weight() + ); + } + + #[test] + fn read_state_works() { + let read = RuntimeRead::Ping; + let expected = "pop".as_bytes().encode(); + let mut env = MockEnvironment::new(FuncId::get(), read.encode()); + assert!(matches!(ReadState::execute(&mut env), Ok(Converging(0)))); + // Check if the contract environment buffer is written correctly. + assert_eq!(env.buffer, expected); + } + + #[test] + fn read_state_result_conversion_works() { + let read = RuntimeRead::Ping; + let expected = RuntimeResult::Pong("pop".to_string()); + let mut env = MockEnvironment::new(FuncId::get(), read.encode()); + assert!(matches!( + ReadStateWithResultConverter::::execute(&mut env), + Ok(Converging(0)) + )); + // Check if the contract environment buffer is written correctly. + assert_eq!(env.buffer, UppercaseConverter::convert(expected, &env)); + } + + #[test] + fn read_state_charges_weight() { + let read = RuntimeRead::Ping; + let encoded_read = read.encode(); + let mut env = MockEnvironment::new(FuncId::get(), encoded_read.clone()); + assert!(ReadState::execute(&mut env).is_ok()); + let expected = "pop".as_bytes().encode(); + assert_eq!( + env.charged(), + read_from_buffer_weight(encoded_read.len() as u32) + + read.weight() + write_to_contract_weight(expected.len() as u32) + ); + } + + #[test] + fn read_state_with_invalid_input_returns_error() { + // Invalid encoded runtime state read. + let input = vec![0]; + let mut env = MockEnvironment::new(FuncId::get(), input.clone()); + let error = pallet_contracts::Error::::DecodingFailed.into(); + let expected = <() as ErrorConverter>::convert(error, &mut env).err(); + assert_eq!(ReadState::execute(&mut env).err(), expected); + } + + #[test] + fn read_state_with_invalid_input_charges_weight() { + // Invalid encoded runtime state read. + let input = vec![0]; + let mut env = MockEnvironment::new(FuncId::get(), input.clone()); + assert!(ReadState::execute(&mut env).is_err()); + assert_eq!(env.charged(), read_from_buffer_weight(input.len() as u32)); + } + } + + #[test] + fn execute_tuple_matches_and_executes_function() { + type Functions = (Noop, Test>,); + let mut env = MockEnvironment::new(NoopFuncId::get(), vec![]); + assert!(matches!(Functions::execute(&mut env), Ok(Converging(0)))); + } + + #[test] + fn execute_tuple_with_invalid_function_fails() { + let input = vec![]; + let mut env = MockEnvironment::new(INVALID_FUNC_ID, input.clone()); + let error = pallet_contracts::Error::::DecodingFailed.into(); + let expected = <() as ErrorConverter>::convert(error, &mut env).err(); + assert_eq!(Functions::execute(&mut env).err(), expected); + } + + #[test] + fn execute_tuple_with_invalid_function_does_not_charge_weight() { + let input = vec![]; + let mut env = MockEnvironment::new(INVALID_FUNC_ID, input.clone()); + assert!(Functions::execute(&mut env).is_err()); + // No weight charged as no function in the `Functions` tuple is matched to charge weight. + // See extension tests for extension call weight charges. + assert_eq!(env.charged(), Weight::default()); + } + + #[test] + fn default_error_conversion_works() { + let env = MockEnvironment::default(); + assert!(matches!( + <() as ErrorConverter>::convert(DispatchError::BadOrigin, &env), + Err(DispatchError::BadOrigin) + )); + } + + #[test] + fn default_conversion_works() { + let env = MockEnvironment::default(); + let source = "pop".to_string(); + assert_eq!(DefaultConverter::convert(source.clone(), &env), source.as_bytes()); + } +} diff --git a/extension/src/lib.rs b/extension/src/lib.rs index 650f73f8..875867f8 100644 --- a/extension/src/lib.rs +++ b/extension/src/lib.rs @@ -1,324 +1,228 @@ #![cfg_attr(not(feature = "std"), no_std)] -use codec::Encode; +use core::marker::PhantomData; +pub use decoding::{Decode, Decodes, DecodingFailed, Identity, Processor}; +pub use environment::{BufIn, BufOut, Environment, Ext}; use frame_support::{ - dispatch::{GetDispatchInfo, PostDispatchInfo}, - pallet_prelude::*, - traits::OriginTrait, + dispatch::{GetDispatchInfo, PostDispatchInfo, RawOrigin}, + ensure, + traits::{Contains, OriginTrait}, + weights::Weight, }; -use frame_system::RawOrigin; -use pallet_contracts::chain_extension::{ - BufInBufOutState, ChainExtension, Environment, Ext, InitState, RetVal, +pub use functions::{ + Converter, DefaultConverter, DispatchCall, ErrorConverter, Function, ReadState, Readable, }; -use sp_core::crypto::UncheckedFrom; +pub use matching::{Equals, FunctionId, Matches}; +pub use pallet_contracts::chain_extension::{Result, RetVal, State}; +use pallet_contracts::{ + chain_extension::{ChainExtension, InitState, RetVal::Converging}, + WeightInfo, +}; +use sp_core::Get; use sp_runtime::{traits::Dispatchable, DispatchError}; use sp_std::vec::Vec; +mod decoding; +mod environment; +mod functions; +mod matching; +// Mock runtime/environment for unit/integration testing. +#[cfg(test)] +mod mock; +// Integration tests using proxy contract and mock runtime. #[cfg(test)] mod tests; -mod v0; - -/// Logging target for categorizing messages from the Pop API extension module. -const LOG_TARGET: &str = "pop-api::extension"; - -const DECODING_FAILED_ERROR: DispatchError = DispatchError::Other("DecodingFailed"); -// TODO: issue #93, we can also encode the `pop_primitives::Error::UnknownCall` which means we do use -// `Error` in the runtime and it should stay in primitives. Perhaps issue #91 will also influence -// here. Should be looked at together. -const DECODING_FAILED_ERROR_ENCODED: [u8; 4] = [255u8, 0, 0, 0]; -const UNKNOWN_CALL_ERROR: DispatchError = DispatchError::Other("UnknownCall"); -// TODO: see above. -const UNKNOWN_CALL_ERROR_ENCODED: [u8; 4] = [254u8, 0, 0, 0]; - -type ContractSchedule = ::Schedule; - -/// Type of the state reader. -pub trait ReadState { - /// Query of the state read operations. - type StateQuery: Decode; - - /// Check if a state query is allowed. - fn contains(c: &Self::StateQuery) -> bool; - - /// Reads state using the provided query, returning the result as a byte vector. - fn read(read: Self::StateQuery) -> Vec; - - /// Decodes parameters into state query. - fn decode(params: &mut &[u8]) -> Result { - decode_checked(params) - } -} - -/// Type of the dispatch call filter. -pub trait CallFilter { - /// Query of the dispatch calls operations. - type Call: Decode; - /// Check if runtime call is allowed. - fn contains(t: &Self::Call) -> bool; -} +type AccountIdOf = ::AccountId; +pub type ContractWeightsOf = ::WeightInfo; +type RuntimeCallOf = ::RuntimeCall; -/// Pop API chain extension. +/// A configurable chain extension. #[derive(Default)] -pub struct ApiExtension(PhantomData); - -impl ChainExtension for ApiExtension +pub struct Extension(PhantomData); +impl ChainExtension for Extension where - T: pallet_contracts::Config + Runtime: pallet_contracts::Config + frame_system::Config< RuntimeCall: GetDispatchInfo + Dispatchable, >, - T::AccountId: UncheckedFrom + AsRef<[u8]>, - // Bound the type by the two traits which need to be implemented by the runtime. - I: ReadState + CallFilter::RuntimeCall> + 'static, + Config: self::Config> + 'static, { - fn call>( + /// Call the chain extension logic. + /// + /// # Parameters + /// - `env`: Access to the remaining arguments and the execution environment. + fn call>( &mut self, - env: Environment, - ) -> Result { - log::debug!(target:LOG_TARGET, " extension called "); - let mut env = env.buf_in_buf_out(); - // Charge weight for making a call from a contract to the runtime. - // `debug_message` weight is a good approximation of the additional overhead of going - // from contract layer to substrate layer. - // reference: https://github.com/paritytech/ink-examples/blob/b8d2caa52cf4691e0ddd7c919e4462311deb5ad0/psp22-extension/runtime/psp22-extension-example.rs#L236 - let contract_host_weight = ContractSchedule::::get().host_fn_weights; - env.charge_weight(contract_host_weight.debug_message)?; - - let (version, function_id, pallet_index, call_index) = extract_env(&env); - - let result = match FuncId::try_from(function_id) { - // Read encoded parameters from buffer and calculate weight for reading `len` bytes`. - Ok(function_id) => { - // reference: https://github.com/paritytech/polkadot-sdk/blob/117a9433dac88d5ac00c058c9b39c511d47749d2/substrate/frame/contracts/src/wasm/runtime.rs#L267 - let len = env.in_len(); - env.charge_weight(contract_host_weight.return_per_byte.saturating_mul(len.into()))?; - let params = env.read(len)?; - match function_id { - FuncId::Dispatch => { - dispatch::(&mut env, version, pallet_index, call_index, params) - }, - FuncId::ReadState => { - read_state::(&mut env, version, pallet_index, call_index, params) - }, - } - }, - Err(e) => Err(e), - }; + env: pallet_contracts::chain_extension::Environment, + ) -> Result { + let mut env = environment::Env(env.buf_in_buf_out()); + self.call(&mut env) + } +} - match result { - Ok(_) => Ok(RetVal::Converging(0)), - Err(e) => Ok(RetVal::Converging(convert_to_status_code(e, version))), - } +impl< + Runtime: pallet_contracts::Config, + Config: self::Config>, + > Extension +{ + fn call( + &mut self, + env: &mut (impl Environment + BufIn + BufOut), + ) -> Result { + log::trace!(target: Config::LOG_TARGET, "extension called"); + // Charge weight for making a call from a contract to the runtime. + // `debug_message` weight is a good approximation of the additional overhead of going from + // contract layer to substrate layer. reference: https://github.com/paritytech/polkadot-sdk/pull/4233/files#:~:text=DebugMessage(len)%20%3D%3E%20T%3A%3AWeightInfo%3A%3Aseal_debug_message(len)%2C + let len = env.in_len(); + let overhead = ContractWeightsOf::::seal_debug_message(len); + let charged = env.charge_weight(overhead)?; + log::debug!(target: Config::LOG_TARGET, "extension call weight charged: len={len}, weight={overhead}, charged={charged:?}"); + // Execute the function + Config::Functions::execute(env) } } -/// Extract discriminators (version, function_id, pallet_index, call_index) from the encoded call. -fn extract_env>(env: &Environment) -> (u8, u8, u8, u8) { - // Extract version and function_id from first two bytes. - let (version, function_id) = { - let bytes = env.func_id().to_le_bytes(); - (bytes[0], bytes[1]) - }; - // Extract pallet index and call / key index from last two bytes. - let (pallet_index, call_index) = { - let bytes = env.ext_id().to_le_bytes(); - (bytes[0], bytes[1]) - }; +/// Trait for configuration of the chain extension. +pub trait Config { + /// The function(s) available with the chain extension. + type Functions: Function; - (version, function_id, pallet_index, call_index) + /// The log target. + const LOG_TARGET: &'static str; } -fn read_state, StateReader: ReadState>( - env: &mut Environment, - version: u8, - pallet_index: u8, - call_index: u8, - mut params: Vec, -) -> Result<(), DispatchError> { - // Prefix params with version, pallet, index to simplify decoding. - params.insert(0, version); - params.insert(1, pallet_index); - params.insert(2, call_index); - let (mut encoded_version, mut encoded_read) = (¶ms[..1], ¶ms[1..]); - let version = decode_checked::(&mut encoded_version)?; - - // Charge weight for doing one storage read. - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - let result = match version { - VersionedStateRead::V0 => { - let read = StateReader::decode(&mut encoded_read)?; - ensure!(StateReader::contains(&read), UNKNOWN_CALL_ERROR); - StateReader::read(read) - }, - }; - log::trace!( - target:LOG_TARGET, - "{} result: {:?}.", " read_state |", result - ); - env.write(&result, false, None) +/// Trait to enable specification of a log target. +pub trait LogTarget { + /// The log target. + const LOG_TARGET: &'static str; } -fn dispatch( - env: &mut Environment, - version: u8, - pallet_index: u8, - call_index: u8, - mut params: Vec, -) -> Result<(), DispatchError> -where - T: frame_system::Config< - RuntimeCall: GetDispatchInfo + Dispatchable, - >, - E: Ext, - Filter: CallFilter::RuntimeCall> + 'static, -{ - // Prefix params with version, pallet, index to simplify decoding. - params.insert(0, version); - params.insert(1, pallet_index); - params.insert(2, call_index); - let call = decode_checked::>(&mut ¶ms[..])?; - // Contract is the origin by default. - let origin: T::RuntimeOrigin = RawOrigin::Signed(env.ext().address().clone()).into(); - match call { - VersionedDispatch::V0(call) => dispatch_call::(env, call, origin), - } +impl LogTarget for () { + const LOG_TARGET: &'static str = "pop-chain-extension"; } -/// Helper method to decode the byte data to a provided type and throws error if failed. -fn decode_checked(params: &mut &[u8]) -> Result { - T::decode(params).map_err(|_| DECODING_FAILED_ERROR) +#[test] +fn default_log_target_works() { + assert!(matches!(<() as LogTarget>::LOG_TARGET, "pop-chain-extension")); } -fn dispatch_call( - env: &mut Environment, - call: T::RuntimeCall, - mut origin: T::RuntimeOrigin, -) -> Result<(), DispatchError> -where - T: frame_system::Config< - RuntimeCall: GetDispatchInfo + Dispatchable, - >, - E: Ext, - Filter: CallFilter::RuntimeCall> + 'static, -{ - const LOG_PREFIX: &str = " dispatch |"; +#[cfg(test)] +mod extension { + use super::*; + use crate::mock::{ + new_test_ext, DispatchExtFuncId, MockEnvironment, NoopFuncId, ReadExtFuncId, RuntimeCall, + RuntimeRead, Test, INVALID_FUNC_ID, + }; + use codec::Encode; + use frame_system::Call; + + #[test] + fn call_works() { + let input = vec![2, 2]; + let mut env = MockEnvironment::new(NoopFuncId::get(), input.clone()); + let mut extension = Extension::::default(); + assert!(matches!(extension.call(&mut env), Ok(Converging(0)))); + // Charges weight. + assert_eq!(env.charged(), overhead_weight(input.len() as u32)) + } - let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; - log::debug!(target:LOG_TARGET, "{} Inputted RuntimeCall: {:?}", LOG_PREFIX, call); - origin.add_filter(Filter::contains); - match call.dispatch(origin) { - Ok(info) => { - log::debug!(target:LOG_TARGET, "{} success, actual weight: {:?}", LOG_PREFIX, info.actual_weight); - // Refund weight if the actual weight is less than the charged weight. - if let Some(actual_weight) = info.actual_weight { - env.adjust_weight(charged_dispatch_weight, actual_weight); - } - Ok(()) - }, - Err(err) => { - log::debug!(target:LOG_TARGET, "{} failed: error: {:?}", LOG_PREFIX, err.error); - // Refund weight if the actual weight is less than the charged weight. - if let Some(actual_weight) = err.post_info.actual_weight { - env.adjust_weight(charged_dispatch_weight, actual_weight); - } - Err(err.error) - }, + #[test] + fn calling_unknown_function_fails() { + let input = vec![2, 2]; + // No function registered for id 0. + let mut env = MockEnvironment::new(INVALID_FUNC_ID, input.clone()); + let mut extension = Extension::::default(); + assert!(matches!( + extension.call(&mut env), + Err(error) if error == pallet_contracts::Error::::DecodingFailed.into() + )); + // Charges weight. + assert_eq!(env.charged(), overhead_weight(input.len() as u32)) } -} -/// Wrapper to enable versioning of runtime state reads. -#[derive(Decode, Debug)] -enum VersionedStateRead { - /// Version zero of state reads. - #[codec(index = 0)] - V0, -} + #[test] + fn dispatch_call_works() { + new_test_ext().execute_with(|| { + let call = + RuntimeCall::System(Call::remark_with_event { remark: "pop".as_bytes().to_vec() }); + let encoded_call = call.encode(); + let mut env = MockEnvironment::new(DispatchExtFuncId::get(), encoded_call.clone()); + let mut extension = Extension::::default(); + assert!(matches!(extension.call(&mut env), Ok(Converging(0)))); + // Charges weight. + assert_eq!( + env.charged(), + overhead_weight(encoded_call.len() as u32) + + read_from_buffer_weight(encoded_call.len() as u32) + + call.get_dispatch_info().weight + ); + }); + } -/// Wrapper to enable versioning of runtime calls. -#[derive(Decode, Debug)] -enum VersionedDispatch { - /// Version zero of dispatch calls. - #[codec(index = 0)] - V0(RuntimeCall), -} + #[test] + fn dispatch_call_with_invalid_input_returns_error() { + // Invalid encoded runtime call. + let input = vec![0u8, 99]; + let mut env = MockEnvironment::new(DispatchExtFuncId::get(), input.clone()); + let mut extension = Extension::::default(); + assert!(extension.call(&mut env).is_err()); + // Charges weight. + assert_eq!( + env.charged(), + overhead_weight(input.len() as u32) + read_from_buffer_weight(input.len() as u32) + ); + } -/// Function identifiers used in the Pop API. -/// -/// The `FuncId` specifies the available functions that can be called through the Pop API. Each -/// variant corresponds to a specific functionality provided by the API, facilitating the -/// interaction between smart contracts and the runtime. -#[derive(Debug)] -pub enum FuncId { - /// Represents a function call to dispatch a runtime call. - Dispatch, - /// Represents a function call to read the state from the runtime. - ReadState, -} + #[test] + fn read_state_works() { + let read = RuntimeRead::Ping; + let encoded_read = read.encode(); + let expected = "pop".as_bytes().encode(); + let mut env = MockEnvironment::new(ReadExtFuncId::get(), encoded_read.clone()); + let mut extension = Extension::::default(); + assert!(matches!(extension.call(&mut env), Ok(Converging(0)))); + // Charges weight. + assert_eq!( + env.charged(), + overhead_weight(encoded_read.len() as u32) + + read_from_buffer_weight(encoded_read.len() as u32) + + read.weight() + + write_to_contract_weight(expected.len() as u32) + ); + // Check if the contract environment buffer is written correctly. + assert_eq!(env.buffer, expected); + } -impl TryFrom for FuncId { - type Error = DispatchError; + #[test] + fn read_state_with_invalid_input_returns_error() { + let input = vec![0u8, 99]; + let mut env = MockEnvironment::new( + ReadExtFuncId::get(), + // Invalid runtime state read. + input.clone(), + ); + let mut extension = Extension::::default(); + assert!(extension.call(&mut env).is_err()); + // Charges weight. + assert_eq!( + env.charged(), + overhead_weight(input.len() as u32) + read_from_buffer_weight(input.len() as u32) + ); + } - /// Attempts to convert a `u8` value to its corresponding `FuncId` variant. - /// - /// If the `u8` value does not match any known function identifier, it returns a - /// `DispatchError::Other` indicating an unknown function ID. - fn try_from(func_id: u8) -> Result { - let id = match func_id { - 0 => Self::Dispatch, - 1 => Self::ReadState, - _ => { - return Err(UNKNOWN_CALL_ERROR); - }, - }; - Ok(id) + // Weight charged for calling into the runtime from a contract. + fn overhead_weight(input_len: u32) -> Weight { + ContractWeightsOf::::seal_debug_message(input_len) } -} -/// Converts a `DispatchError` to a `u32` status code based on the version of the API the contract uses. -/// The contract calling the chain extension can optionally convert the status code to the descriptive `Error`. -/// -/// For `Error` see `pop_primitives::::error::Error`. -/// -/// The error encoding can vary per version, allowing for flexible and backward-compatible error handling. -/// As a result, contracts maintain compatibility across different versions of the runtime. -/// -/// # Parameters -/// -/// - `error`: The `DispatchError` encountered during contract execution. -/// - `version`: The version of the chain extension, used to determine the known errors. -pub(crate) fn convert_to_status_code(error: DispatchError, version: u8) -> u32 { - let mut encoded_error: [u8; 4] = match error { - // "UnknownCall" and "DecodingFailed" are mapped to specific errors in the API and will - // never change. - UNKNOWN_CALL_ERROR => UNKNOWN_CALL_ERROR_ENCODED, - DECODING_FAILED_ERROR => DECODING_FAILED_ERROR_ENCODED, - _ => { - let mut encoded_error = error.encode(); - // Resize the encoded value to 4 bytes in order to decode the value in a u32 (4 bytes). - encoded_error.resize(4, 0); - encoded_error.try_into().expect("qed, resized to 4 bytes line above") - }, - }; - match version { - // If an unknown variant of the `DispatchError` is detected the error needs to be converted - // into the encoded value of `Error::Other`. This conversion is performed by shifting the bytes one - // position forward (discarding the last byte as it is not used) and setting the first byte to the - // encoded value of `Other` (0u8). This ensures the error is correctly categorized as an `Other` - // variant which provides all the necessary information to debug which error occurred in the runtime. - // - // Byte layout explanation: - // - Byte 0: index of the variant within `Error` - // - Byte 1: - // - Must be zero for `UNIT_ERRORS`. - // - Represents the nested error in `SINGLE_NESTED_ERRORS`. - // - Represents the first level of nesting in `DOUBLE_NESTED_ERRORS`. - // - Byte 2: - // - Represents the second level of nesting in `DOUBLE_NESTED_ERRORS`. - // - Byte 3: - // - Unused or represents further nested information. - 0 => v0::handle_unknown_error(&mut encoded_error), - _ => encoded_error = UNKNOWN_CALL_ERROR_ENCODED, + // Weight charged for reading function call input from buffer. + pub(crate) fn read_from_buffer_weight(input_len: u32) -> Weight { + ContractWeightsOf::::seal_return(input_len) + } + + // Weight charged for writing to contract memory. + pub(crate) fn write_to_contract_weight(len: u32) -> Weight { + ContractWeightsOf::::seal_input(len) } - u32::from_le_bytes(encoded_error) } diff --git a/extension/src/matching.rs b/extension/src/matching.rs new file mode 100644 index 00000000..5966b9ff --- /dev/null +++ b/extension/src/matching.rs @@ -0,0 +1,84 @@ +use super::*; + +/// Trait for matching a function. +pub trait Matches { + /// Determines whether a function is a match. + /// + /// # Parameters + /// - `env` - The current execution environment. + fn matches(env: &impl Environment) -> bool; +} + +/// Matches an extension and function identifier. +pub struct Equals(PhantomData<(E, F)>); +impl, FuncId: Get> Matches for Equals { + fn matches(env: &impl Environment) -> bool { + env.ext_id() == ExtId::get() && env.func_id() == FuncId::get() + } +} + +/// Matches a function identifier only. +pub struct FunctionId(PhantomData); +impl> Matches for FunctionId { + fn matches(env: &impl Environment) -> bool { + env.func_id() == T::get() + } +} + +/// Matches a `u32` function identifier. +pub struct WithFuncId(PhantomData); +impl> Matches for WithFuncId { + fn matches(env: &impl Environment) -> bool { + let ext_id: [u8; 2] = env.ext_id().to_le_bytes(); + let func_id: [u8; 2] = env.func_id().to_le_bytes(); + u32::from_le_bytes([func_id[0], func_id[1], ext_id[0], ext_id[1]]) == T::get() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::MockEnvironment; + use sp_core::{ConstU16, ConstU32}; + + #[test] + fn equals_matches() { + let env = MockEnvironment::new(u32::from_be_bytes([0u8, 1, 0, 2]), vec![]); + assert!(Equals::, ConstU16<2>>::matches(&env)); + } + + #[test] + fn equals_does_not_match() { + // Fails due to the invalid function id. + let env = MockEnvironment::new(u32::from_be_bytes([0u8, 1, 0, 3]), vec![]); + assert!(!Equals::, ConstU16<2>>::matches(&env)); + + // Fails due to the invalid extension id. + let env = MockEnvironment::new(u32::from_be_bytes([0u8, 2, 0, 2]), vec![]); + assert!(!Equals::, ConstU16<2>>::matches(&env)); + } + + #[test] + fn function_id_matches() { + let env = MockEnvironment::new(u32::from_be_bytes([0u8, 1, 0, 2]), vec![]); + assert!(FunctionId::>::matches(&env)); + } + + #[test] + fn function_id_does_not_match() { + let env = MockEnvironment::new(u32::from_be_bytes([0u8, 1, 0, 3]), vec![]); + assert!(!FunctionId::>::matches(&env)); + } + + #[test] + fn func_id_matches() { + let env = MockEnvironment::default(); + assert!(WithFuncId::>::matches(&env)); + } + + #[test] + fn func_id_does_not_match() { + let env = MockEnvironment::new(1, vec![]); + assert!(!WithFuncId::>::matches(&env)); + } +} diff --git a/extension/src/mock.rs b/extension/src/mock.rs new file mode 100644 index 00000000..688bad51 --- /dev/null +++ b/extension/src/mock.rs @@ -0,0 +1,373 @@ +use crate::{ + decoding::Identity, environment, matching::WithFuncId, AccountIdOf, ContractWeightsOf, + Converter, Decodes, DecodingFailed, DefaultConverter, DispatchCall, Extension, Function, + Matches, Processor, ReadState, Readable, +}; +use codec::{Decode, Encode}; +use frame_support::{ + derive_impl, + pallet_prelude::Weight, + parameter_types, + traits::{fungible::Inspect, ConstU32, Everything, Nothing}, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use pallet_contracts::{chain_extension::RetVal, DefaultAddressGenerator, Frame, Schedule}; +use sp_runtime::{BuildStorage, Perbill}; +use std::marker::PhantomData; + +pub(crate) const ALICE: u64 = 1; +pub(crate) const DEBUG_OUTPUT: pallet_contracts::DebugInfo = + pallet_contracts::DebugInfo::UnsafeDebug; +pub(crate) const GAS_LIMIT: Weight = Weight::from_parts(500_000_000_000, 3 * 1024 * 1024); +pub(crate) const INIT_AMOUNT: ::Balance = 100_000_000; +pub(crate) const INVALID_FUNC_ID: u32 = 0; + +pub(crate) type AccountId = AccountIdOf; +pub(crate) type Balance = + <::Currency as Inspect>>::Balance; +type DispatchCallWith>> = DispatchCall< + // Registered with func id 1 + WithFuncId, + // Runtime config + Test, + // Decode inputs to the function as runtime calls + Decodes, DecodingFailed, Processor>, + // Accept any filtering + Filter, +>; +pub(crate) type EventRecord = + frame_system::EventRecord<::RuntimeEvent, HashOf>; +type HashOf = ::Hash; +pub(crate) type MockEnvironment = Environment; +type ReadStateWith>> = ReadState< + // Registered with func id 1 + WithFuncId, + // Runtime config + Test, + // The runtime state reads available. + RuntimeRead, + // Decode inputs to the function as runtime calls + Decodes, DecodingFailed, Processor>, + // Accept any filtering + Filter, + // Convert the result of a read into the expected result + DefaultConverter, +>; + +frame_support::construct_runtime!( + pub enum Test { + System: frame_system, + Balances: pallet_balances, + Timestamp: pallet_timestamp, + Contracts: pallet_contracts, + } +); + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Test { + type AccountId = u64; + type AccountData = pallet_balances::AccountData; + type Block = frame_system::mocking::MockBlock; +} + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +impl pallet_balances::Config for Test { + type AccountStore = System; + type ReserveIdentifier = [u8; 8]; +} + +#[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig as pallet_timestamp::DefaultConfig)] +impl pallet_timestamp::Config for Test {} + +impl pallet_contracts::Config for Test { + type Time = Timestamp; + type Randomness = Test; + type Currency = Balances; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type CallFilter = (); //TestFilter; + type CallStack = [Frame; 5]; + type WeightPrice = (); //Self; + type WeightInfo = (); + type ChainExtension = Extension; + type Schedule = MySchedule; + type DepositPerByte = DepositPerByte; + type DepositPerItem = DepositPerItem; + type DefaultDepositLimit = DefaultDepositLimit; + type AddressGenerator = DefaultAddressGenerator; + type MaxCodeLen = ConstU32<{ 100 * 1024 }>; + type MaxStorageKeyLen = ConstU32<128>; + type UnsafeUnstableInterface = (); //UnstableInterface; + type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; + type RuntimeHoldReason = RuntimeHoldReason; + type Migrations = (); //crate::migration::codegen::BenchMigrations; + type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; + type MaxDelegateDependencies = MaxDelegateDependencies; + type Debug = (); //TestDebug; + type Environment = (); + type Xcm = (); +} + +parameter_types! { + pub MySchedule: Schedule = { + let schedule = >::default(); + schedule + }; + pub static DepositPerByte: ::Balance = 1; + pub const DepositPerItem: ::Balance = 2; + pub static MaxDelegateDependencies: u32 = 32; + pub static MaxTransientStorageSize: u32 = 4 * 1024; + pub static CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); + pub static DefaultDepositLimit: ::Balance = 10_000_000; +} + +impl frame_support::traits::Randomness, BlockNumberFor> for Test { + fn random(_subject: &[u8]) -> (HashOf, BlockNumberFor) { + (Default::default(), Default::default()) + } +} + +parameter_types! { + // IDs for functions for extension tests. + pub const DispatchExtFuncId : u32 = 1; + pub const ReadExtFuncId : u32 = 2; + // IDs for functions for contract tests. + pub const DispatchContractFuncId : u32 = 3; + pub const ReadContractFuncId : u32 = 4; + // IDs for function for contract tests but do nothing. + pub const DispatchContractNoopFuncId : u32 = 5; + pub const ReadContractNoopFuncId : u32 = 6; + // ID for function that does nothing + pub const NoopFuncId : u32 = u32::MAX; +} + +/// A query of mock runtime state. +#[derive(Encode, Decode, Debug)] +#[repr(u8)] +pub enum RuntimeRead { + #[codec(index = 1)] + Ping, +} +impl Readable for RuntimeRead { + /// The corresponding type carrying the result of the query for mock runtime state. + type Result = RuntimeResult; + + /// Determines the weight of the read, used to charge the appropriate weight before the read is + /// performed. + fn weight(&self) -> Weight { + match self { + RuntimeRead::Ping => Weight::from_parts(1_000u64, 1u64), + } + } + + /// Performs the read and returns the result. + fn read(self) -> Self::Result { + match self { + RuntimeRead::Ping => RuntimeResult::Pong("pop".to_string()), + } + } +} + +/// The result of a mock runtime state read. +#[derive(Debug, Decode, Encode)] +pub enum RuntimeResult { + #[codec(index = 1)] + Pong(String), +} + +impl Into> for RuntimeResult { + fn into(self) -> Vec { + match self { + RuntimeResult::Pong(value) => value.encode(), + } + } +} + +pub(crate) type Functions = ( + // Functions that allow everything for extension testing. + DispatchCallWith, + ReadStateWith, + // Functions that allow everything for contract testing. + DispatchCallWith, + ReadStateWith, + // Functions that allow nothing for contract testing. + DispatchCallWith, + ReadStateWith, + // Function that does nothing. + Noop, Test>, +); + +#[derive(Default)] +pub struct Config; +impl super::Config for Config { + type Functions = Functions; + const LOG_TARGET: &'static str = "pop-chain-extension"; +} + +// Removes first bytes of the encoded call, added by the chain extension call within the proxy +// contract. +pub struct RemoveFirstByte; +impl Processor for RemoveFirstByte { + type Value = Vec; + const LOG_TARGET: &'static str = ""; + + fn process(mut value: Self::Value, _env: &impl crate::Environment) -> Self::Value { + if !value.is_empty() { + value.remove(0); + } + value + } +} + +// A function that does nothing. +pub struct Noop(PhantomData<(M, C)>); +impl Function for Noop { + type Config = Config; + type Error = (); + + fn execute( + _env: &mut (impl environment::Environment + crate::BufIn), + ) -> pallet_contracts::chain_extension::Result { + Ok(RetVal::Converging(0)) + } +} +impl Matches for Noop { + fn matches(env: &impl crate::Environment) -> bool { + M::matches(env) + } +} + +/// A mocked chain extension environment. +pub(crate) struct Environment { + func_id: u16, + ext_id: u16, + charged: Vec, + pub(crate) buffer: Vec, + ext: E, +} + +impl Default for Environment { + fn default() -> Self { + Self::new(0, [].to_vec()) + } +} + +impl Environment { + pub(crate) fn new(id: u32, buffer: Vec) -> Self { + Self { + func_id: (id & 0x0000FFFF) as u16, + ext_id: (id >> 16) as u16, + charged: Vec::new(), + buffer, + ext: E::default(), + } + } + + pub(crate) fn charged(&self) -> Weight { + self.charged.iter().fold(Weight::zero(), |acc, b| acc.saturating_add(*b)) + } +} + +impl> + Clone> environment::Environment + for Environment +{ + type AccountId = E::AccountId; + type ChargedAmount = Weight; + + fn func_id(&self) -> u16 { + self.func_id + } + + fn ext_id(&self) -> u16 { + self.ext_id + } + + fn charge_weight( + &mut self, + amount: Weight, + ) -> pallet_contracts::chain_extension::Result { + self.charged.push(amount); + Ok(amount) + } + + fn adjust_weight(&mut self, charged: Self::ChargedAmount, actual_weight: Weight) { + let last = self + .charged + .iter() + .enumerate() + .filter_map(|(i, c)| (c == &charged).then_some(i)) + .last() + .unwrap(); + self.charged.remove(last); + self.charged.insert(last, actual_weight) + } + + fn ext(&mut self) -> impl environment::Ext { + self.ext.clone() + } +} + +impl environment::BufIn for Environment { + fn in_len(&self) -> u32 { + self.buffer.len() as u32 + } + + fn read(&self, _max_len: u32) -> pallet_contracts::chain_extension::Result> { + // TODO: handle max_len + Ok(self.buffer.clone()) + } +} + +impl environment::BufOut for Environment { + fn write( + &mut self, + buffer: &[u8], + _allow_skip: bool, + _weight_per_byte: Option, + ) -> pallet_contracts::chain_extension::Result<()> { + self.buffer = buffer.to_vec(); + Ok(()) + } +} + +/// A mocked smart contract environment. +#[derive(Clone, Default)] +pub(crate) struct MockExt { + pub(crate) address: AccountIdOf, +} +impl environment::Ext for MockExt { + type AccountId = AccountIdOf; + + fn address(&self) -> &Self::AccountId { + &self.address + } +} + +/// Test externalities. +pub(crate) fn new_test_ext() -> sp_io::TestExternalities { + let _ = env_logger::try_init(); + + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { balances: vec![(ALICE, INIT_AMOUNT)] } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +/// A converter for converting string results to uppercase. +pub(crate) struct UppercaseConverter; +impl Converter for UppercaseConverter { + type Source = RuntimeResult; + type Target = Vec; + const LOG_TARGET: &'static str = ""; + + fn convert(value: Self::Source, _env: &impl crate::Environment) -> Self::Target { + match value { + RuntimeResult::Pong(value) => value.to_uppercase().encode(), + } + } +} diff --git a/extension/src/tests.rs b/extension/src/tests.rs index a47feef9..8d527df6 100644 --- a/extension/src/tests.rs +++ b/extension/src/tests.rs @@ -1,135 +1,230 @@ -use codec::{Decode, Encode}; - -// Test ensuring `func_id()` and `ext_id()` work as expected, i.e. extracting the first two -// bytes and the last two bytes, respectively, from a 4 byte array. -#[test] -fn test_byte_extraction() { - use rand::Rng; +use core::fmt::Debug; +use std::{path::Path, sync::LazyLock}; - // Helper functions - fn func_id(id: u32) -> u16 { - (id & 0x0000FFFF) as u16 - } - fn ext_id(id: u32) -> u16 { - (id >> 16) as u16 +use crate::{ + mock::{self, *}, + ErrorConverter, +}; +use codec::{Decode, Encode}; +use frame_support::weights::Weight; +use frame_system::Call; +use pallet_contracts::{Code, CollectEvents, ContractExecResult, Determinism, StorageDeposit}; +use sp_runtime::{ + DispatchError::{self, BadOrigin, Module}, + ModuleError, +}; + +static CONTRACT: LazyLock> = + LazyLock::new(|| initialize_contract("contract/target/ink/proxy.wasm")); + +mod dispatch_call { + use super::*; + + #[test] + fn dispatch_call_works() { + new_test_ext().execute_with(|| { + // Instantiate a new contract. + let contract = instantiate(); + let dispatch_result = call( + contract, + DispatchContractFuncId::get(), + RuntimeCall::System(Call::remark_with_event { remark: "pop".as_bytes().to_vec() }), + GAS_LIMIT, + ); + // Successfully return data. + let return_value = dispatch_result.result.unwrap(); + let decoded = , u32>>::decode(&mut &return_value.data[..]).unwrap(); + assert!(decoded.unwrap().is_empty()); + // Successfully emit event. + assert!(dispatch_result.events.unwrap().iter().any(|e| matches!(e.event, + RuntimeEvent::System(frame_system::Event::::Remarked { sender, .. }) + if sender == contract))); + assert_eq!(dispatch_result.storage_deposit, StorageDeposit::Charge(0)); + }); } - // Number of test iterations - let test_iterations = 1_000_000; - - // Create a random number generator - let mut rng = rand::thread_rng(); - - // Run the test for a large number of random 4-byte arrays - for _ in 0..test_iterations { - // Generate a random 4-byte array - let bytes: [u8; 4] = rng.gen(); - - // Convert the 4-byte array to a u32 value - let value = u32::from_le_bytes(bytes); - - // Extract the first two bytes (least significant 2 bytes) - let first_two_bytes = func_id(value); - - // Extract the last two bytes (most significant 2 bytes) - let last_two_bytes = ext_id(value); - - // Check if the first two bytes match the expected value - assert_eq!([bytes[0], bytes[1]], first_two_bytes.to_le_bytes()); + #[test] + fn dispatch_call_filtering_works() { + new_test_ext().execute_with(|| { + // Instantiate a new contract. + let contract = instantiate(); + let dispatch_result = call( + contract, + DispatchContractNoopFuncId::get(), + RuntimeCall::System(Call::remark_with_event { remark: "pop".as_bytes().to_vec() }), + GAS_LIMIT, + ); + assert_eq!( + dispatch_result.result, + Err(Module(ModuleError { + index: 0, + error: [5, 0, 0, 0], + message: Some("CallFiltered") + })) + ); + }); + } - // Check if the last two bytes match the expected value - assert_eq!([bytes[2], bytes[3]], last_two_bytes.to_le_bytes()); + #[test] + fn dispatch_call_returns_error() { + new_test_ext().execute_with(|| { + // Instantiate a new contract. + let contract = instantiate(); + let dispatch_result = call( + contract, + DispatchContractFuncId::get(), + // `set_code` requires root origin, expect throwing error. + RuntimeCall::System(Call::set_code { code: "pop".as_bytes().to_vec() }), + GAS_LIMIT, + ); + assert_eq!(dispatch_result.result.err(), Some(BadOrigin)) + }) } } -// Test showing all the different type of variants and its encoding. -#[test] -fn encoding_of_enum() { - #[derive(Debug, PartialEq, Encode, Decode)] - enum ComprehensiveEnum { - SimpleVariant, - DataVariant(u8), - NamedFields { w: u8 }, - NestedEnum(InnerEnum), - OptionVariant(Option), - VecVariant(Vec), - TupleVariant(u8, u8), - NestedStructVariant(NestedStruct), - NestedEnumStructVariant(NestedEnumStruct), +mod read_state { + use super::*; + + #[test] + fn read_state_works() { + new_test_ext().execute_with(|| { + // Instantiate a new contract. + let contract = instantiate(); + // Successfully return data. + let read_result = + call(contract, ReadContractFuncId::get(), RuntimeRead::Ping, GAS_LIMIT); + let return_value = read_result.result.unwrap(); + let decoded = , u32>>::decode(&mut &return_value.data[1..]).unwrap(); + let result = Ok("pop".as_bytes().to_vec()); + assert_eq!(decoded, result); + }); } - #[derive(Debug, PartialEq, Encode, Decode)] - enum InnerEnum { - A, - B { inner_data: u8 }, - C(u8), + #[test] + fn read_state_filtering_works() { + new_test_ext().execute_with(|| { + // Instantiate a new contract. + let contract = instantiate(); + // Successfully return data. + let read_result = + call(contract, ReadContractNoopFuncId::get(), RuntimeRead::Ping, GAS_LIMIT); + assert_eq!( + read_result.result, + Err(Module(ModuleError { + index: 0, + error: [5, 0, 0, 0], + message: Some("CallFiltered") + })) + ); + }); } - #[derive(Debug, PartialEq, Encode, Decode)] - struct NestedStruct { - x: u8, - y: u8, + #[test] + fn read_state_with_invalid_input_returns_error() { + new_test_ext().execute_with(|| { + // Instantiate a new contract. + let contract = instantiate(); + let read_result = call(contract, ReadExtFuncId::get(), 99u8, GAS_LIMIT); + let expected: DispatchError = pallet_contracts::Error::::DecodingFailed.into(); + // Make sure the error is passed through the error converter. + let error = + <() as ErrorConverter>::convert(expected, &mock::MockEnvironment::default()).err(); + assert_eq!(read_result.result.err(), error); + }) } +} - #[derive(Debug, PartialEq, Encode, Decode)] - struct NestedEnumStruct { - inner_enum: InnerEnum, - } +#[test] +fn noop_function_works() { + new_test_ext().execute_with(|| { + // Instantiate a new contract. + let contract = instantiate(); + let noop_result = call(contract, NoopFuncId::get(), (), GAS_LIMIT); + // Successfully return data. + let return_value = noop_result.result.unwrap(); + let decoded = , u32>>::decode(&mut &return_value.data[..]).unwrap(); + assert!(decoded.unwrap().is_empty()); + assert_eq!(noop_result.storage_deposit, StorageDeposit::Charge(0)); + }) +} - // Creating each possible variant for an enum. - let enum_simple = ComprehensiveEnum::SimpleVariant; - let enum_data = ComprehensiveEnum::DataVariant(42); - let enum_named = ComprehensiveEnum::NamedFields { w: 42 }; - let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 }); - let enum_option = ComprehensiveEnum::OptionVariant(Some(42)); - let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]); - let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42); - let enum_nested_struct = ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 }); - let enum_nested_enum_struct = ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct { - inner_enum: InnerEnum::C(42), +#[test] +fn invalid_func_id_fails() { + new_test_ext().execute_with(|| { + // Instantiate a new contract. + let contract = instantiate(); + let result = call(contract, INVALID_FUNC_ID, (), GAS_LIMIT); + let expected: DispatchError = pallet_contracts::Error::::DecodingFailed.into(); + // Make sure the error is passed through the error converter. + let error = + <() as ErrorConverter>::convert(expected, &mock::MockEnvironment::default()).err(); + assert_eq!(result.result.err(), error); }); +} - // Encode and print each variant individually to see their encoded values. - println!("{:?} -> {:?}", enum_simple, enum_simple.encode()); - println!("{:?} -> {:?}", enum_data, enum_data.encode()); - println!("{:?} -> {:?}", enum_named, enum_named.encode()); - println!("{:?} -> {:?}", enum_nested, enum_nested.encode()); - println!("{:?} -> {:?}", enum_option, enum_option.encode()); - println!("{:?} -> {:?}", enum_vec, enum_vec.encode()); - println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode()); - println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode()); - println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode()); +/// Initializing a new contract file if it does not exist. +fn initialize_contract(contract_path: &str) -> Vec { + if !Path::new(contract_path).exists() { + use contract_build::*; + let manifest_path = ManifestPath::new("contract/Cargo.toml").unwrap(); + let args = ExecuteArgs { + build_artifact: BuildArtifacts::CodeOnly, + build_mode: BuildMode::Debug, + manifest_path, + output_type: OutputType::Json, + verbosity: Verbosity::Quiet, + skip_wasm_validation: true, + ..Default::default() + }; + execute(args).unwrap(); + } + std::fs::read(contract_path).unwrap() } -#[test] -fn encoding_decoding_dispatch_error() { - use sp_runtime::{ArithmeticError, DispatchError, ModuleError, TokenError}; +/// Instantiating the contract. +fn instantiate() -> AccountId { + let result = Contracts::bare_instantiate( + ALICE, + 0, + GAS_LIMIT, + None, + Code::Upload(CONTRACT.clone()), + function_selector("new"), + Default::default(), + DEBUG_OUTPUT, + CollectEvents::UnsafeCollect, + ); + log::debug!("instantiate result: {result:?}"); + let result = result.result.unwrap(); + assert!(!result.result.did_revert()); + result.account_id +} - let error = DispatchError::Module(ModuleError { - index: 255, - error: [2, 0, 0, 0], - message: Some("error message"), - }); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 255, 2, 0, 0, 0]); - assert_eq!( - decoded, - // `message` is skipped for encoding. - DispatchError::Module(ModuleError { index: 255, error: [2, 0, 0, 0], message: None }) +/// Perform a call to a specified contract. +fn call( + contract: AccountId, + func_id: u32, + input: impl Encode + Debug, + gas_limit: Weight, +) -> ContractExecResult { + log::debug!("call: func_id={func_id}, input={input:?}"); + let result = Contracts::bare_call( + ALICE, + contract, + 0, + gas_limit, + None, + [function_selector("call"), (func_id, input.encode()).encode()].concat(), + DEBUG_OUTPUT, + CollectEvents::UnsafeCollect, + Determinism::Enforced, ); + log::debug!("gas consumed: {:?}", result.gas_consumed); + log::debug!("call result: {result:?}"); + result +} - // Example DispatchError::Token - let error = DispatchError::Token(TokenError::UnknownAsset); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![7, 4]); - assert_eq!(decoded, error); - - // Example DispatchError::Arithmetic - let error = DispatchError::Arithmetic(ArithmeticError::Overflow); - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![8, 1]); - assert_eq!(decoded, error); +/// Construct the hashed bytes as a selector of function. +fn function_selector(name: &str) -> Vec { + sp_io::hashing::blake2_256(name.as_bytes())[0..4].to_vec() } diff --git a/extension/src/v0.rs b/extension/src/v0.rs deleted file mode 100644 index 4c3536a4..00000000 --- a/extension/src/v0.rs +++ /dev/null @@ -1,298 +0,0 @@ -#[cfg(test)] -use crate::convert_to_status_code; - -pub(crate) fn handle_unknown_error(encoded_error: &mut [u8; 4]) { - let unknown = match encoded_error[0] { - code if UNIT_ERRORS.contains(&code) => nested_errors(&encoded_error[1..], None), - // Single nested errors with a limit in their nesting. - // - // `TokenError`: has ten variants - translated to a limit of nine. - 7 => nested_errors(&encoded_error[1..], Some(9)), - // `ArithmeticError`: has 3 variants - translated to a limit of two. - 8 => nested_errors(&encoded_error[1..], Some(2)), - // `TransactionalError`: has 2 variants - translated to a limit of one. - 9 => nested_errors(&encoded_error[1..], Some(1)), - code if DOUBLE_NESTED_ERRORS.contains(&code) => nested_errors(&encoded_error[3..], None), - _ => true, - }; - if unknown { - encoded_error[..].rotate_right(1); - encoded_error[0] = 0u8; - } -} - -// Unit `Error` variants. -// (variant: index): -// - CannotLookup: 1, -// - BadOrigin: 2, -// - ConsumerRemaining: 4, -// - NoProviders: 5, -// - TooManyConsumers: 6, -// - Exhausted: 10, -// - Corruption: 11, -// - Unavailable: 12, -// - RootNotAllowed: 13, -// - UnknownFunctionId: 254, -// - DecodingFailed: 255, -const UNIT_ERRORS: [u8; 11] = [1, 2, 4, 5, 6, 10, 11, 12, 13, 254, 255]; - -#[cfg(test)] -const SINGLE_NESTED_ERRORS: [u8; 3] = [7, 8, 9]; - -// Double nested `Error` variants -// (variant: index): -// - Module: 3, -const DOUBLE_NESTED_ERRORS: [u8; 1] = [3]; - -// Checks for unknown nested errors within the `DispatchError`. -// - For single nested errors with a limit, it verifies if the nested value exceeds the limit. -// - For other nested errors, it checks if any subsequent bytes are non-zero. -// -// `nested_error` - The slice of bytes representing the nested error. -// `limit` - An optional limit for single nested errors. -fn nested_errors(nested_error: &[u8], limit: Option) -> bool { - match limit { - Some(l) => nested_error[0] > l || nested_error[1..].iter().any(|&x| x != 0u8), - None => nested_error.iter().any(|&x| x != 0u8), - } -} - -#[cfg(test)] -mod tests { - use super::*; - use pop_primitives::error::{ - ArithmeticError::*, - Error::{self, *}, - TokenError::*, - TransactionalError::*, - }; - use sp_runtime::DispatchError; - - // Compare all the different `DispatchError` variants with the expected `Error`. - #[test] - fn dispatch_error_to_error() { - let test_cases = vec![ - ( - DispatchError::Other(""), - (Other { dispatch_error_index: 0, error_index: 0, error: 0 }), - ), - (DispatchError::Other("UnknownCall"), UnknownCall), - (DispatchError::Other("DecodingFailed"), DecodingFailed), - (DispatchError::CannotLookup, CannotLookup), - (DispatchError::BadOrigin, BadOrigin), - ( - DispatchError::Module(sp_runtime::ModuleError { - index: 1, - error: [2, 0, 0, 0], - message: Some("hallo"), - }), - Module { index: 1, error: 2 }, - ), - (DispatchError::ConsumerRemaining, ConsumerRemaining), - (DispatchError::NoProviders, NoProviders), - (DispatchError::TooManyConsumers, TooManyConsumers), - (DispatchError::Token(sp_runtime::TokenError::BelowMinimum), Token(BelowMinimum)), - ( - DispatchError::Arithmetic(sp_runtime::ArithmeticError::Overflow), - Arithmetic(Overflow), - ), - ( - DispatchError::Transactional(sp_runtime::TransactionalError::LimitReached), - Transactional(LimitReached), - ), - (DispatchError::Exhausted, Exhausted), - (DispatchError::Corruption, Corruption), - (DispatchError::Unavailable, Unavailable), - (DispatchError::RootNotAllowed, RootNotAllowed), - ]; - for (dispatch_error, expected) in test_cases { - let status_code = crate::convert_to_status_code(dispatch_error, 0); - let error: Error = status_code.into(); - assert_eq!(error, expected); - } - } - - // Compare all the different `DispatchError::Other` possibilities with the expected `Error`. - #[test] - fn other_error() { - let test_cases = vec![ - ( - DispatchError::Other("Random"), - (Other { dispatch_error_index: 0, error_index: 0, error: 0 }), - ), - (DispatchError::Other("UnknownCall"), UnknownCall), - (DispatchError::Other("DecodingFailed"), DecodingFailed), - ]; - for (dispatch_error, expected) in test_cases { - let status_code = convert_to_status_code(dispatch_error, 0); - let error: Error = status_code.into(); - assert_eq!(error, expected); - } - } - - // Compare all the different `DispatchError::Module` nesting possibilities, which can not be - // handled, with the expected `Error`. See `double_nested_error_variants` fourth byte nesting. - #[test] - fn test_module_error() { - let test_cases = vec![ - DispatchError::Module(sp_runtime::ModuleError { - index: 1, - error: [2, 2, 0, 0], - message: Some("Random"), - }), - DispatchError::Module(sp_runtime::ModuleError { - index: 1, - error: [2, 2, 2, 0], - message: Some("Random"), - }), - DispatchError::Module(sp_runtime::ModuleError { - index: 1, - error: [2, 2, 2, 2], - message: Some("Random"), - }), - ]; - for dispatch_error in test_cases { - let status_code = convert_to_status_code(dispatch_error, 0); - let error: Error = status_code.into(); - assert_eq!(error, Other { dispatch_error_index: 3, error_index: 1, error: 2 }); - } - } - - // Converts 4 bytes into `Error` and handles unknown errors (used in `convert_to_status_code`). - fn into_error(mut error_bytes: [u8; 4]) -> Error { - handle_unknown_error(&mut error_bytes); - u32::from_le_bytes(error_bytes).into() - } - - // Tests the `handle_unknown_error` for `Error`, version 0. - // - // Unit variants: - // If the encoded value indicates a nested `Error` which is known by V0 as a - // unit variant, the encoded value is converted into `Error::Other`. - // - // Example: the error `BadOrigin` (encoded: `[2, 0, 0, 0]`) with a non-zero value for one - // of the bytes [1..4]: `[2, 0, 1, 0]` is converted into `[0, 2, 0, 1]` (shifting the bits - // one forward). This is decoded to `Error::Other { dispatch_error: 2, index: 0, error: 1 }`. - #[test] - fn unit_error_variants() { - let errors = vec![ - CannotLookup, - BadOrigin, - ConsumerRemaining, - NoProviders, - TooManyConsumers, - Exhausted, - Corruption, - Unavailable, - RootNotAllowed, - UnknownCall, - DecodingFailed, - ]; - // Compare an `Error`, which is converted from an encoded value, with the expected `Error`. - for (i, &error_code) in UNIT_ERRORS.iter().enumerate() { - // No nesting and unit variant correctly returned. - assert_eq!(into_error([error_code, 0, 0, 0]), errors[i]); - // Unexpected second byte nested. - assert_eq!( - into_error([error_code, 1, 0, 0]), - (Other { dispatch_error_index: error_code, error_index: 1, error: 0 }), - ); - // Unexpected third byte nested. - assert_eq!( - into_error([error_code, 1, 1, 0]), - (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }), - ); - // Unexpected fourth byte nested. - assert_eq!( - into_error([error_code, 1, 1, 1]), - (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }), - ); - } - } - - // Single nested variants: - // If the encoded value indicates a double nested `Error` which is known by V0 - // as a single nested variant, the encoded value is converted into `Error::Other`. - // - // Example: the error `Arithmetic(Overflow)` (encoded: `[8, 1, 0, 0]`) with a non-zero - // value for one of the bytes [2..4]: `[8, 1, 1, 0]` is converted into `[0, 8, 1, 1]`. This is - // decoded to `Error::Other { dispatch_error: 8, index: 1, error: 1 }`. - #[test] - fn single_nested_error_variants() { - let errors = vec![ - [Token(FundsUnavailable), Token(OnlyProvider)], - [Arithmetic(Underflow), Arithmetic(Overflow)], - [Transactional(LimitReached), Transactional(NoLayer)], - ]; - // Compare an `Error`, which is converted from an encoded value, with the expected `Error`. - for (i, &error_code) in SINGLE_NESTED_ERRORS.iter().enumerate() { - // No nested and single nested variant correctly returned. - assert_eq!(into_error([error_code, 0, 0, 0]), errors[i][0]); - assert_eq!(into_error([error_code, 1, 0, 0]), errors[i][1]); - // Unexpected third byte nested. - assert_eq!( - into_error([error_code, 1, 1, 0]), - (Other { dispatch_error_index: error_code, error_index: 1, error: 1 }), - ); - // Unexpected fourth byte nested. - assert_eq!( - into_error([error_code, 1, 1, 1]), - Other { dispatch_error_index: error_code, error_index: 1, error: 1 }, - ); - } - } - - #[test] - fn single_nested_unknown_variants() { - // Unknown `TokenError` variant. - assert_eq!( - into_error([7, 10, 0, 0]), - Other { dispatch_error_index: 7, error_index: 10, error: 0 } - ); - // Unknown `Arithmetic` variant. - assert_eq!( - into_error([8, 3, 0, 0]), - Other { dispatch_error_index: 8, error_index: 3, error: 0 } - ); - // Unknown `Transactional` variant. - assert_eq!( - into_error([9, 2, 0, 0]), - Other { dispatch_error_index: 9, error_index: 2, error: 0 } - ); - } - - // Double nested variants: - // If the encoded value indicates a triple nested `Error` which is known by V0 - // as a double nested variant, the encoded value is converted into `Error::Other`. - // - // Example: the error `Module { index: 10, error 5 }` (encoded: `[3, 10, 5, 0]`) with a non-zero - // value for the last byte: `[3, 10, 5, 3]` is converted into `[0, 3, 10, 5]`. This is - // decoded to `Error::Other { dispatch_error: 3, index: 10, error: 5 }`. - #[test] - fn double_nested_error_variants() { - // Compare an `Error`, which is converted from an encoded value, with the expected `Error`. - // No nesting and unit variant correctly returned. - assert_eq!(into_error([3, 0, 0, 0]), Module { index: 0, error: 0 }); - // Allowed single nesting and variant correctly returned. - assert_eq!(into_error([3, 1, 0, 0]), Module { index: 1, error: 0 }); - // Allowed double nesting and variant correctly returned. - assert_eq!(into_error([3, 1, 1, 0]), Module { index: 1, error: 1 }); - // Unexpected fourth byte nested. - assert_eq!( - into_error([3, 1, 1, 1]), - Other { dispatch_error_index: 3, error_index: 1, error: 1 }, - ); - } - - #[test] - fn test_random_encoded_values() { - assert_eq!( - into_error([100, 100, 100, 100]), - Other { dispatch_error_index: 100, error_index: 100, error: 100 } - ); - assert_eq!( - into_error([200, 200, 200, 200]), - Other { dispatch_error_index: 200, error_index: 200, error: 200 } - ); - } -} diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index c42035f9..eddbc103 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -299,7 +299,9 @@ fn reserve_transfer_native_asset_from_relay_to_para() { let delivery_fees = PaseoRelay::execute_with(|| { xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >( + test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest + ) }); let sender_balance_after = test.sender.balance; @@ -353,7 +355,9 @@ fn reserve_transfer_native_asset_from_para_to_relay() { let delivery_fees = PopNetworkPara::execute_with(|| { xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >( + test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest + ) }); // Sender's balance is reduced @@ -399,7 +403,9 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { let delivery_fees = AssetHubPaseoPara::execute_with(|| { xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >( + test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest + ) }); // Sender's balance is reduced @@ -417,7 +423,8 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { fn reserve_transfer_native_asset_from_para_to_system_para() { init_tracing(); - // Setup: reserve transfer from AH to Pop, so that sovereign account accurate for return transfer + // Setup: reserve transfer from AH to Pop, so that sovereign account accurate for return + // transfer let amount_to_send: Balance = ASSET_HUB_PASEO_ED * 1000; fund_pop_from_system_para( AssetHubPaseoParaSender::get(), @@ -462,7 +469,9 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { let delivery_fees = PopNetworkPara::execute_with(|| { xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >( + test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest + ) }); // Sender's balance is reduced @@ -482,8 +491,8 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { // // let beneficiary: sp_runtime::AccountId32 = [1u8; 32].into(); // -// // Setup: reserve transfer from relay to Pop, so that sovereign account accurate for return transfer -// let amount_to_send: Balance = pop_runtime::UNIT * 1000; +// // Setup: reserve transfer from relay to Pop, so that sovereign account accurate for return +// transfer let amount_to_send: Balance = pop_runtime::UNIT * 1000; // fund_pop_from_relay(PaseoRelaySender::get(), amount_to_send, beneficiary.clone()); // // let message = { @@ -554,11 +563,11 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { // PaseoRelay, // vec![ // // We currently only check that the message was processed successfully -// RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, -// // TODO: check order placed once we can have on-demand para id registered (probably via setting raw storage as a workaround) -// // RuntimeEvent::OnDemandAssignmentProvider(assigner_on_demand::Event::OnDemandOrderPlaced { -// // .. -// // }) => {}, +// RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => +// {}, // TODO: check order placed once we can have on-demand para id registered (probably via +// setting raw storage as a workaround) // +// RuntimeEvent::OnDemandAssignmentProvider(assigner_on_demand::Event::OnDemandOrderPlaced { // +// .. // }) => {}, // ] // ); // }); @@ -570,8 +579,8 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { // PopNetworkPara, // vec![ // RuntimeEvent::PolkadotXcm(pallet_xcm::Event::ResponseReady { query_id: 0, .. }) => {}, -// RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, -// ] +// RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => +// {}, ] // ); // }); // } diff --git a/node/src/command.rs b/node/src/command.rs index b1fcd614..a83253fc 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -64,9 +64,8 @@ impl RuntimeResolver for PathBuf { fn load_spec(id: &str) -> std::result::Result, String> { Ok(match id { - "dev" | "devnet" | "dev-paseo" => { - Box::new(chain_spec::development_config(Relay::PaseoLocal)) - }, + "dev" | "devnet" | "dev-paseo" => + Box::new(chain_spec::development_config(Relay::PaseoLocal)), "test" | "testnet" | "pop-paseo" => Box::new(chain_spec::testnet_config(Relay::Paseo)), "" | "local" => Box::new(chain_spec::development_config(Relay::PaseoLocal)), path => { diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml index f9a807a3..d2d444bf 100644 --- a/pallets/api/Cargo.toml +++ b/pallets/api/Cargo.toml @@ -11,8 +11,12 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec.workspace = true +log.workspace = true scale-info.workspace = true +# Local +pop-chain-extension.workspace = true + # Substrate frame-benchmarking.workspace = true frame-support.workspace = true @@ -42,6 +46,7 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-balances/std", + "pop-chain-extension/std", "scale-info/std", "sp-core/std", "sp-io/std", diff --git a/pallets/api/src/extension.rs b/pallets/api/src/extension.rs new file mode 100644 index 00000000..8469ae40 --- /dev/null +++ b/pallets/api/src/extension.rs @@ -0,0 +1,180 @@ +use core::{fmt::Debug, marker::PhantomData}; +use frame_support::traits::Get; +pub use pop_chain_extension::{ + Config, ContractWeightsOf, DecodingFailed, DispatchCall, ReadState, Readable, +}; +use pop_chain_extension::{ + Converter, Decodes, Environment, LogTarget, Matches, Processor, Result, RetVal, +}; +use sp_runtime::DispatchError; +use sp_std::vec::Vec; + +/// Encoded version of `pallet_contracts::Error::DecodingFailed`, as found within +/// `DispatchError::ModuleError`. +pub const DECODING_FAILED_ERROR: [u8; 4] = [11, 0, 0, 0]; +/// The logging target for the chain extension. +pub const LOG_TARGET: &str = "pop-api::extension"; + +/// The chain extension used by the API. +pub type Extension = pop_chain_extension::Extension; +/// Decodes output by prepending bytes from ext_id() + func_id() +pub type DecodesAs = + Decodes; + +/// Prepends bytes from ext_id() + func_id() to prefix the encoded input bytes to determine the +/// versioned output +pub struct Prepender; +impl Processor for Prepender { + /// The type of value to be processed. + type Value = Vec; + + /// The log target. + const LOG_TARGET: &'static str = "pop-api::extension::processor"; + + /// Processes the provided value. + /// + /// # Parameters + /// - `value` - The value to be processed. + /// - `env` - The current execution environment. + fn process(mut value: Self::Value, env: &impl Environment) -> Self::Value { + // Resolve version, pallet and call index from environment + let version = version(env); + let (module, index) = module_and_index(env); + // Prepend bytes + value.splice(0..0, [version, module, index]); + log::debug!(target: Self::LOG_TARGET, "prepender: version={version}, module={module}, index={index}"); + value + } +} + +/// Matches on the first byte of a function identifier only. +pub struct IdentifiedByFirstByteOfFunctionId(PhantomData); +impl> Matches for IdentifiedByFirstByteOfFunctionId { + fn matches(env: &impl Environment) -> bool { + func_id(env) == T::get() + } +} + +/// A log target for dispatched calls. +pub struct DispatchCallLogTarget; +impl LogTarget for DispatchCallLogTarget { + const LOG_TARGET: &'static str = "pop-api::extension::dispatch"; +} + +/// A log target for state reads. +pub struct ReadStateLogTarget; +impl LogTarget for ReadStateLogTarget { + const LOG_TARGET: &'static str = "pop-api::extension::read-state"; +} + +/// Conversion of a `DispatchError` to a versioned error. +pub struct VersionedErrorConverter(PhantomData); +impl + Into + Debug> pop_chain_extension::ErrorConverter + for VersionedErrorConverter +{ + /// The log target. + const LOG_TARGET: &'static str = "pop-api::extension::converters::versioned-error"; + + /// Converts the provided error. + /// + /// # Parameters + /// - `error` - The error to be converted. + /// - `env` - The current execution environment. + fn convert(error: DispatchError, env: &impl Environment) -> Result { + // Defer to supplied versioned error conversion type + let version = version(env); + log::debug!(target: Self::LOG_TARGET, "versioned error converter: error={error:?}, version={version}"); + let error: Error = (error, version).into(); + log::debug!(target: Self::LOG_TARGET, "versioned error converter: converted error={error:?}"); + Ok(RetVal::Converging(error.into())) + } +} + +/// Conversion of a read result to a versioned read result. +pub struct VersionedResultConverter(PhantomData<(S, T)>); +impl + Debug> Converter + for VersionedResultConverter +{ + /// The type of value to be converted. + type Source = Source; + /// The target type. + type Target = Target; + /// The log target. + const LOG_TARGET: &'static str = "pop-api::extension::converters::versioned-result"; + + /// Converts the provided value. + /// + /// # Parameters + /// - `value` - The value to be converted. + /// - `env` - The current execution environment. + fn convert(value: Self::Source, env: &impl Environment) -> Self::Target { + // Defer to supplied versioned result conversion type + let version = version(env); + log::debug!(target: Self::LOG_TARGET, "versioned result converter: result={value:?}, version={version}"); + let converted: Target = (value, version).into(); + log::debug!(target: Self::LOG_TARGET, "versioned result converter: converted result={converted:?}"); + converted + } +} + +fn func_id(env: &impl Environment) -> u8 { + // TODO: update once the encoding scheme order has been finalised: expected to be + // env.ext_id().to_le_bytes()[0] + env.func_id().to_le_bytes()[1] +} + +fn module_and_index(env: &impl Environment) -> (u8, u8) { + // TODO: update once the encoding scheme order has been finalised: expected to be + // env.func_id().to_le_bytes()[0..1] + let bytes = env.ext_id().to_le_bytes(); + (bytes[0], bytes[1]) +} + +fn version(env: &impl Environment) -> u8 { + // TODO: update once the encoding scheme order has been finalised: expected to be + // env.ext_id().to_le_bytes()[1] + env.func_id().to_le_bytes()[0] +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::extension::Prepender; + use frame_support::pallet_prelude::Weight; + use pop_chain_extension::Ext; + + #[test] + fn prepender_works() { + let env = MockEnvironment { func_id: 1, ext_id: u16::from_le_bytes([2, 3]) }; + assert_eq!(Prepender::process(vec![0u8], &env), vec![1, 2, 3, 0]); + } + + struct MockEnvironment { + func_id: u16, + ext_id: u16, + } + impl Environment for MockEnvironment { + type AccountId = (); + type ChargedAmount = Weight; + + fn func_id(&self) -> u16 { + self.func_id + } + + fn ext_id(&self) -> u16 { + self.ext_id + } + + fn charge_weight(&mut self, _amount: Weight) -> Result { + unimplemented!() + } + + fn adjust_weight(&mut self, _charged: Self::ChargedAmount, _actual_weight: Weight) { + unimplemented!() + } + + fn ext(&mut self) -> impl Ext { + unimplemented!() + } + } +} diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index 6ff8ac87..dac002e9 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -81,6 +81,41 @@ pub mod pallet { AssetExists(AssetIdOf), } + /// Results of state reads for the fungibles API. + #[derive(Debug)] + pub enum ReadResult { + /// Total token supply for a specified asset. + TotalSupply(BalanceOf), + /// Account balance for a specified `asset` and `owner`. + BalanceOf(BalanceOf), + /// Allowance for a `spender` approved by an `owner`, for a specified `asset`. + Allowance(BalanceOf), + /// Name of the specified asset. + TokenName(Vec), + /// Symbol for the specified asset. + TokenSymbol(Vec), + /// Decimals for the specified asset. + TokenDecimals(u8), + /// Whether the specified asset exists. + AssetExists(bool), + } + + impl ReadResult { + /// Encodes the result. + pub fn encode(&self) -> Vec { + use ReadResult::*; + match self { + TotalSupply(result) => result.encode(), + BalanceOf(result) => result.encode(), + Allowance(result) => result.encode(), + TokenName(result) => result.encode(), + TokenSymbol(result) => result.encode(), + TokenDecimals(result) => result.encode(), + AssetExists(result) => result.encode(), + } + } + } + /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] pub trait Config: frame_system::Config + pallet_assets::Config { @@ -385,7 +420,8 @@ pub mod pallet { AssetsOf::::clear_metadata(origin, asset.into()) } - /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. + /// Creates `value` amount of tokens and assigns them to `account`, increasing the total + /// supply. /// /// # Parameters /// - `asset` - The asset to mint. @@ -435,38 +471,50 @@ pub mod pallet { } impl Pallet { - /// Reads fungible asset state based on the provided value. + fn weight_approve(approve: u32, cancel: u32) -> Weight { + ::WeightInfo::approve(cancel, approve) + } + } + + impl crate::Read for Pallet { + /// The type of read requested. + type Read = Read; + /// The type or result returned. + type Result = ReadResult; + + /// Determines the weight of the requested read, used to charge the appropriate weight + /// before the read is performed. /// - /// This function matches the value to determine the type of state query and returns the - /// encoded result. + /// # Parameters + /// - `request` - The read request. + fn weight(_request: &Self::Read) -> Weight { + // TODO: match on request and return benchmarked weight + T::DbWeight::get().reads(1_u64) + } + + /// Performs the requested read and returns the result. /// - /// # Parameter - /// - `value` - An instance of `Read`, which specifies the type of state query and - /// the associated parameters. - pub fn read_state(value: Read) -> Vec { + /// # Parameters + /// - `request` - The read request. + fn read(request: Self::Read) -> Self::Result { use Read::*; - - match value { - TotalSupply(asset) => AssetsOf::::total_supply(asset).encode(), - BalanceOf { asset, owner } => AssetsOf::::balance(asset, owner).encode(), - Allowance { asset, owner, spender } => { - AssetsOf::::allowance(asset, &owner, &spender).encode() - }, - TokenName(asset) => { - as MetadataInspect>>::name(asset).encode() - }, - TokenSymbol(asset) => { - as MetadataInspect>>::symbol(asset).encode() - }, - TokenDecimals(asset) => { - as MetadataInspect>>::decimals(asset).encode() - }, - AssetExists(asset) => AssetsOf::::asset_exists(asset).encode(), + match request { + TotalSupply(asset) => ReadResult::TotalSupply(AssetsOf::::total_supply(asset)), + BalanceOf { asset, owner } => + ReadResult::BalanceOf(AssetsOf::::balance(asset, owner)), + Allowance { asset, owner, spender } => + ReadResult::Allowance(AssetsOf::::allowance(asset, &owner, &spender)), + TokenName(asset) => ReadResult::TokenName( as MetadataInspect< + AccountIdOf, + >>::name(asset)), + TokenSymbol(asset) => ReadResult::TokenSymbol( as MetadataInspect< + AccountIdOf, + >>::symbol(asset)), + TokenDecimals(asset) => ReadResult::TokenDecimals( + as MetadataInspect>>::decimals(asset), + ), + AssetExists(asset) => ReadResult::AssetExists(AssetsOf::::asset_exists(asset)), } } - - fn weight_approve(approve: u32, cancel: u32) -> Weight { - ::WeightInfo::approve(cancel, approve) - } } } diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index d881a3c1..d6d4ef2f 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -1,4 +1,4 @@ -use crate::{fungibles::Read::*, mock::*}; +use crate::{fungibles::Read::*, mock::*, Read}; use codec::Encode; use frame_support::{ assert_ok, @@ -236,7 +236,10 @@ fn burn_works() { fn total_supply_works() { new_test_ext().execute_with(|| { create_asset_and_mint_to(ALICE, ASSET, ALICE, 100); - assert_eq!(Assets::total_supply(ASSET).encode(), Fungibles::read_state(TotalSupply(ASSET))); + assert_eq!( + Assets::total_supply(ASSET).encode(), + Fungibles::read(TotalSupply(ASSET)).encode() + ); }); } @@ -246,7 +249,7 @@ fn balance_of_works() { create_asset_and_mint_to(ALICE, ASSET, ALICE, 100); assert_eq!( Assets::balance(ASSET, ALICE).encode(), - Fungibles::read_state(BalanceOf { asset: ASSET, owner: ALICE }) + Fungibles::read(BalanceOf { asset: ASSET, owner: ALICE }).encode() ); }); } @@ -257,7 +260,7 @@ fn allowance_works() { create_asset_mint_and_approve(ALICE, ASSET, BOB, 100, ALICE, 50); assert_eq!( Assets::allowance(ASSET, &ALICE, &BOB).encode(), - Fungibles::read_state(Allowance { asset: ASSET, owner: ALICE, spender: BOB }) + Fungibles::read(Allowance { asset: ASSET, owner: ALICE, spender: BOB }).encode() ); }); } @@ -269,9 +272,12 @@ fn token_metadata_works() { let symbol: Vec = vec![21, 22, 23]; let decimals: u8 = 69; create_asset_and_set_metadata(ALICE, ASSET, name.clone(), symbol.clone(), decimals); - assert_eq!(Assets::name(ASSET).encode(), Fungibles::read_state(TokenName(ASSET))); - assert_eq!(Assets::symbol(ASSET).encode(), Fungibles::read_state(TokenSymbol(ASSET))); - assert_eq!(Assets::decimals(ASSET).encode(), Fungibles::read_state(TokenDecimals(ASSET))); + assert_eq!(Assets::name(ASSET).encode(), Fungibles::read(TokenName(ASSET)).encode()); + assert_eq!(Assets::symbol(ASSET).encode(), Fungibles::read(TokenSymbol(ASSET)).encode()); + assert_eq!( + Assets::decimals(ASSET).encode(), + Fungibles::read(TokenDecimals(ASSET)).encode() + ); }); } @@ -279,7 +285,10 @@ fn token_metadata_works() { fn asset_exists_works() { new_test_ext().execute_with(|| { create_asset(ALICE, ASSET); - assert_eq!(Assets::asset_exists(ASSET).encode(), Fungibles::read_state(AssetExists(ASSET))); + assert_eq!( + Assets::asset_exists(ASSET).encode(), + Fungibles::read(AssetExists(ASSET)).encode() + ); }); } diff --git a/pallets/api/src/lib.rs b/pallets/api/src/lib.rs index 5cba0551..d94d1978 100644 --- a/pallets/api/src/lib.rs +++ b/pallets/api/src/lib.rs @@ -1,5 +1,30 @@ #![cfg_attr(not(feature = "std"), no_std)] +pub use extension::Extension; +use frame_support::pallet_prelude::Weight; + +pub mod extension; pub mod fungibles; #[cfg(test)] mod mock; + +/// Trait for performing reads of runtime state. +pub trait Read { + /// The type of read requested. + type Read; + /// The type or result returned. + type Result; + + /// Determines the weight of the requested read, used to charge the appropriate weight before + /// the read is performed. + /// + /// # Parameters + /// - `request` - The read request. + fn weight(read: &Self::Read) -> Weight; + + /// Performs the requested read and returns the result. + /// + /// # Parameters + /// - `request` - The read request. + fn read(request: Self::Read) -> Self::Result; +} diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml index 7ab2d0fb..499ad991 100644 --- a/pop-api/integration-tests/Cargo.toml +++ b/pop-api/integration-tests/Cargo.toml @@ -14,6 +14,7 @@ scale = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } frame-support = { version = "29.0.0", default-features = false } frame-system = { version = "29.0.0", default-features = false } +log = "0.4.22" pallet-balances = { version = "29.0.2", default-features = false } pallet-assets = { version = "30.0.0", default-features = false } pallet-contracts = { version = "28.0.0", default-features = false } diff --git a/pop-api/integration-tests/src/fungibles/mod.rs b/pop-api/integration-tests/src/fungibles/mod.rs index 0ca7d4f9..d1c0e2ae 100644 --- a/pop-api/integration-tests/src/fungibles/mod.rs +++ b/pop-api/integration-tests/src/fungibles/mod.rs @@ -1,9 +1,5 @@ use super::*; -use pop_primitives::error::{ - ArithmeticError::*, - Error::{self, *}, - TokenError::*, -}; +use pop_primitives::{ArithmeticError::*, AssetId, Error::*, TokenError::*, *}; use utils::*; mod utils; @@ -86,23 +82,29 @@ fn transfer_works() { let amount: Balance = 100 * UNIT; // Asset does not exist. - assert_eq!(transfer(addr.clone(), 1, BOB, amount), Err(Module { index: 52, error: 3 })); + assert_eq!( + transfer(addr.clone(), 1, BOB, amount), + Err(Module { index: 52, error: [3, 0] }) + ); // Create asset with Alice as owner and mint `amount` to contract address. let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(ALICE, asset); assert_eq!( transfer(addr.clone(), asset, BOB, amount), - Err(Module { index: 52, error: 16 }) + Err(Module { index: 52, error: [16, 0] }) ); thaw_asset(ALICE, asset); // Not enough balance. assert_eq!( transfer(addr.clone(), asset, BOB, amount + 1 * UNIT), - Err(Module { index: 52, error: 0 }) + Err(Module { index: 52, error: [0, 0] }) ); // Not enough balance due to ED. - assert_eq!(transfer(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 0 })); + assert_eq!( + transfer(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: [0, 0] }) + ); // Successful transfer. let balance_before_transfer = Assets::balance(asset, &BOB); assert_ok!(transfer(addr.clone(), asset, BOB, amount / 2)); @@ -114,7 +116,7 @@ fn transfer_works() { start_destroy_asset(ALICE, asset); assert_eq!( transfer(addr.clone(), asset, BOB, amount / 4), - Err(Module { index: 52, error: 16 }) + Err(Module { index: 52, error: [16, 0] }) ); }); } @@ -129,14 +131,14 @@ fn transfer_from_works() { // Asset does not exist. assert_eq!( transfer_from(addr.clone(), 1, ALICE, BOB, amount / 2), - Err(Module { index: 52, error: 3 }), + Err(Module { index: 52, error: [3, 0] }), ); // Create asset with Alice as owner and mint `amount` to contract address. let asset = create_asset_and_mint_to(ALICE, 1, ALICE, amount); // Unapproved transfer. assert_eq!( transfer_from(addr.clone(), asset, ALICE, BOB, amount / 2), - Err(Module { index: 52, error: 10 }) + Err(Module { index: 52, error: [10, 0] }) ); assert_ok!(Assets::approve_transfer( RuntimeOrigin::signed(ALICE.into()), @@ -148,13 +150,13 @@ fn transfer_from_works() { freeze_asset(ALICE, asset); assert_eq!( transfer_from(addr.clone(), asset, ALICE, BOB, amount), - Err(Module { index: 52, error: 16 }), + Err(Module { index: 52, error: [16, 0] }), ); thaw_asset(ALICE, asset); // Not enough balance. assert_eq!( transfer_from(addr.clone(), asset, ALICE, BOB, amount + 1 * UNIT), - Err(Module { index: 52, error: 0 }), + Err(Module { index: 52, error: [0, 0] }), ); // Successful transfer. let balance_before_transfer = Assets::balance(asset, &BOB); @@ -172,7 +174,7 @@ fn approve_works() { let amount: Balance = 100 * UNIT; // Asset does not exist. - assert_eq!(approve(addr.clone(), 0, BOB, amount), Err(Module { index: 52, error: 3 })); + assert_eq!(approve(addr.clone(), 0, BOB, amount), Err(Module { index: 52, error: [3, 0] })); let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); assert_eq!(approve(addr.clone(), asset, BOB, amount), Err(ConsumerRemaining)); let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); @@ -180,7 +182,10 @@ fn approve_works() { let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(ALICE, asset); - assert_eq!(approve(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + assert_eq!( + approve(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: [16, 0] }) + ); thaw_asset(ALICE, asset); // Successful approvals: assert_eq!(0, Assets::allowance(asset, &addr, &BOB)); @@ -191,7 +196,10 @@ fn approve_works() { assert_eq!(Assets::allowance(asset, &addr, &BOB), amount / 2); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(ALICE, asset); - assert_eq!(approve(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + assert_eq!( + approve(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: [16, 0] }) + ); }); } @@ -205,7 +213,7 @@ fn increase_allowance_works() { // Asset does not exist. assert_eq!( increase_allowance(addr.clone(), 0, BOB, amount), - Err(Module { index: 52, error: 3 }) + Err(Module { index: 52, error: [3, 0] }) ); let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); assert_eq!(increase_allowance(addr.clone(), asset, BOB, amount), Err(ConsumerRemaining)); @@ -218,7 +226,7 @@ fn increase_allowance_works() { freeze_asset(ALICE, asset); assert_eq!( increase_allowance(addr.clone(), asset, BOB, amount), - Err(Module { index: 52, error: 16 }) + Err(Module { index: 52, error: [16, 0] }) ); thaw_asset(ALICE, asset); // Successful approvals: @@ -232,7 +240,7 @@ fn increase_allowance_works() { start_destroy_asset(ALICE, asset); assert_eq!( increase_allowance(addr.clone(), asset, BOB, amount), - Err(Module { index: 52, error: 16 }) + Err(Module { index: 52, error: [16, 0] }) ); }); } @@ -247,7 +255,7 @@ fn decrease_allowance_works() { // Asset does not exist. assert_eq!( decrease_allowance(addr.clone(), 0, BOB, amount), - Err(Module { index: 52, error: 3 }), + Err(Module { index: 52, error: [3, 0] }), ); // Create asset and mint `amount` to contract address, then approve Bob to spend `amount`. let asset = @@ -256,7 +264,7 @@ fn decrease_allowance_works() { freeze_asset(addr.clone(), asset); assert_eq!( decrease_allowance(addr.clone(), asset, BOB, amount), - Err(Module { index: 52, error: 16 }), + Err(Module { index: 52, error: [16, 0] }), ); thaw_asset(addr.clone(), asset); // Successfully decrease allowance. @@ -268,7 +276,7 @@ fn decrease_allowance_works() { start_destroy_asset(addr.clone(), asset); assert_eq!( decrease_allowance(addr.clone(), asset, BOB, amount), - Err(Module { index: 52, error: 16 }), + Err(Module { index: 52, error: [16, 0] }), ); }); } @@ -327,7 +335,7 @@ fn create_works() { // No balance to pay for fees. assert_eq!( create(addr.clone(), ASSET_ID, addr.clone(), 1), - Err(Module { index: 10, error: 2 }), + Err(Module { index: 10, error: [2, 0] }), ); // Instantiate a contract without balance for deposit. @@ -335,18 +343,27 @@ fn create_works() { // No balance to pay the deposit. assert_eq!( create(addr.clone(), ASSET_ID, addr.clone(), 1), - Err(Module { index: 10, error: 2 }), + Err(Module { index: 10, error: [2, 0] }), ); // Instantiate a contract with enough balance. let addr = instantiate(CONTRACT, INIT_VALUE, vec![2]); - assert_eq!(create(addr.clone(), ASSET_ID, BOB, 0), Err(Module { index: 52, error: 7 }),); + assert_eq!( + create(addr.clone(), ASSET_ID, BOB, 0), + Err(Module { index: 52, error: [7, 0] }), + ); // The minimal balance for an asset must be non zero. - assert_eq!(create(addr.clone(), ASSET_ID, BOB, 0), Err(Module { index: 52, error: 7 }),); + assert_eq!( + create(addr.clone(), ASSET_ID, BOB, 0), + Err(Module { index: 52, error: [7, 0] }), + ); // Create asset successfully. assert_ok!(create(addr.clone(), ASSET_ID, BOB, 1)); // Asset ID is already taken. - assert_eq!(create(addr.clone(), ASSET_ID, BOB, 1), Err(Module { index: 52, error: 5 }),); + assert_eq!( + create(addr.clone(), ASSET_ID, BOB, 1), + Err(Module { index: 52, error: [5, 0] }), + ); }); } @@ -361,7 +378,7 @@ fn instantiate_and_create_fungible_works() { create_asset(ALICE, 0, 1); assert_eq!( instantiate_and_create_fungible(contract, 0, 1), - Err(Module { index: 52, error: 5 }) + Err(Module { index: 52, error: [5, 0] }) ); // Successfully create an asset when instantiating the contract. assert_ok!(instantiate_and_create_fungible(contract, ASSET_ID, 1)); @@ -376,11 +393,11 @@ fn start_destroy_works() { let addr = instantiate(CONTRACT, INIT_VALUE, vec![2]); // Asset does not exist. - assert_eq!(start_destroy(addr.clone(), ASSET_ID), Err(Module { index: 52, error: 3 }),); + assert_eq!(start_destroy(addr.clone(), ASSET_ID), Err(Module { index: 52, error: [3, 0] }),); // Create assets where contract is not the owner. let asset = create_asset(ALICE, 0, 1); // No Permission. - assert_eq!(start_destroy(addr.clone(), asset), Err(Module { index: 52, error: 2 }),); + assert_eq!(start_destroy(addr.clone(), asset), Err(Module { index: 52, error: [2, 0] }),); let asset = create_asset(addr.clone(), ASSET_ID, 1); assert_ok!(start_destroy(addr.clone(), asset)); }); @@ -398,21 +415,21 @@ fn set_metadata_works() { // Asset does not exist. assert_eq!( set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], 0u8), - Err(Module { index: 52, error: 3 }), + Err(Module { index: 52, error: [3, 0] }), ); // Create assets where contract is not the owner. let asset = create_asset(ALICE, 0, 1); // No Permission. assert_eq!( set_metadata(addr.clone(), asset, vec![0], vec![0], 0u8), - Err(Module { index: 52, error: 2 }), + Err(Module { index: 52, error: [2, 0] }), ); let asset = create_asset(addr.clone(), ASSET_ID, 1); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(addr.clone(), asset); assert_eq!( set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], 0u8), - Err(Module { index: 52, error: 16 }), + Err(Module { index: 52, error: [16, 0] }), ); thaw_asset(addr.clone(), asset); // TODO: calling the below with a vector of length `100_000` errors in pallet contracts @@ -420,7 +437,7 @@ fn set_metadata_works() { // Set bad metadata - too large values. assert_eq!( set_metadata(addr.clone(), ASSET_ID, vec![0; 1000], vec![0; 1000], 0u8), - Err(Module { index: 52, error: 9 }), + Err(Module { index: 52, error: [9, 0] }), ); // Set metadata successfully. assert_ok!(set_metadata(addr.clone(), ASSET_ID, name, symbol, decimals)); @@ -428,7 +445,7 @@ fn set_metadata_works() { start_destroy_asset(addr.clone(), asset); assert_eq!( set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], 0), - Err(Module { index: 52, error: 16 }), + Err(Module { index: 52, error: [16, 0] }), ); }); } @@ -443,18 +460,18 @@ fn clear_metadata_works() { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); // Asset does not exist. - assert_eq!(clear_metadata(addr.clone(), 0), Err(Module { index: 52, error: 3 }),); + assert_eq!(clear_metadata(addr.clone(), 0), Err(Module { index: 52, error: [3, 0] }),); // Create assets where contract is not the owner. let asset = create_asset_and_set_metadata(ALICE, 0, vec![0], vec![0], 0); // No Permission. - assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: 2 }),); + assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: [2, 0] }),); let asset = create_asset(addr.clone(), ASSET_ID, 1); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(addr.clone(), asset); - assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: 16 }),); + assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: [16, 0] }),); thaw_asset(addr.clone(), asset); // No metadata set. - assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: 3 }),); + assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: [3, 0] }),); set_metadata_asset(addr.clone(), asset, name, symbol, decimals); // Clear metadata successfully. assert_ok!(clear_metadata(addr.clone(), ASSET_ID)); @@ -462,7 +479,7 @@ fn clear_metadata_works() { start_destroy_asset(addr.clone(), asset); assert_eq!( set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], decimals), - Err(Module { index: 52, error: 16 }), + Err(Module { index: 52, error: [16, 0] }), ); }); } @@ -493,13 +510,16 @@ fn mint_works() { assert_eq!(mint(addr.clone(), 1, BOB, amount), Err(Token(UnknownAsset))); let asset = create_asset(ALICE, 1, 1); // Minting can only be done by the owner. - assert_eq!(mint(addr.clone(), asset, BOB, 1), Err(Module { index: 52, error: 2 })); + assert_eq!(mint(addr.clone(), asset, BOB, 1), Err(Module { index: 52, error: [2, 0] })); let asset = create_asset(addr.clone(), 2, 2); // Minimum balance of an asset can not be zero. assert_eq!(mint(addr.clone(), asset, BOB, 1), Err(Token(BelowMinimum))); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(addr.clone(), asset); - assert_eq!(mint(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + assert_eq!( + mint(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: [16, 0] }) + ); thaw_asset(addr.clone(), asset); // Successful mint. let balance_before_mint = Assets::balance(asset, &BOB); @@ -510,7 +530,10 @@ fn mint_works() { assert_eq!(mint(addr.clone(), asset, BOB, Balance::MAX,), Err(Arithmetic(Overflow))); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(addr.clone(), asset); - assert_eq!(mint(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + assert_eq!( + mint(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: [16, 0] }) + ); }); } @@ -522,17 +545,20 @@ fn burn_works() { let amount: Balance = 100 * UNIT; // Asset does not exist. - assert_eq!(burn(addr.clone(), 1, BOB, amount), Err(Module { index: 52, error: 3 })); + assert_eq!(burn(addr.clone(), 1, BOB, amount), Err(Module { index: 52, error: [3, 0] })); let asset = create_asset(ALICE, 1, 1); // Bob has no tokens and thus pallet assets doesn't know the account. - assert_eq!(burn(addr.clone(), asset, BOB, 1), Err(Module { index: 52, error: 1 })); + assert_eq!(burn(addr.clone(), asset, BOB, 1), Err(Module { index: 52, error: [1, 0] })); // Burning can only be done by the manager. mint_asset(ALICE, asset, BOB, amount); - assert_eq!(burn(addr.clone(), asset, BOB, 1), Err(Module { index: 52, error: 2 })); + assert_eq!(burn(addr.clone(), asset, BOB, 1), Err(Module { index: 52, error: [2, 0] })); let asset = create_asset_and_mint_to(addr.clone(), 2, BOB, amount); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(addr.clone(), asset); - assert_eq!(burn(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + assert_eq!( + burn(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: [16, 0] }) + ); thaw_asset(addr.clone(), asset); // Successful mint. let balance_before_burn = Assets::balance(asset, &BOB); @@ -541,6 +567,9 @@ fn burn_works() { assert_eq!(balance_after_burn, balance_before_burn - amount); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(addr.clone(), asset); - assert_eq!(burn(addr.clone(), asset, BOB, amount), Err(Module { index: 52, error: 16 })); + assert_eq!( + burn(addr.clone(), asset, BOB, amount), + Err(Module { index: 52, error: [16, 0] }) + ); }); } diff --git a/pop-api/integration-tests/src/lib.rs b/pop-api/integration-tests/src/lib.rs index b728fca6..1dab5b85 100644 --- a/pop-api/integration-tests/src/lib.rs +++ b/pop-api/integration-tests/src/lib.rs @@ -76,6 +76,7 @@ fn bare_call( CollectEvents::Skip, Determinism::Enforced, ); + log::info!("contract exec result={result:?}"); result.result } diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 4f270e6b..56d2f9af 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -485,7 +485,7 @@ mod tests { use super::FungiblesError; use crate::{ constants::{ASSETS, BALANCES}, - primitives::error::{ + primitives::{ ArithmeticError::*, Error::{self, *}, TokenError::*, @@ -524,11 +524,11 @@ mod tests { #[test] fn conversion_status_code_into_fungibles_error_works() { let other_errors = vec![ - Other { dispatch_error_index: 5, error_index: 5, error: 1 }, + Other, CannotLookup, BadOrigin, // `ModuleError` other than assets module. - Module { index: 2, error: 5 }, + Module { index: 2, error: [5, 0] }, ConsumerRemaining, NoProviders, TooManyConsumers, @@ -539,7 +539,7 @@ mod tests { Corruption, Unavailable, RootNotAllowed, - UnknownCall, + Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, DecodingFailed, ]; for error in other_errors { @@ -549,32 +549,35 @@ mod tests { } assert_eq!( - into_fungibles_error(Module { index: BALANCES, error: 2 }), + into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), FungiblesError::NoBalance ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: 0 }), + into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), FungiblesError::NoAccount ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: 1 }), + into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), FungiblesError::NoPermission ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: 2 }), + into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), FungiblesError::Unknown ); - assert_eq!(into_fungibles_error(Module { index: ASSETS, error: 3 }), FungiblesError::InUse); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: 5 }), + into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), + FungiblesError::InUse + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), FungiblesError::MinBalanceZero ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: 7 }), + into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), FungiblesError::InsufficientAllowance ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: 10 }), + into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), FungiblesError::AssetNotLive ); } diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index a4824327..55732e2d 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -1,7 +1,7 @@ use crate::{ build_extension_method, constants::{DISPATCH, READ_STATE}, - primitives::error::Error, + primitives::Error, StatusCode, }; use ink::env::chain_extension::ChainExtensionMethod; diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index a51661ea..e15b142c 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -3,14 +3,16 @@ use codec::{Decode, Encode}; #[cfg(feature = "std")] use scale_info::TypeInfo; -pub use v0::error; +pub use v0::*; /// Identifier for the class of asset. pub type AssetId = u32; pub mod v0 { use super::*; - pub mod error { + pub use error::*; + + mod error { use super::*; /// Reason why a Pop API call failed. @@ -19,25 +21,21 @@ pub mod v0 { #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Error { - /// An unknown error occurred. This variant captures any unexpected errors that the - /// contract cannot specifically handle. It is useful for cases where there are breaking - /// changes in the runtime or when an error falls outside the predefined categories. The - /// variant includes: - /// - /// - `dispatch_error_index`: The index within the `DispatchError`. - /// - `error_index`: The index within the `DispatchError` variant (e.g. a `TokenError`). - /// - `error`: The specific error code or sub-index, providing additional context (e.g. - /// `error` in `ModuleError`). - Other { dispatch_error_index: u8, error_index: u8, error: u8 } = 0, - /// Failed to lookup some data. + /// Some error occurred. + Other = 0, + /// Failed to look up some data. CannotLookup = 1, /// A bad origin. BadOrigin = 2, /// A custom error in a module. - /// - /// - `index`: The pallet index. - /// - `error`: The error within the pallet. - Module { index: u8, error: u8 } = 3, + Module { + /// The pallet index. + index: u8, + /// The error within the pallet. + // Supports a single level of nested error only, due to status code type size + // constraints. + error: [u8; 2], + } = 3, /// At least one consumer is remaining so the account cannot be destroyed. ConsumerRemaining = 4, /// There are no providers so the account cannot be created. @@ -48,21 +46,34 @@ pub mod v0 { Token(TokenError) = 7, /// An arithmetic error. Arithmetic(ArithmeticError) = 8, - /// The number of transactional layers has been reached, or we are not in a transactional - /// layer. + /// The number of transactional layers has been reached, or we are not in a + /// transactional layer. Transactional(TransactionalError) = 9, - /// Resources exhausted, e.g. attempt to read/write data which is too large to manipulate. + /// Resources exhausted, e.g. attempt to read/write data which is too large to + /// manipulate. Exhausted = 10, /// The state is corrupt; this is generally not going to fix itself. Corruption = 11, - /// Some resource (e.g. a preimage) is unavailable right now. This might fix itself later. + /// Some resource (e.g. a preimage) is unavailable right now. This might fix itself + /// later. Unavailable = 12, /// Root origin is not allowed. RootNotAllowed = 13, - /// Unknown call. - UnknownCall = 254, /// Decoding failed. - DecodingFailed = 255, + DecodingFailed = 254, + /// An unknown error occurred. This variant captures any unexpected errors that the + /// contract cannot specifically handle. It is useful for cases where there are + /// breaking changes in the runtime or when an error falls outside the predefined + /// categories. + Unknown { + /// The index within the `DispatchError`. + dispatch_error_index: u8, + /// The index within the `DispatchError` variant (e.g. a `TokenError`). + error_index: u8, + /// The specific error code or sub-index, providing additional context (e.g. + /// `error` in `ModuleError`). + error: u8, + } = 255, } impl From for Error { @@ -77,14 +88,26 @@ pub mod v0 { } } + impl From for u32 { + fn from(value: Error) -> Self { + let mut encoded_error = value.encode(); + // Resize the encoded value to 4 bytes in order to decode the value into a u32 (4 + // bytes). + encoded_error.resize(4, 0); + u32::from_le_bytes( + encoded_error.try_into().expect("qed, resized to 4 bytes line above"), + ) + } + } + /// Description of what went wrong when trying to complete an operation on a token. #[derive(Encode, Decode, Debug, Eq, PartialEq)] #[cfg_attr(feature = "std", derive(TypeInfo))] pub enum TokenError { /// Funds are unavailable. FundsUnavailable, - /// Some part of the balance gives the only provider reference to the account and thus cannot - /// be (re)moved. + /// Some part of the balance gives the only provider reference to the account and thus + /// cannot be (re)moved. OnlyProvider, /// Account cannot exist with the funds that would be given. BelowMinimum, diff --git a/runtime/devnet/src/config/api.rs b/runtime/devnet/src/config/api.rs deleted file mode 100644 index 4a404c99..00000000 --- a/runtime/devnet/src/config/api.rs +++ /dev/null @@ -1,68 +0,0 @@ -use crate::{ - config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall, RuntimeEvent, -}; -use codec::{Decode, Encode, MaxEncodedLen}; -use pop_chain_extension::{CallFilter, ReadState}; -use sp_std::vec::Vec; - -/// A query of runtime state. -#[derive(Encode, Decode, Debug, MaxEncodedLen)] -#[repr(u8)] -pub enum RuntimeRead { - /// Fungible token queries. - #[codec(index = 150)] - Fungibles(fungibles::Read), -} - -/// A struct that implement requirements for the Pop API chain extension. -#[derive(Default)] -pub struct Extension; -impl ReadState for Extension { - type StateQuery = RuntimeRead; - - fn contains(c: &Self::StateQuery) -> bool { - use fungibles::Read::*; - matches!( - c, - RuntimeRead::Fungibles( - TotalSupply(..) - | BalanceOf { .. } | Allowance { .. } - | TokenName(..) | TokenSymbol(..) - | TokenDecimals(..) | AssetExists(..) - ) - ) - } - - fn read(read: RuntimeRead) -> Vec { - match read { - RuntimeRead::Fungibles(key) => fungibles::Pallet::read_state(key), - } - } -} - -impl CallFilter for Extension { - type Call = RuntimeCall; - - fn contains(c: &Self::Call) -> bool { - use fungibles::Call::*; - matches!( - c, - RuntimeCall::Fungibles( - transfer { .. } - | transfer_from { .. } - | approve { .. } | increase_allowance { .. } - | decrease_allowance { .. } - | create { .. } | set_metadata { .. } - | start_destroy { .. } - | clear_metadata { .. } - | mint { .. } | burn { .. } - ) - ) - } -} - -impl fungibles::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type AssetsInstance = TrustBackedAssetsInstance; - type WeightInfo = fungibles::weights::SubstrateWeight; -} diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs new file mode 100644 index 00000000..ac956eb2 --- /dev/null +++ b/runtime/devnet/src/config/api/mod.rs @@ -0,0 +1,213 @@ +use crate::{ + config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall, RuntimeEvent, +}; +use codec::Decode; +use core::marker::PhantomData; +use cumulus_primitives_core::Weight; +use frame_support::traits::Contains; +pub(crate) use pallet_api::Extension; +use pallet_api::{extension::*, Read}; +use sp_core::ConstU8; +use sp_runtime::DispatchError; +use sp_std::vec::Vec; +use versioning::*; + +mod versioning; + +type DecodingFailedError = DecodingFailed; +type DecodesAs = pallet_api::extension::DecodesAs< + Output, + ContractWeightsOf, + DecodingFailedError, + Logger, +>; + +/// A query of runtime state. +#[derive(Decode, Debug)] +#[repr(u8)] +pub enum RuntimeRead { + /// Fungible token queries. + #[codec(index = 150)] + Fungibles(fungibles::Read), +} + +impl Readable for RuntimeRead { + /// The corresponding type carrying the result of the query for runtime state. + type Result = RuntimeResult; + + /// Determines the weight of the read, used to charge the appropriate weight before the read is + /// performed. + fn weight(&self) -> Weight { + match self { + RuntimeRead::Fungibles(key) => fungibles::Pallet::weight(key), + } + } + + /// Performs the read and returns the result. + fn read(self) -> Self::Result { + match self { + RuntimeRead::Fungibles(key) => RuntimeResult::Fungibles(fungibles::Pallet::read(key)), + } + } +} + +/// The result of a runtime state read. +#[derive(Debug)] +pub enum RuntimeResult { + /// Fungible token read results. + Fungibles(fungibles::ReadResult), +} + +impl RuntimeResult { + /// Encodes the result. + fn encode(&self) -> Vec { + match self { + RuntimeResult::Fungibles(result) => result.encode(), + } + } +} + +impl fungibles::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type AssetsInstance = TrustBackedAssetsInstance; + type WeightInfo = fungibles::weights::SubstrateWeight; +} + +#[derive(Default)] +pub struct Config; +impl pallet_api::extension::Config for Config { + /// Functions used by the Pop API. + /// + /// Each function corresponds to specific functionality provided by the API, facilitating the + /// interaction between smart contracts and the runtime. + type Functions = ( + // Dispatching calls + DispatchCall< + // Function ID: 0. + IdentifiedByFirstByteOfFunctionId>, + // The runtime configuration. + Runtime, + // Decode as a versioned runtime call. + DecodesAs, + // Apply any filtering. + Filter, + // Ensure errors are versioned. + VersionedErrorConverter, + // Logging with a specific target. + DispatchCallLogTarget, + >, + // Reading state + ReadState< + // Function ID: 1. + IdentifiedByFirstByteOfFunctionId>, + // The runtime configuration. + Runtime, + // The runtime state reads available. + RuntimeRead, + // Decode as a versioned runtime read. + DecodesAs, + // Apply any filtering. + Filter, + // Convert the result of a read into the expected versioned result + VersionedResultConverter, + // Ensure errors are versioned. + VersionedErrorConverter, + // Logging with a specific target. + ReadStateLogTarget, + >, + ); + + /// The log target. + const LOG_TARGET: &'static str = LOG_TARGET; +} + +/// Filters used by the chain extension. +pub struct Filter(PhantomData); + +impl> Contains for Filter { + fn contains(c: &RuntimeCall) -> bool { + use fungibles::Call::*; + T::BaseCallFilter::contains(c) && + matches!( + c, + RuntimeCall::Fungibles( + transfer { .. } | + transfer_from { .. } | + approve { .. } | increase_allowance { .. } | + decrease_allowance { .. } | + create { .. } | set_metadata { .. } | + start_destroy { .. } | + clear_metadata { .. } | + mint { .. } | burn { .. } + ) + ) + } +} + +impl Contains for Filter { + fn contains(r: &RuntimeRead) -> bool { + use fungibles::Read::*; + matches!( + r, + RuntimeRead::Fungibles( + TotalSupply(..) | + BalanceOf { .. } | + Allowance { .. } | + TokenName(..) | TokenSymbol(..) | + TokenDecimals(..) | + AssetExists(..) + ) + ) + } +} + +#[test] +fn filter_prevents_runtime_filtered_calls() { + use pallet_balances::{AdjustmentDirection, Call::*}; + use sp_runtime::MultiAddress; + use RuntimeCall::Balances; + + const CALLS: [RuntimeCall; 4] = [ + Balances(force_adjust_total_issuance { + direction: AdjustmentDirection::Increase, + delta: 0, + }), + Balances(force_set_balance { who: MultiAddress::Address32([0u8; 32]), new_free: 0 }), + Balances(force_transfer { + source: MultiAddress::Address32([0u8; 32]), + dest: MultiAddress::Address32([0u8; 32]), + value: 0, + }), + Balances(force_unreserve { who: MultiAddress::Address32([0u8; 32]), amount: 0 }), + ]; + + for call in CALLS { + assert!(!Filter::::contains(&call)) + } +} + +#[test] +fn filter_allows_fungibles_calls() { + use pallet_api::fungibles::Call::*; + use sp_core::crypto::AccountId32; + use RuntimeCall::Fungibles; + + const ACCOUNT: AccountId32 = AccountId32::new([0u8; 32]); + const CALLS: [RuntimeCall; 11] = [ + Fungibles(transfer { asset: 0, to: ACCOUNT, value: 0 }), + Fungibles(transfer_from { asset: 0, from: ACCOUNT, to: ACCOUNT, value: 0 }), + Fungibles(approve { asset: 0, spender: ACCOUNT, value: 0 }), + Fungibles(increase_allowance { asset: 0, spender: ACCOUNT, value: 0 }), + Fungibles(decrease_allowance { asset: 0, spender: ACCOUNT, value: 0 }), + Fungibles(create { id: 0, admin: ACCOUNT, min_balance: 0 }), + Fungibles(set_metadata { asset: 0, name: vec![], symbol: vec![], decimals: 0 }), + Fungibles(start_destroy { asset: 0 }), + Fungibles(clear_metadata { asset: 0 }), + Fungibles(mint { asset: 0, account: ACCOUNT, value: 0 }), + Fungibles(burn { asset: 0, account: ACCOUNT, value: 0 }), + ]; + + for call in CALLS { + assert!(Filter::::contains(&call)) + } +} diff --git a/runtime/devnet/src/config/api/versioning.rs b/runtime/devnet/src/config/api/versioning.rs new file mode 100644 index 00000000..50041340 --- /dev/null +++ b/runtime/devnet/src/config/api/versioning.rs @@ -0,0 +1,218 @@ +use super::*; +use sp_runtime::ModuleError; + +type Version = u8; + +/// Versioned runtime calls. +#[derive(Decode, Debug)] +pub enum VersionedRuntimeCall { + /// Version zero of runtime calls. + #[codec(index = 0)] + V0(RuntimeCall), +} + +impl From for RuntimeCall { + fn from(value: VersionedRuntimeCall) -> Self { + // Allows mapping from some previous runtime call shape to a current valid runtime call + match value { + VersionedRuntimeCall::V0(call) => call, + } + } +} + +/// Versioned runtime state reads. +#[derive(Decode, Debug)] +pub enum VersionedRuntimeRead { + /// Version zero of runtime state reads. + #[codec(index = 0)] + V0(RuntimeRead), +} + +impl From for RuntimeRead { + fn from(value: VersionedRuntimeRead) -> Self { + // Allows mapping from some previous runtime read shape to a current valid runtime read + match value { + VersionedRuntimeRead::V0(read) => read, + } + } +} + +/// Versioned runtime state read results. +#[derive(Debug)] +pub enum VersionedRuntimeResult { + /// Version zero of runtime read results. + V0(RuntimeResult), +} + +impl From<(RuntimeResult, Version)> for VersionedRuntimeResult { + fn from(value: (RuntimeResult, Version)) -> Self { + let (result, version) = value; + match version { + // Allows mapping from current `RuntimeResult` to a specific/prior version + 0 => VersionedRuntimeResult::V0(result), + // TODO: should never occur due to version processing/validation when request received + _ => unimplemented!(), + } + } +} + +impl From for Vec { + fn from(result: VersionedRuntimeResult) -> Self { + match result { + // Simply unwrap and return the encoded result + VersionedRuntimeResult::V0(result) => result.encode(), + } + } +} + +/// Versioned errors. +#[derive(Debug)] +pub enum VersionedError { + /// Version zero of errors. + V0(pop_primitives::v0::Error), +} + +impl From<(DispatchError, Version)> for VersionedError { + fn from(value: (DispatchError, Version)) -> Self { + let (error, version) = value; + match version { + // Allows mapping from current `DispatchError` to a specific/prior version of `Error` + 0 => VersionedError::V0(V0Error::from(error).0), + // TODO: should never occur due to version processing/validation when request received + _ => unimplemented!(), + } + } +} + +impl From for u32 { + fn from(value: VersionedError) -> Self { + match value { + VersionedError::V0(error) => error.into(), + } + } +} + +struct V0Error(pop_primitives::v0::Error); +impl From for V0Error { + fn from(error: DispatchError) -> Self { + use pop_primitives::v0::*; + use sp_runtime::{ArithmeticError::*, TokenError::*, TransactionalError::*}; + use DispatchError::*; + // Mappings exist here to avoid taking a dependency of sp_runtime on pop-primitives + Self(match error { + Other(_message) => { + // Note: lossy conversion: message not used due to returned contract status code + // size limitation + Error::Other + }, + CannotLookup => Error::CannotLookup, + BadOrigin => Error::BadOrigin, + Module(error) => { + // Note: message not used + let ModuleError { index, error, message: _message } = error; + // Map `pallet-contracts::Error::DecodingFailed` to `Error::DecodingFailed` + if index as usize == + ::index() && + error == DECODING_FAILED_ERROR + { + Error::DecodingFailed + } else { + // Note: lossy conversion of error value due to returned contract status code + // size limitation + Error::Module { index, error: [error[0], error[1]] } + } + }, + ConsumerRemaining => Error::ConsumerRemaining, + NoProviders => Error::NoProviders, + TooManyConsumers => Error::TooManyConsumers, + Token(error) => Error::Token(match error { + FundsUnavailable => TokenError::FundsUnavailable, + OnlyProvider => TokenError::OnlyProvider, + BelowMinimum => TokenError::BelowMinimum, + CannotCreate => TokenError::CannotCreate, + UnknownAsset => TokenError::UnknownAsset, + Frozen => TokenError::Frozen, + Unsupported => TokenError::Unsupported, + CannotCreateHold => TokenError::CannotCreateHold, + NotExpendable => TokenError::NotExpendable, + Blocked => TokenError::Blocked, + }), + Arithmetic(error) => Error::Arithmetic(match error { + Underflow => ArithmeticError::Underflow, + Overflow => ArithmeticError::Overflow, + DivisionByZero => ArithmeticError::DivisionByZero, + }), + Transactional(error) => Error::Transactional(match error { + LimitReached => TransactionalError::LimitReached, + NoLayer => TransactionalError::NoLayer, + }), + Exhausted => Error::Exhausted, + Corruption => Error::Corruption, + Unavailable => Error::Unavailable, + RootNotAllowed => Error::RootNotAllowed, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use pop_primitives::{ArithmeticError::*, Error, TokenError::*, TransactionalError::*}; + use sp_runtime::ModuleError; + use DispatchError::*; + + // Compare all the different `DispatchError` variants with the expected `Error`. + #[test] + fn dispatch_error_to_error() { + let test_cases = vec![ + (Other(""), (Error::Other)), + (Other("UnknownCall"), Error::Other), + (Other("DecodingFailed"), Error::Other), + (Other("Random"), (Error::Other)), + (CannotLookup, Error::CannotLookup), + (BadOrigin, Error::BadOrigin), + ( + Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: Some("hallo") }), + Error::Module { index: 1, error: [2, 0] }, + ), + ( + Module(ModuleError { index: 1, error: [2, 2, 0, 0], message: Some("hallo") }), + Error::Module { index: 1, error: [2, 2] }, + ), + ( + Module(ModuleError { index: 1, error: [2, 2, 2, 0], message: Some("hallo") }), + Error::Module { index: 1, error: [2, 2] }, + ), + ( + Module(ModuleError { index: 1, error: [2, 2, 2, 4], message: Some("hallo") }), + Error::Module { index: 1, error: [2, 2] }, + ), + (pallet_contracts::Error::::DecodingFailed.into(), Error::DecodingFailed), + (ConsumerRemaining, Error::ConsumerRemaining), + (NoProviders, Error::NoProviders), + (TooManyConsumers, Error::TooManyConsumers), + (Token(sp_runtime::TokenError::BelowMinimum), Error::Token(BelowMinimum)), + (Arithmetic(sp_runtime::ArithmeticError::Overflow), Error::Arithmetic(Overflow)), + ( + Transactional(sp_runtime::TransactionalError::LimitReached), + Error::Transactional(LimitReached), + ), + (Exhausted, Error::Exhausted), + (Corruption, Error::Corruption), + (Unavailable, Error::Unavailable), + (RootNotAllowed, Error::RootNotAllowed), + ]; + for (dispatch_error, expected) in test_cases { + let error = V0Error::from(dispatch_error).0; + assert_eq!(error, expected); + } + } + + #[test] + fn decoding_failed_error_encoding_works() { + let Module(error) = pallet_contracts::Error::::DecodingFailed.into() else { + unreachable!() + }; + assert_eq!(error.error, DECODING_FAILED_ERROR) + } +} diff --git a/runtime/devnet/src/config/contracts.rs b/runtime/devnet/src/config/contracts.rs index 5dc613b5..67a2f33c 100644 --- a/runtime/devnet/src/config/contracts.rs +++ b/runtime/devnet/src/config/contracts.rs @@ -1,4 +1,4 @@ -use super::api::Extension; +use super::api::{self, Config}; use crate::{ deposit, Balance, Balances, BalancesCall, Perbill, Runtime, RuntimeCall, RuntimeEvent, RuntimeHoldReason, Timestamp, @@ -64,7 +64,7 @@ impl pallet_contracts::Config for Runtime { type CallStack = [pallet_contracts::Frame; 23]; type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; - type ChainExtension = pop_chain_extension::ApiExtension; + type ChainExtension = api::Extension; type Schedule = Schedule; type AddressGenerator = pallet_contracts::DefaultAddressGenerator; // This node is geared towards development and testing of contracts. diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index 07d5f0f8..c1142126 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -13,77 +13,77 @@ impl InstanceFilter for ProxyType { ProxyType::Any => true, ProxyType::NonTransfer => !matches!( c, - RuntimeCall::Balances { .. } - | RuntimeCall::Assets { .. } - | RuntimeCall::Nfts { .. } + RuntimeCall::Balances { .. } | + RuntimeCall::Assets { .. } | + RuntimeCall::Nfts { .. } ), ProxyType::CancelProxy => matches!( c, - RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), ProxyType::Assets => { matches!( c, - RuntimeCall::Assets { .. } - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } - | RuntimeCall::Nfts { .. } + RuntimeCall::Assets { .. } | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } | + RuntimeCall::Nfts { .. } ) }, ProxyType::AssetOwner => matches!( c, - RuntimeCall::Assets(AssetsCall::create { .. }) - | RuntimeCall::Assets(AssetsCall::start_destroy { .. }) - | RuntimeCall::Assets(AssetsCall::destroy_accounts { .. }) - | RuntimeCall::Assets(AssetsCall::destroy_approvals { .. }) - | RuntimeCall::Assets(AssetsCall::finish_destroy { .. }) - | RuntimeCall::Assets(AssetsCall::transfer_ownership { .. }) - | RuntimeCall::Assets(AssetsCall::set_team { .. }) - | RuntimeCall::Assets(AssetsCall::set_metadata { .. }) - | RuntimeCall::Assets(AssetsCall::clear_metadata { .. }) - | RuntimeCall::Assets(AssetsCall::set_min_balance { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::Assets(AssetsCall::create { .. }) | + RuntimeCall::Assets(AssetsCall::start_destroy { .. }) | + RuntimeCall::Assets(AssetsCall::destroy_accounts { .. }) | + RuntimeCall::Assets(AssetsCall::destroy_approvals { .. }) | + RuntimeCall::Assets(AssetsCall::finish_destroy { .. }) | + RuntimeCall::Assets(AssetsCall::transfer_ownership { .. }) | + RuntimeCall::Assets(AssetsCall::set_team { .. }) | + RuntimeCall::Assets(AssetsCall::set_metadata { .. }) | + RuntimeCall::Assets(AssetsCall::clear_metadata { .. }) | + RuntimeCall::Assets(AssetsCall::set_min_balance { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), ProxyType::AssetManager => matches!( c, - RuntimeCall::Assets(AssetsCall::mint { .. }) - | RuntimeCall::Assets(AssetsCall::burn { .. }) - | RuntimeCall::Assets(AssetsCall::freeze { .. }) - | RuntimeCall::Assets(AssetsCall::block { .. }) - | RuntimeCall::Assets(AssetsCall::thaw { .. }) - | RuntimeCall::Assets(AssetsCall::freeze_asset { .. }) - | RuntimeCall::Assets(AssetsCall::thaw_asset { .. }) - | RuntimeCall::Assets(AssetsCall::touch_other { .. }) - | RuntimeCall::Assets(AssetsCall::refund_other { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::Assets(AssetsCall::mint { .. }) | + RuntimeCall::Assets(AssetsCall::burn { .. }) | + RuntimeCall::Assets(AssetsCall::freeze { .. }) | + RuntimeCall::Assets(AssetsCall::block { .. }) | + RuntimeCall::Assets(AssetsCall::thaw { .. }) | + RuntimeCall::Assets(AssetsCall::freeze_asset { .. }) | + RuntimeCall::Assets(AssetsCall::thaw_asset { .. }) | + RuntimeCall::Assets(AssetsCall::touch_other { .. }) | + RuntimeCall::Assets(AssetsCall::refund_other { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), ProxyType::Collator => matches!( c, - RuntimeCall::CollatorSelection { .. } - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::CollatorSelection { .. } | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), } } diff --git a/runtime/devnet/src/config/xcm.rs b/runtime/devnet/src/config/xcm.rs index b58baf2f..a5b7a04d 100644 --- a/runtime/devnet/src/config/xcm.rs +++ b/runtime/devnet/src/config/xcm.rs @@ -116,8 +116,8 @@ pub struct NativeAssetFrom(PhantomData); impl> ContainsPair for NativeAssetFrom { fn contains(asset: &Asset, origin: &Location) -> bool { let loc = T::get(); - &loc == origin - && matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) } + &loc == origin && + matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) } if *asset_loc == Location::from(Parent)) } } diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index e1ef6c6d..4f4b2e22 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -242,10 +242,10 @@ impl Contains for FilteredCalls { matches!( c, RuntimeCall::Balances( - force_adjust_total_issuance { .. } - | force_set_balance { .. } - | force_transfer { .. } - | force_unreserve { .. } + force_adjust_total_issuance { .. } | + force_set_balance { .. } | + force_transfer { .. } | + force_unreserve { .. } ) ) } diff --git a/runtime/testnet/src/config/proxy.rs b/runtime/testnet/src/config/proxy.rs index 07d5f0f8..c1142126 100644 --- a/runtime/testnet/src/config/proxy.rs +++ b/runtime/testnet/src/config/proxy.rs @@ -13,77 +13,77 @@ impl InstanceFilter for ProxyType { ProxyType::Any => true, ProxyType::NonTransfer => !matches!( c, - RuntimeCall::Balances { .. } - | RuntimeCall::Assets { .. } - | RuntimeCall::Nfts { .. } + RuntimeCall::Balances { .. } | + RuntimeCall::Assets { .. } | + RuntimeCall::Nfts { .. } ), ProxyType::CancelProxy => matches!( c, - RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), ProxyType::Assets => { matches!( c, - RuntimeCall::Assets { .. } - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } - | RuntimeCall::Nfts { .. } + RuntimeCall::Assets { .. } | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } | + RuntimeCall::Nfts { .. } ) }, ProxyType::AssetOwner => matches!( c, - RuntimeCall::Assets(AssetsCall::create { .. }) - | RuntimeCall::Assets(AssetsCall::start_destroy { .. }) - | RuntimeCall::Assets(AssetsCall::destroy_accounts { .. }) - | RuntimeCall::Assets(AssetsCall::destroy_approvals { .. }) - | RuntimeCall::Assets(AssetsCall::finish_destroy { .. }) - | RuntimeCall::Assets(AssetsCall::transfer_ownership { .. }) - | RuntimeCall::Assets(AssetsCall::set_team { .. }) - | RuntimeCall::Assets(AssetsCall::set_metadata { .. }) - | RuntimeCall::Assets(AssetsCall::clear_metadata { .. }) - | RuntimeCall::Assets(AssetsCall::set_min_balance { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::Assets(AssetsCall::create { .. }) | + RuntimeCall::Assets(AssetsCall::start_destroy { .. }) | + RuntimeCall::Assets(AssetsCall::destroy_accounts { .. }) | + RuntimeCall::Assets(AssetsCall::destroy_approvals { .. }) | + RuntimeCall::Assets(AssetsCall::finish_destroy { .. }) | + RuntimeCall::Assets(AssetsCall::transfer_ownership { .. }) | + RuntimeCall::Assets(AssetsCall::set_team { .. }) | + RuntimeCall::Assets(AssetsCall::set_metadata { .. }) | + RuntimeCall::Assets(AssetsCall::clear_metadata { .. }) | + RuntimeCall::Assets(AssetsCall::set_min_balance { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), ProxyType::AssetManager => matches!( c, - RuntimeCall::Assets(AssetsCall::mint { .. }) - | RuntimeCall::Assets(AssetsCall::burn { .. }) - | RuntimeCall::Assets(AssetsCall::freeze { .. }) - | RuntimeCall::Assets(AssetsCall::block { .. }) - | RuntimeCall::Assets(AssetsCall::thaw { .. }) - | RuntimeCall::Assets(AssetsCall::freeze_asset { .. }) - | RuntimeCall::Assets(AssetsCall::thaw_asset { .. }) - | RuntimeCall::Assets(AssetsCall::touch_other { .. }) - | RuntimeCall::Assets(AssetsCall::refund_other { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::Assets(AssetsCall::mint { .. }) | + RuntimeCall::Assets(AssetsCall::burn { .. }) | + RuntimeCall::Assets(AssetsCall::freeze { .. }) | + RuntimeCall::Assets(AssetsCall::block { .. }) | + RuntimeCall::Assets(AssetsCall::thaw { .. }) | + RuntimeCall::Assets(AssetsCall::freeze_asset { .. }) | + RuntimeCall::Assets(AssetsCall::thaw_asset { .. }) | + RuntimeCall::Assets(AssetsCall::touch_other { .. }) | + RuntimeCall::Assets(AssetsCall::refund_other { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), ProxyType::Collator => matches!( c, - RuntimeCall::CollatorSelection { .. } - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::CollatorSelection { .. } | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), } } diff --git a/runtime/testnet/src/config/xcm.rs b/runtime/testnet/src/config/xcm.rs index b58baf2f..a5b7a04d 100644 --- a/runtime/testnet/src/config/xcm.rs +++ b/runtime/testnet/src/config/xcm.rs @@ -116,8 +116,8 @@ pub struct NativeAssetFrom(PhantomData); impl> ContainsPair for NativeAssetFrom { fn contains(asset: &Asset, origin: &Location) -> bool { let loc = T::get(); - &loc == origin - && matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) } + &loc == origin && + matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) } if *asset_loc == Location::from(Parent)) } } diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index a6e309f9..fc228b03 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -1,7 +1,7 @@ -use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, + traits::{Contains, OriginTrait}, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index 52104c43..700257fa 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -244,10 +244,10 @@ impl Contains for FilteredCalls { matches!( c, RuntimeCall::Balances( - force_adjust_total_issuance { .. } - | force_set_balance { .. } - | force_transfer { .. } - | force_unreserve { .. } + force_adjust_total_issuance { .. } | + force_set_balance { .. } | + force_transfer { .. } | + force_unreserve { .. } ) ) } From ec49dc3aea6f6b1a9c15e89eeed724ac59f92509 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Sat, 7 Sep 2024 20:42:55 +0700 Subject: [PATCH 050/161] chore: resolve conflicts for `daan/api` (#267) Signed-off-by: dependabot[bot] Co-authored-by: Frank Bell Co-authored-by: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> Co-authored-by: Peter White Co-authored-by: Daanvdplas Co-authored-by: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alex Bean Co-authored-by: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> --- .githooks/README.md | 41 + .githooks/pre-push | 49 + .github/ISSUE_TEMPLATE/release_tracking.md | 97 + .github/workflows/ci.yml | 16 + .github/workflows/release.yml | 6 +- .rustfmt.toml | 32 +- .taplo.toml | 17 + Cargo.lock | 4269 +++++++++++------ Cargo.toml | 267 +- README.md | 2 +- extension/Cargo.toml | 52 +- extension/contract/Cargo.toml | 10 +- extension/src/decoding.rs | 12 +- extension/src/environment.rs | 5 +- extension/src/functions.rs | 29 +- extension/src/lib.rs | 6 +- extension/src/matching.rs | 3 +- extension/src/mock.rs | 65 +- extension/src/tests.rs | 9 +- integration-tests/Cargo.toml | 106 +- .../src/chains/asset_hub_paseo/mod.rs | 5 +- integration-tests/src/chains/paseo/genesis.rs | 14 +- integration-tests/src/chains/paseo/mod.rs | 5 +- .../src/chains/pop_network/mod.rs | 24 +- integration-tests/src/lib.rs | 29 +- networks/mainnet.toml | 40 + networks/testnet.toml | 10 +- node/Cargo.toml | 66 +- node/src/chain_spec.rs | 154 +- node/src/cli.rs | 5 - node/src/command.rs | 113 +- node/src/rpc.rs | 1 - node/src/service.rs | 185 +- pallets/api/Cargo.toml | 47 +- pallets/api/src/extension.rs | 7 +- pallets/api/src/fungibles/benchmarking.rs | 3 +- pallets/api/src/fungibles/mod.rs | 4 +- pallets/api/src/fungibles/tests.rs | 3 +- pallets/api/src/mock.rs | 66 +- pop-api/Cargo.toml | 23 +- pop-api/examples/balance-transfer/Cargo.toml | 22 +- pop-api/examples/fungibles/Cargo.toml | 16 +- pop-api/examples/fungibles/lib.rs | 2 +- pop-api/examples/nfts/Cargo.toml | 22 +- pop-api/examples/place-spot-order/Cargo.toml | 22 +- .../examples/read-runtime-state/Cargo.toml | 22 +- pop-api/integration-tests/Cargo.toml | 49 +- .../integration-tests/contracts/.gitignore | 9 - .../create_token_in_constructor/Cargo.toml | 16 +- .../contracts/fungibles/Cargo.toml | 16 +- .../integration-tests/src/fungibles/mod.rs | 2 +- pop-api/integration-tests/src/lib.rs | 2 +- primitives/Cargo.toml | 11 +- primitives/src/lib.rs | 3 +- runtime/common/Cargo.toml | 18 +- runtime/common/src/lib.rs | 11 +- runtime/devnet/Cargo.toml | 293 +- runtime/devnet/build.rs | 13 +- runtime/devnet/src/config/api/mod.rs | 12 +- runtime/devnet/src/config/api/versioning.rs | 6 +- runtime/devnet/src/config/assets.rs | 86 +- runtime/devnet/src/config/contracts.rs | 52 +- runtime/devnet/src/config/proxy.rs | 59 +- runtime/devnet/src/config/xcm.rs | 109 +- runtime/devnet/src/lib.rs | 394 +- .../devnet/src/weights/paritydb_weights.rs | 3 +- runtime/devnet/src/weights/rocksdb_weights.rs | 3 +- runtime/mainnet/Cargo.toml | 220 + runtime/mainnet/build.rs | 16 + runtime/mainnet/src/config/mod.rs | 2 + runtime/mainnet/src/config/proxy.rs | 57 + runtime/mainnet/src/config/xcm.rs | 213 + runtime/mainnet/src/lib.rs | 1015 ++++ runtime/mainnet/src/weights/block_weights.rs | 53 + .../mainnet/src/weights/extrinsic_weights.rs | 53 + runtime/mainnet/src/weights/mod.rs | 27 + .../mainnet/src/weights/paritydb_weights.rs | 64 + .../mainnet/src/weights/rocksdb_weights.rs | 64 + runtime/testnet/Cargo.toml | 284 +- runtime/testnet/build.rs | 13 +- runtime/testnet/src/config/assets.rs | 95 +- runtime/testnet/src/config/contracts.rs | 52 +- runtime/testnet/src/config/proxy.rs | 59 +- runtime/testnet/src/config/xcm.rs | 109 +- runtime/testnet/src/extensions.rs | 28 +- runtime/testnet/src/lib.rs | 392 +- .../testnet/src/weights/paritydb_weights.rs | 3 +- .../testnet/src/weights/rocksdb_weights.rs | 3 +- rust-toolchain.toml | 4 +- tests/contracts/filtered-call/Cargo.toml | 18 +- 90 files changed, 6766 insertions(+), 3248 deletions(-) create mode 100644 .githooks/README.md create mode 100755 .githooks/pre-push create mode 100644 .github/ISSUE_TEMPLATE/release_tracking.md create mode 100644 .taplo.toml create mode 100644 networks/mainnet.toml delete mode 100755 pop-api/integration-tests/contracts/.gitignore create mode 100644 runtime/mainnet/Cargo.toml create mode 100644 runtime/mainnet/build.rs create mode 100644 runtime/mainnet/src/config/mod.rs create mode 100644 runtime/mainnet/src/config/proxy.rs create mode 100644 runtime/mainnet/src/config/xcm.rs create mode 100644 runtime/mainnet/src/lib.rs create mode 100644 runtime/mainnet/src/weights/block_weights.rs create mode 100644 runtime/mainnet/src/weights/extrinsic_weights.rs create mode 100644 runtime/mainnet/src/weights/mod.rs create mode 100644 runtime/mainnet/src/weights/paritydb_weights.rs create mode 100644 runtime/mainnet/src/weights/rocksdb_weights.rs diff --git a/.githooks/README.md b/.githooks/README.md new file mode 100644 index 00000000..3ea52c72 --- /dev/null +++ b/.githooks/README.md @@ -0,0 +1,41 @@ +# Git Hooks + +A pre-push hook which checks formatting of Rust files. Additional checks may be added in the future. + +# Prerequisites + +The following prerequisites are required: + +## Rust Nightly + +The nightly version of Rust provides additional formatting benefits over the stable version. + +```shell +rustup toolchain install nightly --profile minimal --component rustfmt +``` + +## Taplo + +Formatting of TOML documents is done via `taplo`. +Find more about taplo [here](https://taplo.tamasfe.dev/). + +``` +cargo install taplo-cli --locked +``` + +## Zepter + +Analyze, fix and format features in your Rust workspace. +Find more about zepter [here](https://github.com/ggwpez/zepter). + +``` +cargo install zepter -f --locked +``` + +# Installation + +Use the following command in the root directory of the local repository to configure Git to use the hooks: + +```shell +git config core.hooksPath .githooks +``` diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 00000000..f50f255a --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,49 @@ +#!/bin/sh + +set -eu + +# Are deps installed +if ! command -v cargo > /dev/null 2>&1 +then + echo "cargo couldn't be found, please confirm your set up is properly configured." + exit 1 +else + # Check Rust formatting + if ! cargo +nightly fmt --all -- --check + then + echo "There are some code style issues." + # shellcheck disable=SC2006 + echo "Run 'cargo +nightly fmt --all' first." + exit 1 + fi +fi + +if ! command -v taplo > /dev/null 2>&1 +then + echo "taplo couldn't be found. Please, refer to .githooks/README.md." + exit 1 +else + # Check TOML formatting + if ! taplo format --check + then + echo "There are some code style issues." + echo "Run 'taplo fmt' first." + exit 1 + fi +fi + +if ! command -v zepter > /dev/null 2>&1 +then + echo "zepter couldn't be found. Please, refer to .githooks/README.md." + exit 1 +else + # Check for feature formatting + if ! zepter format features + then + echo "There are some code style issues." + echo "Run 'zepter format features --fix' first." + exit 1 + fi +fi + +exit 0 diff --git a/.github/ISSUE_TEMPLATE/release_tracking.md b/.github/ISSUE_TEMPLATE/release_tracking.md new file mode 100644 index 00000000..7ea4f8d2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/release_tracking.md @@ -0,0 +1,97 @@ +--- +name: New Release +about: Create a tracking issue for a new release. +title: '-v' +assignees: '' +--- + +## Release Readiness Tracking + +> _Node Release_ + +- [ ] All changes have passed peer-review. < link PR > +- [ ] `pop-node` crate version has been updated. +- [ ] The new binary is able to sync the live network and peers with other active nodes, logs are healthy. +- [ ] One collator runs with the new binary, syncs the network and peers with other nodes, produces blocks and logs are healthy. + +> _Runtime Release_ + +- [ ] All changes have passed peer-review. < link PR > +- [ ] Update runtime crate version. Note that `pop-runtime-devnet` is usually not updated. +- [ ] Runtime spec version is updated. +- [ ] If needed, new benchmarks have been run. A diff between the new weights and the current ones has been reviewed. + - [`substrate-weight-compare`](https://github.com/ggwpez/substrate-weight-compare) can be used for this purpose. +- [ ] Execution of [`try-runtime`](https://github.com/paritytech/try-runtime-cli) doesn't point out any missing migrations or other items requiring action. + + + +## Testing Tracking + +- [ ] Local upgrade test runs as expected. + +1. Build the latest release. +2. Launch a network using `pop up parachiain -f networks/testnet.toml -v`. + - `pop-node` version can be verified via: `rpc calls -> system -> version()` + - Runtime version can be verified via: `rpc calls -> state -> getRuntimeVersion()` + + +> _Node release_ + +3. Switch to the new release branch and rebuild. +4. Kill the running `pop-node` process +> For instance, on Mac one can look in Activity Monitor, find the `pop-node` process and force quit. The network will still be running, but without the collator so Pop Network might not be producing blocks. +6. Run the new `pop-node` binary using the command prompted in step `2`, with the same specs that are prompted at step `2`. +7. Verify that the new node is producing blocks. +8. Verify running versions as needed. + +> _Runtime release_ + +_The new runtime might need a certian `pop-node` version to be deployed first, if that is the case make sure you follow the above steps for a Node Release_ + +3. Do a runtime upgrade using the new runtime release -- can be found in `./target/release/wbuild/pop-runtime-testnet/pop_runtime_testnet.compact.compressed.wasm`. +4. Verify the runtime upgrade was successful: + - The runtime version should have changed. + - The corresponding migrations should have run. + - Pop Network is still producing blocks. + + +- [ ] Successful execution of `try-runtime` . +``` +cargo build --release --features=try-runtime -p +try-runtime --runtime ./target/release/wbuild/pop-runtime-testnet/pop_runtime_testnet.compact.compressed.wasm on-runtime-upgrade live --uri wss://rpc3.paseo.popnetwork.xyz:443 +``` + +- [ ] (Advised) Runtime upgrade on a local **fork** of Pop Network. + +_More instructions around using chopsticks for this can be found in [.chopsticks directory](../../.chopsticks)_ + +1. Launch the local fork: +```shell + npx @acala-network/chopsticks@latest xcm -r ./.chopsticks/paseo.yml -p ./.chopsticks/testnet.yml +``` +2. Do a runtime upgrade using the new runtime release -- can be found in `./target/release/wbuild/pop-runtime-testnet/pop_runtime_testnet.compact.compressed.wasm`. +3. Might be needed to trigger block production on Pop Network: +```shell + websocat ws://localhost:8000 + {"jsonrpc":"2.0","id":2,"method":"dev_newBlock","params":[{"count":20}]} +``` + + +## Release + +> _Node release_ + +- [ ] New node release has been created: e.g. https://github.com/r0gue-io/pop-node/releases/tag/node-v0.2.0-alpha + - Create a tag like `node-v`. + - Point to the previous node release to create a proper diff. + - Provide a description and then release notes. + +> _Runtime release_ + +- [ ] New runtime release has been created: e.g. https://github.com/r0gue-io/pop-node/releases/tag/runtime-v0.4.0-alpha + - Create a tag like `runtime-v`. + - Point to the previous runtime release to create a proper diff. + - Provide a description and then release notes. + +- [ ] Create the authorization call data + - < Edit with authorized runtime call data > diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8e2b2cc..953aa723 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,11 +12,26 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: "./.github/actions/init" + - name: Check formatting run: | rustup toolchain install nightly --profile minimal --component rustfmt cargo +nightly fmt --all -- --check + - name: Check manifests + run: | + cargo install taplo-cli --locked + taplo format --check + + - name: Check features + run: | + cargo install zepter --locked + zepter lint propagate-feature --feature try-runtime --left-side-feature-missing=ignore --workspace --feature-enables-dep="try-runtime:frame-try-runtime" --locked + zepter lint propagate-feature --feature runtime-benchmarks --left-side-feature-missing=ignore --workspace --feature-enables-dep="runtime-benchmarks:frame-benchmarking" --locked + zepter lint propagate-feature --feature std --left-side-feature-missing=ignore --workspace --locked + zepter format features + check: needs: lint runs-on: ubuntu-latest @@ -35,6 +50,7 @@ jobs: permissions: checks: write env: + RUSTFLAGS: "-Wmissing_docs" SKIP_WASM_BUILD: 1 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c82d1b9f..bbbac837 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,7 +28,7 @@ jobs: contents: write strategy: matrix: - runtime: [ "devnet", "testnet" ] + runtime: [ "devnet", "testnet", "mainnet" ] steps: - name: Checkout sources uses: actions/checkout@v4 @@ -45,6 +45,8 @@ jobs: - name: Build ${{ matrix.runtime }} runtime id: srtool_build uses: chevdor/srtool-actions@v0.9.2 + env: + BUILD_OPTS: "--features on-chain-release-build" with: chain: ${{ matrix.runtime }} package: "pop-runtime-${{ matrix.runtime }}" @@ -166,7 +168,7 @@ jobs: run: rustup target add ${{ matrix.platform.target }} - name: Build node - run: cargo build --profile=production -p pop-node --target ${{ matrix.platform.target }} + run: cargo build --profile=production -p pop-node --features on-chain-release-build --target ${{ matrix.platform.target }} - name: Package binary (Linux) if: contains(matrix.platform.target, 'linux') diff --git a/.rustfmt.toml b/.rustfmt.toml index c3421539..8743bd4c 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,24 +1,24 @@ -# Basic +# Non-default formatting configuration options: use with `cargo +nightly fmt --all` +binop_separator = "Back" +chain_width = 80 +combine_control_expr = false +comment_width = 100 +condense_wildcard_suffixes = true edition = "2021" +format_code_in_doc_comments = true +format_strings = true +group_imports = "StdExternalCrate" hard_tabs = true -max_width = 100 -use_small_heuristics = "Max" -# Imports imports_granularity = "Crate" -reorder_imports = true -# Consistency -newline_style = "Unix" -# Misc -chain_width = 80 -spaces_around_ranges = false -binop_separator = "Back" -reorder_impl_items = false -match_arm_leading_pipes = "Preserve" match_arm_blocks = false match_block_trailing_comma = true -trailing_comma = "Vertical" +newline_style = "Unix" +normalize_comments = true +reorder_impl_items = true trailing_semicolon = false +unstable_features = true use_field_init_shorthand = true -# Format comments -comment_width = 100 +# Uses max_width or its default value (100) if not specified. +use_small_heuristics = "Max" +use_try_shorthand = true wrap_comments = true diff --git a/.taplo.toml b/.taplo.toml new file mode 100644 index 00000000..ea64cf51 --- /dev/null +++ b/.taplo.toml @@ -0,0 +1,17 @@ +# all options https://taplo.tamasfe.dev/configuration/formatter-options.html + +exclude = [ "networks/**", "target/**" ] + +# global rules +[formatting] +array_auto_collapse = false +array_auto_expand = true +compact_arrays = false # zepter compatibility +indent_string = " " # tab +inline_table_expand = false +reorder_arrays = true +reorder_keys = true + +[[rule]] +include = [ "Cargo.toml" ] +keys = [ "workspace.dependencies" ] diff --git a/Cargo.lock b/Cargo.lock index 26fb5d46..960e68f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,12 +36,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - [[package]] name = "aead" version = "0.5.2" @@ -74,7 +68,7 @@ dependencies = [ "cipher 0.4.4", "ctr", "ghash", - "subtle 2.4.1", + "subtle 2.5.0", ] [[package]] @@ -83,7 +77,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 +89,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", @@ -353,12 +347,6 @@ dependencies = [ "rand", ] -[[package]] -name = "array-bytes" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" - [[package]] name = "array-bytes" version = "6.2.3" @@ -392,8 +380,24 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", + "asn1-rs-derive 0.4.0", + "asn1-rs-impl 0.1.0", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +dependencies = [ + "asn1-rs-derive 0.5.1", + "asn1-rs-impl 0.2.0", "displaydoc", "nom", "num-traits", @@ -414,6 +418,18 @@ dependencies = [ "synstructure 0.12.6", ] +[[package]] +name = "asn1-rs-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure 0.13.1", +] + [[package]] name = "asn1-rs-impl" version = "0.1.0" @@ -425,6 +441,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "assert_matches" version = "1.5.0" @@ -432,13 +459,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] -name = "asset-hub-paseo-runtime" +name = "asset-hub-polkadot-runtime" version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" dependencies = [ "assets-common", - "bp-asset-hub-paseo", - "bp-bridge-hub-paseo", + "bp-asset-hub-kusama", + "bp-asset-hub-polkadot", + "bp-bridge-hub-kusama", + "bp-bridge-hub-polkadot", + "collectives-polkadot-runtime-constants", "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", "cumulus-pallet-session-benchmarking", @@ -456,6 +486,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", + "kusama-runtime-constants", "log", "pallet-asset-conversion", "pallet-asset-conversion-tx-payment", @@ -481,12 +512,13 @@ dependencies = [ "pallet-xcm-bridge-hub-router", "parachains-common", "parity-scale-codec", - "paseo-runtime-constants", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-runtime-common", + "polkadot-runtime-constants", "primitive-types", "scale-info", + "serde_json", "snowbridge-router-primitives", "sp-api", "sp-block-builder", @@ -509,13 +541,14 @@ dependencies = [ "staging-xcm-executor", "substrate-wasm-builder", "system-parachains-constants", + "xcm-runtime-apis", ] [[package]] name = "asset-test-utils" -version = "8.0.1" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d78501ca6b4c848efe233672124ebab9293d8efefc44a728d70f3245a8ef595" +checksum = "8ccc232efa79f7f180856e9bc8535dbb2d813b62418cda7bf154a713adb9ea36" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-pallet-xcmp-queue", @@ -526,6 +559,7 @@ dependencies = [ "pallet-balances", "pallet-collator-selection", "pallet-session", + "pallet-timestamp", "pallet-xcm", "pallet-xcm-bridge-hub-router", "parachains-common", @@ -543,9 +577,9 @@ dependencies = [ [[package]] name = "assets-common" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e90021d772c2dd82d45fd085e05a2cb5866464d4c7421ac6a8007733b350bb" +checksum = "d4e2360c96927aa33b3fef7190eabf2aa4129fe3505c11dfa860ada0f27fd1b1" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -585,7 +619,7 @@ dependencies = [ "concurrent-queue", "event-listener-strategy", "futures-core", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -669,7 +703,7 @@ checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ "event-listener 5.3.1", "event-listener-strategy", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -745,7 +779,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -760,6 +794,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "attohttpc" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" +dependencies = [ + "http 0.2.12", + "log", + "url", +] + [[package]] name = "autocfg" version = "1.3.0" @@ -776,7 +821,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide 0.7.3", + "miniz_oxide", "object 0.36.0", "rustc-demangle", ] @@ -828,9 +873,9 @@ dependencies = [ [[package]] name = "binary-merkle-tree" -version = "14.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf857f8f411164ce1af14a778626af96251de7a77837711efbc440807e7053f" +checksum = "4b5c0fd4282c30c05647e1052d71bf1a0c8067ab1e9a8fc6d0c292dce0ecb237" dependencies = [ "hash-db", "log", @@ -872,19 +917,31 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ - "bitcoin_hashes", - "rand", - "rand_core 0.6.4", - "serde", - "unicode-normalization", + "bitcoin_hashes 0.11.0", ] +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + [[package]] name = "bitcoin_hashes" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -1026,7 +1083,7 @@ dependencies = [ "hyper-util", "hyperlocal-next", "log", - "pin-project-lite 0.2.14", + "pin-project-lite", "serde", "serde_derive", "serde_json", @@ -1073,11 +1130,28 @@ dependencies = [ ] [[package]] -name = "bp-asset-hub-paseo" +name = "bp-asset-hub-kusama" +version = "1.0.0" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +dependencies = [ + "bp-xcm-bridge-hub-router", + "frame-support", + "parity-scale-codec", + "scale-info", + "sp-std", + "staging-xcm", + "system-parachains-constants", +] + +[[package]] +name = "bp-asset-hub-polkadot" version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" dependencies = [ + "bp-xcm-bridge-hub-router", "frame-support", + "parity-scale-codec", + "scale-info", "sp-std", "staging-xcm", "system-parachains-constants", @@ -1085,9 +1159,9 @@ dependencies = [ [[package]] name = "bp-bridge-hub-cumulus" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e91ab68506081576066d3641d7794f63d96f3ca1eee0c059c2cc2174e55f638" +checksum = "d48cca10dce1c6d2914e48594f13add2da4a5b7c3ed54fd0fa324054dfb8569a" dependencies = [ "bp-messages", "bp-polkadot-core", @@ -1100,28 +1174,47 @@ dependencies = [ ] [[package]] -name = "bp-bridge-hub-paseo" +name = "bp-bridge-hub-kusama" version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" dependencies = [ "bp-bridge-hub-cumulus", "bp-messages", "bp-runtime", "frame-support", - "parity-scale-codec", - "scale-info", + "kusama-runtime-constants", + "polkadot-runtime-constants", + "sp-api", + "sp-runtime", + "sp-std", + "system-parachains-constants", +] + +[[package]] +name = "bp-bridge-hub-polkadot" +version = "1.0.0" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +dependencies = [ + "bp-bridge-hub-cumulus", + "bp-messages", + "bp-polkadot-bulletin", + "bp-runtime", + "frame-support", + "kusama-runtime-constants", + "polkadot-runtime-constants", "snowbridge-core", "sp-api", "sp-runtime", "sp-std", "staging-xcm", + "system-parachains-constants", ] [[package]] name = "bp-header-chain" -version = "0.8.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4d2c457d5e18a5dbfe47a2ecd01f95036930a4a7ac0f3e47c2843bb067331b" +checksum = "57cac4b71008e46d43e346476ed1be85cf7b505efacee17dad84d687344bf1b1" dependencies = [ "bp-runtime", "finality-grandpa", @@ -1137,9 +1230,9 @@ dependencies = [ [[package]] name = "bp-messages" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf43a49ea13d4c2f141481b6cbff85a197c47fe6aec1f5af21e40b68e8fd02fd" +checksum = "f97eec00a98efeb052ac9fc9676d9fccf5acd19e3b18530f3d72af1a1faf21ec" dependencies = [ "bp-header-chain", "bp-runtime", @@ -1153,9 +1246,9 @@ dependencies = [ [[package]] name = "bp-parachains" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "762e309a008b2ad4088d4c4e9d39fa9f78f59124b6a52c25ceb0ef5f22d901f5" +checksum = "60c0bde723a5daf39f4f02816483c9ac049818990b06858dff751736636a4ea2" dependencies = [ "bp-header-chain", "bp-polkadot-core", @@ -1169,11 +1262,30 @@ dependencies = [ "sp-std", ] +[[package]] +name = "bp-polkadot-bulletin" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb5b3cd885b40b52bf96e52ffbec92d0c435f7303fc11374ccfcfa5bebfbc4f" +dependencies = [ + "bp-header-chain", + "bp-messages", + "bp-polkadot-core", + "bp-runtime", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-runtime", + "sp-std", +] + [[package]] name = "bp-polkadot-core" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b862e8dcccc9a3fafb58a1735bc205b7663d3335d7b3dd942503b98f28d6b067" +checksum = "6ef2272823ecfee580c00f6542dfcab3ec7abdb00857af853429736847c3a2d9" dependencies = [ "bp-messages", "bp-runtime", @@ -1190,9 +1302,9 @@ dependencies = [ [[package]] name = "bp-relayers" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a4b0e2771227611fe9e6a2c37ba2bf7408cf2385a9eb2f44e6096bb0e616ec" +checksum = "5a589f5bb70baa4377a798823be752042aa6c220d51afc559716667e29b0203d" dependencies = [ "bp-messages", "bp-runtime", @@ -1205,9 +1317,9 @@ dependencies = [ [[package]] name = "bp-runtime" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b29668fffbc3e4a7ad789b498424ed6d8a313f93544a090bbaaef8a1f7fd243" +checksum = "904644c23b437dde65741f3148067624ed0b4d8360f68adf9e92273aeb970814" dependencies = [ "frame-support", "frame-system", @@ -1229,9 +1341,9 @@ dependencies = [ [[package]] name = "bp-test-utils" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6640a95733148b4f2004d362471eba49583da4b961681f5ea722039478924d31" +checksum = "85062410c8f85ba074f04d843c59f39c7fcb64b83f2ece5bd4379f8c34a4bf15" dependencies = [ "bp-header-chain", "bp-parachains", @@ -1250,18 +1362,18 @@ dependencies = [ [[package]] name = "bp-xcm-bridge-hub" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6663e0179d475e30cfcf28cf597cdc8f4bb1c2c39a557b4cbe0057db0657fb67" +checksum = "192804908f1d3b7bfad12abce448fb3b7ec8dda765cac4a8d811fa75557e528f" dependencies = [ "sp-std", ] [[package]] name = "bp-xcm-bridge-hub-router" -version = "0.7.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ff4abe93be7bc1663adc41817b1aa3476fbec953ce361537419924310d5dd4" +checksum = "b7dae4d1ec894ee920195dd39070b279ef3c1d4d078c3fcf7336c93a1d502a9d" dependencies = [ "parity-scale-codec", "scale-info", @@ -1271,9 +1383,9 @@ dependencies = [ [[package]] name = "bridge-runtime-common" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be96f5eb3ef2ce92e0337e06b76a2e0e9f120a5f6fd96bf8db817e5643c118b9" +checksum = "639591635551f94b6e310852430b669495bd99cfd2af20b00a00f6cc7169e70d" dependencies = [ "bp-header-chain", "bp-messages", @@ -1303,6 +1415,7 @@ dependencies = [ "sp-trie", "staging-xcm", "staging-xcm-builder", + "tuplex", ] [[package]] @@ -1443,6 +1556,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -1532,7 +1651,20 @@ dependencies = [ "multibase", "multihash 0.17.0", "serde", - "unsigned-varint", + "unsigned-varint 0.7.2", +] + +[[package]] +name = "cid" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3" +dependencies = [ + "core2", + "multibase", + "multihash 0.18.1", + "serde", + "unsigned-varint 0.7.2", ] [[package]] @@ -1555,15 +1687,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ckb-merkle-mountain-range" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ccb671c5921be8a84686e6212ca184cb1d7c51cadcdbfcbd1cc3f042f5dfb8" -dependencies = [ - "cfg-if", -] - [[package]] name = "clang-sys" version = "1.8.1" @@ -1637,6 +1760,11 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "collectives-polkadot-runtime-constants" +version = "1.0.0" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" + [[package]] name = "color-print" version = "0.3.6" @@ -1674,6 +1802,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "comfy-table" version = "7.1.1" @@ -1734,7 +1872,7 @@ 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", ] @@ -1894,7 +2032,7 @@ dependencies = [ "gimli 0.27.3", "hashbrown 0.13.2", "log", - "regalloc2", + "regalloc2 0.6.1", "smallvec", "target-lexicon", ] @@ -1968,6 +2106,21 @@ dependencies = [ "wasmtime-types", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.4.2" @@ -2049,8 +2202,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array 0.14.7", - "rand_core 0.6.4", - "subtle 2.4.1", + "rand_core", + "subtle 2.5.0", "zeroize", ] @@ -2061,7 +2214,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.7", - "rand_core 0.6.4", + "rand_core", "typenum", ] @@ -2082,17 +2235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ "generic-array 0.14.7", - "subtle 2.4.1", -] - -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array 0.14.7", - "subtle 2.4.1", + "subtle 2.5.0", ] [[package]] @@ -2106,9 +2249,9 @@ dependencies = [ [[package]] name = "cumulus-client-cli" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d2597fe3235d263457aaff65d0fb5bed506698b81530e2e6afecd6d6c9af32" +checksum = "b64901f2fde878bec8f4c3949b5e5ee6fb5de45dd19b45d9fcd6a23a859fd0cc" dependencies = [ "clap", "parity-scale-codec", @@ -2124,9 +2267,9 @@ dependencies = [ [[package]] name = "cumulus-client-collator" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c06ae72a125d056da3b722f00f87881a2afbb2af8fe9fa9a91587f139b9667e" +checksum = "2311f438161902135ff57db8a81ed3c701e33fd4bccbcc72e785f1efc73e1df3" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", @@ -2148,9 +2291,9 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-aura" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f4977f6a88af39c46832d571ac0d95e8322bf22eab42550fec34f72da9f034" +checksum = "76c45052da56eb1631e177812f47c9426cb2617a5bfcc4c76a746e6a4c660df2" dependencies = [ "async-trait", "cumulus-client-collator", @@ -2162,6 +2305,7 @@ dependencies = [ "cumulus-relay-chain-interface", "futures", "parity-scale-codec", + "parking_lot 0.12.3", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-overseer", @@ -2191,9 +2335,9 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350db1fc8841a44f344474b791d2ebe61b79bf6061043a7d826b3d02d1935a56" +checksum = "83b4de5c24c4304b509dffccb95218f22c2ef619a91aee85a3d9523b63347be2" dependencies = [ "async-trait", "cumulus-client-pov-recovery", @@ -2215,15 +2359,16 @@ dependencies = [ "sp-runtime", "sp-timestamp", "sp-trie", + "sp-version", "substrate-prometheus-endpoint", "tracing", ] [[package]] name = "cumulus-client-consensus-proposer" -version = "0.8.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38028f75597a34d447f059d6a7fd9c1c91bce0b8c48b08b1cbd19eb3def9c376" +checksum = "56e980b3e5c05415eaa4ac07f398bc8e74666811f3112f19a654ccb3a948018e" dependencies = [ "anyhow", "async-trait", @@ -2237,9 +2382,9 @@ dependencies = [ [[package]] name = "cumulus-client-network" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ac095ef439c595ccb998be5a9d40778d8963c5a8ebbaed838fed6293232915b" +checksum = "ed8d6844af4dbb35a925d493331b631f4ccd3b15568643e92afbf0ee7f4b22e3" dependencies = [ "async-trait", "cumulus-relay-chain-interface", @@ -2248,22 +2393,25 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "polkadot-node-primitives", + "polkadot-node-subsystem", "polkadot-parachain-primitives", "polkadot-primitives", "sc-client-api", + "sp-api", "sp-blockchain", "sp-consensus", "sp-core", "sp-runtime", "sp-state-machine", + "sp-version", "tracing", ] [[package]] name = "cumulus-client-parachain-inherent" -version = "0.2.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b516290cd4a6efc117824135761f3642dc57685e13da00727c460053ce978fe" +checksum = "e99367f72d7bce6d8996eb397d265290e4a982fbbc4b0fd7659e57a2ad5b6b7b" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2286,9 +2434,9 @@ dependencies = [ [[package]] name = "cumulus-client-pov-recovery" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d55e96004ca9aa9d9b96a28ab2d97b1ca8d303c9d2405ea34cdf1462d4c4f0" +checksum = "21e3bd944ef351edb61fdaca5bf6d9a964d7c7571bd0b0236ea51f167bec9b6f" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2303,17 +2451,19 @@ dependencies = [ "rand", "sc-client-api", "sc-consensus", + "sp-api", "sp-consensus", "sp-maybe-compressed-blob", "sp-runtime", + "sp-version", "tracing", ] [[package]] name = "cumulus-client-service" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "657f57c56159bb6cb74d9221de8f11c9e09962666381357896562662d3019799" +checksum = "fb134f1526eba4455290859ad34174ab787c8f36f509063f41eeac17202a8f78" dependencies = [ "cumulus-client-cli", "cumulus-client-collator", @@ -2342,15 +2492,16 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-core", + "sp-io", "sp-runtime", "sp-transaction-pool", ] [[package]] name = "cumulus-pallet-aura-ext" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8e78b18548ae3454bc8a46e2bc2e3f521ea547844cbaecc9344d4741f4b1ef" +checksum = "c5e8af48090936c45483d489ee681acb54277763586b53fa3dbd17173aa474fc" dependencies = [ "cumulus-pallet-parachain-system", "frame-support", @@ -2367,9 +2518,9 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" -version = "0.8.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a215fe4d66d23e8f3956bd21b9d80d2b33239f3b150b36d56fa238cfc9421a5" +checksum = "300d5509bd8ac95bafe158fa475278315175a4eb0422c2cd82e08e8b9dde035c" dependencies = [ "bytes", "cumulus-pallet-parachain-system-proc-macro", @@ -2398,6 +2549,7 @@ dependencies = [ "sp-trie", "sp-version", "staging-xcm", + "staging-xcm-builder", "trie-db", ] @@ -2415,9 +2567,9 @@ dependencies = [ [[package]] name = "cumulus-pallet-session-benchmarking" -version = "10.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3259f743f70f39baa3abf2d9d8de864e18120465f8731b99bef039a3bf9329" +checksum = "506daacefa861aa2909b64f26e76495ce029227fd8355b97e074cc1d5dc54ab2" dependencies = [ "frame-benchmarking", "frame-support", @@ -2430,9 +2582,9 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e802291060763f8d1176bf808da97aafe5afe7351f62bb093c317c1d35c5cee" +checksum = "8d5224285f60e5159bab549f458079d606a7f95ef779def8b89f1a244dc7cf81" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2447,9 +2599,9 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa22d6e479a4d3a2790bab291269ba0917a1ac384255a54a2ebc3f7c37e505e" +checksum = "0adf5409618b21e754fef0ac70f257878d22d61c48fdeefcab666835dcb8e0f0" dependencies = [ "bounded-collections", "bp-xcm-bridge-hub-router", @@ -2468,14 +2620,15 @@ dependencies = [ "sp-runtime", "sp-std", "staging-xcm", + "staging-xcm-builder", "staging-xcm-executor", ] [[package]] name = "cumulus-primitives-aura" -version = "0.8.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f07d6177692154043d7ddcc0b87ca5365ae8e4d94b90d9931f6b2f76e162f09" +checksum = "3e7977947ad43a4cbc532ca33abcde136ae3deffdc7168b2ae253d73ccd371e4" dependencies = [ "parity-scale-codec", "polkadot-core-primitives", @@ -2488,9 +2641,9 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" -version = "0.8.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9df07f6825fd50ea30aae335e43dc1a615a05de7465f5f329b9e414f2c886a12" +checksum = "751e64b89a839d5cfabebc1c797936e5eee791d0fa2322d91e86f8440a743ddb" dependencies = [ "parity-scale-codec", "polkadot-core-primitives", @@ -2506,9 +2659,9 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" -version = "0.8.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ad140a065a6b8001fb26ec42b91391e90fde120f5b4e57986698249a9b98c8" +checksum = "df521e13b48278b86d02c61d6e44036d6d263deb5aaec4838b1751da8988d3d2" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2516,26 +2669,46 @@ dependencies = [ "scale-info", "sp-core", "sp-inherents", + "sp-runtime", + "sp-state-machine", "sp-std", "sp-trie", ] [[package]] name = "cumulus-primitives-proof-size-hostfunction" -version = "0.3.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b74f9141190b9f4bf96a947ade46da64097b77f1ebfa8d611c81724250e119" +checksum = "9f973d2a7262c90e48dcd42062bcb1e0fbf48bbcdac4ea6df3d85212d8d8be5d" dependencies = [ "sp-externalities", "sp-runtime-interface", "sp-trie", ] +[[package]] +name = "cumulus-primitives-storage-weight-reclaim" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29a7e13063f593f21534a7b64c96f311c40cd4d3c72649e0bd063a34506fdd70" +dependencies = [ + "cumulus-primitives-core", + "cumulus-primitives-proof-size-hostfunction", + "docify", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + [[package]] name = "cumulus-primitives-utility" -version = "0.8.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e65466e56d642f979b556d098a03755ae51972fff5fa0f9b1cdcfdb3df062ea3" +checksum = "05742c520065e3870d419683113ed7f6d35de66f0c80af6828e7878d1bb0ea94" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2554,9 +2727,9 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-inprocess-interface" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff27dec2eab6cd1d854756d62bd7053721ccd115f36f9e8b0976b1e46b70ef7" +checksum = "511675c9780fe8396e2b0c3ca8a04ff0ddc57d837fd9fe4086cb9aac1b107523" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2579,9 +2752,9 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-interface" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c736f39b50eecf194707e15d0359677bb8fe8138b01f6493ab9b7e10d2d1ae" +checksum = "36abc0a30972529fad05c4fae9f6866ec6c3edfaf2e20977219c94a807d96ffa" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2593,16 +2766,17 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-state-machine", + "sp-version", "thiserror", ] [[package]] name = "cumulus-relay-chain-minimal-node" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7718fe298d567adc44fae3dd7024418d6eff08264041e4b0544d1892861cd6" +checksum = "b39ec9de6ed195263af022094d63689fc6a914f48f70d74eb3fed8ee48973ea3" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "async-trait", "cumulus-primitives-core", "cumulus-relay-chain-interface", @@ -2621,6 +2795,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", + "polkadot-service", "sc-authority-discovery", "sc-client-api", "sc-network", @@ -2640,9 +2815,9 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-rpc-interface" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e2269d4c1f37593257b3d7b90f8b56adab0793d9b9f5c1b5334c9ca7e3b10b" +checksum = "b22c43792fa5d56a2360bcdbdc58c47aafa23688072d2b6e61844864e69a15c8" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2680,9 +2855,9 @@ dependencies = [ [[package]] name = "cumulus-test-relay-sproof-builder" -version = "0.8.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfff604ad01c5c0c397f9a971c8cec6443aea3658813778875b4f64de07847d5" +checksum = "e1f4ab9d64a581d4a5431f2554f4602a4208c5e28b30be01af386e24d8447599" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -2693,19 +2868,6 @@ dependencies = [ "sp-trie", ] -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle 2.4.1", - "zeroize", -] - [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -2718,7 +2880,7 @@ dependencies = [ "digest 0.10.7", "fiat-crypto", "rustc_version", - "subtle 2.4.1", + "subtle 2.5.0", "zeroize", ] @@ -2741,7 +2903,7 @@ checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" dependencies = [ "byteorder", "digest 0.9.0", - "rand_core 0.6.4", + "rand_core", "subtle-ng", "zeroize", ] @@ -2790,6 +2952,19 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -2832,7 +3007,21 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" dependencies = [ - "asn1-rs", + "asn1-rs 0.5.2", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der-parser" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +dependencies = [ + "asn1-rs 0.6.2", "displaydoc", "nom", "num-bigint", @@ -2929,7 +3118,7 @@ dependencies = [ "block-buffer 0.10.4", "const-oid", "crypto-common", - "subtle 2.4.1", + "subtle 2.5.0", ] [[package]] @@ -3079,6 +3268,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", + "serdect", "signature", "spki", ] @@ -3099,26 +3289,12 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.3", + "curve25519-dalek", "ed25519", - "rand_core 0.6.4", + "rand_core", "serde", "sha2 0.10.8", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "ed25519-zebra" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" -dependencies = [ - "curve25519-dalek 3.2.0", - "hashbrown 0.12.3", - "hex", - "rand_core 0.6.4", - "sha2 0.9.9", + "subtle 2.5.0", "zeroize", ] @@ -3128,11 +3304,11 @@ version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ - "curve25519-dalek 4.1.3", + "curve25519-dalek", "ed25519", "hashbrown 0.14.5", "hex", - "rand_core 0.6.4", + "rand_core", "sha2 0.10.8", "zeroize", ] @@ -3156,17 +3332,18 @@ dependencies = [ "generic-array 0.14.7", "group", "pkcs8", - "rand_core 0.6.4", + "rand_core", "sec1", - "subtle 2.4.1", + "serdect", + "subtle 2.5.0", "zeroize", ] [[package]] name = "emulated-integration-tests-common" -version = "4.0.0" +version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a73ae1af5bb264240ccd199335ae78db85d055da4f749d44333d21719e5896" +checksum = "aef7c980b99bb2e4edfc9535d4096c1d0b5c8e3b52aab38a497a79563e6005f7" dependencies = [ "asset-test-utils", "bp-messages", @@ -3183,12 +3360,13 @@ dependencies = [ "parachains-common", "parity-scale-codec", "paste", + "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-parachains", - "polkadot-service", "sc-consensus-grandpa", "sp-authority-discovery", "sp-consensus-babe", + "sp-consensus-beefy", "sp-core", "sp-runtime", "staging-xcm", @@ -3213,6 +3391,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "enumflags2" version = "0.7.10" @@ -3357,7 +3547,7 @@ checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -3368,7 +3558,7 @@ checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -3378,7 +3568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ "event-listener 5.3.1", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -3390,18 +3580,6 @@ dependencies = [ "futures", ] -[[package]] -name = "expander" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a718c0675c555c5f976fff4ea9e2c150fa06cefa201cadef87cfbf9324075881" -dependencies = [ - "blake3", - "fs-err", - "proc-macro2", - "quote", -] - [[package]] name = "expander" version = "2.2.1" @@ -3423,6 +3601,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + [[package]] name = "fastrand" version = "1.9.0" @@ -3440,9 +3624,9 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fatality" -version = "0.0.6" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad875162843b0d046276327afe0136e9ed3a23d5a754210fb6f1f33610d39ab" +checksum = "ec6f82451ff7f0568c6181287189126d492b5654e30a788add08027b6363d019" dependencies = [ "fatality-proc-macro", "thiserror", @@ -3450,17 +3634,16 @@ dependencies = [ [[package]] name = "fatality-proc-macro" -version = "0.0.6" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" +checksum = "eb42427514b063d97ce21d5199f36c0c307d981434a6be32582bc79fe5bd2303" dependencies = [ - "expander 0.0.4", - "indexmap 1.9.3", - "proc-macro-crate 1.1.3", + "expander", + "indexmap 2.2.6", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 1.0.109", - "thiserror", + "syn 2.0.66", ] [[package]] @@ -3479,8 +3662,8 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core 0.6.4", - "subtle 2.4.1", + "rand_core", + "subtle 2.5.0", ] [[package]] @@ -3555,17 +3738,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" -[[package]] -name = "flate2" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" -dependencies = [ - "crc32fast", - "libz-sys", - "miniz_oxide 0.8.0", -] - [[package]] name = "float-cmp" version = "0.9.0" @@ -3581,11 +3753,26 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "fork-tree" -version = "12.0.0" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93d3f0315c2eccf23453609e0ab92fe7c6ad1ca8129bcaf80b9a08c8d7fc52b" +checksum = "ad4cc2314d3be8b49c555f6a7e550f5559e73ffd6ef9690ffbd9a706774452e0" dependencies = [ "parity-scale-codec", ] @@ -3599,6 +3786,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "forwarded-header-value" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9" +dependencies = [ + "nonempty", + "thiserror", +] + [[package]] name = "fragile" version = "2.0.0" @@ -3607,9 +3804,9 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "frame-benchmarking" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4090659c6aaa3c4d5b6c6ec909b4b0a25dec10ad92aad5f729efa8d5bd4d806a" +checksum = "709b26657ebbba53dc7bb616577375ca462b20fef1b00e8d9b20d2435e87f7bc" dependencies = [ "frame-support", "frame-support-procedural", @@ -3633,12 +3830,12 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" -version = "33.0.0" +version = "40.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efe02c96362e3c7308cdea7545859f767194a1f3f00928f0e1357f4b8a0b3b2c" +checksum = "49302558cac41cba0a28aa784615daea85c49253ecc6d6a6c4a8ee2f2303655a" dependencies = [ "Inflector", - "array-bytes 6.2.3", + "array-bytes", "chrono", "clap", "comfy-table", @@ -3647,7 +3844,7 @@ dependencies = [ "frame-system", "gethostname", "handlebars", - "itertools 0.10.5", + "itertools 0.11.0", "lazy_static", "linked-hash-map", "log", @@ -3655,6 +3852,7 @@ dependencies = [ "rand", "rand_pcg", "sc-block-builder", + "sc-chain-spec", "sc-cli", "sc-client-api", "sc-client-db", @@ -3668,6 +3866,7 @@ dependencies = [ "sp-core", "sp-database", "sp-externalities", + "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keystore", @@ -3682,9 +3881,9 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" -version = "13.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5c3bff645e46577c69c272733c53fa3a77d1ee6e40dfb66157bc94b0740b8fc" +checksum = "1388eb632484a1208a5b51d7d822a7df995f37bb10878b2a88f4ec89cbe5e6b2" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", @@ -3694,9 +3893,9 @@ dependencies = [ [[package]] name = "frame-election-provider-support" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87da19ee99e6473cd057ead84337d20011fe5e299c6750e88e43b8b7963b8852" +checksum = "b1ec289ebad5e601bb165cf7eb6ec2179ae34280ee310d0710a3111d4f8f8f94" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -3712,10 +3911,11 @@ dependencies = [ [[package]] name = "frame-executive" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bff9574ee2dcc349f646e1d2faadf76afd688c2ea1bbac5e4a0e19a0c19c59" +checksum = "4d878830330eaa9e8b886279c338556b05702d0059989cb51cfb226b70bf3fa4" dependencies = [ + "aquamarine", "frame-support", "frame-system", "frame-try-runtime", @@ -3743,11 +3943,11 @@ dependencies = [ [[package]] name = "frame-metadata-hash-extension" -version = "0.1.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb1eec9eb46d3e016c95b2fa875118c04609f2150013c56a894cae00581e265" +checksum = "cf37fc730bf4b51e82a34c6357eebe32c04dbacf6525e0a7b9726f6a17ec9427" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "docify", "frame-support", "frame-system", @@ -3757,37 +3957,14 @@ dependencies = [ "sp-runtime", ] -[[package]] -name = "frame-remote-externalities" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360bfdb6821372164a65933d9a6d5998f38c722360b59b69d2bf78a87ef58b2a" -dependencies = [ - "futures", - "indicatif", - "jsonrpsee", - "log", - "parity-scale-codec", - "serde", - "sp-core", - "sp-crypto-hashing", - "sp-io", - "sp-runtime", - "sp-state-machine", - "spinners", - "substrate-rpc-client", - "tokio", - "tokio-retry", -] - [[package]] name = "frame-support" -version = "29.0.2" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e52c84b611d2049d9253f83a62ab0f093e4be5c42a7ef42ea5bb16d6611e32" +checksum = "512b517645f29d76c79e4c97bf8b0f4dcb6708a2af3be24b1956085dcdcf6ce5" dependencies = [ "aquamarine", - "array-bytes 6.2.3", + "array-bytes", "bitflags 1.3.2", "docify", "environmental", @@ -3824,18 +4001,18 @@ dependencies = [ [[package]] name = "frame-support-procedural" -version = "24.0.0" +version = "30.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf1d648c4007d421b9677b3c893256913498fff159dc2d85022cdd9cc432f3c" +checksum = "fd94af68373e179c32c360b3c280497a9cf0f45a4f47f0ee6539a6c6c9cf2343" dependencies = [ "Inflector", "cfg-expr", - "derive-syn-parse 0.1.5", - "expander 2.2.1", + "derive-syn-parse 0.2.0", + "expander", "frame-support-procedural-tools", - "itertools 0.10.5", + "itertools 0.11.0", "macro_magic", - "proc-macro-warning", + "proc-macro-warning 1.0.2", "proc-macro2", "quote", "sp-crypto-hashing", @@ -3844,9 +4021,9 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" -version = "10.0.0" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3363df38464c47a73eb521a4f648bfcc7537a82d70347ef8af3f73b6d019e910" +checksum = "bead15a320be1764cdd50458c4cfacb23e0cee65f64f500f8e34136a94c7eeca" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate 3.1.0", @@ -3857,9 +4034,9 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" -version = "11.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68672b9ec6fe72d259d3879dc212c5e42e977588cdac830c76f54d9f492aeb58" +checksum = "ed971c6435503a099bdac99fe4c5bea08981709e5b5a0a8535a1856f48561191" dependencies = [ "proc-macro2", "quote", @@ -3868,9 +4045,9 @@ dependencies = [ [[package]] name = "frame-system" -version = "29.0.0" +version = "36.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc20a793c3cec0b11165c1075fe11a255b2491f3eef8230bb3073cb296e7383" +checksum = "64d6a0e7bb6503facdcc6f8e19c83cd0bfc8bbbd268522b1a50e107dfc6b972d" dependencies = [ "cfg-if", "docify", @@ -3889,9 +4066,9 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac47ee48fee3a0b49c9ab9ee68997dee3733776a355f780cf2858449cf495d69" +checksum = "15afc91c7780e18274dcea58ed1edb700c48d10e086a9785e3f6708099cd3250" dependencies = [ "frame-benchmarking", "frame-support", @@ -3905,9 +4082,9 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c1b20433c3c76b56ce905ed971631ec8c34fa64cf6c20e590afe46455fc0cc8" +checksum = "c9e9e2b7b85e451e367f4fb85ff3295bd039e17f64de1906154d3976e2638ee8" dependencies = [ "parity-scale-codec", "sp-api", @@ -3915,9 +4092,9 @@ dependencies = [ [[package]] name = "frame-try-runtime" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eab87d07bc2f9a2160b818d1b7506c303b3b28b6a8a5f01dc5e2641390450b5" +checksum = "ae6ba8b36a52775ad39ccfb45ff4ad814c3cb45ec74d0a4271889e00bd791c6c" dependencies = [ "frame-support", "parity-scale-codec", @@ -3976,6 +4153,16 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-bounded" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b07bbbe7d7e78809544c6f718d875627addc73a7c3582447abc052cd3dc67e0" +dependencies = [ + "futures-timer", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -4021,7 +4208,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.14", + "pin-project-lite", "waker-fn", ] @@ -4035,7 +4222,7 @@ dependencies = [ "futures-core", "futures-io", "parking", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -4051,13 +4238,12 @@ dependencies = [ [[package]] name = "futures-rustls" -version = "0.22.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd" +checksum = "35bd3cf68c183738046838e300353e4716c674dc5e56890de4826801a6622a28" dependencies = [ "futures-io", - "rustls 0.20.9", - "webpki", + "rustls 0.21.12", ] [[package]] @@ -4091,7 +4277,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.14", + "pin-project-lite", "pin-utils", "slab", ] @@ -4135,17 +4321,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -4154,7 +4329,7 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -4164,7 +4339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" dependencies = [ "rand", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -4183,11 +4358,21 @@ version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" dependencies = [ - "fallible-iterator", + "fallible-iterator 0.2.0", "indexmap 1.9.3", "stable_deref_trait", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +dependencies = [ + "fallible-iterator 0.3.0", + "stable_deref_trait", +] + [[package]] name = "gimli" version = "0.29.0" @@ -4200,6 +4385,26 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "governor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" +dependencies = [ + "cfg-if", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot 0.12.3", + "portable-atomic", + "quanta", + "rand", + "smallvec", + "spinning_top", +] + [[package]] name = "group" version = "0.13.0" @@ -4207,8 +4412,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core 0.6.4", - "subtle 2.4.1", + "rand_core", + "subtle 2.5.0", ] [[package]] @@ -4230,11 +4435,30 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "handlebars" -version = "4.5.0" +version = "5.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" +checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" dependencies = [ "log", "pest", @@ -4327,6 +4551,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + [[package]] name = "hex-literal" version = "0.4.1" @@ -4352,16 +4582,6 @@ dependencies = [ "digest 0.9.0", ] -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac 0.11.1", - "digest 0.9.0", -] - [[package]] name = "hmac" version = "0.12.1" @@ -4432,7 +4652,7 @@ checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http 0.2.12", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -4455,15 +4675,9 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.1", - "pin-project-lite 0.2.14", + "pin-project-lite", ] -[[package]] -name = "http-range-header" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" - [[package]] name = "httparse" version = "1.9.4" @@ -4492,13 +4706,13 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.14", + "pin-project-lite", "socket2 0.5.7", "tokio", "tower-service", @@ -4515,11 +4729,13 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.1", "httparse", + "httpdate", "itoa", - "pin-project-lite 0.2.14", + "pin-project-lite", "smallvec", "tokio", "want", @@ -4534,7 +4750,7 @@ dependencies = [ "hex", "hyper 1.4.1", "hyper-util", - "pin-project-lite 0.2.14", + "pin-project-lite", "tokio", "tower-service", "winapi", @@ -4551,9 +4767,9 @@ dependencies = [ "hyper 0.14.29", "log", "rustls 0.21.12", - "rustls-native-certs", + "rustls-native-certs 0.6.3", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", ] [[package]] @@ -4568,7 +4784,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "hyper 1.4.1", - "pin-project-lite 0.2.14", + "pin-project-lite", "socket2 0.5.7", "tokio", "tower", @@ -4586,7 +4802,7 @@ dependencies = [ "http-body-util", "hyper 1.4.1", "hyper-util", - "pin-project-lite 0.2.14", + "pin-project-lite", "tokio", "tower-service", ] @@ -4743,6 +4959,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "1.0.0" @@ -4785,19 +5011,38 @@ dependencies = [ ] [[package]] -name = "impl-codec" -version = "0.6.0" +name = "igd-next" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +checksum = "064d90fec10d541084e7b39ead8875a5a80d9114a2b18791565253bae25f49e4" dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-num-traits" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951641f13f873bff03d4bf19ae8bec531935ac0ac2cc775f84d7edfdcfed3f17" + "async-trait", + "attohttpc", + "bytes", + "futures", + "http 0.2.12", + "hyper 0.14.29", + "log", + "rand", + "tokio", + "url", + "xmltree", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-num-traits" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "951641f13f873bff03d4bf19ae8bec531935ac0ac2cc775f84d7edfdcfed3f17" dependencies = [ "integer-sqrt", "num-traits", @@ -4880,19 +5125,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" -[[package]] -name = "indicatif" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" -dependencies = [ - "console", - "instant", - "number_prefix", - "portable-atomic", - "unicode-width", -] - [[package]] name = "inout" version = "0.1.3" @@ -4930,7 +5162,7 @@ dependencies = [ name = "integration-tests" version = "0.0.0" dependencies = [ - "asset-hub-paseo-runtime", + "asset-hub-polkadot-runtime", "asset-test-utils", "cumulus-primitives-core", "emulated-integration-tests-common", @@ -4940,12 +5172,13 @@ dependencies = [ "pallet-message-queue", "pallet-xcm", "parity-scale-codec", - "paseo-runtime", - "paseo-runtime-constants", "polkadot-primitives", + "polkadot-runtime", + "polkadot-runtime-constants", "polkadot-runtime-parachains", "pop-runtime-common", "pop-runtime-devnet", + "pop-runtime-mainnet", "sp-authority-discovery", "sp-consensus-aura", "sp-consensus-babe", @@ -5043,6 +5276,26 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jobserver" version = "0.1.31" @@ -5063,12 +5316,11 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138572befc78a9793240645926f30161f8b4143d2be18d09e44ed9814bd7ee2c" +checksum = "62b089779ad7f80768693755a031cc14a7766aba707cbe886674e3f79e9b7e47" dependencies = [ "jsonrpsee-core", - "jsonrpsee-http-client", "jsonrpsee-proc-macros", "jsonrpsee-server", "jsonrpsee-types", @@ -5079,19 +5331,22 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c671353e4adf926799107bd7f5724a06b6bc0a333db442a0843c58640bdd0c1" +checksum = "08163edd8bcc466c33d79e10f695cdc98c00d1e6ddfb95cec41b6b0279dd5432" dependencies = [ + "base64 0.22.1", "futures-util", - "http 0.2.12", + "http 1.1.0", "jsonrpsee-core", "pin-project", - "rustls-native-certs", - "soketto", + "rustls 0.23.10", + "rustls-pki-types", + "rustls-platform-verifier", + "soketto 0.8.0", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", "tokio-util", "tracing", "url", @@ -5099,77 +5354,65 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f24ea59b037b6b9b0e2ebe2c30a3e782b56bd7c76dcc5d6d70ba55d442af56e3" +checksum = "79712302e737d23ca0daa178e752c9334846b08321d439fd89af9a384f8c830b" dependencies = [ "anyhow", - "async-lock 2.8.0", "async-trait", "beef", + "bytes", "futures-timer", "futures-util", - "hyper 0.14.29", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "jsonrpsee-types", "parking_lot 0.12.3", + "pin-project", "rand", "rustc-hash", "serde", "serde_json", - "soketto", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "jsonrpsee-http-client" -version = "0.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c7b9f95208927653e7965a98525e7fc641781cab89f0e27c43fa2974405683" -dependencies = [ - "async-trait", - "hyper 0.14.29", - "hyper-rustls", - "jsonrpsee-core", - "jsonrpsee-types", - "serde", - "serde_json", "thiserror", "tokio", - "tower", + "tokio-stream", "tracing", - "url", ] [[package]] name = "jsonrpsee-proc-macros" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc0eba68ba205452bcb4c7b80a79ddcb3bf36c261a841b239433142db632d24" +checksum = "7895f186d5921065d96e16bd795e5ca89ac8356ec423fafc6e3d7cf8ec11aee4" dependencies = [ - "heck 0.4.1", - "proc-macro-crate 1.1.3", + "heck 0.5.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] name = "jsonrpsee-server" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a482bc4e25eebd0adb61a3468c722763c381225bd3ec46e926f709df8a8eb548" +checksum = "654afab2e92e5d88ebd8a39d6074483f3f2bfdf91c5ac57fe285e7127cdd4f51" dependencies = [ + "anyhow", "futures-util", - "http 0.2.12", - "hyper 0.14.29", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-util", "jsonrpsee-core", "jsonrpsee-types", + "pin-project", "route-recognizer", "serde", "serde_json", - "soketto", + "soketto 0.8.0", "thiserror", "tokio", "tokio-stream", @@ -5180,25 +5423,24 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3264e339143fe37ed081953842ee67bfafa99e3b91559bdded6e4abd8fc8535e" +checksum = "d9c465fbe385238e861fdc4d1c85e04ada6c1fd246161d26385c1b311724d2af" dependencies = [ - "anyhow", "beef", + "http 1.1.0", "serde", "serde_json", "thiserror", - "tracing", ] [[package]] name = "jsonrpsee-ws-client" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d06eeabbb55f0af8405288390a358ebcceb6e79e1390741e6f152309c4d6076" +checksum = "1c28759775f5cb2f1ea9667672d3fe2b0e701d1f4b7b67954e60afe7fd058b5e" dependencies = [ - "http 0.2.12", + "http 1.1.0", "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", @@ -5215,6 +5457,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", + "serdect", "sha2 0.10.8", ] @@ -5233,6 +5476,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28" +[[package]] +name = "kusama-runtime-constants" +version = "1.0.0" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +dependencies = [ + "frame-support", + "polkadot-primitives", + "polkadot-runtime-common", + "smallvec", + "sp-core", + "sp-runtime", + "sp-weights", + "staging-xcm-builder", +] + [[package]] name = "kvdb" version = "0.13.0" @@ -5302,7 +5560,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -5313,14 +5571,15 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libp2p" -version = "0.51.4" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f35eae38201a993ece6bdc823292d6abd1bffed1c4d0f4a3517d2bd8e1d917fe" +checksum = "e94495eb319a85b70a68b85e2389a95bb3555c71c49025b78c691a854a7e6464" dependencies = [ "bytes", + "either", "futures", "futures-timer", - "getrandom 0.2.15", + "getrandom", "instant", "libp2p-allow-block-list", "libp2p-connection-limits", @@ -5337,18 +5596,21 @@ dependencies = [ "libp2p-request-response", "libp2p-swarm", "libp2p-tcp", + "libp2p-upnp", "libp2p-wasm-ext", "libp2p-websocket", "libp2p-yamux", - "multiaddr", + "multiaddr 0.18.1", "pin-project", + "rw-stream-sink", + "thiserror", ] [[package]] name = "libp2p-allow-block-list" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "510daa05efbc25184458db837f6f9a5143888f1caa742426d92e1833ddd38a50" +checksum = "55b46558c5c0bf99d3e2a1a38fd54ff5476ca66dd1737b12466a1824dd219311" dependencies = [ "libp2p-core", "libp2p-identity", @@ -5358,9 +5620,9 @@ dependencies = [ [[package]] name = "libp2p-connection-limits" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4caa33f1d26ed664c4fe2cca81a08c8e07d4c1c04f2f4ac7655c2dd85467fda0" +checksum = "2f5107ad45cb20b2f6c3628c7b6014b996fcb13a88053f4569c872c6e30abf58" dependencies = [ "libp2p-core", "libp2p-identity", @@ -5370,9 +5632,9 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.39.2" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c1df63c0b582aa434fb09b2d86897fa2b419ffeccf934b36f87fcedc8e835c2" +checksum = "dd44289ab25e4c9230d9246c475a22241e301b23e8f4061d3bdef304a1a99713" dependencies = [ "either", "fnv", @@ -5381,8 +5643,8 @@ dependencies = [ "instant", "libp2p-identity", "log", - "multiaddr", - "multihash 0.17.0", + "multiaddr 0.18.1", + "multihash 0.19.1", "multistream-select", "once_cell", "parking_lot 0.12.3", @@ -5392,18 +5654,20 @@ dependencies = [ "rw-stream-sink", "smallvec", "thiserror", - "unsigned-varint", + "unsigned-varint 0.7.2", "void", ] [[package]] name = "libp2p-dns" -version = "0.39.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146ff7034daae62077c415c2376b8057368042df6ab95f5432ad5e88568b1554" +checksum = "e6a18db73084b4da2871438f6239fef35190b05023de7656e877c18a00541a3b" dependencies = [ + "async-trait", "futures", "libp2p-core", + "libp2p-identity", "log", "parking_lot 0.12.3", "smallvec", @@ -5412,19 +5676,20 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.42.2" +version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5455f472243e63b9c497ff320ded0314254a9eb751799a39c283c6f20b793f3c" +checksum = "45a96638a0a176bec0a4bcaebc1afa8cf909b114477209d7456ade52c61cd9cd" dependencies = [ "asynchronous-codec", "either", "futures", + "futures-bounded", "futures-timer", "libp2p-core", "libp2p-identity", "libp2p-swarm", "log", - "lru 0.10.1", + "lru 0.12.4", "quick-protobuf", "quick-protobuf-codec", "smallvec", @@ -5434,27 +5699,27 @@ dependencies = [ [[package]] name = "libp2p-identity" -version = "0.1.3" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" +checksum = "55cca1eb2bc1fd29f099f3daaab7effd01e1a54b7c577d0ed082521034d912e8" dependencies = [ - "bs58 0.4.0", + "bs58 0.5.1", "ed25519-dalek", - "log", - "multiaddr", - "multihash 0.17.0", + "hkdf", + "multihash 0.19.1", "quick-protobuf", "rand", "sha2 0.10.8", "thiserror", + "tracing", "zeroize", ] [[package]] name = "libp2p-kad" -version = "0.43.3" +version = "0.44.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39d5ef876a2b2323d63c258e63c2f8e36f205fe5a11f0b3095d59635650790ff" +checksum = "16ea178dabba6dde6ffc260a8e0452ccdc8f79becf544946692fff9d412fc29d" dependencies = [ "arrayvec 0.7.4", "asynchronous-codec", @@ -5469,20 +5734,21 @@ dependencies = [ "libp2p-swarm", "log", "quick-protobuf", + "quick-protobuf-codec", "rand", "sha2 0.10.8", "smallvec", "thiserror", "uint", - "unsigned-varint", + "unsigned-varint 0.7.2", "void", ] [[package]] name = "libp2p-mdns" -version = "0.43.1" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19983e1f949f979a928f2c603de1cf180cc0dc23e4ac93a62651ccb18341460b" +checksum = "42a2567c305232f5ef54185e9604579a894fd0674819402bb0ac0246da82f52a" dependencies = [ "data-encoding", "futures", @@ -5493,38 +5759,43 @@ dependencies = [ "log", "rand", "smallvec", - "socket2 0.4.10", + "socket2 0.5.7", "tokio", - "trust-dns-proto", + "trust-dns-proto 0.22.0", "void", ] [[package]] name = "libp2p-metrics" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a42ec91e227d7d0dafa4ce88b333cdf5f277253873ab087555c92798db2ddd46" +checksum = "239ba7d28f8d0b5d77760dc6619c05c7e88e74ec8fbbe97f856f20a56745e620" dependencies = [ + "instant", "libp2p-core", "libp2p-identify", + "libp2p-identity", "libp2p-kad", "libp2p-ping", "libp2p-swarm", + "once_cell", "prometheus-client", ] [[package]] name = "libp2p-noise" -version = "0.42.2" +version = "0.43.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3673da89d29936bc6435bafc638e2f184180d554ce844db65915113f86ec5e" +checksum = "d2eeec39ad3ad0677551907dd304b2f13f17208ccebe333bef194076cd2e8921" dependencies = [ "bytes", - "curve25519-dalek 3.2.0", + "curve25519-dalek", "futures", "libp2p-core", "libp2p-identity", "log", + "multiaddr 0.18.1", + "multihash 0.19.1", "once_cell", "quick-protobuf", "rand", @@ -5532,21 +5803,22 @@ dependencies = [ "snow", "static_assertions", "thiserror", - "x25519-dalek 1.1.1", + "x25519-dalek", "zeroize", ] [[package]] name = "libp2p-ping" -version = "0.42.0" +version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e57759c19c28a73ef1eb3585ca410cefb72c1a709fcf6de1612a378e4219202" +checksum = "e702d75cd0827dfa15f8fd92d15b9932abe38d10d21f47c50438c71dd1b5dae3" dependencies = [ "either", "futures", "futures-timer", "instant", "libp2p-core", + "libp2p-identity", "libp2p-swarm", "log", "rand", @@ -5555,9 +5827,9 @@ dependencies = [ [[package]] name = "libp2p-quic" -version = "0.7.0-alpha.3" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b26abd81cd2398382a1edfe739b539775be8a90fa6914f39b2ab49571ec735" +checksum = "130d451d83f21b81eb7b35b360bc7972aeafb15177784adc56528db082e6b927" dependencies = [ "bytes", "futures", @@ -5568,18 +5840,20 @@ dependencies = [ "libp2p-tls", "log", "parking_lot 0.12.3", - "quinn-proto", + "quinn 0.10.2", "rand", - "rustls 0.20.9", + "ring 0.16.20", + "rustls 0.21.12", + "socket2 0.5.7", "thiserror", "tokio", ] [[package]] name = "libp2p-request-response" -version = "0.24.1" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffdb374267d42dc5ed5bc53f6e601d4a64ac5964779c6e40bb9e4f14c1e30d5" +checksum = "d8e3b4d67870478db72bac87bfc260ee6641d0734e0e3e275798f089c3fecfd4" dependencies = [ "async-trait", "futures", @@ -5587,15 +5861,17 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm", + "log", "rand", "smallvec", + "void", ] [[package]] name = "libp2p-swarm" -version = "0.42.2" +version = "0.43.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903b3d592d7694e56204d211f29d31bc004be99386644ba8731fc3e3ef27b296" +checksum = "580189e0074af847df90e75ef54f3f30059aedda37ea5a1659e8b9fca05c0141" dependencies = [ "either", "fnv", @@ -5606,6 +5882,8 @@ dependencies = [ "libp2p-identity", "libp2p-swarm-derive", "log", + "multistream-select", + "once_cell", "rand", "smallvec", "tokio", @@ -5614,36 +5892,39 @@ dependencies = [ [[package]] name = "libp2p-swarm-derive" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fba456131824ab6acd4c7bf61e9c0f0a3014b5fc9868ccb8e10d344594cdc4f" +checksum = "c4d5ec2a3df00c7836d7696c136274c9c59705bac69133253696a6c932cd1d74" dependencies = [ "heck 0.4.1", + "proc-macro-warning 0.4.2", + "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] name = "libp2p-tcp" -version = "0.39.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d33698596d7722d85d3ab0c86c2c322254fce1241e91208e3679b4eb3026cf" +checksum = "b558dd40d1bcd1aaaed9de898e9ec6a436019ecc2420dd0016e712fbb61c5508" dependencies = [ "futures", "futures-timer", "if-watch", "libc", "libp2p-core", + "libp2p-identity", "log", - "socket2 0.4.10", + "socket2 0.5.7", "tokio", ] [[package]] name = "libp2p-tls" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff08d13d0dc66e5e9ba6279c1de417b84fa0d0adc3b03e5732928c180ec02781" +checksum = "8218d1d5482b122ccae396bbf38abdcb283ecc96fa54760e1dfd251f0546ac61" dependencies = [ "futures", "futures-rustls", @@ -5651,51 +5932,69 @@ dependencies = [ "libp2p-identity", "rcgen", "ring 0.16.20", - "rustls 0.20.9", + "rustls 0.21.12", + "rustls-webpki 0.101.7", "thiserror", - "webpki", - "x509-parser", + "x509-parser 0.15.1", "yasna", ] +[[package]] +name = "libp2p-upnp" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82775a47b34f10f787ad3e2a22e2c1541e6ebef4fe9f28f3ac553921554c94c1" +dependencies = [ + "futures", + "futures-timer", + "igd-next", + "libp2p-core", + "libp2p-swarm", + "log", + "tokio", + "void", +] + [[package]] name = "libp2p-wasm-ext" -version = "0.39.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77dff9d32353a5887adb86c8afc1de1a94d9e8c3bc6df8b2201d7cdf5c848f43" +checksum = "1e5d8e3a9e07da0ef5b55a9f26c009c8fb3c725d492d8bb4b431715786eea79c" dependencies = [ "futures", "js-sys", "libp2p-core", - "parity-send-wrapper", + "send_wrapper", "wasm-bindgen", "wasm-bindgen-futures", ] [[package]] name = "libp2p-websocket" -version = "0.41.0" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "111273f7b3d3510524c752e8b7a5314b7f7a1fee7e68161c01a7d72cbb06db9f" +checksum = "004ee9c4a4631435169aee6aad2f62e3984dc031c43b6d29731e8e82a016c538" dependencies = [ "either", "futures", "futures-rustls", "libp2p-core", + "libp2p-identity", "log", "parking_lot 0.12.3", - "quicksink", + "pin-project-lite", "rw-stream-sink", - "soketto", + "soketto 0.8.0", + "thiserror", "url", - "webpki-roots", + "webpki-roots 0.25.4", ] [[package]] name = "libp2p-yamux" -version = "0.43.1" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd21d950662700a385d4c6d68e2f5f54d778e97068cdd718522222ef513bda" +checksum = "8eedcb62824c4300efb9cfd4e2a6edaf3ca097b9e68b36dabe45a44469fd6a85" dependencies = [ "futures", "libp2p-core", @@ -5756,7 +6055,7 @@ checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" dependencies = [ "crunchy", "digest 0.9.0", - "subtle 2.4.1", + "subtle 2.5.0", ] [[package]] @@ -5857,6 +6156,61 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +[[package]] +name = "litep2p" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f46c51c205264b834ceed95c8b195026e700494bc3991aaba3b4ea9e20626d9" +dependencies = [ + "async-trait", + "bs58 0.4.0", + "bytes", + "cid 0.10.1", + "ed25519-dalek", + "futures", + "futures-timer", + "hex-literal", + "indexmap 2.2.6", + "libc", + "mockall 0.12.1", + "multiaddr 0.17.1", + "multihash 0.17.0", + "network-interface", + "nohash-hasher", + "parking_lot 0.12.3", + "pin-project", + "prost 0.12.6", + "prost-build 0.11.9", + "quinn 0.9.4", + "rand", + "rcgen", + "ring 0.16.20", + "rustls 0.20.9", + "serde", + "sha2 0.10.8", + "simple-dns", + "smallvec", + "snow", + "socket2 0.5.7", + "static_assertions", + "str0m", + "thiserror", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tokio-util", + "tracing", + "trust-dns-resolver", + "uint", + "unsigned-varint 0.8.0", + "url", + "webpki", + "x25519-dalek", + "x509-parser 0.16.0", + "yasna", + "zeroize", +] + [[package]] name = "lock_api" version = "0.4.12" @@ -5884,18 +6238,18 @@ dependencies = [ [[package]] name = "lru" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" -dependencies = [ - "hashbrown 0.13.2", -] +checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" [[package]] name = "lru" -version = "0.11.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +dependencies = [ + "hashbrown 0.14.5", +] [[package]] name = "lru-cache" @@ -5937,9 +6291,9 @@ dependencies = [ [[package]] name = "macro_magic" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc33f9f0351468d26fbc53d9ce00a096c8522ecb42f19b50f34f2c422f76d21d" +checksum = "e03844fc635e92f3a0067e25fa4bf3e3dbf3f2927bf3aa01bb7bc8f1c428949d" dependencies = [ "macro_magic_core", "macro_magic_macros", @@ -5949,12 +6303,12 @@ dependencies = [ [[package]] name = "macro_magic_core" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1687dc887e42f352865a393acae7cf79d98fab6351cde1f58e9e057da89bf150" +checksum = "468155613a44cfd825f1fb0ffa532b018253920d404e6fca1e8d43155198a46d" dependencies = [ "const-random", - "derive-syn-parse 0.2.0", + "derive-syn-parse 0.1.5", "macro_magic_core_macros", "proc-macro2", "quote", @@ -5963,9 +6317,9 @@ dependencies = [ [[package]] name = "macro_magic_core_macros" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" +checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" dependencies = [ "proc-macro2", "quote", @@ -5974,21 +6328,15 @@ dependencies = [ [[package]] name = "macro_magic_macros" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" +checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" dependencies = [ "macro_magic_core", "quote", "syn 2.0.66", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "match_cfg" version = "0.1.0" @@ -6080,6 +6428,20 @@ dependencies = [ "hash-db", ] +[[package]] +name = "merkleized-metadata" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f313fcff1d2a4bcaa2deeaa00bf7530d77d5f7bd0467a117dde2e29a75a7a17a" +dependencies = [ + "array-bytes", + "blake3", + "frame-metadata", + "parity-scale-codec", + "scale-decode", + "scale-info", +] + [[package]] name = "merlin" version = "3.0.0" @@ -6088,7 +6450,7 @@ checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder", "keccak", - "rand_core 0.6.4", + "rand_core", "zeroize", ] @@ -6118,15 +6480,6 @@ dependencies = [ "adler", ] -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", -] - [[package]] name = "mio" version = "0.8.11" @@ -6135,7 +6488,7 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -6150,25 +6503,25 @@ dependencies = [ "bitflags 1.3.2", "blake2 0.10.6", "c2-chacha", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "either", "hashlink", "lioness", "log", "parking_lot 0.12.3", "rand", - "rand_chacha 0.3.1", + "rand_chacha", "rand_distr", - "subtle 2.4.1", + "subtle 2.5.0", "thiserror", "zeroize", ] [[package]] name = "mmr-gadget" -version = "30.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f62cddc29c17965ab16a051a745520d41c28d8b4c2b6188aaf661db056d67c9" +checksum = "8f06f25f3b298799dbc20f7ffd40e667adc4fbd664cbb23ead5f7bbda52407ff" dependencies = [ "futures", "log", @@ -6186,9 +6539,9 @@ dependencies = [ [[package]] name = "mmr-rpc" -version = "29.0.0" +version = "35.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2634b45039e064c343a0a77ed45e03ca027c84e1b250b2f3988af7cde9b7e79e" +checksum = "7f9a252b1e03418e99c18ff6e2d4d9748d195395ed3749c8bfd9ca2c7530a43d" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -6210,8 +6563,23 @@ dependencies = [ "downcast", "fragile", "lazy_static", - "mockall_derive", - "predicates", + "mockall_derive 0.11.4", + "predicates 2.1.5", + "predicates-tree", +] + +[[package]] +name = "mockall" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +dependencies = [ + "cfg-if", + "downcast", + "fragile", + "lazy_static", + "mockall_derive 0.12.1", + "predicates 3.1.2", "predicates-tree", ] @@ -6227,6 +6595,24 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "mockall_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "multi-stash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" + [[package]] name = "multiaddr" version = "0.17.1" @@ -6242,7 +6628,26 @@ dependencies = [ "percent-encoding", "serde", "static_assertions", - "unsigned-varint", + "unsigned-varint 0.7.2", + "url", +] + +[[package]] +name = "multiaddr" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b852bc02a2da5feed68cd14fa50d0774b92790a5bdbfa932a813926c8472070" +dependencies = [ + "arrayref", + "byteorder", + "data-encoding", + "libp2p-identity", + "multibase", + "multihash 0.19.1", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint 0.7.2", "url", ] @@ -6268,10 +6673,10 @@ dependencies = [ "blake3", "core2", "digest 0.10.7", - "multihash-derive 0.8.1", + "multihash-derive", "sha2 0.10.8", "sha3", - "unsigned-varint", + "unsigned-varint 0.7.2", ] [[package]] @@ -6280,11 +6685,15 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" dependencies = [ + "blake2b_simd", + "blake2s_simd", + "blake3", "core2", "digest 0.10.7", - "multihash-derive 0.8.1", + "multihash-derive", "sha2 0.10.8", - "unsigned-varint", + "sha3", + "unsigned-varint 0.7.2", ] [[package]] @@ -6294,27 +6703,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" dependencies = [ "core2", - "unsigned-varint", -] - -[[package]] -name = "multihash-codetable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d815ecb3c8238d00647f8630ede7060a642c9f704761cd6082cb4028af6935" -dependencies = [ - "blake2b_simd", - "blake2s_simd", - "blake3", - "core2", - "digest 0.10.7", - "multihash-derive 0.9.0", - "ripemd", - "serde", - "sha1", - "sha2 0.10.8", - "sha3", - "strobe-rs", + "unsigned-varint 0.7.2", ] [[package]] @@ -6332,48 +6721,29 @@ dependencies = [ ] [[package]] -name = "multihash-derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "890e72cb7396cb99ed98c1246a97b243cc16394470d94e0bc8b0c2c11d84290e" -dependencies = [ - "core2", - "multihash 0.19.1", - "multihash-derive-impl", -] - -[[package]] -name = "multihash-derive-impl" -version = "0.1.1" +name = "multimap" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3958713ce794e12f7c6326fac9aa274c68d74c4881dd37b3e2662b8a2046bb19" -dependencies = [ - "proc-macro-crate 2.0.0", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure 0.13.1", -] +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "multistream-select" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8552ab875c1313b97b8d20cb857b9fd63e2d1d6a0a1b53ce9821e575405f27a" +checksum = "ea0df8e5eec2298a62b326ee4f0d7fe1a6b90a09dfcf9df37b38f947a8c42f19" dependencies = [ "bytes", "futures", "log", "pin-project", "smallvec", - "unsigned-varint", + "unsigned-varint 0.7.2", ] [[package]] @@ -6484,6 +6854,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "network-interface" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a43439bf756eed340bdf8feba761e2d50c7d47175d87545cd5cbe4a137c4d1" +dependencies = [ + "cc", + "libc", + "thiserror", + "winapi", +] + [[package]] name = "nix" version = "0.24.3" @@ -6497,15 +6879,22 @@ dependencies = [ [[package]] name = "nix" -version = "0.27.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.5.0", "cfg-if", + "cfg_aliases", "libc", ] +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + [[package]] name = "no-std-net" version = "0.6.0" @@ -6534,12 +6923,34 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nonempty" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" + +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + [[package]] name = "normalize-line-endings" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-bigint" version = "0.4.5" @@ -6565,6 +6976,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "num-format" version = "0.4.4" @@ -6615,12 +7037,6 @@ dependencies = [ "libc", ] -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - [[package]] name = "object" version = "0.30.4" @@ -6633,6 +7049,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "object" version = "0.36.0" @@ -6648,7 +7073,16 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" dependencies = [ - "asn1-rs", + "asn1-rs 0.5.2", +] + +[[package]] +name = "oid-registry" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c958dd45046245b9c3c2547369bb634eb461670b2e7e0de552905801a648d1d" +dependencies = [ + "asn1-rs 0.6.2", ] [[package]] @@ -6669,12 +7103,60 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-src" +version = "300.3.1+3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7259953d42a81bf137fbbd73bd30a8e1914d6dce43c2b90ed575783a22608b91" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -6704,7 +7186,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1344346d5af32c95bbddea91b18a88cc83eac394192d20ef2fc4c40a74332355" dependencies = [ - "expander 2.2.1", + "expander", "indexmap 2.2.6", "itertools 0.11.0", "petgraph", @@ -6733,6 +7215,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "pallet-api" version = "0.1.0" @@ -6754,13 +7242,14 @@ dependencies = [ [[package]] name = "pallet-asset-conversion" -version = "11.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4079f12db3cf98daa717337ab5b7e5ef15aa3bec3b497f501dc715d129b500da" +checksum = "f726ebb59401c1844a4a8703047bdafcd99a1827cd5d8b2c82abeb8948a7f25b" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "parity-scale-codec", "scale-info", "sp-api", @@ -6773,9 +7262,9 @@ dependencies = [ [[package]] name = "pallet-asset-conversion-tx-payment" -version = "11.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2019e84d65bf6c6105edb61cd6b6f4c6d9a1b347e05d9380e92b0dcf2a29fd7" +checksum = "e0fde03a96382f4dbe37ef95cb4ef7aade7c0be410cb6c888eda911c94af3eaf" dependencies = [ "frame-support", "frame-system", @@ -6789,9 +7278,9 @@ dependencies = [ [[package]] name = "pallet-asset-rate" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571ce57fd846911041749832b46a8c2b01f0b79ffebcd7585e3973865607036d" +checksum = "e806842bec955190ec64f8b2179f74f5355137c4cadf04f3269e6196cd19caf9" dependencies = [ "frame-benchmarking", "frame-support", @@ -6805,9 +7294,9 @@ dependencies = [ [[package]] name = "pallet-asset-tx-payment" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed783679921ad8b96807d683d320c314e305753b230d5c04dc713bab7aca64c" +checksum = "100a180dfbf30a1c872100ec2dae8a61c0f5e8b3f2d3a5cbb34093826293e2ab" dependencies = [ "frame-benchmarking", "frame-support", @@ -6824,13 +7313,14 @@ dependencies = [ [[package]] name = "pallet-assets" -version = "30.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46728a98a910af13f6a77033dd053456650773bb7adc71e0ba845bff7e31b33e" +checksum = "f79ef6a7763fc08177f014052469ee12aefcdad0d99a747372360c2f648d2cc4" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "impl-trait-for-tuples", "log", "parity-scale-codec", "scale-info", @@ -6841,9 +7331,9 @@ dependencies = [ [[package]] name = "pallet-aura" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a611bef3c8cf281e41a43f32a4153260bdc8b7b61b901e65c7a4442529224e11" +checksum = "0861b2a1ad6526948567bb59a3fdc4c7f02ee79b07be8b931a544350ec35ab0c" dependencies = [ "frame-support", "frame-system", @@ -6859,9 +7349,9 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" -version = "29.0.1" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd9a381c613e6538638391fb51f353fd13b16f849d0d1ac66a388326bd456f1" +checksum = "ed2c3666a476132f5846fe4d5e1961a923a58a0f54d873d84566f24ffaa3684f" dependencies = [ "frame-support", "frame-system", @@ -6876,9 +7366,9 @@ dependencies = [ [[package]] name = "pallet-authorship" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d83773e731a1760f99684b09961ed7b92acafe335f36f08ebb8313d3b9c72e2" +checksum = "38885846dbcf03b025fdbd7edb3649046dbc68fa0b419ffe8837ef853a10d31f" dependencies = [ "frame-support", "frame-system", @@ -6891,9 +7381,9 @@ dependencies = [ [[package]] name = "pallet-babe" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3f2020c52667a650d64e84a4bbb63388e25bc1c9bc872a8243d03bfcb285049" +checksum = "b23d2d814e3cb793659fcf84533f66fdf0ed9cccb66cb2225851f482843ed096" dependencies = [ "frame-benchmarking", "frame-support", @@ -6916,9 +7406,9 @@ dependencies = [ [[package]] name = "pallet-bags-list" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd27bfa4bfa5751652842b81241c7eff3e68f2806d9dacc17b03d2cb20a39756" +checksum = "af34fa3fb6a0abe3577e435988039a9e441f6705ae2d3ad627a23e3f705baa2d" dependencies = [ "aquamarine", "docify", @@ -6939,9 +7429,9 @@ dependencies = [ [[package]] name = "pallet-balances" -version = "29.0.2" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a54b5d0c7c4c3731883d6b1ac18aff44db20c3d0a3470c8861001a17afdc85" +checksum = "6878e240962d3887f0e0654ac343a18845adb95ad493c9d4d5e803c015d4a4c3" dependencies = [ "docify", "frame-benchmarking", @@ -6956,9 +7446,9 @@ dependencies = [ [[package]] name = "pallet-beefy" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bedd80e9d8b196f31ea134efd271fdc1b8380ca3aa2d8af6ea8b5a0dc4fa460" +checksum = "715dfcd1bf3f1f37af6335d4eb3cef921e746ac54721e2258c4fd968b61eb009" dependencies = [ "frame-support", "frame-system", @@ -6977,11 +7467,11 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d334f24d3c0c016d16aa87d069485847d622e8ebebace18ec5cf56609ca3a67" +checksum = "01d70c6f872eb3f2635355ccbea944a4f9ea411c0aa25f6f1a15219e8da11ad2" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "binary-merkle-tree", "frame-support", "frame-system", @@ -7003,9 +7493,9 @@ dependencies = [ [[package]] name = "pallet-bounties" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4765879e96676c13cdbed746d66fd59dcde1e9e65fda1f064fa2fffa3bc5d597" +checksum = "0566499e74ba4b7ccbd1b667eef0dab76ca28402a8d501e22b73a363717b05a9" dependencies = [ "frame-benchmarking", "frame-support", @@ -7022,9 +7512,9 @@ dependencies = [ [[package]] name = "pallet-bridge-grandpa" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "085573f22a29f8108e2e374b4b4c90702a7449c21edc29d1d614889e9b0c8c0c" +checksum = "61d30a4860bb12559dc28b2d46dd865e2066bce83239230f748e2c569a3cadf4" dependencies = [ "bp-header-chain", "bp-runtime", @@ -7044,9 +7534,9 @@ dependencies = [ [[package]] name = "pallet-bridge-messages" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0aac358f6781471f6fd667d5d5af6ee55c3eb11fc494de76787e942bc43726" +checksum = "e3c0fcb1b9ae50ece73cbe36b72c2778f5d4637e4fb0cfac30cb16f7d4b61d5e" dependencies = [ "bp-messages", "bp-runtime", @@ -7063,9 +7553,9 @@ dependencies = [ [[package]] name = "pallet-bridge-parachains" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6976281a13460098827ef61a368ef5c26f07bb4bfaf81a9ee4105577a73fc488" +checksum = "3974fb658cf1b9ca8c2d3c77bf080b2f94c054c2b466b709ef29f6d3726f2231" dependencies = [ "bp-header-chain", "bp-parachains", @@ -7085,9 +7575,9 @@ dependencies = [ [[package]] name = "pallet-bridge-relayers" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc71ebc287106596ae4d6026d1bdea6448c4b26f08f4477e8e9a2620e5a7c24b" +checksum = "2c92383f4c7d1eaced8413e39b948227a527a0136f705660580c57753dc11568" dependencies = [ "bp-messages", "bp-relayers", @@ -7106,9 +7596,9 @@ dependencies = [ [[package]] name = "pallet-broker" -version = "0.7.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "574c52fd629191c374c24a18036acac008ea92142309e5dd05e7f03149a667c3" +checksum = "cd0d652c399b6ed776ee3322e60f40e323f86b413719d7696eddb8f64c368ac0" dependencies = [ "bitvec", "frame-benchmarking", @@ -7117,6 +7607,7 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", + "sp-api", "sp-arithmetic", "sp-core", "sp-runtime", @@ -7125,9 +7616,9 @@ dependencies = [ [[package]] name = "pallet-child-bounties" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00fd06f2d719f5bb16ab3e836c6b053bbd92631ba694f8c2bf810013b2548167" +checksum = "38e351f103ebbdd1eb095da8c2379caccc82ebc59a740c2731693d2204286b83" dependencies = [ "frame-benchmarking", "frame-support", @@ -7145,9 +7636,9 @@ dependencies = [ [[package]] name = "pallet-collator-selection" -version = "10.0.3" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a36858c4275b7d19671b321e95f545e07c9643f97dffed1b333774cb391a4456" +checksum = "f660cc09f2f277a3976da2eef856b5c725ab7ad1192902ef7f4e4bafd992f04f" dependencies = [ "frame-benchmarking", "frame-support", @@ -7166,9 +7657,9 @@ dependencies = [ [[package]] name = "pallet-collective" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c362a0b8f30895c15ecc7d8c24b0d94bb586c4b9bbd37ac8053b4629d9cc80b" +checksum = "771bf7f6c76c3ea5e965fee0bf1d8a8c79c8c52d75ead65ed3c4d385f333756f" dependencies = [ "frame-benchmarking", "frame-support", @@ -7184,9 +7675,9 @@ dependencies = [ [[package]] name = "pallet-contracts" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b56fe53df97911ed3ecd90d631f8093cedd795c756d4e42d386110e9fe6614f" +checksum = "3e6989ac82690f981959b0d38ac6d6d52fc06bf00a035548d62b9a2e9c220376" dependencies = [ "bitflags 1.3.2", "environmental", @@ -7199,6 +7690,7 @@ dependencies = [ "pallet-contracts-proc-macro", "pallet-contracts-uapi", "parity-scale-codec", + "paste", "rand", "rand_pcg", "scale-info", @@ -7212,14 +7704,14 @@ dependencies = [ "staging-xcm", "staging-xcm-builder", "wasm-instrument", - "wasmi", + "wasmi 0.32.3", ] [[package]] name = "pallet-contracts-proc-macro" -version = "19.0.0" +version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3163c6bc21b55a0ccb74c546ba784d9c9e69beb9240c059d28a3052f4cbce509" +checksum = "94226cbd48516b7c310eb5dae8d50798c1ce73a7421dc0977c55b7fc2237a283" dependencies = [ "proc-macro2", "quote", @@ -7228,9 +7720,9 @@ dependencies = [ [[package]] name = "pallet-contracts-uapi" -version = "6.0.0" +version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61eeda58538dc888c59ae6de2146f0e2f43e9ad0eb1d56c228e5cc7af90d4e52" +checksum = "e1330375dcced95509e3cca7ef6b1c3fac648df995b86d39467d082ba981dc46" dependencies = [ "bitflags 1.3.2", "parity-scale-codec", @@ -7241,9 +7733,9 @@ dependencies = [ [[package]] name = "pallet-conviction-voting" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aee3a8b6fcde893f862993f9d45eb0fcd492dde0967fd56ef78d79fc7b53dc0" +checksum = "9033f0d23500bbc39298fd50c07b89a2f2d9f07300139b4df8005995ef683875" dependencies = [ "assert_matches", "frame-benchmarking", @@ -7257,11 +7749,26 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-delegated-staking" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0596ec5ab55e02b1b5637b3ec2b99027d036fe97a1ab4733ae105474dfa727cf" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-staking", + "sp-std", +] + [[package]] name = "pallet-democracy" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa781d632063087bcd3ff46eb1a668f15647ab116f1c8a7c573b7168f62d72c3" +checksum = "7ccd68a2bf5f2dfda2b810cbe1a779492d4c2e99338989fede4389d412ae325b" dependencies = [ "frame-benchmarking", "frame-support", @@ -7278,9 +7785,9 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b54d1d3fe9ae61a144d581147e699b7c3009169de0019a0f87cca0bed82681e7" +checksum = "bd1090fdc6ccdd8ff08c60000c970428baaaf0b33e7a6b01a91ec8b697a650a3" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7297,14 +7804,14 @@ dependencies = [ "sp-npos-elections", "sp-runtime", "sp-std", - "strum 0.24.1", + "strum 0.26.2", ] [[package]] name = "pallet-election-provider-support-benchmarking" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46ec87816a1e32a1ab6deececa99e21e6684b111efe87b11b8298328dbbefd01" +checksum = "93475989d2f6900caf8f1c847a55d909295c156525a7510c5f1dde176ec7c714" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7317,9 +7824,9 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" -version = "30.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cb0158cc7461fda5db04c5791d0df34635bec37181763aca449bade677d12d" +checksum = "9320d95c95e2d4d3ee24c9292b4ee8562ecb724b985613cfa7f274912bad2c9d" dependencies = [ "frame-benchmarking", "frame-support", @@ -7337,9 +7844,9 @@ dependencies = [ [[package]] name = "pallet-fast-unstake" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2222607a0dba10a9d57cab5360a6549b5fda925181c3c7af481246c0964998df" +checksum = "9155f4f762513e0287320411415c76a647152799ad33db1785c9b71c36a14575" dependencies = [ "docify", "frame-benchmarking", @@ -7357,9 +7864,9 @@ dependencies = [ [[package]] name = "pallet-grandpa" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b20be8592eed7ebca2ee661fc43450088552ebe0bd483d7b101cf5968ab12d" +checksum = "8244b686d5cae6a8af1557ed0f49db08f812f0e7942a8d2da554b4da8a69daf0" dependencies = [ "frame-benchmarking", "frame-support", @@ -7381,9 +7888,9 @@ dependencies = [ [[package]] name = "pallet-identity" -version = "29.0.1" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "452bba25325b7f0148eeecbde13e7c26dfb677ad46b3f160b359d7643b44c94b" +checksum = "4555795a3e0e3aa49ea432b7afecb9c71a7db8793a99c68bd8dd3a52a12571f3" dependencies = [ "enumflags2", "frame-benchmarking", @@ -7399,9 +7906,9 @@ dependencies = [ [[package]] name = "pallet-im-online" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598ea5c87351edc953d1f455f32ff456cf2f1daf7bbada1f1e03be8e384852ab" +checksum = "fa761292e95020304b58b50e5187f8bb82f557c8c2d013e3c96ab41d611873b0" dependencies = [ "frame-benchmarking", "frame-support", @@ -7420,9 +7927,9 @@ dependencies = [ [[package]] name = "pallet-indices" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e880ebdb429ca76fb400b1b361ed7fce018a5ea2fc2da4764de5156fffdfa73" +checksum = "b183880ad5efae06afe6066e76f2bac5acf67f34b3cfab7352ceec46accf4b45" dependencies = [ "frame-benchmarking", "frame-support", @@ -7438,9 +7945,9 @@ dependencies = [ [[package]] name = "pallet-membership" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad901cdf3de23daf23ff8b092ab318b13faebfc1aa4d84263f2fdc84feaf3e9b" +checksum = "34006cf047f47edbef33874cc64895918e2c5d7562795209068d5fb388c53a30" dependencies = [ "frame-benchmarking", "frame-support", @@ -7456,9 +7963,9 @@ dependencies = [ [[package]] name = "pallet-message-queue" -version = "32.0.0" +version = "39.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccb23dee70b184a214d729db550117a0965a69107d466d35181d60a6feede38" +checksum = "20e65a37881d1998546254a5e50a1f768b3f82deabe774e750f4ea95aba8030c" dependencies = [ "environmental", "frame-benchmarking", @@ -7477,9 +7984,9 @@ dependencies = [ [[package]] name = "pallet-mmr" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f1f23a70764dad2b4094d8be12ebbb82df210f2e80dd36fa941a5ac191c6cd" +checksum = "cf8ccec82827413f031689fef4c714fdb0213d58c7a6e208d33f5eab80483770" dependencies = [ "frame-benchmarking", "frame-support", @@ -7496,9 +8003,9 @@ dependencies = [ [[package]] name = "pallet-multisig" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176f6a5c170185f892a047c0ae189bc52eb390f2c0b94d4261ed0ebc7f82a548" +checksum = "be58483d827602eb8353ecf36aed65c857f0974db5d27981831e5ebf853040bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -7513,9 +8020,9 @@ dependencies = [ [[package]] name = "pallet-nft-fractionalization" -version = "11.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4225c31beb3a10235dd165c78f340c344ee78f6ebccd7c99d62a71fb76d2e39" +checksum = "7dcaa330221f60feaf3b23d495cccc3bf2a3d6254c596b3c032273c2b46d4078" dependencies = [ "frame-benchmarking", "frame-support", @@ -7531,9 +8038,9 @@ dependencies = [ [[package]] name = "pallet-nfts" -version = "23.0.0" +version = "30.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a8978bd9c43ac5ebaa7a26e5bd0c130b037d7cde97189e1a62fa64e5ee1ef1" +checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" dependencies = [ "enumflags2", "frame-benchmarking", @@ -7550,9 +8057,9 @@ dependencies = [ [[package]] name = "pallet-nfts-runtime-api" -version = "15.0.0" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c412ca82207d43e651ef80a3be837220b82ad0d6c3174922c369ef301ea0e5af" +checksum = "b0ca7a0446d2d3c27f726a016c6366218df2e0bfef9ed35886b252cfa9757f6c" dependencies = [ "pallet-nfts", "parity-scale-codec", @@ -7562,9 +8069,9 @@ dependencies = [ [[package]] name = "pallet-nis" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a64a0e80dec2c60d5962dd249061a47dc4356db440f26cdec50b8acaded1d3" +checksum = "e77cba0e15749c8de2be65efffa51e02bd051b4e6fcf23360d43c3b6a859187c" dependencies = [ "frame-benchmarking", "frame-support", @@ -7579,9 +8086,9 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" -version = "26.0.1" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62091305ec7426e71c3da2b0944c2df5a804109ee4d2e8f4fe34865e049f8ac" +checksum = "36f8c994eb7298a394b58f98afd520b521b5d46f6f39eade4657eeaac9962471" dependencies = [ "frame-support", "frame-system", @@ -7599,15 +8106,16 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-benchmarking" -version = "27.0.0" +version = "34.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a1eba3078e2492cad15e4695f90eb3fc570386d9f71f8b81f709c7123fc6b5" +checksum = "39ee599f2861e55fc6113c01e9b14d6e85fda46bac36a906b5dd5a951fa0455c" dependencies = [ "frame-benchmarking", "frame-election-provider-support", "frame-support", "frame-system", "pallet-bags-list", + "pallet-delegated-staking", "pallet-nomination-pools", "pallet-staking", "parity-scale-codec", @@ -7620,9 +8128,9 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" -version = "24.0.0" +version = "31.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5b35e6c471a669437b987ff02e11e2283412c9ebaeec5334dec3f73bcea652" +checksum = "2906899d8f029780f0d9da77b90ae86f42bcfda5ac402c931406cd84852012ed" dependencies = [ "pallet-nomination-pools", "parity-scale-codec", @@ -7632,9 +8140,9 @@ dependencies = [ [[package]] name = "pallet-offences" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b5bcfdc4f6032d7570929094fd459de12d840c440c395fb4d365d679e13eda" +checksum = "4859e7bb2af46d2e0f137c2f777adf39f0e5d4d188226158d599f1cfcfb76b9e" dependencies = [ "frame-support", "frame-system", @@ -7650,9 +8158,9 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc33e3086c19235cb903cbbbde1bc1c4f428519ad4c23446dc84c75d0061582" +checksum = "4351b0edafcdf3240f0471c638b39d2c981bde9d17c0172536a0aa3b7c3097ef" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7673,11 +8181,30 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-parameters" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58d9a81a93202105a660e6aa3d3f81638bdd109ca0497f3e528529cd52d034db" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-preimage" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7344a30c304771beb90aec34604100185e47cdc0366e268ad18922de602a0c7e" +checksum = "68ac726abc5b1bcd6c8f783514b8e1a48be32c7d15e0b263e4bc28cc1e4e7763" dependencies = [ "frame-benchmarking", "frame-support", @@ -7693,9 +8220,9 @@ dependencies = [ [[package]] name = "pallet-proxy" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7aa31a0b91e8060b808c3e3407e4578a5e94503b174b9e99769147b24fb2c56" +checksum = "b4e12680e176607815a78a0cd10a52af50790292cb950404f30a885e2a7229e9" dependencies = [ "frame-benchmarking", "frame-support", @@ -7709,9 +8236,9 @@ dependencies = [ [[package]] name = "pallet-ranked-collective" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3733dbfc44d8f5e1a08287a9064e5794e9d0e92b1bd68cdad2e22202b1964528" +checksum = "862ea8d386ed5737e859470c43cbfd9652c81398cad29e03ae7846c21aaee4c6" dependencies = [ "frame-benchmarking", "frame-support", @@ -7729,9 +8256,9 @@ dependencies = [ [[package]] name = "pallet-recovery" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "797b554ddc87082c18223440d61a81cf35ccab6573321ce473a099e7a709a760" +checksum = "b24d4131bc79fee0b07550136ca6329faa84c1c3e76ae62a74aef6b1da0b95b4" dependencies = [ "frame-benchmarking", "frame-support", @@ -7745,9 +8272,9 @@ dependencies = [ [[package]] name = "pallet-referenda" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da850889e7101b63cadb980b7f39df67feb6d63bc6092769b9b708e9eb596db1" +checksum = "b2c906a9c4573eb58de4134ec7180bf12c6769df2b9859dae8adcbc5fce78add" dependencies = [ "assert_matches", "frame-benchmarking", @@ -7765,9 +8292,9 @@ dependencies = [ [[package]] name = "pallet-root-testing" -version = "5.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59171cbf2b823c13685b1b80dd3e1e84425680ff4e006d8016f8c14d2ec44974" +checksum = "fa61642f7bdc1a393798aa1ff67bb8c29f8f184b6fce165e1079010d446a1e29" dependencies = [ "frame-support", "frame-system", @@ -7781,9 +8308,9 @@ dependencies = [ [[package]] name = "pallet-scheduler" -version = "30.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e2a4ebe6a5f98b14a26deed8d7a1ea28bb2c2d3ad4d6dc129a725523a2042d" +checksum = "b170d6aa191197d3f50b1193925546972ffc394376ead4d2739eb40909b73c85" dependencies = [ "docify", "frame-benchmarking", @@ -7800,9 +8327,9 @@ dependencies = [ [[package]] name = "pallet-session" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7412ac59247b300feee53709f7009a23d1c6f8c70528599f48f44e102d896d03" +checksum = "7c92b24c911c2cfa5351616edc7f2f93427ea6f4f95efdb13f0f5d51997939c3" dependencies = [ "frame-support", "frame-system", @@ -7823,9 +8350,9 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9c2731415381020db1e78db8b40207f8423a16099e78f2fde599cbcb57ea8db" +checksum = "bd02aaf5f10734670346677042ece94fae20dcd5436eafeb9b429d8d6d5b6385" dependencies = [ "frame-benchmarking", "frame-support", @@ -7841,16 +8368,16 @@ dependencies = [ [[package]] name = "pallet-society" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba64f96619c25ae7a0b41f4a5111c2d3102e8b8c6cbce80ece6955e825f9de2" +checksum = "66b60b1d726532317f9965bab4995aa49b73f9b7ca3b9a0f75d158bd84686c5f" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "parity-scale-codec", - "rand_chacha 0.2.2", + "rand_chacha", "scale-info", "sp-arithmetic", "sp-io", @@ -7860,9 +8387,9 @@ dependencies = [ [[package]] name = "pallet-staking" -version = "29.0.3" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061b00814eb794a40df4eca7972a7c67b26473cd85cc7c54f5816ae49ad6e11b" +checksum = "fbebdb060417654f215fc6f03675e5f44cfc83837d9e523e1b8fd9a4a2e1bdc2" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7872,7 +8399,7 @@ dependencies = [ "pallet-authorship", "pallet-session", "parity-scale-codec", - "rand_chacha 0.2.2", + "rand_chacha", "scale-info", "serde", "sp-application-crypto", @@ -7884,9 +8411,9 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" -version = "11.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efca5a4a423427d2c83af5fe07ab648c16b91e3782c3cc23316fe0bd96b4c794" +checksum = "db5e6b1d8ee9d3f6894c5abd8c3e17737ed738c9854f87bfd16239741b7f4d5d" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", @@ -7896,9 +8423,9 @@ dependencies = [ [[package]] name = "pallet-staking-reward-fn" -version = "20.0.0" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505d45e08bad052f55fb51f00a6b6244d23ee46ffdc8091f6cddf4e3a880319d" +checksum = "988a7ebeacc84d4bdb0b12409681e956ffe35438447d8f8bc78db547cffb6ebc" dependencies = [ "log", "sp-arithmetic", @@ -7906,9 +8433,9 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" -version = "15.0.1" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47c73850103db30b61ef170107afe1ef0dab6905c495bd6dfb57b3c1dd81bc7" +checksum = "3350ef1795b832f4adc464e88fb6d44827bd3f98701b0b0bbee495267b444a92" dependencies = [ "parity-scale-codec", "sp-api", @@ -7917,9 +8444,9 @@ dependencies = [ [[package]] name = "pallet-state-trie-migration" -version = "30.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e52dedc146b7a9c3b7c5a6ff4c4c442a8ab8cc58ec30e90e1e98cdc51ad34" +checksum = "e07f8626f4ff62ac79d6ad0bd01fab7645897ce35706ddb95fa084e75be9306d" dependencies = [ "frame-benchmarking", "frame-support", @@ -7935,9 +8462,9 @@ dependencies = [ [[package]] name = "pallet-sudo" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d02f7855d411913e77e57126f4a8b8a32d90d9bf47d0b747e367a1301729c3" +checksum = "1bd2a8797c1bb3d3897b4f87a7716111da5eeb8561345277b6e6d70349ec8b35" dependencies = [ "docify", "frame-benchmarking", @@ -7952,9 +8479,9 @@ dependencies = [ [[package]] name = "pallet-timestamp" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b8810ddfb254c7fb8cd7698229cce513d309a43ff117b38798dae6120f477b" +checksum = "ae789d344be857679b0b98b28a67c747119724847f81d704d3fd03ee13fb6841" dependencies = [ "docify", "frame-benchmarking", @@ -7973,9 +8500,9 @@ dependencies = [ [[package]] name = "pallet-tips" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca4b9921c9e9b59e8eeb64677ba6ec49743ef5fe98e0b63f77411b2b9f6cc99" +checksum = "f7dfec7872ee9e071209ae860094569745e8bd47564bacdba739256ee52cf78c" dependencies = [ "frame-benchmarking", "frame-support", @@ -7993,9 +8520,9 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" -version = "29.0.2" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5ba71f06f09e955b80dc313c333be3f8d9e8505b051558e0b7af4806b13310" +checksum = "74fb6114223c8d967c3c2f21cbc845e8ea604ff7e21a8e59d119d5a9257ba886" dependencies = [ "frame-support", "frame-system", @@ -8010,9 +8537,9 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" -version = "31.0.0" +version = "38.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ef209d2d5d077e325bf49b024fd2eff109a5c2ca0d84ce0d50a65839e6b026" +checksum = "a82898085607c7b00ef20fdce7c621790bf2b644c134918a172fe0a8f7f08e6c" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -8027,9 +8554,9 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c78bcba80c7c61712b98a6b5640975ebd25ceb688c18e975af78a0fac81785b0" +checksum = "f4bad1700ad7eb5ab254189e1df894d1d16b3626a3c4b9c45259ec4d9efc262c" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -8040,9 +8567,9 @@ dependencies = [ [[package]] name = "pallet-treasury" -version = "28.0.1" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eca44990d0d759213744f2d1f6fe1fadec1079a3e4e4da40556d6b4e42abbcd" +checksum = "9c502615bb4fdd02856a131cb2a612ad40c26435ec938f65f11cae4ff230812b" dependencies = [ "docify", "frame-benchmarking", @@ -8060,9 +8587,9 @@ dependencies = [ [[package]] name = "pallet-uniques" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9449d6e2cdcc4456466eff97a065c43dde678620551f5fd79072dec3b9f560" +checksum = "4a59e8599a8c19908e934645f845b5cb546cef1f08745319db7e5b9c24f9e0e4" dependencies = [ "frame-benchmarking", "frame-support", @@ -8076,9 +8603,9 @@ dependencies = [ [[package]] name = "pallet-utility" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "954f15b98c3fdebb763bb5cea4ec6803fd180d540ec5b07a9fcb2c118251d52c" +checksum = "3238fe6ad00da6a137be115904c39cab97eb5c7f03da0bb1a20de1bef03f0c71" dependencies = [ "frame-benchmarking", "frame-support", @@ -8093,9 +8620,9 @@ dependencies = [ [[package]] name = "pallet-vesting" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4525f3038cdf078fea39d913c563ca626f09a615e7724f0c9eac97743c75ff44" +checksum = "78f7f0f4fe5e1d851e85d81e5e73b6f929f0c35af786ce8be9c9e3363717c136" dependencies = [ "frame-benchmarking", "frame-support", @@ -8109,9 +8636,9 @@ dependencies = [ [[package]] name = "pallet-whitelist" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0ad4ce05688bdddcdb682cbed2f3edff0ee5349f0b745ebacc27d179582432" +checksum = "3e4f27640279229eb73fde0cb06e98b799305e6b0bc724f4dfbef2001ab4ad00" dependencies = [ "frame-benchmarking", "frame-support", @@ -8125,9 +8652,9 @@ dependencies = [ [[package]] name = "pallet-xcm" -version = "8.0.5" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba9138b04168b07b1aff4a2079f5514753c31dddba40e5fb471b9cda7da27ad6" +checksum = "fe7409458b7fedc5c7d46459da154ccc2dc22a843ce08e8ab6c1743ef5cf972c" dependencies = [ "bounded-collections", "frame-benchmarking", @@ -8145,13 +8672,14 @@ dependencies = [ "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", + "xcm-runtime-apis", ] [[package]] name = "pallet-xcm-benchmarks" -version = "8.0.2" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c10e1c92086ce2069a3d2387d9431f48660b6ec92054c4d0a4e30a9f54e7ad3" +checksum = "2f177a171203cc0bec3cff1bdd5d3b926abfbd0ecf347e044b147194e664f717" dependencies = [ "frame-benchmarking", "frame-support", @@ -8169,9 +8697,9 @@ dependencies = [ [[package]] name = "pallet-xcm-bridge-hub-router" -version = "0.6.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5bd3947da7f031c86904f12b6690bbecd2efa122906a8dd838499150fe4322" +checksum = "f48bd38d4061a51f263f4c08021e66100e16cbda9978fba163d2544637b31dab" dependencies = [ "bp-xcm-bridge-hub-router", "frame-benchmarking", @@ -8189,9 +8717,9 @@ dependencies = [ [[package]] name = "parachains-common" -version = "8.0.1" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711a4c073e7c83aac7e414ba16c7c641d6d9e22e6d32f9775ff35b2464ffd7ff" +checksum = "9319e656eebdf161666e54a4d8e24f73137f702f01600247f7be650bc4d46167" dependencies = [ "cumulus-primitives-core", "cumulus-primitives-utility", @@ -8221,9 +8749,9 @@ dependencies = [ [[package]] name = "parachains-runtimes-test-utils" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d295b9c391ce15f68ddcd7b0d428eb2d3338643a4d1f471b3dd8a15538865e17" +checksum = "c778447d2e71a418b083c0458579d0f8d13872f43c63142d9e5157edea000bdd" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-pallet-xcmp-queue", @@ -8235,6 +8763,7 @@ dependencies = [ "pallet-balances", "pallet-collator-selection", "pallet-session", + "pallet-timestamp", "pallet-xcm", "parity-scale-codec", "polkadot-parachain-primitives", @@ -8250,6 +8779,19 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "parity-bip39" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" +dependencies = [ + "bitcoin_hashes 0.13.0", + "rand", + "rand_core", + "serde", + "unicode-normalization", +] + [[package]] name = "parity-bytes" version = "0.1.2" @@ -8304,12 +8846,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "parity-send-wrapper" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" - [[package]] name = "parity-util-mem" version = "0.12.0" @@ -8406,113 +8942,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7924d1d0ad836f665c9065e26d016c673ece3993f30d340068b16f282afc1156" [[package]] -name = "paseo-runtime" -version = "1.2.5" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" -dependencies = [ - "binary-merkle-tree", - "frame-benchmarking", - "frame-election-provider-support", - "frame-executive", - "frame-metadata-hash-extension", - "frame-support", - "frame-system", - "frame-system-benchmarking", - "frame-system-rpc-runtime-api", - "frame-try-runtime", - "log", - "pallet-asset-rate", - "pallet-authority-discovery", - "pallet-authorship", - "pallet-babe", - "pallet-bags-list", - "pallet-balances", - "pallet-beefy", - "pallet-beefy-mmr", - "pallet-bounties", - "pallet-child-bounties", - "pallet-conviction-voting", - "pallet-election-provider-multi-phase", - "pallet-election-provider-support-benchmarking", - "pallet-fast-unstake", - "pallet-grandpa", - "pallet-identity", - "pallet-indices", - "pallet-message-queue", - "pallet-mmr", - "pallet-multisig", - "pallet-nomination-pools", - "pallet-nomination-pools-benchmarking", - "pallet-nomination-pools-runtime-api", - "pallet-offences", - "pallet-offences-benchmarking", - "pallet-preimage", - "pallet-proxy", - "pallet-referenda", - "pallet-scheduler", - "pallet-session", - "pallet-session-benchmarking", - "pallet-staking", - "pallet-staking-reward-curve", - "pallet-staking-reward-fn", - "pallet-staking-runtime-api", - "pallet-state-trie-migration", - "pallet-sudo", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-treasury", - "pallet-utility", - "pallet-vesting", - "pallet-whitelist", - "pallet-xcm", - "pallet-xcm-benchmarks", - "parity-scale-codec", - "paseo-runtime-constants", - "polkadot-primitives", - "polkadot-runtime-common", - "polkadot-runtime-parachains", - "scale-info", - "sp-api", - "sp-application-crypto", - "sp-arithmetic", - "sp-authority-discovery", - "sp-block-builder", - "sp-consensus-babe", - "sp-consensus-beefy", - "sp-core", - "sp-debug-derive", - "sp-genesis-builder", - "sp-inherents", - "sp-io", - "sp-npos-elections", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-staking", - "sp-std", - "sp-storage", - "sp-transaction-pool", - "sp-version", - "staging-xcm", - "staging-xcm-builder", - "staging-xcm-executor", - "substrate-wasm-builder", -] - -[[package]] -name = "paseo-runtime-constants" -version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ - "frame-support", - "polkadot-primitives", - "polkadot-runtime-common", - "smallvec", - "sp-core", - "sp-runtime", - "sp-weights", - "staging-xcm-builder", + "base64ct", + "rand_core", + "subtle 2.5.0", ] [[package]] @@ -8521,15 +8958,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pbkdf2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" -dependencies = [ - "crypto-mac 0.11.1", -] - [[package]] name = "pbkdf2" version = "0.12.2" @@ -8537,6 +8965,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", + "password-hash", ] [[package]] @@ -8635,12 +9064,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "pin-project-lite" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -8682,14 +9105,14 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "polkadot-approval-distribution" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cdfa52beecc446ccf733dede1a0089e6396d3df13401004d27c0ce2530816bc" +checksum = "61d39d6552d00ade2d668b8171aa7d6a1f5da4c7ebff402b5a9877b5d1e45b4e" dependencies = [ "bitvec", "futures", "futures-timer", - "itertools 0.10.5", + "itertools 0.11.0", "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", @@ -8703,9 +9126,9 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80ffc856dfbdb31178625760824ae320ddb7dd5694b217f489bd2832b8de15a5" +checksum = "cd0a8b5280959524f84b09c27ef0dbceeced6d19537f8fd43d03a08414f8b93d" dependencies = [ "always-assert", "futures", @@ -8720,9 +9143,9 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d05c26cc8d6fa0f5f432d9de880f20ad0d24ca51a618834ea6612d1bd96ab1" +checksum = "adfe520a9c8dbe6c5db06c0b919c53441927babc1c02b9df76718fc4b80c5c4f" dependencies = [ "derive_more", "fatality", @@ -8735,6 +9158,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "rand", + "sc-network", "schnellru", "sp-core", "sp-keystore", @@ -8744,9 +9168,9 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d77e0b979f43861ab4c78c216c2729644bb12812f9bc859858bd3b8fc56b4d6" +checksum = "727f02306a3a51eb0b8efca3e1e14c5efa2daf921c9be7c46d9c5d68670a9b51" dependencies = [ "async-trait", "fatality", @@ -8766,11 +9190,21 @@ dependencies = [ "tracing-gum", ] +[[package]] +name = "polkadot-ckb-merkle-mountain-range" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b44320e5f7ce2c18227537a3032ae5b2c476a7e8eddba45333e1011fc31b92" +dependencies = [ + "cfg-if", + "itertools 0.10.5", +] + [[package]] name = "polkadot-cli" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef362c44280e3883a39ca452acc4a4fb61a18250d634d68578b22df7edd8290c" +checksum = "141a62da626bba7c4a29b8e5d20a975efa6439095a352ebfc47f068e4dfd82fd" dependencies = [ "cfg-if", "clap", @@ -8790,16 +9224,16 @@ dependencies = [ "sp-io", "sp-keyring", "sp-maybe-compressed-blob", + "sp-runtime", "substrate-build-script-utils", "thiserror", - "try-runtime-cli", ] [[package]] name = "polkadot-collator-protocol" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507391f1be9f9b9a8fbf28ca13b0ab3f04947a54a1115d423d115aacf8889bf4" +checksum = "75bd07cc8a0bfabe6464d40072e30bd87f52730fbc26c733f0a8ffa97918c0a8" dependencies = [ "bitvec", "fatality", @@ -8820,9 +9254,9 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" -version = "8.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a08e4e014c853b252ecbbe3ccd67b2d33d78e46988d309b8cccf4ac06e25ef" +checksum = "17c72ee63bcf920f963cd7ac066759b0b649350c8ab3781a85a6aac87b1488f2" dependencies = [ "parity-scale-codec", "scale-info", @@ -8833,9 +9267,9 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae32e83ef6bc0ec2874c76c19dff8f3795832ccc27f0abc587a7137994c42d26" +checksum = "09c49e68add45aa6c2b85e97f0d09b81f26b1428117bdc9284eaa74a1eb63daf" dependencies = [ "derive_more", "fatality", @@ -8859,9 +9293,9 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" -version = "8.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b10514ace3272d38b602e1795a5a340b265285c4af875473d682a5c9d6c831c" +checksum = "6a39a54a269817e09d602b4e9c527905f9e367ff7c6337b1b3e1e048515f6b59" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -8874,9 +9308,9 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01f05f7f60022d4beb30414f1f7c7e4ae728fea02086a4a0f8ff0a73e73ea4aa" +checksum = "53b56e8fe08e4ed30af0d296870b12b5a7411695f2b79b3c5842d04b9a347200" dependencies = [ "futures", "futures-timer", @@ -8885,7 +9319,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "rand", - "rand_chacha 0.3.1", + "rand_chacha", "sc-network", "sc-network-common", "sp-application-crypto", @@ -8897,9 +9331,9 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049ec1298ac6e96bcf4d980cd5864aceeee73b3298ab5d6dd7a3193d47578abc" +checksum = "178b92197936c23ae8a936ec74b83a15a9fe0978c7f3de677db141ba9c524a63" dependencies = [ "always-assert", "async-trait", @@ -8921,9 +9355,9 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f1211ab8b154c2e2b4b89c64f57f96056c881e4fcfa2ce29b6e5cbc978e74f1" +checksum = "869534f66d5a38443acf4b9fec3a4919f59f293e6fdee4177cd7cece1c4a85ef" dependencies = [ "futures", "parity-scale-codec", @@ -8940,15 +9374,15 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61a17b7e4edd3b73afbe0c6e8b5369bf3b721361a232baf11fb1698077067a4" +checksum = "ed3629b2d93b5f152bc75437fb68326ebf9267885ff89f2abede9b8a050e9288" dependencies = [ "bitvec", "derive_more", "futures", "futures-timer", - "itertools 0.10.5", + "itertools 0.11.0", "kvdb", "merlin", "parity-scale-codec", @@ -8959,8 +9393,8 @@ dependencies = [ "polkadot-overseer", "polkadot-primitives", "rand", - "rand_chacha 0.3.1", - "rand_core 0.6.4", + "rand_chacha", + "rand_core", "sc-keystore", "schnellru", "schnorrkel 0.11.4", @@ -8974,9 +9408,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b334f06423ff701e4b807d6832741ec24e0e97ebc13b560fc99bc0652926c0" +checksum = "8487c45eedaaf535ccc78bf4f459eae9443c4c9cfcca31dc3838950f3a3426e3" dependencies = [ "bitvec", "futures", @@ -8997,9 +9431,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" -version = "8.0.1" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07f8840f3f2f0bee6264c18ce471c99c925f9afb65952e1d584b6d773cf4115" +checksum = "b493dff8562ce2675dbb0e5c8594e145085a4536de435f5061f577bdaba2195e" dependencies = [ "bitvec", "fatality", @@ -9018,9 +9452,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0687006f843d6da8687eb24da735a04cbdcf4c3a98d82055b9b3a9047537e17e" +checksum = "5946d61086be5096e8dafd731d0881fa41e12f21a1f3a8b9d7ff6f1294914b98" dependencies = [ "futures", "polkadot-node-subsystem", @@ -9034,9 +9468,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3035acf9069801e980b91b5178591f8a7052b4409de13824db7a6c798b36b98" +checksum = "389b6d8da9a7cf825f97ff4da4ef754a1371de0358e896fbec973f4ff1dfe011" dependencies = [ "async-trait", "futures", @@ -9056,9 +9490,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c990b9ffdde6725fe79f55e3b7c4c32ce2134a06103708476fa595a4ac652e95" +checksum = "29086798f24839c9dc1c8b080ffc68bbfe2a5fdc5f29de557b9d224a45011094" dependencies = [ "futures", "polkadot-node-metrics", @@ -9071,9 +9505,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451965f3ace786d392c407872d61324765061b87027890b02ffd625554531f97" +checksum = "79c8bcae78a4562bc8b3b786e08cb1b3c96c29554da7d57b6806a6723b1540b0" dependencies = [ "futures", "futures-timer", @@ -9089,9 +9523,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13ea9d5b4aa43b5b1f718c3ec951adff0b0d74909cb1fe28206f5d88492247d" +checksum = "459e1da76e61c2f5636123ae7c19097067dcc1d07e0d5e77eae4eb87e5cb999d" dependencies = [ "fatality", "futures", @@ -9109,9 +9543,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6574c0bda4e10d722f761d4b8ab5d1708f0f963e5840370aa9cee8f559c90a23" +checksum = "18e4d2b44748657a68c8ff2995b0b39609f5186bc4b07040ebb6b389dbf1047b" dependencies = [ "async-trait", "futures", @@ -9127,9 +9561,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-prospective-parachains" -version = "7.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "160f80a11b9d2b8e36e510ea54ce5b06e77179c0c502f7e19e5a5809bc1523ee" +checksum = "756205c36293216422775c6fa1be9fc4bdb99fa5cafd86b96e7feae13e669e79" dependencies = [ "bitvec", "fatality", @@ -9145,9 +9579,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" -version = "8.0.1" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d0a64371700537c3dc15b3956536e4541f093b7c38ac21737ea9fea3562a83" +checksum = "d6f090dc90bbe0b452a57a3129b53a6129e357ff4607e9db27a54b291d7a747b" dependencies = [ "bitvec", "fatality", @@ -9157,24 +9591,23 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", + "schnellru", "thiserror", "tracing-gum", ] [[package]] name = "polkadot-node-core-pvf" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3bbb1b5f4b966f21a0336e94c0a0222958d2f3cba451da1157af271d07f9748" +checksum = "2eea57cb8ce66c2952b87b2476b46d6316ae58342f198abd09c391827ed5402d" dependencies = [ "always-assert", - "array-bytes 6.2.3", + "array-bytes", "blake3", "cfg-if", "futures", "futures-timer", - "is_executable", - "libc", "parity-scale-codec", "pin-project", "polkadot-core-primitives", @@ -9187,8 +9620,6 @@ dependencies = [ "rand", "slotmap", "sp-core", - "sp-maybe-compressed-blob", - "sp-wasm-interface", "tempfile", "thiserror", "tokio", @@ -9197,9 +9628,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-checker" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ab4a91e62a9f7e67cf400931578f2505417cc43a32ac29458163604f2b277b" +checksum = "6483e6db611d96b14deb298bcf877c44905ba2b45207183d62d0fda9c2fcfec2" dependencies = [ "futures", "polkadot-node-primitives", @@ -9214,16 +9645,15 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-common" -version = "8.0.0" +version = "14.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003981d3b63e4f527ef7f03cbe280e41ec649d9be365668887f0b107610640f4" +checksum = "d0eca24abc74c0c3f02f9986edbda12b3e8b6d294c39b238cf39e94e246aa2b9" dependencies = [ - "cfg-if", "cpu-time", "futures", "landlock", "libc", - "nix 0.27.1", + "nix 0.28.0", "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-primitives", @@ -9242,9 +9672,9 @@ dependencies = [ [[package]] name = "polkadot-node-core-runtime-api" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6ea6a03f297b7387fc59c41c3c32285803971cb27e81d7e9ca696824d6773" +checksum = "0024b2f4e4a03e4fda348183bbfe5eb51dd6e90b57eabc83596ee4d0079fd0e8" dependencies = [ "futures", "polkadot-node-metrics", @@ -9258,9 +9688,9 @@ dependencies = [ [[package]] name = "polkadot-node-jaeger" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d113b48e7b6126964c3a790b101d99e17fd3cb75a92e94d54587ce1340df21" +checksum = "b671c3407a7e325264af798664ca60c985873c04f54f53cc8f02aa81512fd40a" dependencies = [ "lazy_static", "log", @@ -9270,6 +9700,7 @@ dependencies = [ "polkadot-node-primitives", "polkadot-primitives", "sc-network", + "sc-network-types", "sp-core", "thiserror", "tokio", @@ -9277,9 +9708,9 @@ dependencies = [ [[package]] name = "polkadot-node-metrics" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef2e2a934f0d0d606fcfc53fc26f4cacd8b9f18fb2118829203fa813af2cdae" +checksum = "bae429c6a40f782a615d7ec863c4eda83c36bee5f6b542bcf86f754342f97b5a" dependencies = [ "bs58 0.5.1", "futures", @@ -9297,9 +9728,9 @@ dependencies = [ [[package]] name = "polkadot-node-network-protocol" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07f9e67b0f25d695947a15b6fe8ee6f8e83f3dfcbca124a13281c0edd0dc4703" +checksum = "cf88dcc39ac21e12a65c255707b89933ddf3dadfb2c422d9f0fd8ff644229e77" dependencies = [ "async-channel 1.9.0", "async-trait", @@ -9315,16 +9746,18 @@ dependencies = [ "rand", "sc-authority-discovery", "sc-network", - "strum 0.24.1", + "sc-network-types", + "sp-runtime", + "strum 0.26.2", "thiserror", "tracing-gum", ] [[package]] name = "polkadot-node-primitives" -version = "8.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375744eee7a53576387e14856e1c65be8ecef8b449567bb2cff85706266c8912" +checksum = "779833f70a1563ed042d3c6b831a45c5ea0f80caa8f4ede487f7bee3130168fb" dependencies = [ "bitvec", "bounded-vec", @@ -9346,9 +9779,9 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d6c226cdbcd48ab1e506d8512f0fb01839f9a72eec2fc0cf7771f6d3352171" +checksum = "6a338e574c2416135b0004ebef226be22db13c44532e2a0f33b67648afb3ca12" dependencies = [ "polkadot-node-jaeger", "polkadot-node-subsystem-types", @@ -9357,13 +9790,14 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1404525da0ab9d44bac1041449bf0c5576240f9031b305dc41654567e98b6021" +checksum = "b0df39c7eef657b1e28917529f0b0c2aa5f0b013f4f298cfb3620b54449f0c95" dependencies = [ "async-trait", "bitvec", "derive_more", + "fatality", "futures", "orchestra", "polkadot-node-jaeger", @@ -9373,6 +9807,7 @@ dependencies = [ "polkadot-statement-table", "sc-client-api", "sc-network", + "sc-network-types", "sc-transaction-pool-api", "smallvec", "sp-api", @@ -9386,21 +9821,22 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65a7d101f28bf718d15f01a060ed8cf7a7e2d8d5705c494b49ece696cada0adf" +checksum = "a55a268e05c8c39aeb81b9ad59dfd18a7a711c8f8fa19bf83c75025de25466b7" dependencies = [ "async-trait", "derive_more", "fatality", "futures", "futures-channel", - "itertools 0.10.5", + "itertools 0.11.0", "kvdb", "parity-db", "parity-scale-codec", "parking_lot 0.12.3", "pin-project", + "polkadot-erasure-coding", "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", @@ -9422,9 +9858,9 @@ dependencies = [ [[package]] name = "polkadot-overseer" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5ed988deffeddf440473586f62efc5dd498f6016e6650881db09dd60b3b24f" +checksum = "c2456c1b2d176550e91e2e1ddb092390b00e20898e5c4fd9b5978d56ab1bbf24" dependencies = [ "async-trait", "futures", @@ -9445,9 +9881,9 @@ dependencies = [ [[package]] name = "polkadot-parachain-primitives" -version = "7.0.0" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248ab090959a92e61493277e33b7e85104280a4beb4cb0815137d3c8c50a07f4" +checksum = "f61070d0ff28f596890def0e0d03c231860796130b2a43e293106fa86a50c9a9" dependencies = [ "bounded-collections", "derive_more", @@ -9463,9 +9899,9 @@ dependencies = [ [[package]] name = "polkadot-primitives" -version = "8.0.1" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d5f9930210cab0233d81204415c9ef4a8889cdf3e60de1435250481a2773ca" +checksum = "5a4879609f4340138930c3c7313256941104a3ff6f7ecb2569d15223da9b35b2" dependencies = [ "bitvec", "hex-literal", @@ -9491,9 +9927,9 @@ dependencies = [ [[package]] name = "polkadot-rpc" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4747cb8faa532e8446b38b74266fd626d6b660fe6b00776dd6c4543cc0457f" +checksum = "0dc80e33ff0a7155588d7b6cadffbbad7e8e489c2275f6f49ce61cb5cdfedca7" dependencies = [ "jsonrpsee", "mmr-rpc", @@ -9513,21 +9949,121 @@ dependencies = [ "sc-sync-state-rpc", "sc-transaction-pool-api", "sp-api", + "sp-application-crypto", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", + "sp-consensus-beefy", "sp-keystore", "sp-runtime", "substrate-frame-rpc-system", "substrate-state-trie-migration-rpc", ] +[[package]] +name = "polkadot-runtime" +version = "1.0.0" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +dependencies = [ + "binary-merkle-tree", + "frame-benchmarking", + "frame-election-provider-support", + "frame-executive", + "frame-metadata-hash-extension", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "log", + "pallet-asset-rate", + "pallet-authority-discovery", + "pallet-authorship", + "pallet-babe", + "pallet-bags-list", + "pallet-balances", + "pallet-beefy", + "pallet-beefy-mmr", + "pallet-bounties", + "pallet-broker", + "pallet-child-bounties", + "pallet-conviction-voting", + "pallet-election-provider-multi-phase", + "pallet-election-provider-support-benchmarking", + "pallet-fast-unstake", + "pallet-grandpa", + "pallet-im-online", + "pallet-indices", + "pallet-message-queue", + "pallet-mmr", + "pallet-multisig", + "pallet-nomination-pools", + "pallet-nomination-pools-benchmarking", + "pallet-nomination-pools-runtime-api", + "pallet-offences", + "pallet-offences-benchmarking", + "pallet-preimage", + "pallet-proxy", + "pallet-referenda", + "pallet-scheduler", + "pallet-session", + "pallet-session-benchmarking", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-staking-reward-fn", + "pallet-staking-runtime-api", + "pallet-state-trie-migration", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", + "pallet-utility", + "pallet-vesting", + "pallet-whitelist", + "pallet-xcm", + "pallet-xcm-benchmarks", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-runtime-common", + "polkadot-runtime-constants", + "polkadot-runtime-parachains", + "scale-info", + "serde_json", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-authority-discovery", + "sp-block-builder", + "sp-consensus-babe", + "sp-consensus-beefy", + "sp-core", + "sp-debug-derive", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-npos-elections", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", + "sp-storage", + "sp-transaction-pool", + "sp-version", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "substrate-wasm-builder", + "xcm-runtime-apis", +] + [[package]] name = "polkadot-runtime-common" -version = "8.0.3" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a70422ca43d30457e2d9502a5e4af35e20fa2ff3f7cd46e0d2997c784f2665" +checksum = "28fdcb41bb21c7b14d0341a9a17364ccc04ad34de05d41e7938cb03acbc11066" dependencies = [ "bitvec", "frame-benchmarking", @@ -9575,11 +10111,26 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "polkadot-runtime-constants" +version = "1.0.0" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +dependencies = [ + "frame-support", + "polkadot-primitives", + "polkadot-runtime-common", + "smallvec", + "sp-core", + "sp-runtime", + "sp-weights", + "staging-xcm-builder", +] + [[package]] name = "polkadot-runtime-metrics" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3566c6fd0c21b5dd555309427c984cf506f875ee90f710acea295b478fecbe0" +checksum = "ac75b3fea8464e5681b44733ed11cf09e22ff1e956f6703b918b637bd40e7427" dependencies = [ "bs58 0.5.1", "frame-benchmarking", @@ -9591,9 +10142,9 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" -version = "8.0.3" +version = "15.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d37cd3e014b06daf396d1483b5327782a0ebadc816423419665166b75b3e3e" +checksum = "cb7e68cb26f9025daaad694d8192fd0e63e92c8761c45a339dd7a5b7925a3cb6" dependencies = [ "bitflags 1.3.2", "bitvec", @@ -9619,8 +10170,7 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-metrics", "rand", - "rand_chacha 0.3.1", - "rustc-hex", + "rand_chacha", "scale-info", "serde", "sp-api", @@ -9641,9 +10191,9 @@ dependencies = [ [[package]] name = "polkadot-service" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2fd665185877bec296588c7cf1ec0ef75e0545050b5e1d42d94240a284149da" +checksum = "fa560fb67981865b895082845c4ec43fabb206da5bf583ec5ef3561a8e3fc333" dependencies = [ "async-trait", "frame-benchmarking", @@ -9659,7 +10209,6 @@ dependencies = [ "log", "mmr-gadget", "pallet-babe", - "pallet-im-online", "pallet-staking", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -9751,17 +10300,19 @@ dependencies = [ "sp-transaction-pool", "sp-version", "sp-weights", + "staging-xcm", "substrate-prometheus-endpoint", "thiserror", "tracing-gum", "westend-runtime", + "xcm-runtime-apis", ] [[package]] name = "polkadot-statement-distribution" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff6d16cbd994987f48a9f107f12e4c7fff26cdd71df6288e9521adc7cff3427" +checksum = "16020ecadd1826ffbce2693ba1490123a0f7ca74d233c9bc8c0cbfc23bb4df2a" dependencies = [ "arrayvec 0.7.4", "bitvec", @@ -9783,9 +10334,9 @@ dependencies = [ [[package]] name = "polkadot-statement-table" -version = "8.0.1" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5e010da3c6a65d8f263d0f825a04d995ffc8a37f886f674fcbbc73bf158d01" +checksum = "947e9e3c8f71b9678f39a01f371a808b574823967dd9da187e6f886f5f08691c" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -9793,27 +10344,51 @@ dependencies = [ "tracing-gum", ] +[[package]] +name = "polkavm" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3693e5efdb2bf74e449cd25fd777a28bd7ed87e41f5d5da75eb31b4de48b94" +dependencies = [ + "libc", + "log", + "polkavm-assembler", + "polkavm-common", + "polkavm-linux-raw", +] + +[[package]] +name = "polkavm-assembler" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa96d6d868243acc12de813dd48e756cbadcc8e13964c70d272753266deadc1" +dependencies = [ + "log", +] + [[package]] name = "polkavm-common" -version = "0.5.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b4e215c80fe876147f3d58158d5dfeae7dabdd6047e175af77095b78d0035c" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" +dependencies = [ + "log", +] [[package]] name = "polkavm-derive" -version = "0.5.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6380dbe1fb03ecc74ad55d841cfc75480222d153ba69ddcb00977866cbdabdb8" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" dependencies = [ - "polkavm-derive-impl", - "syn 2.0.66", + "polkavm-derive-impl-macro", ] [[package]] name = "polkavm-derive-impl" -version = "0.5.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc8211b3365bbafb2fb32057d68b0e1ca55d079f5cf6f9da9b98079b94b3987d" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" dependencies = [ "polkavm-common", "proc-macro2", @@ -9821,6 +10396,37 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +dependencies = [ + "polkavm-derive-impl", + "syn 2.0.66", +] + +[[package]] +name = "polkavm-linker" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7be503e60cf56c0eb785f90aaba4b583b36bff00e93997d93fef97f9553c39" +dependencies = [ + "gimli 0.28.1", + "hashbrown 0.14.5", + "log", + "object 0.32.2", + "polkavm-common", + "regalloc2 0.9.3", + "rustc-demangle", +] + +[[package]] +name = "polkavm-linux-raw" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26e85d3456948e650dff0cfc85603915847faf893ed1e66b020bb82ef4557120" + [[package]] name = "polling" version = "2.8.0" @@ -9833,7 +10439,7 @@ dependencies = [ "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.14", + "pin-project-lite", "windows-sys 0.48.0", ] @@ -9846,7 +10452,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi 0.4.0", - "pin-project-lite 0.2.14", + "pin-project-lite", "rustix 0.38.34", "tracing", "windows-sys 0.52.0", @@ -9899,7 +10505,7 @@ dependencies = [ [[package]] name = "pop-node" -version = "0.1.0-alpha" +version = "0.2.0-alpha" dependencies = [ "clap", "color-print", @@ -9918,12 +10524,14 @@ dependencies = [ "futures", "jsonrpsee", "log", + "pallet-multisig", "pallet-transaction-payment-rpc", "parity-scale-codec", "polkadot-cli", "polkadot-primitives", "pop-runtime-common", "pop-runtime-devnet", + "pop-runtime-mainnet", "pop-runtime-testnet", "sc-basic-authorship", "sc-chain-spec", @@ -9993,10 +10601,13 @@ dependencies = [ "cumulus-pallet-xcmp-queue", "cumulus-primitives-aura", "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-utility", + "enumflags2", "env_logger 0.11.5", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -10056,9 +10667,76 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "pop-runtime-mainnet" +version = "0.1.0" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-aura", + "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", + "cumulus-primitives-utility", + "enumflags2", + "env_logger 0.11.5", + "frame-benchmarking", + "frame-executive", + "frame-metadata-hash-extension", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-message-queue", + "pallet-multisig", + "pallet-preimage", + "pallet-proxy", + "pallet-scheduler", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-utility", + "pallet-xcm", + "parachains-common", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-runtime-common", + "pop-runtime-common", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "staging-parachain-info", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "substrate-wasm-builder", +] + [[package]] name = "pop-runtime-testnet" -version = "0.2.0" +version = "0.4.1" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", @@ -10067,10 +10745,13 @@ dependencies = [ "cumulus-pallet-xcmp-queue", "cumulus-primitives-aura", "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-utility", + "enumflags2", "env_logger 0.11.5", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -10160,6 +10841,16 @@ dependencies = [ "regex", ] +[[package]] +name = "predicates" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" +dependencies = [ + "anstyle", + "predicates-core", +] + [[package]] name = "predicates-core" version = "1.0.6" @@ -10237,15 +10928,6 @@ dependencies = [ "toml 0.5.11", ] -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", -] - [[package]] name = "proc-macro-crate" version = "3.1.0" @@ -10279,6 +10961,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-warning" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "proc-macro-warning" version = "1.0.2" @@ -10315,9 +11008,9 @@ dependencies = [ [[package]] name = "prometheus-client" -version = "0.19.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6fa99d535dd930d1249e6c79cb3c2915f9172a540fe2b02a4c8f9ca954721e" +checksum = "3c99afa9a01501019ac3a14d71d9f94050346f55ca471ce90c799a15c58f61e2" dependencies = [ "dtoa", "itoa", @@ -10367,17 +11060,38 @@ dependencies = [ "itertools 0.10.5", "lazy_static", "log", - "multimap", + "multimap 0.8.3", "petgraph", "prettyplease 0.1.25", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "regex", "syn 1.0.109", "tempfile", "which 4.4.2", ] +[[package]] +name = "prost-build" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +dependencies = [ + "bytes", + "heck 0.5.0", + "itertools 0.11.0", + "log", + "multimap 0.10.0", + "once_cell", + "petgraph", + "prettyplease 0.2.20", + "prost 0.12.6", + "prost-types 0.12.6", + "regex", + "syn 2.0.66", + "tempfile", +] + [[package]] name = "prost-derive" version = "0.11.9" @@ -10413,6 +11127,15 @@ dependencies = [ "prost 0.11.9", ] +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost 0.12.6", +] + [[package]] name = "psm" version = "0.1.21" @@ -10422,6 +11145,21 @@ dependencies = [ "cc", ] +[[package]] +name = "quanta" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -10439,44 +11177,112 @@ dependencies = [ [[package]] name = "quick-protobuf-codec" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1693116345026436eb2f10b677806169c1a1260c1c60eaaffe3fb5a29ae23d8b" +checksum = "f8ededb1cd78531627244d51dd0c7139fbe736c7d57af0092a76f0ffb2f56e98" dependencies = [ "asynchronous-codec", "bytes", "quick-protobuf", "thiserror", - "unsigned-varint", + "unsigned-varint 0.7.2", ] [[package]] -name = "quicksink" -version = "0.1.2" +name = "quinn" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e8b432585672228923edbbf64b8b12c14e1112f62e88737655b4a083dbcd78e" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto 0.9.6", + "quinn-udp 0.3.2", + "rustc-hash", + "rustls 0.20.9", + "thiserror", + "tokio", + "tracing", + "webpki", +] + +[[package]] +name = "quinn" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" +dependencies = [ + "bytes", + "futures-io", + "pin-project-lite", + "quinn-proto 0.10.6", + "quinn-udp 0.4.1", + "rustc-hash", + "rustls 0.21.12", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" +dependencies = [ + "bytes", + "rand", + "ring 0.16.20", + "rustc-hash", + "rustls 0.20.9", + "slab", + "thiserror", + "tinyvec", + "tracing", + "webpki", +] + +[[package]] +name = "quinn-proto" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "141bf7dfde2fbc246bfd3fe12f2455aa24b0fbd9af535d8c86c7bd1381ff2b1a" +dependencies = [ + "bytes", + "rand", + "ring 0.16.20", + "rustc-hash", + "rustls 0.21.12", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" +checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4" dependencies = [ - "futures-core", - "futures-sink", - "pin-project-lite 0.1.12", + "libc", + "quinn-proto 0.9.6", + "socket2 0.4.10", + "tracing", + "windows-sys 0.42.0", ] [[package]] -name = "quinn-proto" -version = "0.9.6" +name = "quinn-udp" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" +checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" dependencies = [ "bytes", - "rand", - "ring 0.16.20", - "rustc-hash", - "rustls 0.20.9", - "slab", - "thiserror", - "tinyvec", + "libc", + "socket2 0.5.7", "tracing", - "webpki", + "windows-sys 0.48.0", ] [[package]] @@ -10501,18 +11307,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -10522,16 +11318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -10540,7 +11327,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom", ] [[package]] @@ -10559,7 +11346,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" dependencies = [ - "rand_core 0.6.4", + "rand_core", +] + +[[package]] +name = "raw-cpuid" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" +dependencies = [ + "bitflags 2.5.0", ] [[package]] @@ -10633,7 +11429,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ - "getrandom 0.2.15", + "getrandom", "libredox", "thiserror", ] @@ -10682,6 +11478,19 @@ dependencies = [ "smallvec", ] +[[package]] +name = "regalloc2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +dependencies = [ + "hashbrown 0.13.2", + "log", + "rustc-hash", + "slice-group-by", + "smallvec", +] + [[package]] name = "regex" version = "1.10.5" @@ -10743,7 +11552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac 0.12.1", - "subtle 2.4.1", + "subtle 2.5.0", ] [[package]] @@ -10769,22 +11578,13 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom", "libc", "spin 0.9.8", "untrusted 0.9.0", "windows-sys 0.52.0", ] -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", -] - [[package]] name = "rlp" version = "0.5.2" @@ -10807,11 +11607,12 @@ dependencies = [ [[package]] name = "rococo-runtime" -version = "8.0.1" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa4cc054efdd3bfbec965da01b1ae16475031308c109c173347717091f6e3a5" +checksum = "0874c053846cd50170370d88244fd00ed299d3d3833804f0929371a9ed836137" dependencies = [ "binary-merkle-tree", + "bitvec", "frame-benchmarking", "frame-executive", "frame-metadata-hash-extension", @@ -10837,7 +11638,6 @@ dependencies = [ "pallet-elections-phragmen", "pallet-grandpa", "pallet-identity", - "pallet-im-online", "pallet-indices", "pallet-membership", "pallet-message-queue", @@ -10845,6 +11645,7 @@ dependencies = [ "pallet-multisig", "pallet-nis", "pallet-offences", + "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", @@ -10876,6 +11677,7 @@ dependencies = [ "scale-info", "serde", "serde_derive", + "serde_json", "smallvec", "sp-api", "sp-arithmetic", @@ -10883,6 +11685,7 @@ dependencies = [ "sp-block-builder", "sp-consensus-babe", "sp-consensus-beefy", + "sp-consensus-grandpa", "sp-core", "sp-genesis-builder", "sp-inherents", @@ -10901,13 +11704,14 @@ dependencies = [ "staging-xcm-executor", "static_assertions", "substrate-wasm-builder", + "xcm-runtime-apis", ] [[package]] name = "rococo-runtime-constants" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b45c21ccb0f8777512a65510c106aeee4b59682944b9a5cb31cd7b8ed4ccb47" +checksum = "2ef330dc0657ac9e4ff93ff320e2ee1a120493bceb91010c7ef7b08fe8e27950" dependencies = [ "frame-support", "polkadot-primitives", @@ -11045,7 +11849,6 @@ version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" dependencies = [ - "log", "ring 0.16.20", "sct", "webpki", @@ -11059,10 +11862,25 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring 0.17.8", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "log", + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki 0.102.4", + "subtle 2.5.0", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -11070,7 +11888,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.2", + "rustls-pki-types", "schannel", "security-framework", ] @@ -11084,6 +11915,49 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-platform-verifier" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93bda3f493b9abe5b93b3e7e3ecde0df292f2bd28c0296b90586ee0055ff5123" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.10", + "rustls-native-certs 0.7.0", + "rustls-platform-verifier-android", + "rustls-webpki 0.102.4", + "security-framework", + "security-framework-sys", + "webpki-roots 0.26.3", + "winapi", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -11094,6 +11968,17 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -11113,9 +11998,9 @@ dependencies = [ [[package]] name = "rw-stream-sink" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26338f5e09bb721b85b135ea05af7767c90b52f6de4f087d4f4a3a9d64e7dc04" +checksum = "d8c9026ff5d2f23da5e45bbc283f156383001bfb09c4e44256d02c1a685fe9a1" dependencies = [ "futures", "pin-project", @@ -11148,9 +12033,9 @@ dependencies = [ [[package]] name = "sc-allocator" -version = "24.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357127c91373ed6d1ae582f6e3300ab5b13bcde43bbf270a891f44194ef48b70" +checksum = "b975ee3a95eaacb611e7b415737a7fa2db4d8ad7b880cc1b97371b04e95c7903" dependencies = [ "log", "sp-core", @@ -11160,24 +12045,25 @@ dependencies = [ [[package]] name = "sc-authority-discovery" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb3c14cb8022844835a6f7209196b8c6544d389fe5d2972d8df2ae4ca75afbe" +checksum = "7ae99d03b5cf657754241180c4aedd14c4851a08f3fa56814106b3cc02083d2c" dependencies = [ "async-trait", "futures", "futures-timer", "ip_network", "libp2p", + "linked_hash_set", "log", - "multihash 0.18.1", - "multihash-codetable", + "multihash 0.19.1", "parity-scale-codec", "prost 0.12.6", - "prost-build", + "prost-build 0.12.6", "rand", "sc-client-api", "sc-network", + "sc-network-types", "sp-api", "sp-authority-discovery", "sp-blockchain", @@ -11190,9 +12076,9 @@ dependencies = [ [[package]] name = "sc-basic-authorship" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "724c3a6eee5f0829a1b79a15e12d63ed81b33281b14004a6331a8883b2fd8fd1" +checksum = "5c31a124aa02343a17cb86cc714bc2b66ce18c7f17530178767388de8a37b152" dependencies = [ "futures", "futures-timer", @@ -11213,9 +12099,9 @@ dependencies = [ [[package]] name = "sc-block-builder" -version = "0.34.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8b0640994965c6ff3afa13242d95a61611b83da21fd86ac2b1ebd03e241a02" +checksum = "d6345fb862e10aaa7d88d6689a7c247448c40ae465253c83566dc76a17ec1426" dependencies = [ "parity-scale-codec", "sp-api", @@ -11229,11 +12115,11 @@ dependencies = [ [[package]] name = "sc-chain-spec" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f73880050f8b04fed7f6301279ef3899df13a3891bd06156d56f9a1c50fefba" +checksum = "e04100ec7ff9cf1f2052b05086c77cc216ff7268b8c4fe41007de420bc1f70be" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "docify", "log", "memmap2 0.9.4", @@ -11252,13 +12138,14 @@ dependencies = [ "sp-io", "sp-runtime", "sp-state-machine", + "sp-tracing", ] [[package]] name = "sc-chain-spec-derive" -version = "11.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e80fbdaea194762d4b4b0eec389037c25ad102676203b42d684774ae3019b8" +checksum = "b18cef11d2c69703e0d7c3528202ef4ed1cd2b47a6f063e9e17cad8255b1fa94" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", @@ -11268,20 +12155,20 @@ dependencies = [ [[package]] name = "sc-cli" -version = "0.37.0" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a284c10ea92b1fe789b9f0e5815d393f3a1e3bf6a4adaa884f24e36143b83b" +checksum = "23a50b5a5de473b38de8a909b125b9747a30158900159e59251bb716f80d6d22" dependencies = [ - "array-bytes 6.2.3", - "bip39", + "array-bytes", "chrono", "clap", "fdlimit", "futures", - "itertools 0.10.5", + "itertools 0.11.0", "libp2p-identity", "log", "names", + "parity-bip39", "parity-scale-codec", "rand", "regex", @@ -11310,9 +12197,9 @@ dependencies = [ [[package]] name = "sc-client-api" -version = "29.0.0" +version = "35.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e914dfadaaf384d8869ae47f3ec783bf6a1ac24e7827f5fec2e0e649a450a91" +checksum = "1bb517f4418644aeefd7c29bbe34bfc56ba8b5ea56e0b661a48a4d4d6afef40b" dependencies = [ "fnv", "futures", @@ -11338,9 +12225,9 @@ dependencies = [ [[package]] name = "sc-client-db" -version = "0.36.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f08c4f29e6d2b8915bab6435b8817fa39ef7708c04a7cf6226f803e133b017c" +checksum = "2e3c685871877f39df000ec446f65fc8d502a7cecfc437cdac59866349642dc3" dependencies = [ "hash-db", "kvdb", @@ -11365,18 +12252,17 @@ dependencies = [ [[package]] name = "sc-consensus" -version = "0.34.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e1ac2c698b828073982b6f5b1a466fcc345a452983356af74254ade8e9987d" +checksum = "2b2927954d83d4c055a8699cad8ae093fc921ce73694da6773bd06d195e9a8dd" dependencies = [ "async-trait", "futures", - "futures-timer", - "libp2p-identity", "log", - "mockall", + "mockall 0.11.4", "parking_lot 0.12.3", "sc-client-api", + "sc-network-types", "sc-utils", "serde", "sp-api", @@ -11391,9 +12277,9 @@ dependencies = [ [[package]] name = "sc-consensus-aura" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a16fd09794291795ad43ea1df7190083f9a47fc0a73e9b8ec0ae98fbe53a2b34" +checksum = "017320849a7fce8200da88ccf07785d461c4d144032788f09eb4316742649a38" dependencies = [ "async-trait", "futures", @@ -11421,9 +12307,9 @@ dependencies = [ [[package]] name = "sc-consensus-babe" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82ec3dc31f8fd024684d1306488836680558b680a8ec38219e19f20854811f02" +checksum = "91c28b231f19a90917fde889a5077a796e2f9cb4dc6b62f861a8d859437a54cc" dependencies = [ "async-trait", "fork-tree", @@ -11458,9 +12344,9 @@ dependencies = [ [[package]] name = "sc-consensus-babe-rpc" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf2b3004672f9eea0d9af6c9b944fa3ef0bc72fd88cea9075cdf6dc96d1439ac" +checksum = "879efb0d8d0bd363d38ca314fbe4c44363dc1bdcab0ba1c21e78d9a68fd4398b" dependencies = [ "futures", "jsonrpsee", @@ -11481,11 +12367,11 @@ dependencies = [ [[package]] name = "sc-consensus-beefy" -version = "14.0.0" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ce3ee15eff7fa642791966d427f185184df3c7f4e58893705f3e7781da8ef5" +checksum = "5ddcd779375dc2aa4abfb2ff8e001d0901593b58e5c70e1720472a001fe13105" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "async-channel 1.9.0", "async-trait", "fnv", @@ -11498,6 +12384,7 @@ dependencies = [ "sc-network", "sc-network-gossip", "sc-network-sync", + "sc-network-types", "sc-utils", "sp-api", "sp-application-crypto", @@ -11508,7 +12395,6 @@ dependencies = [ "sp-core", "sp-crypto-hashing", "sp-keystore", - "sp-mmr-primitives", "sp-runtime", "substrate-prometheus-endpoint", "thiserror", @@ -11518,9 +12404,9 @@ dependencies = [ [[package]] name = "sc-consensus-beefy-rpc" -version = "14.0.0" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a1ed5e8ac2cb53c6a248c8f469353f55bd23c72f23fe371ac19c1d46618de1a" +checksum = "54e88abb3353e3ed98bcb8ab829dc84dfdf9d17f5312568bdf2361a1bde7ce0a" dependencies = [ "futures", "jsonrpsee", @@ -11530,6 +12416,7 @@ dependencies = [ "sc-consensus-beefy", "sc-rpc", "serde", + "sp-application-crypto", "sp-consensus-beefy", "sp-core", "sp-runtime", @@ -11538,9 +12425,9 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" -version = "0.34.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f68ddb91626f901578515eed93c7919f739660161f4e9f7b9407e2d0ede981" +checksum = "8c983798bfea80e629ffa4faa7c299f8522d382703cd32f7a299beaf69631586" dependencies = [ "fork-tree", "parity-scale-codec", @@ -11552,12 +12439,12 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa" -version = "0.20.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae91e5b5a120be4d13a59eaf94fd85d7c7af528482b8e21d861fa1167df3083" +checksum = "c7c6c62a03b54973f1a608a405908af0fe957fefaf77483cce96bd213eee7ed0" dependencies = [ "ahash 0.8.11", - "array-bytes 6.2.3", + "array-bytes", "async-trait", "dyn-clone", "finality-grandpa", @@ -11576,6 +12463,7 @@ dependencies = [ "sc-network-common", "sc-network-gossip", "sc-network-sync", + "sc-network-types", "sc-telemetry", "sc-transaction-pool-api", "sc-utils", @@ -11596,9 +12484,9 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa-rpc" -version = "0.20.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697cbd528516561dbc818a8990d5477169e86d9335a0b29207cf6f6a90269e7c" +checksum = "9ef329f23bdafaeb57e131b81cc479a85b6ecb25e42435b6a6a544d048207685" dependencies = [ "finality-grandpa", "futures", @@ -11617,9 +12505,9 @@ dependencies = [ [[package]] name = "sc-consensus-slots" -version = "0.34.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567bddd65d52951fb9bc7a7e05d1dfdfc47ff2c594ec5ca9756d27e7226635bb" +checksum = "4dca112d43c7785193362b33aa7941947bb84d65db9187abe72f1f7a969474c0" dependencies = [ "async-trait", "futures", @@ -11641,13 +12529,14 @@ dependencies = [ [[package]] name = "sc-executor" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2ac6c356538d67987bbb867e11a12a84ba87250c70fd50005b6d74f570a4f7" +checksum = "39f5767bf6a6bad29365d6d08fcf940ee453d31457ed034cf14f0392877daafd" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "sc-executor-common", + "sc-executor-polkavm", "sc-executor-wasmtime", "schnellru", "sp-api", @@ -11664,10 +12553,11 @@ dependencies = [ [[package]] name = "sc-executor-common" -version = "0.30.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07498138dee3ddf2c71299ca372d8449880bb3a8a8a299a483094e9c26b0823e" +checksum = "0c3b703a33dcb7cddf19176fdf12294b9a6408125836b0f4afee3e6969e7f190" dependencies = [ + "polkavm", "sc-allocator", "sp-maybe-compressed-blob", "sp-wasm-interface", @@ -11675,11 +12565,23 @@ dependencies = [ "wasm-instrument", ] +[[package]] +name = "sc-executor-polkavm" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fe58d9cacfab73e5595fa84b80f7bd03efebe54a0574daaeb221a1d1f7ab80" +dependencies = [ + "log", + "polkavm", + "sc-executor-common", + "sp-wasm-interface", +] + [[package]] name = "sc-executor-wasmtime" -version = "0.30.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a387779ab54ec1ffce0bf3a6631faada079459d42796c1895683767918a642" +checksum = "8cd498f2f77ec1f861c30804f5bfd796d4afcc8ce44ea1f11bfbe2847551d161" dependencies = [ "anyhow", "cfg-if", @@ -11696,9 +12598,9 @@ dependencies = [ [[package]] name = "sc-informant" -version = "0.34.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb603a0a703f1bc10a4e6462bec1036d8fb8b3e3eff5513a9c07f98ccb8d662d" +checksum = "74c3751acd690bc469b859d0ad899b076642db9b107e31c28cbd99749b6ecb91" dependencies = [ "ansi_term", "futures", @@ -11714,11 +12616,11 @@ dependencies = [ [[package]] name = "sc-keystore" -version = "26.0.0" +version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc4f6a558dd23e3bae2e9f195da822465258b9aaf211c34360d7f6efb944e54" +checksum = "267c8cfaceaeecb25484bad8668c17036016e46053a23509d44486474dbf44d3" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "parking_lot 0.12.3", "serde_json", "sp-application-crypto", @@ -11729,24 +12631,24 @@ dependencies = [ [[package]] name = "sc-mixnet" -version = "0.5.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45fb213c15679fe5b87c383815d7fb758c70d3e7c573948bd7fe26ff344d2272" +checksum = "a5a72a92dc72572a0facd73b410855d7f6edf38b32aef46c4798c74f25e595d5" dependencies = [ - "array-bytes 4.2.0", + "array-bytes", "arrayvec 0.7.4", "blake2 0.10.6", "bytes", "futures", "futures-timer", - "libp2p-identity", "log", "mixnet", - "multiaddr", + "multiaddr 0.18.1", "parity-scale-codec", "parking_lot 0.12.3", "sc-client-api", "sc-network", + "sc-network-types", "sc-transaction-pool-api", "sp-api", "sp-consensus", @@ -11759,15 +12661,16 @@ dependencies = [ [[package]] name = "sc-network" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f231c7d5e749ec428b4cfa669d759ae76cd3da4f50d7352a2d711acdc7532891" +checksum = "04be75f35cea819bae84be99cde138872b17494acf0e54f5f0ae8b0ed3fbe51a" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "async-channel 1.9.0", "async-trait", "asynchronous-codec", "bytes", + "cid 0.9.0", "either", "fnv", "futures", @@ -11775,16 +12678,22 @@ dependencies = [ "ip_network", "libp2p", "linked_hash_set", + "litep2p", "log", - "mockall", + "mockall 0.11.4", + "once_cell", "parity-scale-codec", "parking_lot 0.12.3", "partial_sort", "pin-project", + "prost 0.12.6", + "prost-build 0.12.6", "rand", "sc-client-api", "sc-network-common", + "sc-network-types", "sc-utils", + "schnellru", "serde", "serde_json", "smallvec", @@ -11796,45 +12705,26 @@ dependencies = [ "thiserror", "tokio", "tokio-stream", - "unsigned-varint", + "unsigned-varint 0.7.2", + "void", "wasm-timer", "zeroize", ] -[[package]] -name = "sc-network-bitswap" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2f89b0134738cb3d982b6e625ca93ae8dbe83ce2a06e4b6a396e4df09ed3499" -dependencies = [ - "async-channel 1.9.0", - "cid", - "futures", - "libp2p-identity", - "log", - "prost 0.12.6", - "prost-build", - "sc-client-api", - "sc-network", - "sp-blockchain", - "sp-runtime", - "thiserror", - "unsigned-varint", -] - [[package]] name = "sc-network-common" -version = "0.34.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3504bbff5ab016948dbab0f21a8be26324810b76eff3627ce744adb5bfc1b3ce" +checksum = "2ec0c3c5629a418fb26b56963d40c5ca3fd02dd94eb5753e9eb72cea5c2eeb2f" dependencies = [ "async-trait", "bitflags 1.3.2", "futures", "libp2p-identity", "parity-scale-codec", - "prost-build", + "prost-build 0.12.6", "sc-consensus", + "sc-network-types", "sp-consensus", "sp-consensus-grandpa", "sp-runtime", @@ -11842,18 +12732,18 @@ dependencies = [ [[package]] name = "sc-network-gossip" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad02cf809c34b53614fa61377e3289064edf6c78eb11df071d11fbf7546d7e9" +checksum = "0ae1836528495b6aa5140da39ed0278f5086c21ce530c37964db1b2e2c101ab1" dependencies = [ "ahash 0.8.11", "futures", "futures-timer", - "libp2p", "log", "sc-network", "sc-network-common", "sc-network-sync", + "sc-network-types", "schnellru", "sp-runtime", "substrate-prometheus-endpoint", @@ -11862,20 +12752,20 @@ dependencies = [ [[package]] name = "sc-network-light" -version = "0.34.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84ef0b212c775f58e0304ec09166089f6b09afddf559b7c2b5702933b3be4" +checksum = "f5e6deda277664336c26ea251cc1ebff7a165df0e3ad4ae23113380d9863ea40" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "async-channel 1.9.0", "futures", - "libp2p-identity", "log", "parity-scale-codec", "prost 0.12.6", - "prost-build", + "prost-build 0.12.6", "sc-client-api", "sc-network", + "sc-network-types", "sp-blockchain", "sp-core", "sp-runtime", @@ -11884,11 +12774,11 @@ dependencies = [ [[package]] name = "sc-network-sync" -version = "0.34.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa9377059deece4e7d419d9ec456f657268c0c603e1cf98df4a920f6da83461" +checksum = "ee9ab31b84534c487b9fb84e83db47890fcbd350f354b1e6484892d3d42d0020" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "async-channel 1.9.0", "async-trait", "fork-tree", @@ -11896,14 +12786,15 @@ dependencies = [ "futures-timer", "libp2p", "log", - "mockall", + "mockall 0.11.4", "parity-scale-codec", "prost 0.12.6", - "prost-build", + "prost-build 0.12.6", "sc-client-api", "sc-consensus", "sc-network", "sc-network-common", + "sc-network-types", "sc-utils", "schnellru", "smallvec", @@ -11921,38 +12812,55 @@ dependencies = [ [[package]] name = "sc-network-transactions" -version = "0.34.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c9cad4baf348725bd82eadcd1747fc112ec49c76b863755ce79c588fa73fe4" +checksum = "7c2eb55e29b0ca52ad3e209fe569b72dfe6b44cc1da7d722446d5a8333dff8e1" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "futures", - "libp2p", "log", "parity-scale-codec", "sc-network", "sc-network-common", "sc-network-sync", + "sc-network-types", "sc-utils", "sp-consensus", "sp-runtime", "substrate-prometheus-endpoint", ] +[[package]] +name = "sc-network-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c372dbda66644a1df0daa8c0d99c36b6f74db7dca213d2416cd84f507125224" +dependencies = [ + "bs58 0.5.1", + "ed25519-dalek", + "libp2p-identity", + "litep2p", + "log", + "multiaddr 0.18.1", + "multihash 0.19.1", + "rand", + "thiserror", + "zeroize", +] + [[package]] name = "sc-offchain" -version = "30.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aee89f2abd406356bfd688bd7a51155dc963259e4b752bb85d1f8a061a194fd" +checksum = "038d77ad5f923ec4183d6b31c7432fdb56d12ee69cad2cff17d4a39caf933bcb" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "bytes", "fnv", "futures", "futures-timer", "hyper 0.14.29", "hyper-rustls", - "libp2p", "log", "num_cpus", "once_cell", @@ -11962,6 +12870,7 @@ dependencies = [ "sc-client-api", "sc-network", "sc-network-common", + "sc-network-types", "sc-transaction-pool-api", "sc-utils", "sp-api", @@ -11976,9 +12885,9 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8dadb2ae5a316e4d08cad6aacd5de1dec792f3bd94e3960795ff7ffd07211c" +checksum = "f680a0bed67dab19898624246376ba85d5f70a89859ba030830aacd079c28d3c" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -11986,9 +12895,9 @@ dependencies = [ [[package]] name = "sc-rpc" -version = "30.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5acf6d89f062d1334a0c5b67e9dea97666cd47a49acb2696eab55ff1a1bf74" +checksum = "ca9cb792ddb5d0c3df89018e80290de4c769315fa59271bda0a0d29b2d182fdc" dependencies = [ "futures", "jsonrpsee", @@ -12019,9 +12928,9 @@ dependencies = [ [[package]] name = "sc-rpc-api" -version = "0.34.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9db6aaabfa7e0c27ec15d0f0a11b994cd4bcf86e362f0d9732b4a414d793f0f" +checksum = "57b8adf62a207985cf7534abf0d940b335fda0a68eb902da05b7270ee30a6293" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -12040,13 +12949,20 @@ dependencies = [ [[package]] name = "sc-rpc-server" -version = "12.0.0" +version = "16.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691440bbaddd3bc2675309c965cc75f8bf694f51e0a28039bfc9658299fbc394" +checksum = "3c14c236a01e03f55f16b92d89fd902cf2e4e9887357a3c36827a1e39b799c6b" dependencies = [ - "http 0.2.12", + "forwarded-header-value", + "futures", + "governor", + "http 1.1.0", + "http-body-util", + "hyper 1.4.1", + "ip_network", "jsonrpsee", "log", + "serde", "serde_json", "substrate-prometheus-endpoint", "tokio", @@ -12056,11 +12972,11 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f10275c62296a785f6e2ac716521e3b6e0fae470416fdf86491cbbfcc2e23d" +checksum = "4242d30df623f68d5b937ae264cce85e734c35922e0bf196d7a59b8e7f7843c2" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "futures", "futures-util", "hex", @@ -12068,11 +12984,13 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot 0.12.3", + "rand", "sc-chain-spec", "sc-client-api", "sc-rpc", "sc-transaction-pool-api", "sc-utils", + "schnellru", "serde", "sp-api", "sp-blockchain", @@ -12087,9 +13005,9 @@ dependencies = [ [[package]] name = "sc-service" -version = "0.36.0" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ea779b8c5bdb0d0199c8beebcf1fdc5641e468c480e1c4684be660c8c90af" +checksum = "718b7e3a3963b09c2ab18ce13dbc43c0afa8b53169b67372fbcc4c4147b77e05" dependencies = [ "async-trait", "directories", @@ -12110,11 +13028,11 @@ dependencies = [ "sc-informant", "sc-keystore", "sc-network", - "sc-network-bitswap", "sc-network-common", "sc-network-light", "sc-network-sync", "sc-network-transactions", + "sc-network-types", "sc-rpc", "sc-rpc-server", "sc-rpc-spec-v2", @@ -12124,6 +13042,7 @@ dependencies = [ "sc-transaction-pool", "sc-transaction-pool-api", "sc-utils", + "schnellru", "serde", "serde_json", "sp-api", @@ -12151,9 +13070,9 @@ dependencies = [ [[package]] name = "sc-state-db" -version = "0.31.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa842052c41ad379eaecdfddc0d5c953d57e311ae688233f68f461b91d38da0a" +checksum = "f689d0b97c1bbdb2ca31b5f202bda195947f85c7fef990651cad202b99de896b" dependencies = [ "log", "parity-scale-codec", @@ -12163,9 +13082,9 @@ dependencies = [ [[package]] name = "sc-storage-monitor" -version = "0.17.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26cb401aad6732700c8d866cbbef1175b9aeb8230908aff27059ef14bd058ef3" +checksum = "1d117c3945c524b9c0e30966359895f5ad551c2cd4ccbb677b53917fbad5039a" dependencies = [ "clap", "fs4", @@ -12177,9 +13096,9 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" -version = "0.35.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bc382c7d997f4531eee5e5d57f970eaf2761d722298d7747385a4ad69fa6b12" +checksum = "58fca6421f003249095557d97b674a27bf4bbf1f301406eb04c42878a43fc715" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -12197,9 +13116,9 @@ dependencies = [ [[package]] name = "sc-sysinfo" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25d2ab8f15021916a07cfbe7a08be484c5dc7d57f07bc0e2aa03260b55a5632f" +checksum = "7c00ab3d8f51c1905cc3c53cf441b9d94403c67f27968002ff7765248b0f3e6b" dependencies = [ "derive_more", "futures", @@ -12219,9 +13138,9 @@ dependencies = [ [[package]] name = "sc-telemetry" -version = "16.0.0" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0673a93aa0684b606abfc5fce6c882ada7bb5fad8a2ddc66a09a42bcc9664d91" +checksum = "b1fc8e8ad7f84f2ca864ee361b6207fe21e18c8182c60f209732b2a7c0dcbd31" dependencies = [ "chrono", "futures", @@ -12230,6 +13149,7 @@ dependencies = [ "parking_lot 0.12.3", "pin-project", "rand", + "sc-network", "sc-utils", "serde", "serde_json", @@ -12239,9 +13159,9 @@ dependencies = [ [[package]] name = "sc-tracing" -version = "29.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77b4fdb4f359f19c395ba862430f3ca0efb50b0310b09753caaa06997edd606" +checksum = "61151f2d6b7ce3d7174484414dbc4e2f64b05a144c8f0a59ea02284e6c748a19" dependencies = [ "ansi_term", "chrono", @@ -12264,8 +13184,8 @@ dependencies = [ "sp-tracing", "thiserror", "tracing", - "tracing-log 0.1.4", - "tracing-subscriber 0.2.25", + "tracing-log 0.2.0", + "tracing-subscriber 0.3.18", ] [[package]] @@ -12282,9 +13202,9 @@ dependencies = [ [[package]] name = "sc-transaction-pool" -version = "29.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "326dc8ea417c53b6787bd1bb27431d44768504451f5ce4efdde0c15877c7c121" +checksum = "800e35d0d2f2b8e17170ec961d58756fe7891026b19d889be388b9585cb12f90" dependencies = [ "async-trait", "futures", @@ -12310,9 +13230,9 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" -version = "29.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ae888ce3491acb1b489c3dba930d0c46c7ef9f9893ba0ab8af9125362f3d14" +checksum = "b3de6f60df6706970061e225e87d77aab9a764b258fe151b896a700419bc6b9d" dependencies = [ "async-trait", "futures", @@ -12327,9 +13247,9 @@ dependencies = [ [[package]] name = "sc-utils" -version = "15.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b1a238f5baa56405db4e440e2d2f697583736fa2e2f1aac345c438a42975f1" +checksum = "acf1bad736c230f16beb1cf48af9e69564df23b13aca9e5751a61266340b4bb5" dependencies = [ "async-channel 1.9.0", "futures", @@ -12341,6 +13261,29 @@ dependencies = [ "sp-arithmetic", ] +[[package]] +name = "scale-bits" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57b1e7f6b65ed1f04e79a85a57d755ad56d76fdf1e9bddcc9ae14f71fcdcf54" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98f3262c250d90e700bb802eb704e1f841e03331c2eb815e46516c4edbf5b27" +dependencies = [ + "derive_more", + "parity-scale-codec", + "scale-bits", + "scale-type-resolver", + "smallvec", +] + [[package]] name = "scale-info" version = "2.11.3" @@ -12367,6 +13310,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "scale-type-resolver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" + [[package]] name = "schannel" version = "0.1.23" @@ -12397,7 +13346,7 @@ dependencies = [ "arrayvec 0.7.4", "curve25519-dalek-ng", "merlin", - "rand_core 0.6.4", + "rand_core", "sha2 0.9.9", "subtle-ng", "zeroize", @@ -12412,13 +13361,13 @@ dependencies = [ "aead", "arrayref", "arrayvec 0.7.4", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "getrandom_or_panic", "merlin", - "rand_core 0.6.4", + "rand_core", "serde_bytes", "sha2 0.10.8", - "subtle 2.4.1", + "subtle 2.5.0", "zeroize", ] @@ -12444,6 +13393,21 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "sctp-proto" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6220f78bb44c15f326b0596113305f6101097a18755d53727a575c97e09fb24" +dependencies = [ + "bytes", + "crc", + "fxhash", + "log", + "rand", + "slab", + "thiserror", +] + [[package]] name = "sec1" version = "0.7.3" @@ -12454,7 +13418,8 @@ dependencies = [ "der", "generic-array 0.14.7", "pkcs8", - "subtle 2.4.1", + "serdect", + "subtle 2.5.0", "zeroize", ] @@ -12504,6 +13469,7 @@ dependencies = [ "core-foundation", "core-foundation-sys", "libc", + "num-bigint", "security-framework-sys", ] @@ -12541,6 +13507,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" version = "1.0.203" @@ -12639,6 +13611,16 @@ dependencies = [ "time", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -12652,6 +13634,18 @@ dependencies = [ "opaque-debug 0.3.1", ] +[[package]] +name = "sha-1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", + "sha1-asm", +] + [[package]] name = "sha1" version = "0.10.6" @@ -12663,6 +13657,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha1-asm" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "286acebaf8b67c1130aedffad26f594eff0c1292389158135327d2e23aed582b" +dependencies = [ + "cc", +] + [[package]] name = "sha2" version = "0.9.9" @@ -12759,7 +13762,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -12775,6 +13778,15 @@ dependencies = [ "wide", ] +[[package]] +name = "simple-dns" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cae9a3fcdadafb6d97f4c0e007e4247b114ee0f119f650c3cbf3a8b3a1479694" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "simple-mermaid" version = "0.1.1" @@ -12804,9 +13816,9 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "slot-range-helper" -version = "8.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40fa5e14772407fd2ccffdd5971bf055bbf46a40727c0ea96d2bb6563d17e1c" +checksum = "a4d67aa9b1ccfd746c8529754c4ce06445b1d48e189567402ef856340a3a6b14" dependencies = [ "enumn", "parity-scale-codec", @@ -12863,7 +13875,7 @@ dependencies = [ "chacha20", "crossbeam-queue", "derive_more", - "ed25519-zebra 4.0.3", + "ed25519-zebra", "either", "event-listener 2.5.3", "fnv", @@ -12880,11 +13892,11 @@ dependencies = [ "num-bigint", "num-rational", "num-traits", - "pbkdf2 0.12.2", + "pbkdf2", "pin-project", "poly1305", "rand", - "rand_chacha 0.3.1", + "rand_chacha", "ruzstd", "schnorrkel 0.10.2", "serde", @@ -12894,10 +13906,10 @@ dependencies = [ "siphasher", "slab", "smallvec", - "soketto", + "soketto 0.7.1", "twox-hash", - "wasmi", - "x25519-dalek 2.0.1", + "wasmi 0.31.2", + "x25519-dalek", "zeroize", ] @@ -12927,7 +13939,7 @@ dependencies = [ "parking_lot 0.12.3", "pin-project", "rand", - "rand_chacha 0.3.1", + "rand_chacha", "serde", "serde_json", "siphasher", @@ -12952,12 +13964,12 @@ dependencies = [ "aes-gcm", "blake2 0.10.6", "chacha20poly1305", - "curve25519-dalek 4.1.3", - "rand_core 0.6.4", + "curve25519-dalek", + "rand_core", "ring 0.17.8", "rustc_version", "sha2 0.10.8", - "subtle 2.4.1", + "subtle 2.5.0", ] [[package]] @@ -12972,13 +13984,12 @@ dependencies = [ [[package]] name = "snowbridge-beacon-primitives" -version = "0.1.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5404af73550b39022e08e5500b30fba627e109a56407b7e80b08da2305b11bfe" +checksum = "a0ad61e3ab1c48d4c8060c7ef8571c5b6007df26687e8dbfdb6c857d840cfd2c" dependencies = [ "byte-slice-cast", "frame-support", - "frame-system", "hex", "parity-scale-codec", "rlp", @@ -12992,14 +14003,13 @@ dependencies = [ "sp-std", "ssz_rs", "ssz_rs_derive", - "static_assertions", ] [[package]] name = "snowbridge-core" -version = "0.1.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aed4ebefed4c40b9c00e9adf5f02ab2760a7a2dad8bf05110c0013a7a59f4097" +checksum = "668cd71582305168ed51cb0357a4b4ea814c68c7db3898a9ba4d492f712c54e1" dependencies = [ "ethabi-decode", "frame-support", @@ -13021,9 +14031,9 @@ dependencies = [ [[package]] name = "snowbridge-ethereum" -version = "0.2.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "315ad74f081734cb51f48bb10cd18a3f83cfec3c09a551bc936027708635e808" +checksum = "1ef1f6f60f6c8cc3cdb2a829d7452de946d8707f63f70c6f714d1c52cbc0fc17" dependencies = [ "ethabi-decode", "ethbloom", @@ -13032,11 +14042,9 @@ dependencies = [ "parity-bytes", "parity-scale-codec", "rlp", - "rustc-hex", "scale-info", "serde", "serde-big-array", - "sp-core", "sp-io", "sp-runtime", "sp-std", @@ -13059,25 +14067,21 @@ dependencies = [ [[package]] name = "snowbridge-router-primitives" -version = "0.1.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee5cc8e156f033971c5435676be92ab6f70a926b3497ca9c28c0dde9697b8da9" +checksum = "8e8e6707ced1308d763117bfe68f85e3f22fcdca7987b32e438c0485570f6ac7" dependencies = [ - "ethabi-decode", "frame-support", - "frame-system", "hex-literal", "log", "parity-scale-codec", "scale-info", - "serde", "snowbridge-core", "sp-core", "sp-io", "sp-runtime", "sp-std", "staging-xcm", - "staging-xcm-builder", "staging-xcm-executor", ] @@ -13109,20 +14113,34 @@ checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", "bytes", - "flate2", "futures", - "http 0.2.12", "httparse", "log", "rand", - "sha-1", + "sha-1 0.9.8", +] + +[[package]] +name = "soketto" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37468c595637c10857701c990f93a40ce0e357cedb0953d1c26c8d8027f9bb53" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures", + "http 1.1.0", + "httparse", + "log", + "rand", + "sha1", ] [[package]] name = "sp-api" -version = "27.0.1" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e4f8702afd77f14a32733e2b589c02694bf79d0b3a641963c508016208724d0" +checksum = "b7e43fbf034e9dbaa8ffc6a238a22808777eb38c580f66fc6736d8511631789e" dependencies = [ "hash-db", "log", @@ -13133,6 +14151,7 @@ dependencies = [ "sp-externalities", "sp-metadata-ir", "sp-runtime", + "sp-runtime-interface", "sp-state-machine", "sp-std", "sp-trie", @@ -13142,13 +14161,13 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" -version = "15.0.1" +version = "20.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0301e2f77afb450fbf2b093f8b324c7ad88cc82e5e69bd5dc8658a1f068b2a96" +checksum = "c9aadf9e97e694f0e343978aa632938c5de309cbcc8afed4136cb71596737278" dependencies = [ "Inflector", "blake2 0.10.6", - "expander 2.2.1", + "expander", "proc-macro-crate 3.1.0", "proc-macro2", "quote", @@ -13157,9 +14176,9 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "31.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "547cad7a6eabb52c639ec117b3db9c6b43cf1b29a9393b18feb19e101a91833f" +checksum = "0d96d1fc0f1c741bbcbd0dd5470eff7b66f011708cc1942b088ebf0d4efb3d93" dependencies = [ "parity-scale-codec", "scale-info", @@ -13171,10 +14190,11 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "24.0.0" +version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa823ca5adc490d47dccb41d69ad482bc57a317bd341de275868378f48f131c" +checksum = "46d0d0a4c591c421d3231ddd5e27d828618c24456d51445d21a1f79fcee97c23" dependencies = [ + "docify", "integer-sqrt", "num-traits", "parity-scale-codec", @@ -13186,35 +14206,33 @@ dependencies = [ [[package]] name = "sp-authority-discovery" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92b177c72b5d2973c36d60f6ef942d791d9fd91eae8b08c71882e4118d4fbfc" +checksum = "6a4a1e45abc3277f18484ee0b0f9808e4206eb696ad38500c892c72f33480d69" dependencies = [ "parity-scale-codec", "scale-info", "sp-api", "sp-application-crypto", "sp-runtime", - "sp-std", ] [[package]] name = "sp-block-builder" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b36ce171caa7eb2bbe682c089f755fdefa71d3702e4fb1ba30d10146aef99d5" +checksum = "2cf199dc4f9f77abd3fd91c409759118159ce6ffcd8bc90b229b684ccc8c981f" dependencies = [ "sp-api", "sp-inherents", "sp-runtime", - "sp-std", ] [[package]] name = "sp-blockchain" -version = "29.0.0" +version = "35.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31303e766d2e53812641bbc1f1cec03a85793fc9e627e55f0a6854b28708758" +checksum = "f27eb18b6ddf7d663f4886f7edba3eb73bd102d68cf10802c1f862e3b3db32ab" dependencies = [ "futures", "log", @@ -13231,9 +14249,9 @@ dependencies = [ [[package]] name = "sp-consensus" -version = "0.33.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6e512b862c4ff7a26cdcd364898cc42e181ff5cb35fbb226ff27d88c81569a" +checksum = "ab094e8a7e9e5c7f05f8d90592aa1d1cf9b3f547d0dd401daff7ed98af942e12" dependencies = [ "async-trait", "futures", @@ -13247,9 +14265,9 @@ dependencies = [ [[package]] name = "sp-consensus-aura" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf13c293685319751f72fa5216c7fb5f25f3e8e8fe29b4503296ed5f5466b3d" +checksum = "05ebb90bf00f331b898eb729a1f707251846c1d5582d7467f083884799a69b89" dependencies = [ "async-trait", "parity-scale-codec", @@ -13259,15 +14277,14 @@ dependencies = [ "sp-consensus-slots", "sp-inherents", "sp-runtime", - "sp-std", "sp-timestamp", ] [[package]] name = "sp-consensus-babe" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9be2f86a2f0ce2a78b455feb547aa27604fd76a7f7a691995cbad44e0b1b9dd" +checksum = "3aa2de4c7100a3279658d8dd4affd8f92487528deae5cb4b40322717b9175ed5" dependencies = [ "async-trait", "parity-scale-codec", @@ -13279,15 +14296,14 @@ dependencies = [ "sp-core", "sp-inherents", "sp-runtime", - "sp-std", "sp-timestamp", ] [[package]] name = "sp-consensus-beefy" -version = "14.0.0" +version = "20.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ff890a84ef57628b010df0e1d75b3a78fb7f575e4ceeba7215c276902c403e" +checksum = "b277bc109da8e1c3768d3a046e1cd1ab687aabac821c976c5f510deb6f0bc8d3" dependencies = [ "lazy_static", "parity-scale-codec", @@ -13298,17 +14314,17 @@ dependencies = [ "sp-core", "sp-crypto-hashing", "sp-io", + "sp-keystore", "sp-mmr-primitives", "sp-runtime", - "sp-std", - "strum 0.24.1", + "strum 0.26.2", ] [[package]] name = "sp-consensus-grandpa" -version = "14.0.0" +version = "20.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b606164600db36e596db7abf32b4533dc9a74526d9444c4c45035427b2199b" +checksum = "21dd06bf366c60f69411668b26d6ab3c55120aa6d423e6af0373ec23d8957300" dependencies = [ "finality-grandpa", "log", @@ -13320,44 +14336,43 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", - "sp-std", ] [[package]] name = "sp-consensus-slots" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73a5bd1fcd84bbdc7255528c7cdb92f9357fd555f06ee553af7e340cbdab517c" +checksum = "c8ca60d713f8ddb03bbebcc755d5e6463fdc0b6259fabfc4221b20a5f1e428fd" dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std", "sp-timestamp", ] [[package]] name = "sp-core" -version = "29.0.0" +version = "34.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c33c7a1568175250628567d50c4e1c54a6ac5bc1190413b9be29a9e810cbe73" +checksum = "c961a5e33fb2962fa775c044ceba43df9c6f917e2c35d63bfe23738468fa76a7" dependencies = [ - "array-bytes 6.2.3", - "bip39", + "array-bytes", "bitflags 1.3.2", "blake2 0.10.6", "bounded-collections", "bs58 0.5.1", "dyn-clonable", - "ed25519-zebra 3.1.0", + "ed25519-zebra", "futures", "hash-db", "hash256-std-hasher", "impl-serde", - "itertools 0.10.5", + "itertools 0.11.0", + "k256", "libsecp256k1", "log", "merlin", + "parity-bip39", "parity-scale-codec", "parking_lot 0.12.3", "paste", @@ -13430,54 +14445,54 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7096ed024cec397804864898b093b51e14c7299f1d00c67dd5800330e02bb82" +checksum = "a904407d61cb94228c71b55a9d3708e9d6558991f9e83bd42bd91df37a159d30" dependencies = [ "environmental", "parity-scale-codec", - "sp-std", "sp-storage", ] [[package]] name = "sp-genesis-builder" -version = "0.8.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd865540ec19479c7349b584ccd78cc34c3f3a628a2a69dbb6365ceec36295ee" +checksum = "fcd065854d96fd81521c103d0aaa287d4f08b9b15c9fae2a3bfb208b0812bf44" dependencies = [ + "parity-scale-codec", + "scale-info", "serde_json", "sp-api", "sp-runtime", - "sp-std", ] [[package]] name = "sp-inherents" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "607c9e35e96966645ff180a9e9f976433b96e905d0a91d8d5315e605a21f4bc0" +checksum = "53407ba38ec22ca4a16381722c4bd0b559a0428bc1713079b0d5163ada63186a" dependencies = [ "async-trait", "impl-trait-for-tuples", "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std", "thiserror", ] [[package]] name = "sp-io" -version = "31.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec43aa073eab35fcb920d7592474d5427ea3be2bf938706a3ad955d7ba54fd8d" +checksum = "5036cad2e48d41f5caf6785226c8be1a7db15bec14a9fd7aa6cca84f34cf689f" dependencies = [ "bytes", "ed25519-dalek", "libsecp256k1", "log", "parity-scale-codec", + "polkavm-derive", "rustversion", "secp256k1", "sp-core", @@ -13495,26 +14510,25 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "32.0.0" +version = "38.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cf0a2f881958466fc92bc9b39bbc2c0d815ded4a21f8f953372b0ac2e11b02" +checksum = "b03536e1ff3ec2bd8181eeaa26c0d682ebdcbd01548a055cf591077188b8c3f0" dependencies = [ "sp-core", "sp-runtime", - "strum 0.24.1", + "strum 0.26.2", ] [[package]] name = "sp-keystore" -version = "0.35.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444f2d53968b1ce5e908882710ff1f3873fcf3e95f59d57432daf685bbacb959" +checksum = "0248b4d784cb4a01472276928977121fa39d977a5bb24793b6b15e64b046df42" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "sp-core", "sp-externalities", - "thiserror", ] [[package]] @@ -13529,53 +14543,50 @@ dependencies = [ [[package]] name = "sp-metadata-ir" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0b5e87e56c1bb26d9524d48dd127121d630f895bd5914a34f0b017489f7c1d" +checksum = "a616fa51350b35326682a472ee8e6ba742fdacb18babac38ecd46b3e05ead869" dependencies = [ "frame-metadata", "parity-scale-codec", "scale-info", - "sp-std", ] [[package]] name = "sp-mixnet" -version = "0.5.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bebd44b915c65aeb7e7eeaea466aba3b27cdd915c83ea83d4643c54f21ffbbf" +checksum = "2f65a570519da820ce3dc35053497a65f9fbd3f5a7dc81fa03078ca263e9311e" dependencies = [ "parity-scale-codec", "scale-info", "sp-api", "sp-application-crypto", - "sp-std", ] [[package]] name = "sp-mmr-primitives" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891b7263b7c44a569173ee1078f68fb1a01991a44914607c0100aa5ae41f6562" +checksum = "47412a2d2e988430d5f59d7fec1473f229e1ef5ce24c1ea4f601b4b3679cac52" dependencies = [ - "ckb-merkle-mountain-range", "log", "parity-scale-codec", + "polkadot-ckb-merkle-mountain-range", "scale-info", "serde", "sp-api", "sp-core", "sp-debug-derive", "sp-runtime", - "sp-std", "thiserror", ] [[package]] name = "sp-npos-elections" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195d7e1154c91cce5c3abc8c778689c3e5799da6411328dd32ac7a974c68e526" +checksum = "0b0c51a7b60cd663f2661e6949069eb316b092f22c239691d5272a4d0cfca0fb" dependencies = [ "parity-scale-codec", "scale-info", @@ -13583,14 +14594,13 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-runtime", - "sp-std", ] [[package]] name = "sp-offchain" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d83b955dce0b6d143bec3f60571311168f362b1c16cf044da7037a407b66c19" +checksum = "cbe721c367760bddf10fcfa24fb48edd64c442f71db971f043c8ac73f51aa6e9" dependencies = [ "sp-api", "sp-core", @@ -13610,9 +14620,9 @@ dependencies = [ [[package]] name = "sp-rpc" -version = "27.0.0" +version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9af4b73fe7ddd88b1641cca90048c4e525e721763199e6fd29c4f590884f4d16" +checksum = "45458f0955870a92b3969098d4f1f4e9b55b4282d9f1dc112a51bb5bb6584900" dependencies = [ "rustc-hash", "serde", @@ -13621,15 +14631,16 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "32.0.0" +version = "38.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a95e71603a6281e91b0f1fd3d68057644be16d75a4602013187b8137db8abee" +checksum = "89ef409c414546b655ec1e94aaea178e4a97e21284a91b24c762aebf836d3b49" dependencies = [ "docify", "either", "hash256-std-hasher", "impl-trait-for-tuples", "log", + "num-traits", "parity-scale-codec", "paste", "rand", @@ -13646,13 +14657,14 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "25.0.0" +version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2321ab29d4bcc31f1ba1b4f076a81fb2a666465231e5c981c72320d74dbe63" +checksum = "985eb981f40c689c6a0012c937b68ed58dabb4341d06f2dfe4dfd5ed72fa4017" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", + "polkavm-derive", "primitive-types", "sp-externalities", "sp-runtime-interface-proc-macro", @@ -13665,12 +14677,12 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "17.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfaf6e85b2ec12a4b99cd6d8d57d083e30c94b7f1b0d8f93547121495aae6f0c" +checksum = "0195f32c628fee3ce1dfbbf2e7e52a30ea85f3589da9fe62a8b816d70fc06294" dependencies = [ "Inflector", - "expander 2.2.1", + "expander", "proc-macro-crate 3.1.0", "proc-macro2", "quote", @@ -13679,9 +14691,9 @@ dependencies = [ [[package]] name = "sp-session" -version = "28.0.0" +version = "34.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b86531090cc04d2ab3535df07146258e2fb3ab6257b0a77ef14aa08282c3d4a" +checksum = "4daf2e40ffc7e7e8de08efb860eb9534faf614a49c53dc282f430faedb4aed13" dependencies = [ "parity-scale-codec", "scale-info", @@ -13690,14 +14702,13 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-staking", - "sp-std", ] [[package]] name = "sp-staking" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e14d003ecf0b610bf1305a92bdab875289b39d514c073f30e75e78c2763a788" +checksum = "0a0b7abfe66c07a3b6eb99e1286dfa9b6f3b057b0e986e7da2ccbf707f6c781a" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -13705,14 +14716,13 @@ dependencies = [ "serde", "sp-core", "sp-runtime", - "sp-std", ] [[package]] name = "sp-state-machine" -version = "0.36.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67297e702aa32027d7766803f362a420d6d3ec9e2f84961f3c64e2e52b5aaf9" +checksum = "211e528aa6e902261a343f7b40840aa3d66fe4ad3aadbd04a035f10baf96dbc5" dependencies = [ "hash-db", "log", @@ -13723,7 +14733,6 @@ dependencies = [ "sp-core", "sp-externalities", "sp-panic-handler", - "sp-std", "sp-trie", "thiserror", "tracing", @@ -13732,12 +14741,12 @@ dependencies = [ [[package]] name = "sp-statement-store" -version = "11.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "309a9ae4e8134bbed8ffc510cf4d461a4a651f9250b556de782cedd876abe1ff" +checksum = "b03aa86b1b46549889d32348bc85a8135c725665115567507231a6d85712aaac" dependencies = [ "aes-gcm", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "ed25519-dalek", "hkdf", "parity-scale-codec", @@ -13751,9 +14760,8 @@ dependencies = [ "sp-externalities", "sp-runtime", "sp-runtime-interface", - "sp-std", "thiserror", - "x25519-dalek 2.0.1", + "x25519-dalek", ] [[package]] @@ -13764,40 +14772,37 @@ checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" [[package]] name = "sp-storage" -version = "20.0.0" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dba5791cb3978e95daf99dad919ecb3ec35565604e88cd38d805d9d4981e8bd" +checksum = "99c82989b3a4979a7e1ad848aad9f5d0b4388f1f454cc131766526601ab9e8f8" dependencies = [ "impl-serde", "parity-scale-codec", "ref-cast", "serde", "sp-debug-derive", - "sp-std", ] [[package]] name = "sp-timestamp" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "249cd06624f2edb53b25af528ab216a508dc9d0870e158b43caac3a97e86699f" +checksum = "78becf144a76f6fd108dfe94a90e20a185b38c0b310dc5482328196143c8266b" dependencies = [ "async-trait", "parity-scale-codec", "sp-inherents", "sp-runtime", - "sp-std", "thiserror", ] [[package]] name = "sp-tracing" -version = "16.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0351810b9d074df71c4514c5228ed05c250607cba131c1c9d1526760ab69c05c" +checksum = "90b3decf116db9f1dfaf1f1597096b043d0e12c952d3bcdc018c6d6b77deec7e" dependencies = [ "parity-scale-codec", - "sp-std", "tracing", "tracing-core", "tracing-subscriber 0.2.25", @@ -13805,9 +14810,9 @@ dependencies = [ [[package]] name = "sp-transaction-pool" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9742861c5330bdcb42856a6eed3d3745b58ee1c92ca4c9260032ff4e6c387165" +checksum = "a3c9d1604aadc15b70e95f4388d0b1aa380215520b7ddfd372531a6d8262269c" dependencies = [ "sp-api", "sp-runtime", @@ -13815,9 +14820,9 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" -version = "27.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece8e22a5419c7a336a2544654e1389fec8cac19b93081a30912842b44e8167f" +checksum = "5b5a891cb913015bb99401e372255193cc3848c6fe5c2f6fe2383ef9588cb190" dependencies = [ "async-trait", "parity-scale-codec", @@ -13825,15 +14830,14 @@ dependencies = [ "sp-core", "sp-inherents", "sp-runtime", - "sp-std", "sp-trie", ] [[package]] name = "sp-trie" -version = "30.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed48dfd05081e8b36741b10ce4eb686c135a2952227a11fe71caec89890ddbb" +checksum = "841d717c0f465f5371569e6fdc25b6f32d47c15d6e4c92b3b779e1c9b18b951d" dependencies = [ "ahash 0.8.11", "hash-db", @@ -13847,7 +14851,6 @@ dependencies = [ "schnellru", "sp-core", "sp-externalities", - "sp-std", "thiserror", "tracing", "trie-db", @@ -13856,9 +14859,9 @@ dependencies = [ [[package]] name = "sp-version" -version = "30.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4a660c68995663d6778df324f4e2b4efc48d55a8e9c92c22a5fb7dae7899cd" +checksum = "bccf96fefae339dee7c4453f91be64eb28cce4c2fe82130445cf096b18b2c081" dependencies = [ "impl-serde", "parity-scale-codec", @@ -13874,9 +14877,9 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" -version = "13.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9bc3fed32d6dacbbbfb28dd1fe0224affbb737cb6cbfca1d9149351c2b69a7d" +checksum = "5aee8f6730641a65fcf0c8f9b1e448af4b3bb083d08058b47528188bccc7b7a7" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -13886,23 +14889,22 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "20.0.0" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef97172c42eb4c6c26506f325f48463e9bc29b2034a587f1b9e48c751229bee" +checksum = "3b04b919e150b4736d85089d49327eab65507deb1485eec929af69daa2278eb3" dependencies = [ "anyhow", "impl-trait-for-tuples", "log", "parity-scale-codec", - "sp-std", "wasmtime", ] [[package]] name = "sp-weights" -version = "28.0.0" +version = "31.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3be30aec904994451dcacf841a9168cfbbaf817de6b24b6a1c1418cbf1af2fe" +checksum = "93cdaf72a1dad537bbb130ba4d47307ebe5170405280ed1aa31fa712718a400e" dependencies = [ "bounded-collections", "parity-scale-codec", @@ -13911,7 +14913,6 @@ dependencies = [ "smallvec", "sp-arithmetic", "sp-debug-derive", - "sp-std", ] [[package]] @@ -13927,14 +14928,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] -name = "spinners" -version = "4.1.1" +name = "spinning_top" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ef947f358b9c238923f764c72a4a9d42f2d637c46e059dbd319d6e7cfb4f82" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" dependencies = [ - "lazy_static", - "maplit", - "strum 0.24.1", + "lock_api", ] [[package]] @@ -13993,9 +14992,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "staging-parachain-info" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da7dc139d104f676a18c13380a09c3f72d59450a7471116387cbf8cb5f845a0e" +checksum = "cd00d586b0dac4f42736bdd0ad52213a891b240e011ea82b38938263dd821c25" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -14008,11 +15007,11 @@ dependencies = [ [[package]] name = "staging-xcm" -version = "8.0.1" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fa328b87de3466bc38cc9a07244c42c647b7755b81115e1dfeb47cc13fc6e6" +checksum = "f2b7b5f531c6bf9629514ef8e5fda0e9e80dd84516957f710940d0e01d3fb36c" dependencies = [ - "array-bytes 6.2.3", + "array-bytes", "bounded-collections", "derivative", "environmental", @@ -14027,9 +15026,9 @@ dependencies = [ [[package]] name = "staging-xcm-builder" -version = "8.0.3" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b7447c38be3ca9fb21c7434de2243aa6ac74acde8944cda7bb6e2a4f765801" +checksum = "847fa2afe1bed2751eaabf7b91fa4043037947f17653d7cc59ea202cc44c6bb8" dependencies = [ "frame-support", "frame-system", @@ -14050,9 +15049,9 @@ dependencies = [ [[package]] name = "staging-xcm-executor" -version = "8.0.2" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b5c5f2a1d610c5e20e5fae2680c9a28380f305afafeed62f341bfbce57b79a" +checksum = "26b98d8219449eaf02e71a7edf1a14b14d4c713dd01d9df66fde1ce30dba4d6d" dependencies = [ "environmental", "frame-benchmarking", @@ -14105,16 +15104,34 @@ dependencies = [ ] [[package]] -name = "strobe-rs" -version = "0.8.1" +name = "str0m" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabb238a1cccccfa4c4fb703670c0d157e1256c1ba695abf1b93bd2bb14bab2d" +checksum = "6706347e49b13373f7ddfafad47df7583ed52083d6fc8a594eb2c80497ef959d" dependencies = [ - "bitflags 1.3.2", - "byteorder", - "keccak", - "subtle 2.4.1", - "zeroize", + "combine", + "crc", + "fastrand 2.1.0", + "hmac 0.12.1", + "once_cell", + "openssl", + "openssl-sys", + "sctp-proto", + "serde", + "sha-1 0.10.1", + "thiserror", + "tracing", +] + +[[package]] +name = "string-interner" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6a0d765f5807e98a091107bae0a56ea3799f66a5de47b2c84c94a39c09974e" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "serde", ] [[package]] @@ -14128,9 +15145,6 @@ name = "strum" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" -dependencies = [ - "strum_macros 0.24.3", -] [[package]] name = "strum" @@ -14169,14 +15183,14 @@ dependencies = [ [[package]] name = "substrate-bip39" -version = "0.4.6" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a7590dc041b9bc2825e52ce5af8416c73dbe9d0654402bfd4b4941938b94d8f" +checksum = "ca58ffd742f693dc13d69bdbb2e642ae239e0053f6aab3b104252892f856700a" dependencies = [ - "hmac 0.11.0", - "pbkdf2 0.8.0", + "hmac 0.12.1", + "pbkdf2", "schnorrkel 0.11.4", - "sha2 0.9.9", + "sha2 0.10.8", "zeroize", ] @@ -14188,10 +15202,11 @@ checksum = "b285e7d183a32732fdc119f3d81b7915790191fad602b7c709ef247073c77a2e" [[package]] name = "substrate-frame-rpc-system" -version = "29.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332f903d2f34703204f0003136c9abbc569d691028279996a1daf8f248a7369f" +checksum = "02b8837de37f5ea6316846a63dc48489b63ebde05df73ba7d7077b3135487560" dependencies = [ + "docify", "frame-system-rpc-runtime-api", "futures", "jsonrpsee", @@ -14212,32 +15227,18 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8fe06b03b8a291c09507c42f92a2c2c10dd3d62975d02c7f64a92d87bfe09b" dependencies = [ - "hyper 0.14.29", - "log", - "prometheus", - "thiserror", - "tokio", -] - -[[package]] -name = "substrate-rpc-client" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40e5235d8460ec81e9a382345aa80d75e2943f224a332559847344bb62fa13b3" -dependencies = [ - "async-trait", - "jsonrpsee", + "hyper 0.14.29", "log", - "sc-rpc-api", - "serde", - "sp-runtime", + "prometheus", + "thiserror", + "tokio", ] [[package]] name = "substrate-state-trie-migration-rpc" -version = "28.0.0" +version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5768a5d3c76eebfdf94c23a3fde6c832243a043d60561e5ac1a2b475b9ad09f3" +checksum = "df246ac77a641b23068e8c49cff4dfbaefc78405f80c9589a10909e02d525141" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -14253,17 +15254,27 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" -version = "18.0.1" +version = "23.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a39a20e17c24ede36b5bd5e7543a4cef8d8a0daf6e1a046dc31832b837a54a0" +checksum = "7dc993ad871b63fbba60362f3ea86583f5e7e1256e8fdcb3b5b249c9ead354bf" dependencies = [ + "array-bytes", "build-helper", "cargo_metadata 0.15.4", "console", "filetime", + "frame-metadata", + "merkleized-metadata", + "parity-scale-codec", "parity-wasm", + "polkavm-linker", + "sc-executor", + "sp-core", + "sp-io", "sp-maybe-compressed-blob", - "strum 0.24.1", + "sp-tracing", + "sp-version", + "strum 0.26.2", "tempfile", "toml 0.8.14", "walkdir", @@ -14278,9 +15289,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "subtle" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "subtle-ng" @@ -14357,15 +15368,19 @@ dependencies = [ [[package]] name = "system-parachains-constants" version = "1.0.0" -source = "git+https://github.com/paseo-network/runtimes/?tag=v1.2.5-system-chains#2fa66a19eef96bd2c079385057fab2564d09b751" +source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" dependencies = [ "frame-support", + "kusama-runtime-constants", "parachains-common", - "paseo-runtime-constants", "polkadot-core-primitives", "polkadot-primitives", + "polkadot-runtime-constants", "smallvec", + "sp-core", "sp-runtime", + "sp-std", + "staging-xcm", ] [[package]] @@ -14603,7 +15618,7 @@ dependencies = [ "mio", "num_cpus", "parking_lot 0.12.3", - "pin-project-lite 0.2.14", + "pin-project-lite", "signal-hook-registry", "socket2 0.5.7", "tokio-macros", @@ -14622,23 +15637,23 @@ dependencies = [ ] [[package]] -name = "tokio-retry" -version = "0.3.0" +name = "tokio-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "pin-project", - "rand", + "rustls 0.21.12", "tokio", ] [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.21.12", + "rustls 0.23.10", + "rustls-pki-types", "tokio", ] @@ -14649,11 +15664,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", - "pin-project-lite 0.2.14", + "pin-project-lite", "tokio", "tokio-util", ] +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.24.1", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.11" @@ -14664,7 +15694,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.14", + "pin-project-lite", "tokio", ] @@ -14698,17 +15728,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.21.1" @@ -14742,7 +15761,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project", - "pin-project-lite 0.2.14", + "pin-project-lite", "tokio", "tower-layer", "tower-service", @@ -14751,18 +15770,16 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "bitflags 2.5.0", "bytes", - "futures-core", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "http-range-header", - "pin-project-lite 0.2.14", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "pin-project-lite", "tower-layer", "tower-service", ] @@ -14786,7 +15803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", - "pin-project-lite 0.2.14", + "pin-project-lite", "tracing-attributes", "tracing-core", ] @@ -14824,9 +15841,9 @@ dependencies = [ [[package]] name = "tracing-gum" -version = "8.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9690af7fe11d125786fa1b5ca802192f631b61a4411277865c8e0581c887e286" +checksum = "d07f52b2b1a1c1c21094bd0b6fdcf1b7dbe785b937b30e82dba688d55d988efb" dependencies = [ "coarsetime", "polkadot-primitives", @@ -14840,7 +15857,7 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f074568687ffdfd0adb6005aa8d1d96840197f2c159f80471285f08694cf0ce" dependencies = [ - "expander 2.2.1", + "expander", "proc-macro-crate 3.1.0", "proc-macro2", "quote", @@ -14889,7 +15906,6 @@ dependencies = [ "chrono", "lazy_static", "matchers 0.0.1", - "parking_lot 0.11.2", "regex", "serde", "serde_json", @@ -14909,9 +15925,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers 0.1.0", + "nu-ansi-term", "once_cell", + "parking_lot 0.12.3", "regex", "sharded-slab", + "smallvec", "thread_local", "tracing", "tracing-core", @@ -14920,12 +15939,11 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.28.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff28e0f815c2fea41ebddf148e008b077d2faddb026c9555b29696114d602642" +checksum = "0c992b4f40c234a074d48a757efeabb1a6be88af84c0c23f7ca158950cb0ae7f" dependencies = [ "hash-db", - "hashbrown 0.13.2", "log", "rustc-hex", "smallvec", @@ -14949,7 +15967,7 @@ dependencies = [ "async-trait", "cfg-if", "data-encoding", - "enum-as-inner", + "enum-as-inner 0.5.1", "futures-channel", "futures-io", "futures-util", @@ -14966,24 +15984,50 @@ dependencies = [ "url", ] +[[package]] +name = "trust-dns-proto" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner 0.6.0", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "smallvec", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + [[package]] name = "trust-dns-resolver" -version = "0.22.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe" +checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" dependencies = [ "cfg-if", "futures-util", "ipconfig", - "lazy_static", "lru-cache", + "once_cell", "parking_lot 0.12.3", + "rand", "resolv-conf", "smallvec", "thiserror", "tokio", "tracing", - "trust-dns-proto", + "trust-dns-proto 0.23.2", ] [[package]] @@ -14993,47 +16037,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "try-runtime-cli" -version = "0.39.0" +name = "tt-call" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9454e1af0a0be675f837d63080ef8f43510c05df8c059570622386a0cf40b548" +checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" + +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ - "async-trait", - "clap", - "frame-remote-externalities", - "frame-try-runtime", - "hex", + "byteorder", + "bytes", + "data-encoding", + "http 0.2.12", + "httparse", "log", - "parity-scale-codec", - "sc-cli", - "sc-executor", - "serde", - "serde_json", - "sp-api", - "sp-consensus-aura", - "sp-consensus-babe", - "sp-core", - "sp-debug-derive", - "sp-externalities", - "sp-inherents", - "sp-io", - "sp-keystore", - "sp-rpc", - "sp-runtime", - "sp-state-machine", - "sp-timestamp", - "sp-transaction-storage-proof", - "sp-version", - "sp-weights", - "substrate-rpc-client", - "zstd 0.12.4", + "rand", + "rustls 0.21.12", + "sha1", + "thiserror", + "url", + "utf-8", ] [[package]] -name = "tt-call" -version = "1.0.9" +name = "tuplex" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" +checksum = "676ac81d5454c4dcf37955d34fa8626ede3490f744b86ca14a7b90168d2a08aa" [[package]] name = "twox-hash" @@ -15111,7 +16144,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", - "subtle 2.4.1", + "subtle 2.5.0", ] [[package]] @@ -15126,6 +16159,16 @@ dependencies = [ "futures-util", ] +[[package]] +name = "unsigned-varint" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" +dependencies = [ + "bytes", + "tokio-util", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -15150,6 +16193,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf16_iter" version = "1.0.5" @@ -15218,8 +16267,8 @@ dependencies = [ "constcat", "digest 0.10.7", "rand", - "rand_chacha 0.3.1", - "rand_core 0.6.4", + "rand_chacha", + "rand_core", "sha2 0.10.8", "sha3", "thiserror", @@ -15251,12 +16300,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -15269,7 +16312,7 @@ version = "0.12.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" dependencies = [ - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -15411,7 +16454,24 @@ dependencies = [ "smallvec", "spin 0.9.8", "wasmi_arena", - "wasmi_core", + "wasmi_core 0.13.0", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50386c99b9c32bd2ed71a55b6dd4040af2580530fae8bdb9a6576571a80d0cca" +dependencies = [ + "arrayvec 0.7.4", + "multi-stash", + "num-derive", + "num-traits", + "smallvec", + "spin 0.9.8", + "wasmi_collections", + "wasmi_core 0.32.3", "wasmparser-nostd", ] @@ -15421,6 +16481,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" +[[package]] +name = "wasmi_collections" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c128c039340ffd50d4195c3f8ce31aac357f06804cfc494c8b9508d4b30dca4" +dependencies = [ + "ahash 0.8.11", + "hashbrown 0.14.5", + "string-interner", +] + [[package]] name = "wasmi_core" version = "0.13.0" @@ -15433,6 +16504,18 @@ dependencies = [ "paste", ] +[[package]] +name = "wasmi_core" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23b3a7f6c8c3ceeec6b83531ee61f0013c56e51cbf2b14b0f213548b23a4b41" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + [[package]] name = "wasmparser" version = "0.102.0" @@ -15669,18 +16752,24 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.6" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "webpki-roots" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" dependencies = [ - "webpki", + "rustls-pki-types", ] [[package]] name = "westend-runtime" -version = "8.0.1" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4aa5580861b05668a6af845aa271c4f699a2fc26646d524e5b0d9375fb0647e" +checksum = "56b8918bb9fe4938757d4f003b7fa26598a632e350feac4e7477bb6b36e2f2af" dependencies = [ "binary-merkle-tree", "bitvec", @@ -15705,6 +16794,7 @@ dependencies = [ "pallet-beefy-mmr", "pallet-collective", "pallet-conviction-voting", + "pallet-delegated-staking", "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", @@ -15712,7 +16802,6 @@ dependencies = [ "pallet-fast-unstake", "pallet-grandpa", "pallet-identity", - "pallet-im-online", "pallet-indices", "pallet-membership", "pallet-message-queue", @@ -15751,7 +16840,6 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-parachains", - "rustc-hex", "scale-info", "serde", "serde_derive", @@ -15782,13 +16870,14 @@ dependencies = [ "staging-xcm-executor", "substrate-wasm-builder", "westend-runtime-constants", + "xcm-runtime-apis", ] [[package]] name = "westend-runtime-constants" -version = "8.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b080c193714605ce1033311d85035247adca170181cd68a3ad7e3ca87755a14" +checksum = "8c7a91c27c398b11f7633cc2382cbba53b02e7196ebe8fff13c170e54a54e9d8" dependencies = [ "frame-support", "polkadot-primitives", @@ -15891,6 +16980,21 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -16162,40 +17266,45 @@ dependencies = [ [[package]] name = "x25519-dalek" -version = "1.1.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 3.2.0", - "rand_core 0.5.1", + "curve25519-dalek", + "rand_core", + "serde", "zeroize", ] [[package]] -name = "x25519-dalek" -version = "2.0.1" +name = "x509-parser" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" dependencies = [ - "curve25519-dalek 4.1.3", - "rand_core 0.6.4", - "serde", - "zeroize", + "asn1-rs 0.5.2", + "data-encoding", + "der-parser 8.2.0", + "lazy_static", + "nom", + "oid-registry 0.6.1", + "rusticata-macros", + "thiserror", + "time", ] [[package]] name = "x509-parser" -version = "0.14.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" dependencies = [ - "asn1-rs", - "base64 0.13.1", + "asn1-rs 0.6.2", "data-encoding", - "der-parser", + "der-parser 9.0.0", "lazy_static", "nom", - "oid-registry", + "oid-registry 0.7.0", "rusticata-macros", "thiserror", "time", @@ -16203,9 +17312,9 @@ dependencies = [ [[package]] name = "xcm-emulator" -version = "0.6.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b49681988880dd6d08a4d5f6b7cb612a0f12172270349655c1e2f870b3526fd" +checksum = "be630e9b41c5d19d227162afe4cf642be24058b179fb1edbfe132f6328c7bde8" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-pallet-xcmp-queue", @@ -16238,9 +17347,9 @@ dependencies = [ [[package]] name = "xcm-procedural" -version = "8.0.0" +version = "10.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4717a97970a9cda70d7db53cf50d2615c2f6f6b7c857445325b4a39ea7aa2cd" +checksum = "87fb4f14094d65c500a59bcf540cf42b99ee82c706edd6226a92e769ad60563e" dependencies = [ "Inflector", "proc-macro2", @@ -16248,16 +17357,48 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "xcm-runtime-apis" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30fffcd9128a46abd836c37dd001c2cbe122aeb8904cd7b9bac8358564fb7b56" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-std", + "sp-weights", + "staging-xcm", + "staging-xcm-executor", +] + +[[package]] +name = "xml-rs" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "539a77ee7c0de333dcc6da69b177380a0b81e0dacfa4f7344c465a36871ee601" + +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "xml-rs", +] + [[package]] name = "yamux" -version = "0.10.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d9ba232399af1783a58d8eb26f6b5006fbefe2dc9ef36bd283324792d03ea5" +checksum = "9ed0164ae619f2dc144909a9f082187ebb5893693d8c0196e8085283ccd4b776" dependencies = [ "futures", "log", "nohash-hasher", "parking_lot 0.12.3", + "pin-project", "rand", "static_assertions", ] diff --git a/Cargo.toml b/Cargo.toml index 7027423c..3c2f5a1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,175 +2,184 @@ panic = "unwind" [profile.production] +codegen-units = 1 inherits = "release" lto = true -codegen-units = 1 [workspace.package] -authors = ["R0GUE "] +authors = [ "R0GUE " ] +description = "Pop Network makes it easy for smart contract developers to use the Power of Polkadot." edition = "2021" homepage = "https://r0gue.io" license = "Unlicense" repository = "https://github.com/r0gue-io/pop-node/" -description = "Pop Network makes it easy for smart contract developers to use the Power of Polkadot." [workspace] +exclude = [ "extension/contract", "pop-api", "tests/contracts" ] members = [ - "node", - "runtime/devnet", - "runtime/testnet", - "integration-tests", - "pallets/*", - "primitives", + "integration-tests", + "node", + "pallets/*", + "primitives", + "runtime/devnet", + "runtime/mainnet", + "runtime/testnet", ] -exclude = ["extension/contract", "pop-api", "tests/contracts"] resolver = "2" [workspace.dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ - "derive", +clap = { version = "4.4.18", features = [ "derive" ] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ + "derive", ] } contract-build = "4.1.1" env_logger = "0.11.5" +futures = "0.3.28" hex-literal = "0.4.1" impl-trait-for-tuples = "0.2.2" -log = { version = "0.4.20", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = [ - "derive", -] } -smallvec = "1.11.0" -serde = "1.0.195" -clap = { version = "4.4.18", features = ["derive"] } -jsonrpsee = { version = "0.20.3", features = ["server"] } -futures = "0.3.28" +jsonrpsee = { version = "0.23.2", features = [ "server" ] } +log = { version = "0.4.21", default-features = false } rand = "0.8.5" -serde_json = "1.0.111" -tracing-subscriber = { version = "0.3", default-features = false } +scale-info = { version = "2.11.1", default-features = false, features = [ + "derive", +] } +serde = "1.0.197" +serde_json = "1.0.114" +smallvec = "1.11.2" subxt = "0.34.0" subxt-signer = "0.34.0" -tokio = { version = "1.36", features = ["macros", "time", "rt-multi-thread"] } +tokio = { version = "1.36", features = [ "macros", "rt-multi-thread", "time" ] } +tracing-subscriber = { version = "0.3", default-features = false } # Build -substrate-wasm-builder = "18.0.1" substrate-build-script-utils = "11.0.0" +substrate-wasm-builder = "23.0.0" # Local pallet-api = { path = "pallets/api", default-features = false } pop-chain-extension = { path = "./extension", default-features = false } +pop-primitives = { path = "./primitives", default-features = false } +pop-runtime-common = { path = "runtime/common", default-features = false } pop-runtime-devnet = { path = "runtime/devnet", default-features = true } # default-features=true required for `-p pop-node` builds +pop-runtime-mainnet = { path = "runtime/mainnet", default-features = true } # default-features=true required for `-p pop-node` builds pop-runtime-testnet = { path = "runtime/testnet", default-features = true } # default-features=true required for `-p pop-node` builds -pop-runtime-common = { path = "runtime/common", default-features = false } -pop-primitives = { path = "./primitives", default-features = false } # Substrate -sc-basic-authorship = "0.35.0" -sc-chain-spec = "28.0.0" -sc-cli = "0.37.0" -sc-client-api = "29.0.0" -sc-offchain = "30.0.0" -sc-consensus = "0.34.0" -sc-executor = "0.33.0" -sc-network = "0.35.0" -sc-network-sync = "0.34.0" -sc-rpc = "30.0.0" -sc-service = "0.36.0" -sc-sysinfo = "28.0.0" -sc-telemetry = "16.0.0" -sc-tracing = "29.0.0" -sc-transaction-pool = "29.0.0" -sc-transaction-pool-api = "29.0.0" -frame-benchmarking = { version = "29.0.0", default-features = false } -frame-benchmarking-cli = "33.0.0" -frame-executive = { version = "29.0.0", default-features = false } -frame-support = { version = "29.0.2", default-features = false } -frame-system = { version = "29.0.0", default-features = false } -frame-system-benchmarking = { version = "29.0.0", default-features = false } -frame-system-rpc-runtime-api = { version = "27.0.0", default-features = false } -frame-try-runtime = { version = "0.35.0", default-features = false } -pallet-aura = { version = "28.0.0", default-features = false, features = [ - "experimental", -] } -pallet-authorship = { version = "29.0.0", default-features = false } -pallet-assets = { version = "30.0.0", default-features = false } -pallet-balances = { version = "29.0.2", default-features = false } -pallet-contracts = { version = "28.0.0", default-features = false } -pallet-message-queue = { version = "32.0.0", default-features = false } -pallet-multisig = { version = "29.0.0", default-features = false } -pallet-nft-fractionalization = { version = "11.0.0", default-features = false } -pallet-nfts = { version = "23.0.0", default-features = false } -pallet-nfts-runtime-api = { version = "15.0.0", default-features = false } -pallet-preimage = { version = "29.0.0", default-features = false } -pallet-proxy = { version = "29.0.0", default-features = false } -pallet-scheduler = { version = "30.0.0", default-features = false } -pallet-session = { version = "29.0.0", default-features = false } -pallet-sudo = { version = "29.0.0", default-features = false } -pallet-timestamp = { version = "28.0.0", default-features = false } -pallet-transaction-payment = { version = "29.0.2", default-features = false } -pallet-transaction-payment-rpc = "31.0.0" -pallet-transaction-payment-rpc-runtime-api = { version = "29.0.0", default-features = false } -pallet-utility = { version = "29.0.0", default-features = false } -sp-api = { version = "27.0.1", default-features = false } -sp-authority-discovery = { version = "27.0.0", default-features = false } -sp-block-builder = { version = "27.0.0", default-features = false } -sp-blockchain = "29.0.0" -sp-consensus-aura = { version = "0.33.0", default-features = false } -sp-consensus-babe = { version = "0.33.0", default-features = false } -sp-consensus-beefy = { version = "14.0.0", default-features = false } -sp-consensus-grandpa = { version = "14.0.0", default-features = false } -sp-core = { version = "29.0.0", default-features = false } -sp-keystore = "0.35.0" -sp-io = { version = "31.0.0", default-features = false } -sp-genesis-builder = { version = "0.8.0", default-features = false } -sp-inherents = { version = "27.0.0", default-features = false } -sp-offchain = { version = "27.0.0", default-features = false } -sp-runtime = { version = "32.0.0", default-features = false } -sp-timestamp = "27.0.0" -substrate-frame-rpc-system = "29.0.0" -substrate-prometheus-endpoint = "0.17.0" -sp-session = { version = "28.0.0", default-features = false } +frame-benchmarking = { version = "36.0.0", default-features = false } +frame-benchmarking-cli = "40.0.0" +frame-executive = { version = "36.0.0", default-features = false } +frame-metadata-hash-extension = { version = "0.4.0", default-features = false } +frame-support = { version = "36.0.0", default-features = false } +frame-support-procedural = { version = "=30.0.1", default-features = false } +frame-system = { version = "36.1.0", default-features = false } +frame-system-benchmarking = { version = "36.0.0", default-features = false } +frame-system-rpc-runtime-api = { version = "33.0.0", default-features = false } +frame-try-runtime = { version = "0.42.0", default-features = false } +pallet-assets = { version = "37.0.0", default-features = false } +pallet-aura = { version = "35.0.0", default-features = false } +pallet-authorship = { version = "36.0.0", default-features = false } +pallet-balances = { version = "37.0.0", default-features = false } +pallet-contracts = { version = "35.0.0", default-features = false } +pallet-message-queue = { version = "39.0.0", default-features = false } +pallet-multisig = { version = "36.0.0", default-features = false } +pallet-nft-fractionalization = { version = "18.0.0", default-features = false } +pallet-nfts = { version = "30.0.0", default-features = false } +pallet-nfts-runtime-api = { version = "22.0.0", default-features = false } +pallet-preimage = { version = "36.0.0", default-features = false } +pallet-proxy = { version = "36.0.0", default-features = false } +pallet-scheduler = { version = "37.0.0", default-features = false } +pallet-session = { version = "36.0.0", default-features = false } +pallet-sudo = { version = "36.0.0", default-features = false } +pallet-timestamp = { version = "35.0.0", default-features = false } +pallet-transaction-payment = { version = "36.0.0", default-features = false } +pallet-transaction-payment-rpc = "38.0.0" +pallet-transaction-payment-rpc-runtime-api = { version = "36.0.0", default-features = false } +pallet-utility = { version = "36.0.0", default-features = false } +prometheus-endpoint = { version = "0.17.0", default-features = false, package = "substrate-prometheus-endpoint" } +sc-basic-authorship = "0.42.0" +sc-chain-spec = "35.0.0" +sc-cli = "0.44.0" +sc-client-api = "35.1.0" +sc-consensus = "0.41.0" +sc-executor = "0.39.0" +sc-network = "0.42.0" +sc-network-sync = "0.41.0" +sc-offchain = "37.0.0" +sc-rpc = "37.0.0" +sc-service = "0.43.0" +sc-sysinfo = "35.0.0" +sc-telemetry = "22.0.0" +sc-tracing = "35.0.0" +sc-transaction-pool = "35.0.0" +sc-transaction-pool-api = "35.0.0" +sp-api = { version = "33.0.0", default-features = false } +sp-authority-discovery = { version = "33.0.0", default-features = false } +sp-block-builder = { version = "33.0.0", default-features = false } +sp-blockchain = "35.1.0" +sp-consensus-aura = { version = "0.39.0", default-features = false } +sp-consensus-babe = { version = "0.39.0", default-features = false } +sp-consensus-beefy = { version = "20.0.0", default-features = false } +sp-consensus-grandpa = { version = "20.0.0", default-features = false } +sp-core = { version = "34.0.0", default-features = false } +sp-genesis-builder = { version = "0.14.0", default-features = false } +sp-inherents = { version = "33.0.0", default-features = false } +sp-io = { version = "37.0.0", default-features = false } +sp-keystore = "0.40.0" +sp-offchain = { version = "33.0.0", default-features = false } +sp-runtime = { version = "=38.0.0", default-features = false } +sp-session = { version = "34.0.0", default-features = false } sp-std = { version = "14.0.0", default-features = false } -sp-transaction-pool = { version = "27.0.0", default-features = false } -sp-version = { version = "30.0.0", default-features = false } +sp-timestamp = "33.0.0" +sp-transaction-pool = { version = "33.0.0", default-features = false } +sp-version = { version = "36.0.0", default-features = false } +substrate-frame-rpc-system = "36.0.0" # Polkadot -pallet-xcm = { version = "8.0.5", default-features = false } -polkadot-cli = "8.0.0" -polkadot-parachain-primitives = { version = "7.0.0", default-features = false } -polkadot-runtime-parachains = { version = "8.0.3", default-features = false } -polkadot-primitives = { version = "8.0.1", default-features = false } -polkadot-runtime-common = { version = "8.0.3", default-features = false } -xcm = { package = "staging-xcm", version = "8.0.1", default-features = false } -xcm-builder = { package = "staging-xcm-builder", version = "8.0.3", default-features = false } -xcm-executor = { package = "staging-xcm-executor", version = "8.0.2", default-features = false } +pallet-xcm = { version = "15.0.0", default-features = false } +polkadot-cli = "15.0.0" +polkadot-parachain-primitives = { version = "13.0.0", default-features = false } +polkadot-primitives = { version = "14.0.0", default-features = false } +polkadot-runtime-common = { version = "15.0.0", default-features = false } +polkadot-runtime-parachains = { version = "15.0.3", default-features = false } +rococo-runtime = { version = "15.0.0", default-features = false } +rococo-runtime-constants = { version = "15.0.0", default-features = false } +xcm = { version = "14.0.3", package = "staging-xcm", default-features = false } +xcm-builder = { version = "15.0.0", package = "staging-xcm-builder", default-features = false } +xcm-executor = { version = "15.0.0", package = "staging-xcm-executor", default-features = false } # Cumulus -asset-test-utils = { version = "8.0.1", default-features = false } -cumulus-pallet-aura-ext = { version = "0.8.0", default-features = false } -cumulus-pallet-parachain-system = { version = "0.8.1", default-features = false, features = [ - "parameterized-consensus-hook", -] } -cumulus-pallet-session-benchmarking = { version = "10.0.0", default-features = false } -cumulus-pallet-xcm = { version = "0.8.0", default-features = false } -cumulus-pallet-xcmp-queue = { version = "0.8.0", default-features = false } -cumulus-primitives-aura = { version = "0.8.0", default-features = false } -cumulus-primitives-core = { version = "0.8.0", default-features = false } -cumulus-primitives-utility = { version = "0.8.1", default-features = false } -emulated-integration-tests-common = { version = "4.0.0", default-features = false } -pallet-collator-selection = { version = "10.0.3", default-features = false } -parachains-common = { version = "8.0.1", default-features = false } -parachain-info = { package = "staging-parachain-info", version = "0.8.0", default-features = false } -cumulus-primitives-parachain-inherent = "0.8.0" -cumulus-relay-chain-interface = "0.8.0" +asset-hub-rococo-runtime = { version = "0.19.0", default-features = false } +asset-test-utils = { version = "15.0.0", default-features = false } color-print = "0.3.4" -cumulus-client-cli = "0.8.0" -cumulus-client-collator = "0.8.0" -cumulus-client-consensus-aura = "0.8.0" -cumulus-client-consensus-common = "0.8.0" -cumulus-client-consensus-proposer = "0.8.0" -cumulus-client-service = "0.8.0" +cumulus-client-cli = "0.15.0" +cumulus-client-collator = "0.15.0" +cumulus-client-consensus-aura = "0.15.0" +cumulus-client-consensus-common = "0.15.0" +cumulus-client-consensus-proposer = "0.14.0" +cumulus-client-service = "0.15.0" +cumulus-pallet-aura-ext = { version = "0.15.0", default-features = false } +cumulus-pallet-parachain-system = { version = "0.15.0", default-features = false } +cumulus-pallet-session-benchmarking = { version = "17.0.0", default-features = false } +cumulus-pallet-xcm = { version = "0.15.0", default-features = false } +cumulus-pallet-xcmp-queue = { version = "0.15.0", default-features = false } +cumulus-primitives-aura = { version = "0.14.0", default-features = false } +cumulus-primitives-core = { version = "0.14.0", default-features = false } +cumulus-primitives-parachain-inherent = "0.14.0" +cumulus-primitives-storage-weight-reclaim = { version = "6.0.2", default-features = false } +cumulus-primitives-utility = { version = "0.15.0", default-features = false } +cumulus-relay-chain-interface = "0.15.0" +emulated-integration-tests-common = { version = "11.0.0", default-features = false } +pallet-collator-selection = { version = "17.0.0", default-features = false } +parachain-info = { version = "0.15.0", package = "staging-parachain-info", default-features = false } +parachains-common = { version = "15.0.0", default-features = false } + +# TODO: Paseo (note: using polkadot as stopgap until paseo updated to polkadot sdk v1.14.0) +asset-hub-paseo-runtime = { git = "https://github.com/polkadot-fellows/runtimes", default-features = false, package = "asset-hub-polkadot-runtime" } +paseo-runtime = { git = "https://github.com/polkadot-fellows/runtimes", default-features = false, package = "polkadot-runtime" } +paseo-runtime-constants = { git = "https://github.com/polkadot-fellows/runtimes", default-features = false, package = "polkadot-runtime-constants" } # Paseo -asset-hub-paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } -paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } -paseo-runtime-constants = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } +# asset-hub-paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } +# paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } +# paseo-runtime-constants = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } diff --git a/README.md b/README.md index 2ad8d31d..f178037d 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ cargo install pop-cli You can spawn a local network as follows: ```shell -pop up parachain -f ./networks/paseo.toml +pop up parachain -f ./networks/testnet.toml ``` Note: `pop` will automatically source the necessary `polkadot` binaries. Currently, these will have to be built if on a diff --git a/extension/Cargo.toml b/extension/Cargo.toml index 268365be..6ca5e071 100644 --- a/extension/Cargo.toml +++ b/extension/Cargo.toml @@ -1,16 +1,16 @@ [package] -name = "pop-chain-extension" -version = "0.1.0" authors.workspace = true description.workspace = true -license.workspace = true -homepage.workspace = true -repository.workspace = true edition.workspace = true +homepage.workspace = true +license.workspace = true +name = "pop-chain-extension" publish = false +repository.workspace = true +version = "0.1.0" [package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +targets = [ "x86_64-unknown-linux-gnu" ] [dependencies] codec.workspace = true @@ -36,25 +36,25 @@ scale-info.workspace = true sp-io.workspace = true [features] -default = ["std"] -std = [ - "log/std", - "codec/std", - "frame-support/std", - "frame-system/std", - "pallet-balances/std", - "pallet-contracts/std", - "pallet-timestamp/std", - "sp-runtime/std", - "sp-core/std", - "sp-io/std", - "sp-std/std", -] +default = [ "std" ] runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-contracts/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-contracts/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "log/std", + "pallet-balances/std", + "pallet-contracts/std", + "pallet-timestamp/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", ] diff --git a/extension/contract/Cargo.toml b/extension/contract/Cargo.toml index 97ecabf9..52c56f66 100755 --- a/extension/contract/Cargo.toml +++ b/extension/contract/Cargo.toml @@ -1,9 +1,9 @@ [package] -authors = ["R0GUE "] -name = "proxy" +authors = [ "R0GUE " ] description = "Simple contract for proxying a call to a chain extension." -version = "0.1.0" edition = "2021" +name = "proxy" +version = "0.1.0" [dependencies] ink = { version = "5.0.0", default-features = false } @@ -12,5 +12,5 @@ ink = { version = "5.0.0", default-features = false } path = "lib.rs" [features] -default = ["std"] -std = ["ink/std"] +default = [ "std" ] +std = [ "ink/std" ] diff --git a/extension/src/decoding.rs b/extension/src/decoding.rs index 9405aa5b..7269a49a 100644 --- a/extension/src/decoding.rs +++ b/extension/src/decoding.rs @@ -1,7 +1,8 @@ -use super::*; use sp_runtime::DispatchError; use sp_std::vec::Vec; +use super::*; + /// Trait for decoding data read from contract memory. pub trait Decode { /// The output type to be decoded. @@ -42,6 +43,7 @@ pub trait Processor { pub struct Identity(PhantomData); impl Processor for Identity { type Value = Value; + const LOG_TARGET: &'static str = ""; fn process(value: Self::Value, _env: &impl Environment) -> Self::Value { @@ -59,9 +61,10 @@ impl< Logger: LogTarget, > Decode for Decodes { + type Error = Error; type Output = Output; type Processor = ValueProcessor; - type Error = Error; + const LOG_TARGET: &'static str = Logger::LOG_TARGET; /// Decodes data read from contract memory. @@ -99,13 +102,14 @@ impl Get for DecodingFailed { #[cfg(test)] mod tests { + use codec::{Decode as OriginalDecode, Encode}; + use frame_support::assert_ok; + use super::*; use crate::{ extension::read_from_buffer_weight, mock::{MockEnvironment, RemoveFirstByte, Test}, }; - use codec::{Decode as OriginalDecode, Encode}; - use frame_support::assert_ok; type EnumDecodes = Decodes, DecodingFailed>; diff --git a/extension/src/environment.rs b/extension/src/environment.rs index e5eff083..dc3818e8 100644 --- a/extension/src/environment.rs +++ b/extension/src/environment.rs @@ -1,9 +1,11 @@ -use crate::AccountIdOf; use core::fmt::Debug; + use frame_support::pallet_prelude::Weight; use pallet_contracts::chain_extension::{BufInBufOutState, ChargedAmount, Result, State}; use sp_std::vec::Vec; +use crate::AccountIdOf; + /// Provides access to the parameters passed to a chain extension and its execution environment. /// /// A wrapper trait for `pallet_contracts::chain_extension::Environment`. All comments have been @@ -182,6 +184,7 @@ pub(crate) struct ExternalEnvironment<'a, T: pallet_contracts::chain_extension:: impl<'a, E: pallet_contracts::chain_extension::Ext> Ext for ExternalEnvironment<'a, E> { type AccountId = AccountIdOf; + fn address(&self) -> &Self::AccountId { self.0.address() } diff --git a/extension/src/functions.rs b/extension/src/functions.rs index 16ca1f1c..b1a046ea 100644 --- a/extension/src/functions.rs +++ b/extension/src/functions.rs @@ -1,6 +1,7 @@ -use super::*; use core::fmt::Debug; +use super::*; + /// A chain extension function. pub trait Function { /// The configuration of the contracts module. @@ -167,6 +168,7 @@ pub struct DefaultConverter(PhantomData); impl>> Converter for DefaultConverter { type Source = T; type Target = Vec; + const LOG_TARGET: &'static str = ""; fn convert(value: Self::Source, _env: &impl Environment) -> Self::Target { @@ -199,10 +201,11 @@ impl ErrorConverter for () { #[impl_trait_for_tuples::impl_for_tuples(1, 10)] #[tuple_types_custom_trait_bound(Function + Matches)] impl Function for Tuple { - for_tuples!( where #( Tuple: Function )* ); type Config = Runtime; type Error = (); + for_tuples!( where #( Tuple: Function )* ); + fn execute( env: &mut (impl Environment> + BufIn + BufOut), ) -> Result { @@ -222,17 +225,18 @@ impl Function for Tuple { #[cfg(test)] mod tests { + use codec::Encode; + use frame_support::traits::{Everything, Nothing}; + use frame_system::Call; + use mock::{new_test_ext, Functions, MockEnvironment, RuntimeCall, RuntimeRead, Test}; + use sp_core::ConstU32; + use super::*; use crate::{ extension::{read_from_buffer_weight, write_to_contract_weight}, matching::WithFuncId, mock::{Noop, NoopFuncId, INVALID_FUNC_ID}, }; - use codec::Encode; - use frame_support::traits::{Everything, Nothing}; - use frame_system::Call; - use mock::{new_test_ext, Functions, MockEnvironment, RuntimeCall, RuntimeRead, Test}; - use sp_core::ConstU32; type FuncId = ConstU32<42>; @@ -352,21 +356,26 @@ mod tests { #[test] fn dispatch_call_adjusts_weight() { + let migrate_weight = ::WeightInfo::migrate(); + let migration_noop_weight = + ::WeightInfo::migration_noop(); new_test_ext().execute_with(|| { // Attempt to perform non-existent migration with additional weight limit specified. - let weight_limit = Weight::from_parts(123456789, 12345); + let extra_weight = Weight::from_parts(123456789, 12345); + let weight_limit = migration_noop_weight.saturating_add(extra_weight); let call = RuntimeCall::Contracts(pallet_contracts::Call::migrate { weight_limit }); let encoded_call = call.encode(); let mut env = MockEnvironment::new(FuncId::get(), encoded_call.clone()); let expected: DispatchError = pallet_contracts::Error::::NoMigrationPerformed.into(); assert_eq!(DispatchCall::execute(&mut env).err().unwrap(), expected); + // Ensure pre-dispatch weight is weight function + weight limit + assert_eq!(call.get_dispatch_info().weight, migrate_weight + weight_limit); assert_eq!( env.charged(), read_from_buffer_weight(encoded_call.len() as u32) + - // Weight limit subtracted from pre-dispatch weight charged on failure. call.get_dispatch_info().weight - - weight_limit + extra_weight ); }) } diff --git a/extension/src/lib.rs b/extension/src/lib.rs index 875867f8..c2480c06 100644 --- a/extension/src/lib.rs +++ b/extension/src/lib.rs @@ -1,6 +1,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use core::marker::PhantomData; + pub use decoding::{Decode, Decodes, DecodingFailed, Identity, Processor}; pub use environment::{BufIn, BufOut, Environment, Ext}; use frame_support::{ @@ -109,13 +110,14 @@ fn default_log_target_works() { #[cfg(test)] mod extension { + use codec::Encode; + use frame_system::Call; + use super::*; use crate::mock::{ new_test_ext, DispatchExtFuncId, MockEnvironment, NoopFuncId, ReadExtFuncId, RuntimeCall, RuntimeRead, Test, INVALID_FUNC_ID, }; - use codec::Encode; - use frame_system::Call; #[test] fn call_works() { diff --git a/extension/src/matching.rs b/extension/src/matching.rs index 5966b9ff..0dcdd34d 100644 --- a/extension/src/matching.rs +++ b/extension/src/matching.rs @@ -37,9 +37,10 @@ impl> Matches for WithFuncId { #[cfg(test)] mod tests { + use sp_core::{ConstU16, ConstU32}; + use super::*; use crate::mock::MockEnvironment; - use sp_core::{ConstU16, ConstU32}; #[test] fn equals_matches() { diff --git a/extension/src/mock.rs b/extension/src/mock.rs index 688bad51..13ffbf47 100644 --- a/extension/src/mock.rs +++ b/extension/src/mock.rs @@ -1,8 +1,5 @@ -use crate::{ - decoding::Identity, environment, matching::WithFuncId, AccountIdOf, ContractWeightsOf, - Converter, Decodes, DecodingFailed, DefaultConverter, DispatchCall, Extension, Function, - Matches, Processor, ReadState, Readable, -}; +use std::marker::PhantomData; + use codec::{Decode, Encode}; use frame_support::{ derive_impl, @@ -10,10 +7,15 @@ use frame_support::{ parameter_types, traits::{fungible::Inspect, ConstU32, Everything, Nothing}, }; -use frame_system::pallet_prelude::BlockNumberFor; +use frame_system::{pallet_prelude::BlockNumberFor, EnsureSigned}; use pallet_contracts::{chain_extension::RetVal, DefaultAddressGenerator, Frame, Schedule}; use sp_runtime::{BuildStorage, Perbill}; -use std::marker::PhantomData; + +use crate::{ + decoding::Identity, environment, matching::WithFuncId, AccountIdOf, ContractWeightsOf, + Converter, Decodes, DecodingFailed, DefaultConverter, DispatchCall, Extension, Function, + Matches, Processor, ReadState, Readable, +}; pub(crate) const ALICE: u64 = 1; pub(crate) const DEBUG_OUTPUT: pallet_contracts::DebugInfo = @@ -65,8 +67,8 @@ frame_support::construct_runtime!( #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { - type AccountId = u64; type AccountData = pallet_balances::AccountData; + type AccountId = u64; type Block = frame_system::mocking::MockBlock; } @@ -80,31 +82,39 @@ impl pallet_balances::Config for Test { impl pallet_timestamp::Config for Test {} impl pallet_contracts::Config for Test { - type Time = Timestamp; - type Randomness = Test; - type Currency = Balances; - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type CallFilter = (); //TestFilter; + type AddressGenerator = DefaultAddressGenerator; + type ApiVersion = (); + type CallFilter = (); + // TestFilter; type CallStack = [Frame; 5]; - type WeightPrice = (); //Self; - type WeightInfo = (); type ChainExtension = Extension; - type Schedule = MySchedule; + type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; + type Currency = Balances; + type Debug = (); + // TestDebug; + type DefaultDepositLimit = DefaultDepositLimit; type DepositPerByte = DepositPerByte; type DepositPerItem = DepositPerItem; - type DefaultDepositLimit = DefaultDepositLimit; - type AddressGenerator = DefaultAddressGenerator; + type Environment = (); + type InstantiateOrigin = EnsureSigned; type MaxCodeLen = ConstU32<{ 100 * 1024 }>; - type MaxStorageKeyLen = ConstU32<128>; - type UnsafeUnstableInterface = (); //UnstableInterface; type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; - type RuntimeHoldReason = RuntimeHoldReason; - type Migrations = (); //crate::migration::codegen::BenchMigrations; - type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; type MaxDelegateDependencies = MaxDelegateDependencies; - type Debug = (); //TestDebug; - type Environment = (); + type MaxStorageKeyLen = ConstU32<128>; + type Migrations = (); + // crate::migration::codegen::BenchMigrations; + type Randomness = Test; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; + type Schedule = MySchedule; + type Time = Timestamp; + type UnsafeUnstableInterface = (); + // UnstableInterface; + type UploadOrigin = EnsureSigned; + type WeightInfo = (); + type WeightPrice = (); + // Self; type Xcm = (); } @@ -201,6 +211,7 @@ pub(crate) type Functions = ( pub struct Config; impl super::Config for Config { type Functions = Functions; + const LOG_TARGET: &'static str = "pop-chain-extension"; } @@ -209,6 +220,7 @@ impl super::Config for Config { pub struct RemoveFirstByte; impl Processor for RemoveFirstByte { type Value = Vec; + const LOG_TARGET: &'static str = ""; fn process(mut value: Self::Value, _env: &impl crate::Environment) -> Self::Value { @@ -363,6 +375,7 @@ pub(crate) struct UppercaseConverter; impl Converter for UppercaseConverter { type Source = RuntimeResult; type Target = Vec; + const LOG_TARGET: &'static str = ""; fn convert(value: Self::Source, _env: &impl crate::Environment) -> Self::Target { diff --git a/extension/src/tests.rs b/extension/src/tests.rs index 8d527df6..c9588cd3 100644 --- a/extension/src/tests.rs +++ b/extension/src/tests.rs @@ -1,10 +1,6 @@ use core::fmt::Debug; use std::{path::Path, sync::LazyLock}; -use crate::{ - mock::{self, *}, - ErrorConverter, -}; use codec::{Decode, Encode}; use frame_support::weights::Weight; use frame_system::Call; @@ -14,6 +10,11 @@ use sp_runtime::{ ModuleError, }; +use crate::{ + mock::{self, *}, + ErrorConverter, +}; + static CONTRACT: LazyLock> = LazyLock::new(|| initialize_contract("contract/target/ink/proxy.wasm")); diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 0a427f8a..0bbdc053 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -1,34 +1,39 @@ [package] -name = "integration-tests" authors.workspace = true edition.workspace = true homepage.workspace = true license.workspace = true +name = "integration-tests" repository.workspace = true [dev-dependencies] codec.workspace = true -tracing-subscriber = { workspace = true, features = ["env-filter", "fmt", "std", "tracing-log"] } +tracing-subscriber = { workspace = true, features = [ + "env-filter", + "fmt", + "std", + "tracing-log", +] } # Substrate frame-support.workspace = true pallet-assets.workspace = true pallet-balances.workspace = true pallet-message-queue.workspace = true -sp-core.workspace = true sp-authority-discovery.workspace = true sp-consensus-aura.workspace = true sp-consensus-babe.workspace = true sp-consensus-beefy.workspace = true sp-consensus-grandpa.workspace = true +sp-core.workspace = true sp-runtime.workspace = true # Polkadot +pallet-xcm.workspace = true polkadot-primitives.workspace = true +polkadot-runtime-parachains.workspace = true xcm.workspace = true xcm-executor.workspace = true -polkadot-runtime-parachains.workspace = true -pallet-xcm.workspace = true # Cumulus asset-test-utils.workspace = true @@ -41,56 +46,63 @@ paseo-runtime.workspace = true paseo-runtime-constants.workspace = true # Local -pop-runtime-devnet.workspace = true pop-runtime-common.workspace = true +pop-runtime-devnet.workspace = true +pop-runtime-mainnet.workspace = true [features] -default = ["std"] +default = [ "std" ] +mainnet = [ "pop-runtime-mainnet/default" ] std = [ - "asset-hub-paseo-runtime/std", - "cumulus-primitives-core/std", - "frame-support/std", - "pallet-assets/std", - "pallet-balances/std", - "pallet-message-queue/std", - "pallet-xcm/std", - "paseo-runtime/std", - "paseo-runtime-constants/std", - "polkadot-primitives/std", - "polkadot-runtime-parachains/std", - "pop-runtime-devnet/std", - "sp-authority-discovery/std", - "sp-consensus-aura/std", - "sp-consensus-babe/std", - "sp-consensus-beefy/std", - "sp-consensus-grandpa/std", - "sp-core/std", - "sp-runtime/std", - "xcm-executor/std", - "xcm/std", + "asset-hub-paseo-runtime/std", + "cumulus-primitives-core/std", + "frame-support/std", + "pallet-assets/std", + "pallet-balances/std", + "pallet-message-queue/std", + "pallet-xcm/std", + "paseo-runtime-constants/std", + "paseo-runtime/std", + "polkadot-primitives/std", + "polkadot-runtime-parachains/std", + "pop-runtime-common/std", + "pop-runtime-devnet/std", + "pop-runtime-mainnet/std", + "sp-authority-discovery/std", + "sp-consensus-aura/std", + "sp-consensus-babe/std", + "sp-consensus-beefy/std", + "sp-consensus-grandpa/std", + "sp-core/std", + "sp-runtime/std", + "xcm-executor/std", + "xcm/std", ] runtime-benchmarks = [ - "asset-hub-paseo-runtime/runtime-benchmarks", - "cumulus-primitives-core/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "paseo-runtime/runtime-benchmarks", - "polkadot-primitives/runtime-benchmarks", - "pop-runtime-devnet/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", + "asset-hub-paseo-runtime/runtime-benchmarks", + "cumulus-primitives-core/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", + "paseo-runtime/runtime-benchmarks", + "polkadot-primitives/runtime-benchmarks", + "pop-runtime-common/runtime-benchmarks", + "pop-runtime-devnet/runtime-benchmarks", + "pop-runtime-mainnet/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", ] try-runtime = [ - "asset-hub-paseo-runtime/try-runtime", - "frame-support/try-runtime", - "pallet-assets/try-runtime", - "pallet-balances/std", - "pallet-message-queue/try-runtime", - "paseo-runtime/try-runtime", - "pop-runtime-devnet/try-runtime", - "sp-runtime/try-runtime", + "asset-hub-paseo-runtime/try-runtime", + "frame-support/try-runtime", + "pallet-assets/try-runtime", + "pallet-balances/std", + "pallet-message-queue/try-runtime", + "paseo-runtime/try-runtime", + "pop-runtime-devnet/try-runtime", + "pop-runtime-mainnet/try-runtime", + "sp-runtime/try-runtime", ] diff --git a/integration-tests/src/chains/asset_hub_paseo/mod.rs b/integration-tests/src/chains/asset_hub_paseo/mod.rs index 51dae063..0a9620e3 100644 --- a/integration-tests/src/chains/asset_hub_paseo/mod.rs +++ b/integration-tests/src/chains/asset_hub_paseo/mod.rs @@ -1,6 +1,5 @@ pub(crate) mod genesis; -use crate::chains::paseo::Paseo; use emulated_integration_tests_common::{ impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, impl_assets_helpers_for_parachain, impl_foreign_assets_helpers_for_parachain, @@ -34,6 +33,6 @@ decl_test_parachains! { // AssetHubPaseo implementation impl_accounts_helpers_for_parachain!(AssetHubPaseo); impl_assert_events_helpers_for_parachain!(AssetHubPaseo); -impl_assets_helpers_for_parachain!(AssetHubPaseo, Paseo); -impl_foreign_assets_helpers_for_parachain!(AssetHubPaseo, Paseo); +impl_assets_helpers_for_parachain!(AssetHubPaseo); +impl_foreign_assets_helpers_for_parachain!(AssetHubPaseo, xcm::v3::Location); impl_xcm_helpers_for_parachain!(AssetHubPaseo); diff --git a/integration-tests/src/chains/paseo/genesis.rs b/integration-tests/src/chains/paseo/genesis.rs index d4c29ca2..0ecdb1ff 100644 --- a/integration-tests/src/chains/paseo/genesis.rs +++ b/integration-tests/src/chains/paseo/genesis.rs @@ -1,6 +1,5 @@ use emulated_integration_tests_common::{ - accounts, build_genesis_storage, get_account_id_from_seed, get_from_seed, get_host_config, - validators, + accounts, build_genesis_storage, get_from_seed, get_host_config, validators, }; use paseo_runtime_constants::currency::UNITS as PAS; use polkadot_primitives::{AssignmentId, Balance, ValidatorId}; @@ -8,7 +7,7 @@ use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; use sp_consensus_grandpa::AuthorityId as GrandpaId; -use sp_core::{sr25519, storage::Storage}; +use sp_core::storage::Storage; pub(crate) const ED: Balance = paseo_runtime_constants::currency::EXISTENTIAL_DEPOSIT; const ENDOWMENT: u128 = 1_000_000 * PAS; @@ -58,12 +57,13 @@ pub(crate) fn genesis() -> Storage { }, babe: paseo_runtime::BabeConfig { authorities: Default::default(), - epoch_config: Some(paseo_runtime::BABE_GENESIS_EPOCH_CONFIG), + epoch_config: paseo_runtime::BABE_GENESIS_EPOCH_CONFIG, ..Default::default() }, - sudo: paseo_runtime::SudoConfig { - key: Some(get_account_id_from_seed::("Alice")), - }, + // TODO: sudo pallet is not configured in polkadot runtime + // sudo: runtime::SudoConfig { + // key: Some(get_account_id_from_seed::("Alice")), + // }, configuration: paseo_runtime::ConfigurationConfig { config: get_host_config() }, registrar: paseo_runtime::RegistrarConfig { next_free_para_id: polkadot_primitives::LOWEST_PUBLIC_ID, diff --git a/integration-tests/src/chains/paseo/mod.rs b/integration-tests/src/chains/paseo/mod.rs index 735807e5..4df1d2af 100644 --- a/integration-tests/src/chains/paseo/mod.rs +++ b/integration-tests/src/chains/paseo/mod.rs @@ -8,7 +8,7 @@ use emulated_integration_tests_common::{ // Paseo declaration decl_test_relay_chains! { - #[api_version(10)] + #[api_version(11)] pub struct Paseo { genesis = genesis::genesis(), on_init = (), @@ -18,7 +18,8 @@ decl_test_relay_chains! { }, pallets = { XcmPallet: paseo_runtime::XcmPallet, - Sudo: paseo_runtime::Sudo, + // TODO: sudo pallet is not configured in polkadot runtime + // Sudo: paseo_runtime::Sudo, Balances: paseo_runtime::Balances, Hrmp: paseo_runtime::Hrmp, } diff --git a/integration-tests/src/chains/pop_network/mod.rs b/integration-tests/src/chains/pop_network/mod.rs index 42b2cc2e..41daed27 100644 --- a/integration-tests/src/chains/pop_network/mod.rs +++ b/integration-tests/src/chains/pop_network/mod.rs @@ -1,31 +1,32 @@ pub(crate) mod genesis; -use crate::chains::paseo::Paseo; use emulated_integration_tests_common::{ impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, - impl_assets_helpers_for_parachain, impl_xcm_helpers_for_parachain, impls::Parachain, - xcm_emulator::decl_test_parachains, + impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains, }; use frame_support::traits::OnInitialize; +#[cfg(not(feature = "mainnet"))] +use pop_runtime_devnet as runtime; +#[cfg(feature = "mainnet")] +use pop_runtime_mainnet as runtime; // PopNetwork Parachain declaration decl_test_parachains! { pub struct PopNetwork { genesis = genesis::genesis(), on_init = { - pop_runtime_devnet::AuraExt::on_initialize(1); + runtime::AuraExt::on_initialize(1); }, - runtime = pop_runtime_devnet, + runtime = runtime, core = { - XcmpMessageHandler: pop_runtime_devnet::XcmpQueue, - LocationToAccountId: pop_runtime_devnet::config::xcm::LocationToAccountId, - ParachainInfo: pop_runtime_devnet::ParachainInfo, + XcmpMessageHandler: runtime::XcmpQueue, + LocationToAccountId: runtime::config::xcm::LocationToAccountId, + ParachainInfo: runtime::ParachainInfo, MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin, }, pallets = { - PolkadotXcm: pop_runtime_devnet::PolkadotXcm, - Assets: pop_runtime_devnet::Assets, - Balances: pop_runtime_devnet::Balances, + PolkadotXcm: runtime::PolkadotXcm, + Balances: runtime::Balances, } }, } @@ -33,5 +34,4 @@ decl_test_parachains! { // PopNetwork implementation impl_accounts_helpers_for_parachain!(PopNetwork); impl_assert_events_helpers_for_parachain!(PopNetwork); -impl_assets_helpers_for_parachain!(PopNetwork, Paseo); impl_xcm_helpers_for_parachain!(PopNetwork); diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index eddbc103..50513a3e 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -1,10 +1,5 @@ #![cfg(test)] -use crate::chains::{ - asset_hub_paseo::{genesis::ED as ASSET_HUB_PASEO_ED, AssetHubPaseoParaPallet}, - paseo::{genesis::ED as PASEO_ED, PaseoRelayPallet}, - pop_network::PopNetworkParaPallet, -}; use asset_hub_paseo_runtime::xcm_config::XcmConfig as AssetHubPaseoXcmConfig; use asset_test_utils::xcm_helpers; use chains::{asset_hub_paseo::AssetHubPaseo, paseo::Paseo, pop_network::PopNetwork}; @@ -22,6 +17,12 @@ use pop_runtime_common::Balance; use pop_runtime_devnet::config::xcm::XcmConfig as PopNetworkXcmConfig; use xcm::prelude::*; +use crate::chains::{ + asset_hub_paseo::{genesis::ED as ASSET_HUB_PASEO_ED, AssetHubPaseoParaPallet}, + paseo::{genesis::ED as PASEO_ED, PaseoRelayPallet}, + pop_network::PopNetworkParaPallet, +}; + mod chains; decl_test_networks! { @@ -95,7 +96,7 @@ fn para_receiver_assertions(_: Test) { assert_expected_events!( PopNetworkPara, vec![ - RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, + RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, RuntimeEvent::MessageQueue( pallet_message_queue::Event::Processed { success: true, .. } ) => {}, @@ -113,9 +114,7 @@ fn para_to_system_para_sender_assertions(t: ParaToSystemParaTest) { PopNetworkPara, vec![ // Amount to reserve transfer is transferred to Parachain's Sovereign account - RuntimeEvent::Balances( - pallet_balances::Event::Withdraw { who, amount } - ) => { + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { who: *who == t.sender.account_id, amount: *amount == t.args.amount, }, @@ -133,9 +132,7 @@ fn para_to_relay_sender_assertions(t: ParaToRelayTest) { PopNetworkPara, vec![ // Amount to reserve transfer is transferred to Parachain's Sovereign account - RuntimeEvent::Balances( - pallet_balances::Event::Withdraw { who, amount } - ) => { + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { who: *who == t.sender.account_id, amount: *amount == t.args.amount, }, @@ -297,7 +294,7 @@ fn reserve_transfer_native_asset_from_relay_to_para() { test.assert(); let delivery_fees = PaseoRelay::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >( test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest @@ -353,7 +350,7 @@ fn reserve_transfer_native_asset_from_para_to_relay() { let receiver_balance_after = test.receiver.balance; let delivery_fees = PopNetworkPara::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >( test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest @@ -401,7 +398,7 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubPaseoPara::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >( test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest @@ -467,7 +464,7 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { let receiver_balance_after = test.receiver.balance; let delivery_fees = PopNetworkPara::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >( test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest diff --git a/networks/mainnet.toml b/networks/mainnet.toml new file mode 100644 index 00000000..dc1fda4b --- /dev/null +++ b/networks/mainnet.toml @@ -0,0 +1,40 @@ +# pop up parachain -f ./networks/mainnet.toml + +[relaychain] +chain = "paseo-local" + +[relaychain.runtime_genesis_patch.balances] +balances = [ + # Pop sovereign account + ["5Ec4AhPKXY9B4ayGshkz2wFMh7N8gP7XKfAvtt1cigpG9FkJ", 60000000000000000], +] + +[[relaychain.nodes]] +name = "alice" +rpc_port = 8833 +validator = true + +[[relaychain.nodes]] +name = "bob" +validator = true + +[[parachains]] +id = 4001 +chain = "mainnet" +default_command = "./target/release/pop-node" + +[parachains.genesis_overrides.balances] +balances = [ + # Dev accounts + ["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", 10000000000000000], + ["5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", 10000000000000000], + ["5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y", 10000000000000000], + ["5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy", 10000000000000000], + ["5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw", 10000000000000000], + ["5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", 10000000000000000], +] + +[[parachains.collators]] +name = "pop" +rpc_port = 9944 +args = ["-lruntime::contracts=debug", "-lpopapi::extension=debug"] \ No newline at end of file diff --git a/networks/testnet.toml b/networks/testnet.toml index 15ac9b03..450f0532 100644 --- a/networks/testnet.toml +++ b/networks/testnet.toml @@ -37,4 +37,12 @@ balances = [ [[parachains.collators]] name = "pop" rpc_port = 9944 -args = ["-lruntime::contracts=debug", "-lpopapi::extension=debug"] \ No newline at end of file +args = ["-lruntime::contracts=debug", "-lpopapi::extension=debug", "-lxcm=trace"] + +[[parachains]] +id = 1000 +chain = "asset-hub-rococo-local" + +[[parachains.collators]] +name = "asset-hub" +args = ["-lxcm=trace"] \ No newline at end of file diff --git a/node/Cargo.toml b/node/Cargo.toml index b6f258c4..04de08e0 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -1,42 +1,44 @@ [package] -name = "pop-node" -version = "0.1.0-alpha" authors.workspace = true +build = "build.rs" description.workspace = true -license = "Unlicense" -homepage.workspace = true -repository.workspace = true edition.workspace = true -build = "build.rs" +homepage.workspace = true +license = "Unlicense" +name = "pop-node" publish = false +repository.workspace = true +version = "0.2.0-alpha" [dependencies] clap.workspace = true -log.workspace = true codec.workspace = true -serde.workspace = true -jsonrpsee.workspace = true futures.workspace = true +jsonrpsee.workspace = true +log.workspace = true +serde.workspace = true serde_json.workspace = true # Local +pop-runtime-common.workspace = true pop-runtime-devnet.workspace = true +pop-runtime-mainnet.workspace = true pop-runtime-testnet.workspace = true -pop-runtime-common.workspace = true # Substrate frame-benchmarking.workspace = true frame-benchmarking-cli.workspace = true pallet-transaction-payment-rpc.workspace = true +prometheus-endpoint.workspace = true sc-basic-authorship.workspace = true sc-chain-spec.workspace = true sc-cli.workspace = true sc-client-api.workspace = true -sc-offchain.workspace = true sc-consensus.workspace = true sc-executor.workspace = true sc-network.workspace = true sc-network-sync.workspace = true +sc-offchain.workspace = true sc-rpc.workspace = true sc-service.workspace = true sc-sysinfo.workspace = true @@ -49,15 +51,14 @@ sp-block-builder.workspace = true sp-blockchain.workspace = true sp-consensus-aura.workspace = true sp-core.workspace = true -sp-keystore.workspace = true sp-io.workspace = true +sp-keystore.workspace = true sp-offchain.workspace = true sp-runtime.workspace = true sp-session.workspace = true sp-timestamp.workspace = true sp-transaction-pool.workspace = true substrate-frame-rpc-system.workspace = true -substrate-prometheus-endpoint.workspace = true # Polkadot polkadot-cli.workspace = true @@ -65,37 +66,44 @@ polkadot-primitives.workspace = true xcm.workspace = true # Cumulus +color-print.workspace = true cumulus-client-cli.workspace = true cumulus-client-collator.workspace = true cumulus-client-consensus-aura.workspace = true cumulus-client-consensus-common.workspace = true cumulus-client-consensus-proposer.workspace = true -cumulus-primitives-aura.workspace = true cumulus-client-service.workspace = true +cumulus-primitives-aura.workspace = true cumulus-primitives-core.workspace = true cumulus-primitives-parachain-inherent.workspace = true cumulus-relay-chain-interface.workspace = true -color-print.workspace = true [build-dependencies] substrate-build-script-utils.workspace = true +[dev-dependencies] +pallet-multisig.workspace = true + [features] -default = [] runtime-benchmarks = [ - "cumulus-primitives-core/runtime-benchmarks", - "frame-benchmarking-cli/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "pop-runtime-devnet/runtime-benchmarks", - "pop-runtime-testnet/runtime-benchmarks", - "polkadot-cli/runtime-benchmarks", - "polkadot-primitives/runtime-benchmarks", - "sc-service/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", + "cumulus-primitives-core/runtime-benchmarks", + "frame-benchmarking-cli/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "polkadot-cli/runtime-benchmarks", + "polkadot-primitives/runtime-benchmarks", + "pop-runtime-common/runtime-benchmarks", + "pop-runtime-devnet/runtime-benchmarks", + "pop-runtime-mainnet/runtime-benchmarks", + "pop-runtime-testnet/runtime-benchmarks", + "sc-service/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ - "pop-runtime-devnet/try-runtime", - "pop-runtime-testnet/try-runtime", - "polkadot-cli/try-runtime", - "sp-runtime/try-runtime", + "polkadot-cli/try-runtime", + "pop-runtime-devnet/try-runtime", + "pop-runtime-mainnet/try-runtime", + "pop-runtime-testnet/try-runtime", + "sp-runtime/try-runtime", ] + +on-chain-release-build = [ "pop-runtime-mainnet/on-chain-release-build" ] diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index ca6c9542..b41ea8aa 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -1,5 +1,6 @@ use cumulus_primitives_core::ParaId; use pop_runtime_common::{AccountId, AuraId, Signature}; +use pop_runtime_mainnet::SudoAddress; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; @@ -7,12 +8,13 @@ use sp_core::{crypto::Ss58Codec, sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec` for the development parachain runtime. -pub type DevnetChainSpec = - sc_service::GenericChainSpec; +pub type DevnetChainSpec = sc_service::GenericChainSpec; /// Specialized `ChainSpec` for the testnet parachain runtime. -pub type TestnetChainSpec = - sc_service::GenericChainSpec; +pub type TestnetChainSpec = sc_service::GenericChainSpec; + +/// Specialized `ChainSpec` for the mainnet parachain runtime. +pub type MainnetChainSpec = sc_service::GenericChainSpec; /// The default XCM version to set in genesis config. const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; @@ -20,6 +22,7 @@ const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; pub(crate) enum Relay { Paseo, PaseoLocal, + Polkadot, } /// Helper function to generate a crypto pair from seed @@ -31,11 +34,12 @@ pub fn get_from_seed(seed: &str) -> ::Pu /// The extensions for the [`ChainSpec`]. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] -#[serde(deny_unknown_fields)] pub struct Extensions { /// The relay chain of the Parachain. + #[serde(alias = "relayChain", alias = "RelayChain")] pub relay_chain: String, /// The id of the Parachain. + #[serde(alias = "paraId", alias = "ParaId")] pub para_id: u32, } @@ -75,12 +79,17 @@ pub fn pop_devnet_session_keys(keys: AuraId) -> pop_runtime_devnet::SessionKeys pub fn pop_testnet_session_keys(keys: AuraId) -> pop_runtime_testnet::SessionKeys { pop_runtime_testnet::SessionKeys { aura: keys } } +/// Generate the session keys from individual elements. +/// +/// The input must be a tuple of individual keys (a single arg for now since we have just one key). +pub fn pop_mainnet_session_keys(keys: AuraId) -> pop_runtime_mainnet::SessionKeys { + pop_runtime_mainnet::SessionKeys { aura: keys } +} fn configure_for_relay( relay: Relay, properties: &mut sc_chain_spec::Properties, ) -> (Extensions, u32) { - properties.insert("ss58Format".into(), 42.into()); let para_id; match relay { @@ -89,10 +98,22 @@ fn configure_for_relay( properties.insert("tokenSymbol".into(), "PAS".into()); properties.insert("tokenDecimals".into(), 10.into()); - let relay_chain = - if let Relay::Paseo = relay { "paseo".into() } else { "paseo-local".into() }; + let relay_chain = if let Relay::Paseo = relay { + properties.insert("ss58Format".into(), 0.into()); + "paseo".into() + } else { + properties.insert("ss58Format".into(), 42.into()); + "paseo-local".into() + }; (Extensions { relay_chain, para_id }, para_id) }, + Relay::Polkadot => { + para_id = 3395; + properties.insert("ss58Format".into(), 0.into()); + properties.insert("tokenSymbol".into(), "DOT".into()); + properties.insert("tokenDecimals".into(), 10.into()); + (Extensions { relay_chain: "polkadot".into(), para_id }, para_id) + }, } } @@ -174,6 +195,83 @@ pub fn testnet_config(relay: Relay) -> TestnetChainSpec { .build() } +pub fn mainnet_config(relay: Relay) -> MainnetChainSpec { + let mut properties = sc_chain_spec::Properties::new(); + let (extensions, para_id) = configure_for_relay(relay, &mut properties); + + let collator_0_account_id: AccountId = + AccountId::from_ss58check("15B6eUkXgoLA3dWruCRYWeBGNC8SCwuqiMtMTM1Zh2auSg3w").unwrap(); + let collator_0_aura_id: AuraId = + AuraId::from_ss58check("15B6eUkXgoLA3dWruCRYWeBGNC8SCwuqiMtMTM1Zh2auSg3w").unwrap(); + + // Multisig account for sudo, generated from the following signatories: + // - 15VPagCVayS6XvT5RogPYop3BJTJzwqR2mCGR1kVn3w58ygg + // - 142zako1kfvrpQ7pJKYR8iGUD58i4wjb78FUsmJ9WcXmkM5z + // - 15k9niqckMg338cFBoz9vWFGwnCtwPBquKvqJEfHApijZkDz + // - 14G3CUFnZUBnHZUhahexSZ6AgemaW9zMHBnGccy3df7actf4 + // - Threshold 2 + let sudo_account_id: AccountId = SudoAddress::get(); + + #[allow(deprecated)] + MainnetChainSpec::builder( + pop_runtime_mainnet::WASM_BINARY.expect("WASM binary was not built, please build it!"), + extensions, + ) + .with_name("Pop Network") + .with_id("pop") + .with_chain_type(ChainType::Live) + .with_genesis_config_patch(mainnet_genesis( + // initial collators. + vec![ + // POP COLLATOR 0 + (collator_0_account_id, collator_0_aura_id), + ], + sudo_account_id, + para_id.into(), + )) + .with_protocol_id("pop") + .with_properties(properties) + .build() +} + +fn mainnet_genesis( + invulnerables: Vec<(AccountId, AuraId)>, + root: AccountId, + id: ParaId, +) -> serde_json::Value { + use pop_runtime_mainnet::EXISTENTIAL_DEPOSIT; + + serde_json::json!({ + "balances": { + "balances": [], + }, + "parachainInfo": { + "parachainId": id, + }, + "collatorSelection": { + "invulnerables": invulnerables.iter().cloned().map(|(acc, _)| acc).collect::>(), + "candidacyBond": EXISTENTIAL_DEPOSIT * 16, + "desiredCandidates": 0, + }, + "session": { + "keys": invulnerables + .into_iter() + .map(|(acc, aura)| { + ( + acc.clone(), // account id + acc, // validator id + pop_mainnet_session_keys(aura), // session keys + ) + }) + .collect::>(), + }, + "polkadotXcm": { + "safeXcmVersion": Some(SAFE_XCM_VERSION), + }, + "sudo": { "key": Some(root) } + }) +} + fn testnet_genesis( invulnerables: Vec<(AccountId, AuraId)>, root: AccountId, @@ -247,3 +345,43 @@ fn devnet_genesis( "sudo": { "key": Some(root) } }) } + +#[test] +fn sudo_key_valid() { + // Source: https://github.com/paritytech/extended-parachain-template/blob/d08cec37117731953119ecaed79522a0812b46f5/node/src/chain_spec.rs#L79 + fn get_multisig_sudo_key(mut authority_set: Vec, threshold: u16) -> AccountId { + assert!(threshold > 0, "Threshold for sudo multisig cannot be 0"); + assert!(!authority_set.is_empty(), "Sudo authority set cannot be empty"); + assert!( + authority_set.len() >= threshold.into(), + "Threshold must be less than or equal to authority set members" + ); + // Sorting is done to deterministically order the multisig set + // So that a single authority set (A, B, C) may generate only a single unique multisig key + // Otherwise, (B, A, C) or (C, A, B) could produce different keys and cause chaos + authority_set.sort(); + + // Define a multisig threshold for `threshold / authority_set.len()` members + pallet_multisig::Pallet::::multi_account_id( + &authority_set[..], + threshold, + ) + } + + assert_eq!( + get_multisig_sudo_key( + vec![ + AccountId::from_ss58check("15VPagCVayS6XvT5RogPYop3BJTJzwqR2mCGR1kVn3w58ygg") + .unwrap(), + AccountId::from_ss58check("142zako1kfvrpQ7pJKYR8iGUD58i4wjb78FUsmJ9WcXmkM5z") + .unwrap(), + AccountId::from_ss58check("15k9niqckMg338cFBoz9vWFGwnCtwPBquKvqJEfHApijZkDz") + .unwrap(), + AccountId::from_ss58check("14G3CUFnZUBnHZUhahexSZ6AgemaW9zMHBnGccy3df7actf4") + .unwrap(), + ], + 2 + ), + SudoAddress::get() + ) +} diff --git a/node/src/cli.rs b/node/src/cli.rs index 665b1129..19532033 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -38,11 +38,6 @@ pub enum Subcommand { #[command(subcommand)] Benchmark(frame_benchmarking_cli::BenchmarkCmd), - /// Try-runtime has migrated to a standalone - /// [CLI](). The subcommand exists as a stub and - /// deprecation notice. It will be removed entirely some time after Janurary 2024. - TryRuntime, - /// Key management CLI utilities #[command(subcommand)] Key(sc_cli::KeySubcommand), diff --git a/node/src/command.rs b/node/src/command.rs index a83253fc..9da4052d 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -1,5 +1,6 @@ use std::{net::SocketAddr, path::PathBuf}; +use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions; use cumulus_primitives_core::ParaId; use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; use log::info; @@ -9,19 +10,20 @@ use sc_cli::{ NetworkParams, Result, SharedParams, SubstrateCli, }; use sc_service::config::{BasePath, PrometheusConfig}; -use sp_runtime::traits::AccountIdConversion; +use sp_runtime::traits::HashingFor; use crate::{ chain_spec, chain_spec::Relay, cli::{Cli, RelayChainCli, Subcommand}, - service::{new_partial, DevnetRuntimeExecutor, TestnetRuntimeExecutor}, + service::new_partial, }; #[derive(Debug, PartialEq)] enum Runtime { Devnet, Testnet, + Mainnet, } trait RuntimeResolver { @@ -34,8 +36,14 @@ fn runtime(id: &str) -> Runtime { Runtime::Devnet } else if id.starts_with("test") || id.ends_with("testnet") { Runtime::Testnet + } else if id.eq("pop") || id.ends_with("mainnet") { + Runtime::Mainnet } else { - log::warn!("No specific runtime was recognized for ChainSpec's Id: '{}', so Runtime::Devnet will be used", id); + log::warn!( + "No specific runtime was recognized for ChainSpec's Id: '{}', so Runtime::Devnet will \ + be used", + id + ); Runtime::Devnet } } @@ -67,12 +75,15 @@ fn load_spec(id: &str) -> std::result::Result, String> { "dev" | "devnet" | "dev-paseo" => Box::new(chain_spec::development_config(Relay::PaseoLocal)), "test" | "testnet" | "pop-paseo" => Box::new(chain_spec::testnet_config(Relay::Paseo)), + "pop" | "mainnet" | "pop-polkadot" | "pop-network" => + Box::new(chain_spec::mainnet_config(Relay::Polkadot)), "" | "local" => Box::new(chain_spec::development_config(Relay::PaseoLocal)), path => { let path: PathBuf = path.into(); match path.runtime() { Runtime::Devnet => Box::new(chain_spec::DevnetChainSpec::from_json_file(path)?), Runtime::Testnet => Box::new(chain_spec::TestnetChainSpec::from_json_file(path)?), + Runtime::Mainnet => Box::new(chain_spec::MainnetChainSpec::from_json_file(path)?), } }, }) @@ -89,10 +100,9 @@ impl SubstrateCli for Cli { fn description() -> String { format!( - "Pop Collator\n\nThe command-line arguments provided first will be \ - passed to the parachain node, while the arguments provided after -- will be passed \ - to the relay chain node.\n\n\ - {} -- ", + "Pop Collator\n\nThe command-line arguments provided first will be passed to the \ + parachain node, while the arguments provided after -- will be passed to the relay \ + chain node.\n\n{} -- ", Self::executable_name() ) } @@ -125,10 +135,9 @@ impl SubstrateCli for RelayChainCli { fn description() -> String { format!( - "Pop Collator\n\nThe command-line arguments provided first will be \ - passed to the parachain node, while the arguments provided after -- will be passed \ - to the relay chain node.\n\n\ - {} -- ", + "Pop Collator\n\nThe command-line arguments provided first will be passed to the \ + parachain node, while the arguments provided after -- will be passed to the relay \ + chain node.\n\n{} -- ", Self::executable_name() ) } @@ -156,7 +165,7 @@ macro_rules! construct_async_run { match runner.config().chain_spec.runtime() { Runtime::Devnet => { runner.async_run(|$config| { - let $components = new_partial::( + let $components = new_partial::( &$config )?; let task_manager = $components.task_manager; @@ -165,7 +174,16 @@ macro_rules! construct_async_run { } Runtime::Testnet => { runner.async_run(|$config| { - let $components = new_partial::( + let $components = new_partial::( + &$config + )?; + let task_manager = $components.task_manager; + { $( $code )* }.map(|v| (v, task_manager)) + }) + } + Runtime::Mainnet => { + runner.async_run(|$config| { + let $components = new_partial::( &$config )?; let task_manager = $components.task_manager; @@ -180,15 +198,15 @@ macro_rules! construct_benchmark_partials { ($config:expr, |$partials:ident| $code:expr) => { match $config.chain_spec.runtime() { Runtime::Devnet => { - let $partials = - new_partial::(&$config)?; + let $partials = new_partial::(&$config)?; $code }, Runtime::Testnet => { - let $partials = new_partial::< - pop_runtime_testnet::RuntimeApi, - TestnetRuntimeExecutor, - >(&$config)?; + let $partials = new_partial::(&$config)?; + $code + }, + Runtime::Mainnet => { + let $partials = new_partial::(&$config)?; $code }, } @@ -251,9 +269,7 @@ pub fn run() -> Result<()> { Some(Subcommand::ExportGenesisHead(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { - construct_benchmark_partials!(config, |partials| { - cmd.run(partials.client) - }) + construct_benchmark_partials!(config, |partials| cmd.run(partials.client)) }) }, Some(Subcommand::ExportGenesisWasm(cmd)) => { @@ -269,23 +285,24 @@ pub fn run() -> Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| { + cmd.run_with_spec::, ReclaimHostFunctions>(Some( + config.chain_spec, + )) + }) } else { - Err("Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." + Err("Benchmarking wasn't enabled when building the node. You can enable \ + it with `--features runtime-benchmarks`." .into()) }, BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { construct_benchmark_partials!(config, |partials| cmd.run(partials.client)) }), #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => - return Err(sc_cli::Error::Input( - "Compile with --features=runtime-benchmarks \ - to enable storage benchmarks." - .into(), - ) - .into()), + BenchmarkCmd::Storage(_) => Err(sc_cli::Error::Input( + "Compile with --features=runtime-benchmarks to enable storage benchmarks." + .into(), + )), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { construct_benchmark_partials!(config, |partials| { @@ -302,7 +319,6 @@ pub fn run() -> Result<()> { _ => Err("Benchmarking sub-command unsupported".into()), } }, - Some(Subcommand::TryRuntime) => Err("The `try-runtime` subcommand has been migrated to a standalone CLI (https://github.com/paritytech/try-runtime-cli). It is no longer being maintained here and will be removed entirely some time after January 2024. Please remove this subcommand from your runtime and use the standalone CLI.".into()), Some(Subcommand::Key(cmd)) => cmd.run(&cli), None => { let runner = cli.create_runner(&cli.run.normalize())?; @@ -327,17 +343,11 @@ pub fn run() -> Result<()> { let id = ParaId::from(para_id); - let parachain_account = - AccountIdConversion::::into_account_truncating( - &id, - ); - let tokio_handle = config.tokio_handle.clone(); let polkadot_config = SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, tokio_handle) .map_err(|err| format!("Relay chain argument error: {}", err))?; - info!("Parachain Account: {parachain_account}"); info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); match config.chain_spec.runtime() { @@ -345,10 +355,7 @@ pub fn run() -> Result<()> { sp_core::crypto::set_default_ss58_version( pop_runtime_devnet::SS58Prefix::get().into(), ); - crate::service::start_parachain_node::< - pop_runtime_devnet::RuntimeApi, - DevnetRuntimeExecutor, - >( + crate::service::start_parachain_node::( config, polkadot_config, collator_options, @@ -363,10 +370,22 @@ pub fn run() -> Result<()> { sp_core::crypto::set_default_ss58_version( pop_runtime_testnet::SS58Prefix::get().into(), ); - crate::service::start_parachain_node::< - pop_runtime_testnet::RuntimeApi, - TestnetRuntimeExecutor, - >( + crate::service::start_parachain_node::( + config, + polkadot_config, + collator_options, + id, + hwbench, + ) + .await + .map(|r| r.0) + .map_err(Into::into) + }, + Runtime::Mainnet => { + sp_core::crypto::set_default_ss58_version( + pop_runtime_mainnet::SS58Prefix::get().into(), + ); + crate::service::start_parachain_node::( config, polkadot_config, collator_options, diff --git a/node/src/rpc.rs b/node/src/rpc.rs index 39d74019..6265dfd3 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -8,7 +8,6 @@ use std::sync::Arc; use pop_runtime_common::{AccountId, Balance, Block, Nonce}; - pub use sc_rpc::DenyUnsafe; use sc_transaction_pool_api::TransactionPool; use sp_api::ProvideRuntimeApi; diff --git a/node/src/service.rs b/node/src/service.rs index cd3a5a52..95eba022 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -4,11 +4,9 @@ use std::{sync::Arc, time::Duration}; use cumulus_client_cli::CollatorOptions; -// Local Runtime Types -use pop_runtime_common::{AccountId, AuraId, Balance, Block, Hash, Nonce}; - // Cumulus Imports use cumulus_client_collator::service::CollatorService; +use cumulus_client_consensus_aura::collators::lookahead::{self as aura, Params as AuraParams}; use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport; use cumulus_client_consensus_proposer::Proposer; use cumulus_client_service::{ @@ -20,15 +18,14 @@ use cumulus_primitives_core::{ ParaId, }; use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; - // Substrate Imports use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE; +// Local Runtime Types +use pop_runtime_common::{AccountId, AuraId, Balance, Block, Hash, Nonce}; +use prometheus_endpoint::Registry; use sc_client_api::Backend; use sc_consensus::ImportQueue; -use sc_executor::{ - HeapAllocStrategy, NativeElseWasmExecutor, NativeExecutionDispatch, WasmExecutor, - DEFAULT_HEAP_ALLOC_STRATEGY, -}; +use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY}; use sc_network::NetworkBlock; use sc_network_sync::SyncingService; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; @@ -38,72 +35,47 @@ use sp_api::ConstructRuntimeApi; use sp_core::Pair; use sp_keystore::KeystorePtr; use sp_runtime::{app_crypto::AppCrypto, traits::BlakeTwo256}; -use substrate_prometheus_endpoint::Registry; - -/// Devnet Native executor type. -pub struct DevnetRuntimeExecutor; - -impl NativeExecutionDispatch for DevnetRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - pop_runtime_devnet::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - pop_runtime_devnet::native_version() - } -} -/// Testnet Native executor type. -pub struct TestnetRuntimeExecutor; +#[cfg(not(feature = "runtime-benchmarks"))] +type HostFunctions = cumulus_client_service::ParachainHostFunctions; -impl NativeExecutionDispatch for TestnetRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; +#[cfg(feature = "runtime-benchmarks")] +type HostFunctions = ( + cumulus_client_service::ParachainHostFunctions, + frame_benchmarking::benchmarking::HostFunctions, +); - fn dispatch(method: &str, data: &[u8]) -> Option> { - pop_runtime_testnet::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - pop_runtime_testnet::native_version() - } -} +type ParachainExecutor = WasmExecutor; -type ParachainExecutor = NativeElseWasmExecutor; - -type ParachainClient = - TFullClient>; +type ParachainClient = TFullClient; type ParachainBackend = TFullBackend; -type ParachainBlockImport = - TParachainBlockImport>, ParachainBackend>; +type ParachainBlockImport = + TParachainBlockImport>, ParachainBackend>; /// Assembly of PartialComponents (enough to run chain ops subcommands) -type Service = PartialComponents< - ParachainClient, +type Service = PartialComponents< + ParachainClient, ParachainBackend, (), sc_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool>, - (ParachainBlockImport, Option, Option), + sc_transaction_pool::FullPool>, + (ParachainBlockImport, Option, Option), >; /// Starts a `ServiceBuilder` for a full service. /// /// Use this macro if you don't actually need the full service, but just the builder in order to /// be able to perform chain operations. -pub fn new_partial( +pub fn new_partial( config: &Configuration, -) -> Result, sc_service::Error> +) -> Result, sc_service::Error> where - RuntimeApi: - ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: RuntimeApiExt, + RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, + RuntimeApi::RuntimeApi: RuntimeApiExt, sc_client_api::StateBackendFor, Block>: sc_client_api::StateBackend, - Executor: NativeExecutionDispatch + 'static, { let telemetry = config .telemetry_endpoints @@ -120,7 +92,7 @@ where .default_heap_pages .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); - let wasm = WasmExecutor::builder() + let executor = ParachainExecutor::builder() .with_execution_method(config.wasm_method) .with_onchain_heap_alloc_strategy(heap_pages) .with_offchain_heap_alloc_strategy(heap_pages) @@ -128,13 +100,12 @@ where .with_runtime_cache_size(config.runtime_cache_size) .build(); - let executor = NativeElseWasmExecutor::::new_with_wasm_executor(wasm); - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( + sc_service::new_full_parts_record_import::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, + true, )?; let client = Arc::new(client); @@ -153,8 +124,7 @@ where client.clone(), ); - let block_import = - ParachainBlockImport::::new(client.clone(), backend.clone()); + let block_import = ParachainBlockImport::::new(client.clone(), backend.clone()); let import_queue = build_import_queue( client.clone(), @@ -162,7 +132,7 @@ where config, telemetry.as_ref().map(|telemetry| telemetry.handle()), &task_manager, - )?; + ); Ok(PartialComponents { backend, @@ -180,28 +150,26 @@ where /// /// This is the actual implementation that is abstract over the executor and the runtime api. #[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_node_impl( +async fn start_node_impl( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, para_id: ParaId, start_consensus: SC, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> +) -> sc_service::error::Result<(TaskManager, Arc>)> where - RuntimeApi: - ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: RuntimeApiExt, - Executor: NativeExecutionDispatch + 'static, + RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, + RuntimeApi::RuntimeApi: RuntimeApiExt, SC: FnOnce( - Arc>, + Arc>, Arc, - ParachainBlockImport, + ParachainBlockImport, Option<&Registry>, Option, &TaskManager, Arc, - Arc>>, + Arc>>, Arc>, KeystorePtr, Duration, @@ -213,9 +181,13 @@ where { let parachain_config = prepare_node_config(parachain_config); - let params = new_partial::(¶chain_config)?; + let params = new_partial::(¶chain_config)?; let (block_import, mut telemetry, telemetry_worker_handle) = params.other; - let net_config = sc_network::config::FullNetworkConfiguration::new(¶chain_config.network); + let net_config = sc_network::config::FullNetworkConfiguration::< + _, + _, + sc_network::NetworkWorker, + >::new(¶chain_config.network); let client = params.client.clone(); let backend = params.backend.clone(); @@ -264,7 +236,7 @@ where transaction_pool: Some(OffchainTransactionPoolFactory::new( transaction_pool.clone(), )), - network_provider: network.clone(), + network_provider: Arc::new(network.clone()), is_validator: parachain_config.role.is_authority(), enable_http_requests: false, custom_extensions: move |_| vec![], @@ -297,7 +269,7 @@ where config: parachain_config, keystore: params.keystore_container.keystore(), backend: backend.clone(), - network: network.clone(), + network, sync_service: sync_service.clone(), system_rpc_tx, tx_handler_controller, @@ -361,9 +333,9 @@ where prometheus_registry.as_ref(), telemetry.as_ref().map(|t| t.handle()), &task_manager, - relay_chain_interface.clone(), + relay_chain_interface, transaction_pool, - sync_service.clone(), + sync_service, params.keystore_container.keystore(), relay_chain_slot_duration, para_id, @@ -380,21 +352,18 @@ where /// Build the import queue for the parachain runtime. #[allow(clippy::type_complexity)] -pub(crate) fn build_import_queue( - client: Arc>, - block_import: ParachainBlockImport, +pub(crate) fn build_import_queue( + client: Arc>, + block_import: ParachainBlockImport, config: &Configuration, telemetry: Option, task_manager: &TaskManager, -) -> Result, sc_service::Error> +) -> sc_consensus::DefaultImportQueue where - RuntimeApi: - ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: RuntimeApiExt, + RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, + RuntimeApi::RuntimeApi: RuntimeApiExt, { - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - - Ok(cumulus_client_consensus_aura::equivocation_import_queue::fully_verifying_import_queue::< + cumulus_client_consensus_aura::equivocation_import_queue::fully_verifying_import_queue::< sp_consensus_aura::sr25519::AuthorityPair, _, _, @@ -407,25 +376,22 @@ where let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); Ok(timestamp) }, - slot_duration, &task_manager.spawn_essential_handle(), config.prometheus_registry(), telemetry, - )) + ) } #[allow(clippy::too_many_arguments)] -fn start_consensus( - client: Arc>, +fn start_consensus( + client: Arc>, backend: Arc, - block_import: ParachainBlockImport, + block_import: ParachainBlockImport, prometheus_registry: Option<&Registry>, telemetry: Option, task_manager: &TaskManager, relay_chain_interface: Arc, - transaction_pool: Arc< - sc_transaction_pool::FullPool>, - >, + transaction_pool: Arc>>, sync_oracle: Arc>, keystore: KeystorePtr, relay_chain_slot_duration: Duration, @@ -435,18 +401,9 @@ fn start_consensus( announce_block: Arc>) + Send + Sync>, ) -> Result<(), sc_service::Error> where - RuntimeApi: - ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: RuntimeApiExt, - Executor: NativeExecutionDispatch + 'static, + RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, + RuntimeApi::RuntimeApi: RuntimeApiExt, { - use cumulus_client_consensus_aura::collators::lookahead::{self as aura, Params as AuraParams}; - - // NOTE: because we use Aura here explicitly, we can use `CollatorSybilResistance::Resistant` - // when starting the network. - - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( task_manager.spawn_handle(), client.clone(), @@ -478,11 +435,10 @@ where collator_key, para_id, overseer_handle, - slot_duration, relay_chain_slot_duration, proposer, collator_service, - authoring_duration: Duration::from_millis(1500), + authoring_duration: Duration::from_millis(2000), reinitialize: false, }; @@ -496,32 +452,30 @@ where } /// Start a parachain node. -pub async fn start_parachain_node( +pub async fn start_parachain_node( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> +) -> sc_service::error::Result<(TaskManager, Arc>)> where - Executor: NativeExecutionDispatch + 'static, - RuntimeApi: - ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: RuntimeApiExt, + RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, + RuntimeApi::RuntimeApi: RuntimeApiExt, { - start_node_impl::( + start_node_impl::( parachain_config, polkadot_config, collator_options, para_id, - start_consensus::, + start_consensus::, hwbench, ) .await } // Trait alias refactored out from above to simplify repeated trait bounds -pub(crate) trait RuntimeApiExt: +pub(crate) trait RuntimeApiExt: sp_transaction_pool::runtime_api::TaggedTransactionQueue + sp_api::Metadata + sp_session::SessionKeys @@ -548,7 +502,6 @@ impl< + substrate_frame_rpc_system::AccountNonceApi + cumulus_primitives_aura::AuraUnincludedSegmentApi, RuntimeApi, - Executor, - > RuntimeApiExt for T + > RuntimeApiExt for T { } diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml index d2d444bf..55a00789 100644 --- a/pallets/api/Cargo.toml +++ b/pallets/api/Cargo.toml @@ -1,13 +1,13 @@ [package] -name = "pallet-api" authors.workspace = true description = "API pallet, enabling smart(er) contracts with the power of Polkadot" edition.workspace = true license.workspace = true +name = "pallet-api" version = "0.1.0" [package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +targets = [ "x86_64-unknown-linux-gnu" ] [dependencies] codec.workspace = true @@ -31,30 +31,31 @@ sp-core.workspace = true sp-io.workspace = true [features] -default = ["std"] +default = [ "std" ] runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pop-chain-extension/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] std = [ - "codec/std", - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "pallet-assets/std", - "pallet-balances/std", - "pop-chain-extension/std", - "scale-info/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "pallet-assets/std", + "pallet-balances/std", + "pop-chain-extension/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", ] try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "sp-runtime/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "sp-runtime/try-runtime", ] diff --git a/pallets/api/src/extension.rs b/pallets/api/src/extension.rs index 8469ae40..138cdee6 100644 --- a/pallets/api/src/extension.rs +++ b/pallets/api/src/extension.rs @@ -1,4 +1,5 @@ use core::{fmt::Debug, marker::PhantomData}; + use frame_support::traits::Get; pub use pop_chain_extension::{ Config, ContractWeightsOf, DecodingFailed, DispatchCall, ReadState, Readable, @@ -99,6 +100,7 @@ impl + Debug> Converter type Source = Source; /// The target type. type Target = Target; + /// The log target. const LOG_TARGET: &'static str = "pop-api::extension::converters::versioned-result"; @@ -138,11 +140,12 @@ fn version(env: &impl Environment) -> u8 { #[cfg(test)] mod tests { - use super::*; - use crate::extension::Prepender; use frame_support::pallet_prelude::Weight; use pop_chain_extension::Ext; + use super::*; + use crate::extension::Prepender; + #[test] fn prepender_works() { let env = MockEnvironment { func_id: 1, ext_id: u16::from_le_bytes([2, 3]) }; diff --git a/pallets/api/src/fungibles/benchmarking.rs b/pallets/api/src/fungibles/benchmarking.rs index d3d65b97..f346df1a 100644 --- a/pallets/api/src/fungibles/benchmarking.rs +++ b/pallets/api/src/fungibles/benchmarking.rs @@ -1,6 +1,5 @@ //! Benchmarking setup for pallet-api::fungibles -use super::{AccountIdOf, AssetIdOf, AssetsInstanceOf, AssetsOf, BalanceOf, Call, Config, Pallet}; use frame_benchmarking::{account, v2::*}; use frame_support::{ assert_ok, @@ -15,6 +14,8 @@ use frame_support::{ use frame_system::RawOrigin; use sp_runtime::traits::Zero; +use super::{AccountIdOf, AssetIdOf, AssetsInstanceOf, AssetsOf, BalanceOf, Call, Config, Pallet}; + const SEED: u32 = 1; // See if `generic_event` has been emitted. diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index dac002e9..76f3b28a 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -27,8 +27,8 @@ type BalanceOf = > as Inspect< #[frame_support::pallet] pub mod pallet { - use super::*; use core::cmp::Ordering::*; + use frame_support::{ dispatch::{DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo}, pallet_prelude::*, @@ -41,6 +41,8 @@ pub mod pallet { }; use sp_std::vec::Vec; + use super::*; + /// State reads for the fungibles API with required input. #[derive(Encode, Decode, Debug, MaxEncodedLen)] #[repr(u8)] diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index d6d4ef2f..d850474b 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -1,4 +1,3 @@ -use crate::{fungibles::Read::*, mock::*, Read}; use codec::Encode; use frame_support::{ assert_ok, @@ -8,6 +7,8 @@ use frame_support::{ }, }; +use crate::{fungibles::Read::*, mock::*, Read}; + const ASSET: u32 = 42; type Event = crate::fungibles::Event; diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 77e17394..fe2b2c9a 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -32,73 +32,73 @@ parameter_types! { #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { + type AccountData = pallet_balances::AccountData; + type AccountId = AccountId; type BaseCallFilter = Everything; - type BlockWeights = (); + type Block = Block; + type BlockHashCount = BlockHashCount; type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Nonce = u64; + type BlockWeights = (); + type DbWeight = (); type Hash = H256; type Hashing = BlakeTwo256; - type AccountId = AccountId; type Lookup = IdentityLookup; - type Block = Block; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MaxConsumers = ConstU32<16>; + type Nonce = u64; type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; + type OnNewAccount = (); type OnSetCode = (); - type MaxConsumers = ConstU32<16>; + type PalletInfo = PalletInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SS58Prefix = SS58Prefix; + type SystemWeightInfo = (); + type Version = (); } impl pallet_balances::Config for Test { + type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ConstU128<1>; - type AccountStore = System; type FreezeIdentifier = (); type MaxFreezes = ConstU32<0>; - type WeightInfo = (); type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeEvent = RuntimeEvent; type RuntimeFreezeReason = RuntimeFreezeReason; + type RuntimeHoldReason = RuntimeHoldReason; + type WeightInfo = (); } type AssetsInstance = pallet_assets::Instance1; impl pallet_assets::Config for Test { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type RemoveItemsLimit = ConstU32<5>; + type ApprovalDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; + type AssetDeposit = ConstU128<1>; type AssetId = AssetId; type AssetIdParameter = u32; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = EnsureRoot; - type AssetDeposit = ConstU128<1>; - type AssetAccountDeposit = ConstU128<10>; + type Freezer = (); type MetadataDepositBase = ConstU128<1>; type MetadataDepositPerByte = ConstU128<1>; - type ApprovalDeposit = ConstU128<1>; + type RemoveItemsLimit = ConstU32<5>; + type RuntimeEvent = RuntimeEvent; type StringLimit = ConstU32<50>; - type Freezer = (); - type Extra = (); - type CallbackHandle = (); type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } impl crate::fungibles::Config for Test { - type RuntimeEvent = RuntimeEvent; type AssetsInstance = AssetsInstance; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 05dd9715..8296569a 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -1,27 +1,26 @@ [package] -name = "pop-api" description = "Enabling smart(er) contracts with the power of Polkadot" +edition = "2021" license = "GPL-3.0-only" +name = "pop-api" version = "0.0.0" -edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } +pop-primitives = { path = "../primitives", default-features = false } sp-io = { version = "31.0.0", default-features = false, features = [ - "disable_panic_handler", - "disable_oom", - "disable_allocator", + "disable_allocator", + "disable_oom", + "disable_panic_handler", ] } -pop-primitives = { path = "../primitives", default-features = false } - [lib] +crate-type = [ "rlib" ] name = "pop_api" path = "src/lib.rs" -crate-type = ["rlib"] [features] -default = ["std"] -std = ["ink/std", "pop-primitives/std", "sp-io/std"] -assets = [] -fungibles = ["assets"] +assets = [ ] +default = [ "std" ] +fungibles = [ "assets" ] +std = [ "ink/std", "pop-primitives/std", "sp-io/std" ] diff --git a/pop-api/examples/balance-transfer/Cargo.toml b/pop-api/examples/balance-transfer/Cargo.toml index 29cd0ea5..2a12e532 100755 --- a/pop-api/examples/balance-transfer/Cargo.toml +++ b/pop-api/examples/balance-transfer/Cargo.toml @@ -1,14 +1,14 @@ [package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" name = "balance_transfer" version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } [dev-dependencies] ink_e2e = "5.0.0" @@ -17,12 +17,12 @@ ink_e2e = "5.0.0" path = "lib.rs" [features] -default = ["std"] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "pop-api/std", - "scale/std", - "scale-info/std", + "ink/std", + "pop-api/std", + "scale-info/std", + "scale/std", ] -ink-as-dependency = [] -e2e-tests = [] diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 19d9ce12..0b79e1b2 100755 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -1,21 +1,21 @@ [package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" name = "fungibles" version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false, features = ["fungibles"] } +pop-api = { path = "../../../pop-api", default-features = false, features = [ "fungibles" ] } [lib] path = "lib.rs" [features] -default = ["std"] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "pop-api/std", + "ink/std", + "pop-api/std", ] -ink-as-dependency = [] -e2e-tests = [] diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index a6328c37..1ad36de0 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -182,4 +182,4 @@ mod fungibles { PopApiFungiblesExample::new(); } } -} +} \ No newline at end of file diff --git a/pop-api/examples/nfts/Cargo.toml b/pop-api/examples/nfts/Cargo.toml index e931cf9f..ef50b7ec 100755 --- a/pop-api/examples/nfts/Cargo.toml +++ b/pop-api/examples/nfts/Cargo.toml @@ -1,25 +1,25 @@ [package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" name = "nfts" version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } [lib] path = "lib.rs" [features] -default = ["std"] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "pop-api/std", - "scale/std", - "scale-info/std", + "ink/std", + "pop-api/std", + "scale-info/std", + "scale/std", ] -ink-as-dependency = [] -e2e-tests = [] diff --git a/pop-api/examples/place-spot-order/Cargo.toml b/pop-api/examples/place-spot-order/Cargo.toml index 2c67313d..f523bea7 100755 --- a/pop-api/examples/place-spot-order/Cargo.toml +++ b/pop-api/examples/place-spot-order/Cargo.toml @@ -1,25 +1,25 @@ [package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" name = "spot_order" version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } [lib] path = "lib.rs" [features] -default = ["std"] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "pop-api/std", - "scale/std", - "scale-info/std", + "ink/std", + "pop-api/std", + "scale-info/std", + "scale/std", ] -ink-as-dependency = [] -e2e-tests = [] diff --git a/pop-api/examples/read-runtime-state/Cargo.toml b/pop-api/examples/read-runtime-state/Cargo.toml index 379152dd..f5464730 100755 --- a/pop-api/examples/read-runtime-state/Cargo.toml +++ b/pop-api/examples/read-runtime-state/Cargo.toml @@ -1,25 +1,25 @@ [package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" name = "read_relay_blocknumber" version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } [lib] path = "lib.rs" [features] -default = ["std"] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "pop-api/std", - "scale/std", - "scale-info/std", + "ink/std", + "pop-api/std", + "scale-info/std", + "scale/std", ] -ink-as-dependency = [] -e2e-tests = [] diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml index 499ad991..5e0e4f9c 100644 --- a/pop-api/integration-tests/Cargo.toml +++ b/pop-api/integration-tests/Cargo.toml @@ -1,40 +1,41 @@ [package] +build = "build.rs" +edition = "2021" name = "integration-tests" version = "0.1.0" -edition = "2021" -build = "build.rs" [build-dependencies] contract-build = "4.1.1" [dev-dependencies] env_logger = "0.11.2" -scale = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ - "derive", -] } -frame-support = { version = "29.0.0", default-features = false } -frame-system = { version = "29.0.0", default-features = false } +frame-support = { version = "36.0.0", default-features = false } +frame-support-procedural = { version = "=30.0.1", default-features = false } +frame-system = { version = "36.1.0", default-features = false } log = "0.4.22" -pallet-balances = { version = "29.0.2", default-features = false } -pallet-assets = { version = "30.0.0", default-features = false } -pallet-contracts = { version = "28.0.0", default-features = false } +pallet-assets = { version = "37.0.0", default-features = false } +pallet-balances = { version = "37.0.0", default-features = false } +pallet-contracts = { version = "35.0.0", default-features = false } pop-primitives = { path = "../../primitives", default-features = false } pop-runtime-devnet = { path = "../../runtime/devnet", default-features = false } -sp-io = { version = "31.0.0", default-features = false } -sp-runtime = { version = "32.0.0", default-features = false } +scale = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ + "derive", +] } +sp-io = { version = "37.0.0", default-features = false } +sp-runtime = { version = "=38.0.0", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-support/std", - "frame-system/std", - "pallet-balances/std", - "pallet-assets/std", - "pallet-contracts/std", - "pop-primitives/std", - "pop-runtime-devnet/std", - "scale/std", - "sp-io/std", - "sp-runtime/std", -] \ No newline at end of file + "frame-support/std", + "frame-system/std", + "pallet-assets/std", + "pallet-balances/std", + "pallet-contracts/std", + "pop-primitives/std", + "pop-runtime-devnet/std", + "scale/std", + "sp-io/std", + "sp-runtime/std", +] diff --git a/pop-api/integration-tests/contracts/.gitignore b/pop-api/integration-tests/contracts/.gitignore deleted file mode 100755 index d60800c8..00000000 --- a/pop-api/integration-tests/contracts/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Ignore build artifacts from the local tests sub-crate. -**/target/ - -# Ignore backup files creates by cargo fmt. -**/*.rs.bk - -# Remove Cargo.lock when creating an executable, leave it for libraries -# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock -**/Cargo.lock diff --git a/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml b/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml index 2c202715..c3d2c2fc 100755 --- a/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml +++ b/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml @@ -1,21 +1,21 @@ [package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" name = "create_token_in_constructor" version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../..", default-features = false, features = ["fungibles"] } +pop-api = { path = "../../..", default-features = false, features = [ "fungibles" ] } [lib] path = "lib.rs" [features] -default = ["std"] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "pop-api/std", + "ink/std", + "pop-api/std", ] -ink-as-dependency = [] -e2e-tests = [] diff --git a/pop-api/integration-tests/contracts/fungibles/Cargo.toml b/pop-api/integration-tests/contracts/fungibles/Cargo.toml index 7c322004..0d0e80d5 100755 --- a/pop-api/integration-tests/contracts/fungibles/Cargo.toml +++ b/pop-api/integration-tests/contracts/fungibles/Cargo.toml @@ -1,21 +1,21 @@ [package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" name = "fungibles" version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" [dependencies] ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../../pop-api", default-features = false, features = ["fungibles"] } +pop-api = { path = "../../../../pop-api", default-features = false, features = [ "fungibles" ] } [lib] path = "lib.rs" [features] -default = ["std"] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "pop-api/std", + "ink/std", + "pop-api/std", ] -ink-as-dependency = [] -e2e-tests = [] diff --git a/pop-api/integration-tests/src/fungibles/mod.rs b/pop-api/integration-tests/src/fungibles/mod.rs index d1c0e2ae..0d895aa3 100644 --- a/pop-api/integration-tests/src/fungibles/mod.rs +++ b/pop-api/integration-tests/src/fungibles/mod.rs @@ -569,7 +569,7 @@ fn burn_works() { start_destroy_asset(addr.clone(), asset); assert_eq!( burn(addr.clone(), asset, BOB, amount), - Err(Module { index: 52, error: [16, 0] }) + Err(Module { index: 52, error: [17, 0] }) ); }); } diff --git a/pop-api/integration-tests/src/lib.rs b/pop-api/integration-tests/src/lib.rs index 1dab5b85..6499df59 100644 --- a/pop-api/integration-tests/src/lib.rs +++ b/pop-api/integration-tests/src/lib.rs @@ -99,4 +99,4 @@ fn instantiate(contract: &str, init_value: u128, salt: Vec) -> AccountId32 { .unwrap(); assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); result.account_id -} +} \ No newline at end of file diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index e7d55ffe..0cb46198 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -1,17 +1,14 @@ [package] -name = "pop-primitives" description = "Primitives crate for Pop" +edition = "2021" license = "GPL-3.0-only" +name = "pop-primitives" version = "0.0.0" -edition = "2021" [dependencies] codec.workspace = true scale-info.workspace = true [features] -default = ["std"] -std = [ - "codec/std", - "scale-info/std", -] \ No newline at end of file +default = [ "std" ] +std = [ "codec/std", "scale-info/std" ] diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index e15b142c..ef6ae3a9 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -9,9 +9,10 @@ pub use v0::*; pub type AssetId = u32; pub mod v0 { - use super::*; pub use error::*; + use super::*; + mod error { use super::*; diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 0cd9aecb..395abd24 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -4,16 +4,16 @@ description = "Pop Runtime Common" edition.workspace = true license.workspace = true name = "pop-runtime-common" +publish = false repository.workspace = true version = "0.0.0" -publish = false [package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +targets = [ "x86_64-unknown-linux-gnu" ] [dependencies] -codec = { workspace = true, default-features = false, features = ["derive"] } -scale-info = { workspace = true, default-features = false, features = ["derive"] } +codec = { workspace = true, default-features = false, features = [ "derive" ] } +scale-info = { workspace = true, default-features = false, features = [ "derive" ] } # Substrate frame-support = { workspace = true, default-features = false } @@ -24,9 +24,9 @@ parachains-common = { workspace = true, default-features = false } polkadot-primitives = { workspace = true, default-features = false } [features] -default = ["std"] -std = ["frame-support/std", "sp-runtime/std"] +default = [ "std" ] runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] \ No newline at end of file + "frame-support/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +std = [ "frame-support/std", "sp-runtime/std" ] diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 2160ec81..f20ea377 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -1,12 +1,10 @@ #![cfg_attr(not(feature = "std"), no_std)] -use sp_runtime::Perbill; - use frame_support::weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}; - // Cumulus types re-export // These types are shared between the devnet and testnet runtimes pub use parachains_common::{AccountId, AuraId, Balance, Block, BlockNumber, Hash, Signature}; pub use polkadot_primitives::MAX_POV_SIZE; +use sp_runtime::Perbill; /// Nonce for an account pub type Nonce = u32; @@ -47,8 +45,8 @@ pub const MAXIMUM_BLOCK_WEIGHT: Weight = // Unit = the base number of indivisible units for balances pub const UNIT: Balance = 10_000_000_000; // 10 decimals -pub const MILLIUNIT: Balance = UNIT / 1_000; -pub const MICROUNIT: Balance = UNIT / 1_000_000; +pub const MILLIUNIT: Balance = UNIT / 1_000; // 10_000_000 +pub const MICROUNIT: Balance = UNIT / 1_000_000; // 10_000 // Deposits pub const fn deposit(items: u32, bytes: u32) -> Balance { @@ -69,11 +67,12 @@ pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; /// Proxy commons for Pop runtimes pub mod proxy { - use super::{deposit, Balance}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::parameter_types; use sp_runtime::RuntimeDebug; + use super::{deposit, Balance}; + parameter_types! { // One storage item; key size 32, value size 8; . pub const ProxyDepositBase: Balance = deposit(1, 40); diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index 3d2f20d0..b0eec2c2 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "pop-runtime-devnet" -version = "0.1.0" authors.workspace = true description.workspace = true -license = "Unlicense" +edition.workspace = true homepage.workspace = true +license = "Unlicense" +name = "pop-runtime-devnet" repository.workspace = true -edition.workspace = true +version = "0.1.0" [package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +targets = [ "x86_64-unknown-linux-gnu" ] [build-dependencies] substrate-wasm-builder.workspace = true @@ -22,22 +22,23 @@ scale-info.workspace = true smallvec.workspace = true # Local +pallet-api.workspace = true pop-chain-extension.workspace = true pop-primitives.workspace = true pop-runtime-common.workspace = true -pallet-api.workspace = true # Substrate frame-benchmarking.workspace = true frame-executive.workspace = true +frame-metadata-hash-extension.workspace = true frame-support.workspace = true frame-system.workspace = true frame-system-benchmarking.workspace = true frame-system-rpc-runtime-api.workspace = true frame-try-runtime.workspace = true +pallet-assets.workspace = true pallet-aura.workspace = true pallet-authorship.workspace = true -pallet-assets.workspace = true pallet-balances.workspace = true pallet-contracts.workspace = true pallet-message-queue.workspace = true @@ -45,22 +46,22 @@ pallet-multisig.workspace = true pallet-nft-fractionalization.workspace = true pallet-nfts.workspace = true pallet-nfts-runtime-api.workspace = true +pallet-preimage.workspace = true +pallet-proxy.workspace = true pallet-scheduler.workspace = true pallet-session.workspace = true pallet-sudo.workspace = true -pallet-preimage.workspace = true -pallet-proxy.workspace = true pallet-timestamp.workspace = true pallet-transaction-payment.workspace = true pallet-transaction-payment-rpc-runtime-api.workspace = true pallet-utility.workspace = true sp-api.workspace = true -sp-io.workspace = true sp-block-builder.workspace = true sp-consensus-aura.workspace = true sp-core.workspace = true sp-genesis-builder.workspace = true sp-inherents.workspace = true +sp-io.workspace = true sp-offchain.workspace = true sp-runtime.workspace = true sp-session.workspace = true @@ -84,146 +85,166 @@ cumulus-pallet-xcm.workspace = true cumulus-pallet-xcmp-queue.workspace = true cumulus-primitives-aura.workspace = true cumulus-primitives-core.workspace = true +cumulus-primitives-storage-weight-reclaim.workspace = true cumulus-primitives-utility.workspace = true pallet-collator-selection.workspace = true -parachains-common.workspace = true parachain-info.workspace = true +parachains-common.workspace = true [dev-dependencies] +enumflags2 = "0.7.9" env_logger = "0.11.2" hex = "0.4.3" [features] -default = ["std"] +default = [ "std" ] std = [ - "codec/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-session-benchmarking/std", - "cumulus-pallet-xcm/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-primitives-aura/std", - "cumulus-primitives-core/std", - "cumulus-primitives-utility/std", - "frame-benchmarking/std", - "frame-executive/std", - "frame-support/std", - "frame-system-benchmarking/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "frame-try-runtime/std", - "log/std", - "pallet-aura/std", - "pallet-authorship/std", - "pallet-assets/std", - "pallet-balances/std", - "pallet-collator-selection/std", - "pallet-contracts/std", - "pallet-api/std", - "pallet-message-queue/std", - "pallet-multisig/std", - "pallet-nft-fractionalization/std", - "pallet-nfts/std", - "pallet-nfts-runtime-api/std", - "pallet-scheduler/std", - "pallet-session/std", - "pallet-sudo/std", - "pallet-preimage/std", - "pallet-proxy/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-utility/std", - "pallet-xcm/std", - "parachain-info/std", - "parachains-common/std", - "polkadot-parachain-primitives/std", - "polkadot-runtime-common/std", - "pop-chain-extension/std", - "pop-primitives/std", - "scale-info/std", - "sp-api/std", - "sp-io/std", - "sp-block-builder/std", - "sp-consensus-aura/std", - "sp-core/std", - "sp-genesis-builder/std", - "sp-inherents/std", - "sp-offchain/std", - "sp-runtime/std", - "sp-session/std", - "sp-std/std", - "sp-transaction-pool/std", - "sp-version/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", + "codec/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-session-benchmarking/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-aura/std", + "cumulus-primitives-core/std", + "cumulus-primitives-storage-weight-reclaim/std", + "cumulus-primitives-utility/std", + "frame-benchmarking/std", + "frame-executive/std", + "frame-metadata-hash-extension/std", + "frame-support/std", + "frame-system-benchmarking/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "frame-try-runtime/std", + "log/std", + "pallet-api/std", + "pallet-assets/std", + "pallet-aura/std", + "pallet-authorship/std", + "pallet-balances/std", + "pallet-collator-selection/std", + "pallet-contracts/std", + "pallet-message-queue/std", + "pallet-multisig/std", + "pallet-nft-fractionalization/std", + "pallet-nfts-runtime-api/std", + "pallet-nfts/std", + "pallet-preimage/std", + "pallet-proxy/std", + "pallet-scheduler/std", + "pallet-session/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-utility/std", + "pallet-xcm/std", + "parachain-info/std", + "parachains-common/std", + "polkadot-parachain-primitives/std", + "polkadot-runtime-common/std", + "pop-chain-extension/std", + "pop-primitives/std", + "pop-runtime-common/std", + "scale-info/std", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-genesis-builder/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm/std", ] runtime-benchmarks = [ - "cumulus-pallet-parachain-system/runtime-benchmarks", - "cumulus-pallet-session-benchmarking/runtime-benchmarks", - "cumulus-pallet-xcmp-queue/runtime-benchmarks", - "cumulus-primitives-core/runtime-benchmarks", - "cumulus-primitives-utility/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", - "pallet-api/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-collator-selection/runtime-benchmarks", - "pallet-contracts/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "pallet-multisig/runtime-benchmarks", - "pallet-nft-fractionalization/runtime-benchmarks", - "pallet-nfts/runtime-benchmarks", - "pallet-scheduler/runtime-benchmarks", - "pallet-sudo/runtime-benchmarks", - "pallet-preimage/runtime-benchmarks", - "pallet-proxy/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks", - "pallet-utility/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "parachains-common/runtime-benchmarks", - "polkadot-parachain-primitives/runtime-benchmarks", - "polkadot-runtime-common/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", + "cumulus-pallet-parachain-system/runtime-benchmarks", + "cumulus-pallet-session-benchmarking/runtime-benchmarks", + "cumulus-pallet-xcmp-queue/runtime-benchmarks", + "cumulus-primitives-core/runtime-benchmarks", + "cumulus-primitives-utility/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-api/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-collator-selection/runtime-benchmarks", + "pallet-contracts/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-nft-fractionalization/runtime-benchmarks", + "pallet-nfts/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", + "pallet-sudo/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "parachains-common/runtime-benchmarks", + "polkadot-parachain-primitives/runtime-benchmarks", + "polkadot-runtime-common/runtime-benchmarks", + "pop-chain-extension/runtime-benchmarks", + "pop-runtime-common/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", ] try-runtime = [ - "cumulus-pallet-aura-ext/try-runtime", - "cumulus-pallet-parachain-system/try-runtime", - "cumulus-pallet-xcm/try-runtime", - "cumulus-pallet-xcmp-queue/try-runtime", - "frame-executive/try-runtime", - "frame-support/try-runtime", - "frame-system/try-runtime", - "frame-try-runtime/try-runtime", - "pallet-api/try-runtime", - "pallet-aura/try-runtime", - "pallet-authorship/try-runtime", - "pallet-assets/try-runtime", - "pallet-balances/try-runtime", - "pallet-collator-selection/try-runtime", - "pallet-contracts/try-runtime", - "pallet-message-queue/try-runtime", - "pallet-multisig/try-runtime", - "pallet-nft-fractionalization/try-runtime", - "pallet-nfts/try-runtime", - "pallet-scheduler/try-runtime", - "pallet-session/try-runtime", - "pallet-sudo/try-runtime", - "pallet-preimage/try-runtime", - "pallet-proxy/try-runtime", - "pallet-timestamp/try-runtime", - "pallet-transaction-payment/try-runtime", - "pallet-utility/try-runtime", - "pallet-xcm/try-runtime", - "parachain-info/try-runtime", - "polkadot-runtime-common/try-runtime", - "sp-runtime/try-runtime", + "cumulus-pallet-aura-ext/try-runtime", + "cumulus-pallet-parachain-system/try-runtime", + "cumulus-pallet-xcm/try-runtime", + "cumulus-pallet-xcmp-queue/try-runtime", + "frame-executive/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", + "pallet-api/try-runtime", + "pallet-assets/try-runtime", + "pallet-aura/try-runtime", + "pallet-authorship/try-runtime", + "pallet-balances/try-runtime", + "pallet-collator-selection/try-runtime", + "pallet-contracts/try-runtime", + "pallet-message-queue/try-runtime", + "pallet-multisig/try-runtime", + "pallet-nft-fractionalization/try-runtime", + "pallet-nfts/try-runtime", + "pallet-preimage/try-runtime", + "pallet-proxy/try-runtime", + "pallet-scheduler/try-runtime", + "pallet-session/try-runtime", + "pallet-sudo/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-transaction-payment/try-runtime", + "pallet-utility/try-runtime", + "pallet-xcm/try-runtime", + "parachain-info/try-runtime", + "polkadot-runtime-common/try-runtime", + "sp-runtime/try-runtime", ] + +# Enable the metadata hash generation. +# +# This is hidden behind a feature because it increases the compile time. +# The wasm binary needs to be compiled twice, once to fetch the metadata, +# generate the metadata hash and then a second time with the +# `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash` +# extension. +metadata-hash = [ "substrate-wasm-builder/metadata-hash" ] + +# A convenience feature for enabling things when doing a build +# for an on-chain release. +on-chain-release-build = [ "metadata-hash" ] diff --git a/runtime/devnet/build.rs b/runtime/devnet/build.rs index 02d6973f..6293cebb 100644 --- a/runtime/devnet/build.rs +++ b/runtime/devnet/build.rs @@ -1,12 +1,15 @@ -#[cfg(feature = "std")] +#[cfg(all(feature = "std", feature = "metadata-hash"))] fn main() { - substrate_wasm_builder::WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("PAS", 10) .build() } +#[cfg(all(feature = "std", not(feature = "metadata-hash")))] +fn main() { + substrate_wasm_builder::WasmBuilder::build_using_defaults() +} + /// The wasm builder is deactivated when compiling /// this crate for wasm to speed up the compilation. #[cfg(not(feature = "std"))] diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index ac956eb2..16ea92fb 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -1,8 +1,6 @@ -use crate::{ - config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall, RuntimeEvent, -}; -use codec::Decode; use core::marker::PhantomData; + +use codec::Decode; use cumulus_primitives_core::Weight; use frame_support::traits::Contains; pub(crate) use pallet_api::Extension; @@ -12,6 +10,10 @@ use sp_runtime::DispatchError; use sp_std::vec::Vec; use versioning::*; +use crate::{ + config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall, RuntimeEvent, +}; + mod versioning; type DecodingFailedError = DecodingFailed; @@ -68,8 +70,8 @@ impl RuntimeResult { } impl fungibles::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type AssetsInstance = TrustBackedAssetsInstance; + type RuntimeEvent = RuntimeEvent; type WeightInfo = fungibles::weights::SubstrateWeight; } diff --git a/runtime/devnet/src/config/api/versioning.rs b/runtime/devnet/src/config/api/versioning.rs index 50041340..317496df 100644 --- a/runtime/devnet/src/config/api/versioning.rs +++ b/runtime/devnet/src/config/api/versioning.rs @@ -1,6 +1,7 @@ -use super::*; use sp_runtime::ModuleError; +use super::*; + type Version = u8; /// Versioned runtime calls. @@ -156,11 +157,12 @@ impl From for V0Error { #[cfg(test)] mod tests { - use super::*; use pop_primitives::{ArithmeticError::*, Error, TokenError::*, TransactionalError::*}; use sp_runtime::ModuleError; use DispatchError::*; + use super::*; + // Compare all the different `DispatchError` variants with the expected `Error`. #[test] fn dispatch_error_to_error() { diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 78aed8b5..91322ecf 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -38,36 +38,36 @@ parameter_types! { } impl pallet_nfts::Config for Runtime { - type RuntimeEvent = RuntimeEvent; // TODO: source from primitives - type CollectionId = CollectionId; + type ApprovalsLimit = ConstU32<20>; + type AttributeDepositBase = NftsAttributeDepositBase; + type CollectionDeposit = NftsCollectionDeposit; // TODO: source from primitives - type ItemId = ItemId; - type Currency = Balances; + type CollectionId = CollectionId; type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type DepositPerByte = NftsDepositPerByte; + type Features = NftsPalletFeatures; type ForceOrigin = AssetsForceOrigin; - type Locker = (); - type CollectionDeposit = NftsCollectionDeposit; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); + type ItemAttributesApprovalsLimit = ConstU32<30>; type ItemDeposit = NftsItemDeposit; - type MetadataDepositBase = NftsMetadataDepositBase; - type AttributeDepositBase = NftsAttributeDepositBase; - type DepositPerByte = NftsDepositPerByte; - type StringLimit = ConstU32<256>; // TODO: source from primitives - type KeyLimit = ConstU32<64>; - type ValueLimit = ConstU32<256>; + type ItemId = ItemId; // TODO: source from primitives - type ApprovalsLimit = ConstU32<20>; - type ItemAttributesApprovalsLimit = ConstU32<30>; - type MaxTips = ConstU32<10>; - type MaxDeadlineDuration = NftsMaxDeadlineDuration; + type KeyLimit = ConstU32<64>; + type Locker = (); type MaxAttributesPerCall = ConstU32<10>; - type Features = NftsPalletFeatures; - type OffchainSignature = Signature; + type MaxDeadlineDuration = NftsMaxDeadlineDuration; + type MaxTips = ConstU32<10>; + type MetadataDepositBase = NftsMetadataDepositBase; type OffchainPublic = ::Signer; + type OffchainSignature = Signature; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<256>; + type ValueLimit = ConstU32<256>; type WeightInfo = pallet_nfts::weights::SubstrateWeight; - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); } parameter_types! { @@ -77,46 +77,46 @@ parameter_types! { } impl pallet_nft_fractionalization::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Deposit = AssetDeposit; + type AssetBalance = >::Balance; + type AssetId = >::AssetId; + type Assets = Assets; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type Currency = Balances; - type NewAssetSymbol = NewAssetSymbol; + type Deposit = AssetDeposit; type NewAssetName = NewAssetName; - type StringLimit = AssetsStringLimit; + type NewAssetSymbol = NewAssetSymbol; type NftCollectionId = ::CollectionId; type NftId = ::ItemId; - type AssetBalance = >::Balance; - type AssetId = >::AssetId; - type Assets = Assets; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; - type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight; + type RuntimeEvent = RuntimeEvent; type RuntimeHoldReason = RuntimeHoldReason; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type StringLimit = AssetsStringLimit; + type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight; } pub type TrustBackedAssetsInstance = pallet_assets::Instance1; -pub(crate) type AssetsCall = pallet_assets::Call; +pub type TrustBackedAssetsCall = pallet_assets::Call; impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; + type ApprovalDeposit = ApprovalDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = AssetIdForTrustBackedAssets; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = AssetsForceOrigin; - type AssetDeposit = AssetDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type RemoveItemsLimit = ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); type WeightInfo = pallet_assets::weights::SubstrateWeight; - type CallbackHandle = (); - type AssetAccountDeposit = AssetAccountDeposit; - type RemoveItemsLimit = ConstU32<1000>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } diff --git a/runtime/devnet/src/config/contracts.rs b/runtime/devnet/src/config/contracts.rs index 67a2f33c..6cf923b9 100644 --- a/runtime/devnet/src/config/contracts.rs +++ b/runtime/devnet/src/config/contracts.rs @@ -1,13 +1,14 @@ +use frame_support::{ + parameter_types, + traits::{ConstBool, ConstU32, Randomness}, +}; +use frame_system::{pallet_prelude::BlockNumberFor, EnsureSigned}; + use super::api::{self, Config}; use crate::{ deposit, Balance, Balances, BalancesCall, Perbill, Runtime, RuntimeCall, RuntimeEvent, RuntimeHoldReason, Timestamp, }; -use frame_support::{ - parameter_types, - traits::{ConstBool, ConstU32, Randomness}, -}; -use frame_system::pallet_prelude::BlockNumberFor; pub enum AllowBalancesCall {} @@ -46,12 +47,8 @@ parameter_types! { } impl pallet_contracts::Config for Runtime { - type Time = Timestamp; - type Randomness = DummyRandomness; - type Currency = Balances; - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - + type AddressGenerator = pallet_contracts::DefaultAddressGenerator; + type ApiVersion = (); /// The safest default is to allow no calls at all. /// /// Runtimes should whitelist dispatchables that are allowed to be called from contracts @@ -59,14 +56,16 @@ impl pallet_contracts::Config for Runtime { /// change because that would break already deployed contracts. The `RuntimeCall` structure /// itself is not allowed to change the indices of existing pallets, too. type CallFilter = AllowBalancesCall; - type DepositPerItem = DepositPerItem; - type DepositPerByte = DepositPerByte; type CallStack = [pallet_contracts::Frame; 23]; - type WeightPrice = pallet_transaction_payment::Pallet; - type WeightInfo = pallet_contracts::weights::SubstrateWeight; type ChainExtension = api::Extension; - type Schedule = Schedule; - type AddressGenerator = pallet_contracts::DefaultAddressGenerator; + type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; + type Currency = Balances; + type Debug = (); + type DefaultDepositLimit = DefaultDepositLimit; + type DepositPerByte = DepositPerByte; + type DepositPerItem = DepositPerItem; + type Environment = (); + type InstantiateOrigin = EnsureSigned; // This node is geared towards development and testing of contracts. // We decided to increase the default allowed contract size for this // reason (the default is `128 * 1024`). @@ -76,16 +75,19 @@ impl pallet_contracts::Config for Runtime { // less friction during development when the requirement here is // just more lax. type MaxCodeLen = ConstU32<{ 256 * 1024 }>; - type DefaultDepositLimit = DefaultDepositLimit; - type MaxStorageKeyLen = ConstU32<128>; type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; - type UnsafeUnstableInterface = ConstBool; - type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; type MaxDelegateDependencies = ConstU32<32>; - type RuntimeHoldReason = RuntimeHoldReason; - - type Environment = (); - type Debug = (); + type MaxStorageKeyLen = ConstU32<128>; type Migrations = (); + type Randomness = DummyRandomness; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; + type Schedule = Schedule; + type Time = Timestamp; + type UnsafeUnstableInterface = ConstBool; + type UploadOrigin = EnsureSigned; + type WeightInfo = pallet_contracts::weights::SubstrateWeight; + type WeightPrice = pallet_transaction_payment::Pallet; type Xcm = pallet_xcm::Pallet; } diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index c1142126..ff70240e 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -1,5 +1,3 @@ -use super::assets::AssetsCall; -use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; use frame_support::traits::InstanceFilter; use pop_runtime_common::proxy::{ AnnouncementDepositBase, AnnouncementDepositFactor, MaxPending, MaxProxies, ProxyDepositBase, @@ -7,6 +5,9 @@ use pop_runtime_common::proxy::{ }; use sp_runtime::traits::BlakeTwo256; +use super::assets::TrustBackedAssetsCall; +use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; + impl InstanceFilter for ProxyType { fn filter(&self, c: &RuntimeCall) -> bool { match self { @@ -34,16 +35,16 @@ impl InstanceFilter for ProxyType { }, ProxyType::AssetOwner => matches!( c, - RuntimeCall::Assets(AssetsCall::create { .. }) | - RuntimeCall::Assets(AssetsCall::start_destroy { .. }) | - RuntimeCall::Assets(AssetsCall::destroy_accounts { .. }) | - RuntimeCall::Assets(AssetsCall::destroy_approvals { .. }) | - RuntimeCall::Assets(AssetsCall::finish_destroy { .. }) | - RuntimeCall::Assets(AssetsCall::transfer_ownership { .. }) | - RuntimeCall::Assets(AssetsCall::set_team { .. }) | - RuntimeCall::Assets(AssetsCall::set_metadata { .. }) | - RuntimeCall::Assets(AssetsCall::clear_metadata { .. }) | - RuntimeCall::Assets(AssetsCall::set_min_balance { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | @@ -56,15 +57,15 @@ impl InstanceFilter for ProxyType { ), ProxyType::AssetManager => matches!( c, - RuntimeCall::Assets(AssetsCall::mint { .. }) | - RuntimeCall::Assets(AssetsCall::burn { .. }) | - RuntimeCall::Assets(AssetsCall::freeze { .. }) | - RuntimeCall::Assets(AssetsCall::block { .. }) | - RuntimeCall::Assets(AssetsCall::thaw { .. }) | - RuntimeCall::Assets(AssetsCall::freeze_asset { .. }) | - RuntimeCall::Assets(AssetsCall::thaw_asset { .. }) | - RuntimeCall::Assets(AssetsCall::touch_other { .. }) | - RuntimeCall::Assets(AssetsCall::refund_other { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | @@ -94,16 +95,16 @@ impl InstanceFilter for ProxyType { } impl pallet_proxy::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; + type AnnouncementDepositBase = AnnouncementDepositBase; + type AnnouncementDepositFactor = AnnouncementDepositFactor; + type CallHasher = BlakeTwo256; type Currency = Balances; - type ProxyType = ProxyType; + type MaxPending = MaxPending; + type MaxProxies = MaxProxies; type ProxyDepositBase = ProxyDepositBase; type ProxyDepositFactor = ProxyDepositFactor; - type MaxProxies = MaxProxies; + type ProxyType = ProxyType; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_proxy::weights::SubstrateWeight; - type MaxPending = MaxPending; - type CallHasher = BlakeTwo256; - type AnnouncementDepositBase = AnnouncementDepositBase; - type AnnouncementDepositFactor = AnnouncementDepositFactor; } diff --git a/runtime/devnet/src/config/xcm.rs b/runtime/devnet/src/config/xcm.rs index a5b7a04d..40f18c7c 100644 --- a/runtime/devnet/src/config/xcm.rs +++ b/runtime/devnet/src/config/xcm.rs @@ -1,8 +1,5 @@ -use crate::{ - AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, - Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, -}; use core::marker::PhantomData; + use frame_support::{ parameter_types, traits::{ConstU32, Contains, ContainsPair, Everything, Get, Nothing}, @@ -13,24 +10,29 @@ use pallet_xcm::XcmPassthrough; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; use xcm::latest::prelude::*; -#[allow(deprecated)] -use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, - FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, - UsingComponents, WithComputedOrigin, WithUniqueTopic, + FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NativeAsset, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::XcmExecutor; +use crate::{ + AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, + Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, +}; + parameter_types! { pub const RelayLocation: Location = Location::parent(); pub AssetHub: Location = Location::new(1, [Parachain(1000)]); // Note: Paseo currently uses Polkadot https://github.com/paseo-network/runtimes/blob/abc4ae9c5ae8f0166aab7ef2b427b3c2c6d5ce5c/relay/paseo/src/xcm_config.rs#L56 pub const RelayNetwork: Option = Some(Polkadot); pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + // For the real deployment, it is recommended to set `RelayNetwork` according to the relay chain + // and prepend `UniversalLocation` with `GlobalConsensus(RelayNetwork::get())`. pub UniversalLocation: InteriorLocation = Parachain(ParachainInfo::parachain_id().into()).into(); } @@ -48,7 +50,7 @@ pub type LocationToAccountId = ( /// Means for transacting assets on this chain. #[allow(deprecated)] -pub type LocalAssetTransactor = CurrencyAdapter< +pub type LocalAssetTransactor = FungibleAdapter< // Use this currency: Balances, // Use this currency when it is a fungible asset matching the given location or name: @@ -125,33 +127,38 @@ pub type TrustedReserves = (NativeAsset, NativeAssetFrom); pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type Aliasers = Nothing; + type AssetClaims = PolkadotXcm; + type AssetExchanger = (); + type AssetLocker = (); // How to withdraw and deposit an asset. type AssetTransactor = LocalAssetTransactor; - type OriginConverter = XcmOriginToTransactDispatchOrigin; - type IsReserve = TrustedReserves; - type IsTeleporter = (); // Teleporting is disabled. - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = - UsingComponents>; - type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; - type AssetClaims = PolkadotXcm; - type SubscriptionService = PolkadotXcm; - type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); + type Barrier = Barrier; + type CallDispatcher = RuntimeCall; type FeeManager = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); + type HrmpNewChannelOpenRequestHandler = (); + type IsReserve = TrustedReserves; + type IsTeleporter = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type PalletInstancesInfo = AllPalletsWithSystem; + type ResponseHandler = PolkadotXcm; + type RuntimeCall = RuntimeCall; type SafeCallFilter = Everything; - type Aliasers = Nothing; + type SubscriptionService = PolkadotXcm; + type Trader = + UsingComponents>; type TransactionalProcessor = FrameTransactionalProcessor; + type UniversalAliases = Nothing; + // Teleporting is disabled. + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type XcmRecorder = PolkadotXcm; + type XcmSender = XcmRouter; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -167,34 +174,32 @@ pub type XcmRouter = WithUniqueTopic<( )>; impl pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Nothing; - // ^ Disable dispatchable execute on the XCM pallet. - // Needs to be `Everything` for local testing. - type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Nothing; - // TODO: add filter to only allow reserve transfers of native to relay/asset hub - type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdminOrigin = EnsureRoot; // ^ Override for AdvertisedXcmVersion default type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type Currency = Balances; type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = LocationToAccountId; + type ExecuteXcmOrigin = EnsureXcmOrigin; type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SendXcmOrigin = EnsureXcmOrigin; + type SovereignAccountOf = LocationToAccountId; + type TrustedLockers = (); + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type WeightInfo = pallet_xcm::TestWeightInfo; + type XcmExecuteFilter = Everything; + type XcmExecutor = XcmExecutor; + // TODO: add filter to only allow reserve transfers of native to relay/asset hub + type XcmReserveTransferFilter = Everything; + type XcmRouter = XcmRouter; + type XcmTeleportFilter = Everything; + + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 4f4b2e22..ba6ceae6 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -10,34 +10,18 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod config; mod weights; -use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; -use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; -use smallvec::smallvec; -use sp_api::impl_runtime_apis; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, - transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, -}; - -use sp_std::prelude::*; -#[cfg(feature = "std")] -use sp_version::NativeVersion; -use sp_version::RuntimeVersion; - use config::xcm::{RelayLocation, XcmOriginToTransactDispatchOrigin}; +use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; use frame_support::{ - construct_runtime, derive_impl, + derive_impl, dispatch::DispatchClass, - genesis_builder_helper::{build_config, create_default_config}, + genesis_builder_helper::{build_state, get_preset}, parameter_types, traits::{ fungible::HoldConsideration, tokens::nonfungibles_v2::Inspect, ConstBool, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, EverythingBut, - LinearStoragePrice, TransformOrigin, + LinearStoragePrice, TransformOrigin, VariantCountOf, }, weights::{ ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, @@ -49,31 +33,39 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, }; +use pallet_api::fungibles; +use pallet_balances::Call as BalancesCall; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; +use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; +// Polkadot imports +use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; pub use pop_runtime_common::{ deposit, AuraId, Balance, BlockNumber, Hash, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, BLOCK_PROCESSING_VELOCITY, DAYS, EXISTENTIAL_DEPOSIT, HOURS, MAXIMUM_BLOCK_WEIGHT, MICROUNIT, MILLIUNIT, MINUTES, NORMAL_DISPATCH_RATIO, RELAY_CHAIN_SLOT_DURATION_MILLIS, SLOT_DURATION, UNINCLUDED_SEGMENT_CAPACITY, UNIT, }; -pub use sp_runtime::{MultiAddress, Perbill, Permill}; - +use smallvec::smallvec; +use sp_api::impl_runtime_apis; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; - -use pallet_balances::Call as BalancesCall; - -// Polkadot imports -use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; - +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, +}; +pub use sp_runtime::{ExtrinsicInclusionMode, MultiAddress, Perbill, Permill}; +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; - // XCM Imports use xcm::latest::prelude::BodyId; -use pallet_api::fungibles; - /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. pub type AccountId = <::Signer as IdentifyAccount>::AccountId; @@ -103,6 +95,8 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, + frame_metadata_hash_extension::CheckMetadataHash, ); /// Unchecked extrinsic type as expected by this runtime. @@ -131,6 +125,7 @@ pub type Executive = frame_executive::Executive< pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: // we map to 1/10 of that, or 1/10 MILLIUNIT @@ -150,13 +145,13 @@ impl WeightToFeePolynomial for WeightToFee { /// of data like extrinsics, allowing for them to continue syncing the network through upgrades /// to even the core data structures. pub mod opaque { - use super::*; + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; use sp_runtime::{ generic, traits::{BlakeTwo256, Hash as HashT}, }; - pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + use super::*; /// Opaque block header type. pub type Header = generic::Header; /// Opaque block type. @@ -254,48 +249,48 @@ impl Contains for FilteredCalls { /// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from /// [`ParaChainDefaultConfig`](`struct@frame_system::config_preludes::ParaChainDefaultConfig`), /// but overridden as needed. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; /// The identifier used to distinguish between accounts. type AccountId = AccountId; - /// The index type for storing how many extrinsics an account has signed. - type Nonce = Nonce; - /// The type for hashing blocks and tries. - type Hash = Hash; + /// The basic call filter to use in dispatchable. Supports everything as the default. + type BaseCallFilter = EverythingBut; /// The block type. type Block = Block; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount = BlockHashCount; - /// Runtime version. - type Version = Version; - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). type BlockLength = RuntimeBlockLength; - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; - /// The basic call filter to use in dispatchable. Supports everything as the default. - type BaseCallFilter = EverythingBut; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The type for hashing blocks and tries. + type Hash = Hash; + type MaxConsumers = frame_support::traits::ConstU32<16>; + /// The index type for storing how many extrinsics an account has signed. + type Nonce = Nonce; /// The action to take on a Runtime Upgrade type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = frame_support::traits::ConstU32<16>; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// Runtime version. + type Version = Version; } impl pallet_timestamp::Config for Runtime { + type MinimumPeriod = ConstU64<0>; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<0>; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type EventHandler = (CollatorSelection,); + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; } parameter_types! { @@ -303,21 +298,21 @@ parameter_types! { } impl pallet_balances::Config for Runtime { - type MaxLocks = ConstU32<50>; + type AccountStore = System; /// The type for recording an account's balance. type Balance = Balance; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = VariantCountOf; + type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; type RuntimeFreezeReason = RuntimeFreezeReason; - type FreezeIdentifier = (); - type MaxFreezes = ConstU32<0>; + type RuntimeHoldReason = RuntimeHoldReason; + type WeightInfo = pallet_balances::weights::SubstrateWeight; } parameter_types! { @@ -326,17 +321,17 @@ parameter_types! { } impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type LengthToFee = ConstantMultiplier; + type OnChargeTransaction = pallet_transaction_payment::FungibleAdapter; type OperationalFeeMultiplier = ConstU8<5>; + type RuntimeEvent = RuntimeEvent; + type WeightToFee = WeightToFee; } impl pallet_sudo::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -354,17 +349,17 @@ type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< >; impl cumulus_pallet_parachain_system::Config for Runtime { - type WeightInfo = (); - type RuntimeEvent = RuntimeEvent; + type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases; + type ConsensusHook = ConsensusHook; + type DmpQueue = frame_support::traits::EnqueueWithOrigin; type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; type OutboundXcmpMessageSource = XcmpQueue; - type DmpQueue = frame_support::traits::EnqueueWithOrigin; type ReservedDmpWeight = ReservedDmpWeight; - type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases; - type ConsensusHook = ConsensusHook; + type RuntimeEvent = RuntimeEvent; + type SelfParaId = parachain_info::Pallet; + type WeightInfo = (); + type XcmpMessageHandler = XcmpQueue; } impl parachain_info::Config for Runtime {} @@ -374,8 +369,9 @@ parameter_types! { } impl pallet_message_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; + type IdleMaxServiceWeight = (); + type MaxStale = sp_core::ConstU32<8>; #[cfg(feature = "runtime-benchmarks")] type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor< cumulus_primitives_core::AggregateMessageOrigin, @@ -386,28 +382,32 @@ impl pallet_message_queue::Config for Runtime { xcm_executor::XcmExecutor, RuntimeCall, >; - type Size = u32; // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; - type MaxStale = sp_core::ConstU32<8>; + type RuntimeEvent = RuntimeEvent; type ServiceWeight = MessageQueueServiceWeight; + type Size = u32; + type WeightInfo = (); } impl cumulus_pallet_aura_ext::Config for Runtime {} impl cumulus_pallet_xcmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type ChannelInfo = ParachainSystem; - type VersionWrapper = (); - // Enqueue XCMP messages from siblings for later processing. - type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type WeightInfo = (); + // Limit the number of messages and signals a HRML channel can have at most + type MaxActiveOutboundChannels = ConstU32<128>; + type MaxInboundSuspended = sp_core::ConstU32<1_000>; + // Limit the number of HRML channels + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type PriceForSiblingDelivery = NoPriceForMessageDelivery; + type RuntimeEvent = RuntimeEvent; + type VersionWrapper = (); + type WeightInfo = (); + // Enqueue XCMP messages from siblings for later processing. + type XcmpQueue = TransformOrigin; } parameter_types! { @@ -416,24 +416,24 @@ parameter_types! { } impl pallet_session::Config for Runtime { + type Keys = SessionKeys; + type NextSessionRotation = pallet_session::PeriodicSessions; type RuntimeEvent = RuntimeEvent; + // Essentially just Aura, but let's be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = CollatorSelection; + type ShouldEndSession = pallet_session::PeriodicSessions; type ValidatorId = ::AccountId; // we don't have stash and controller, thus we don't need the convert as well. type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = CollatorSelection; - // Essentially just Aura, but let's be pedantic. - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; type WeightInfo = (); } impl pallet_aura::Config for Runtime { + type AllowMultipleBlocksPerSlot = ConstBool; type AuthorityId = AuraId; type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; - type AllowMultipleBlocksPerSlot = ConstBool; type SlotDuration = ConstU64; } @@ -451,15 +451,15 @@ pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< >; impl pallet_collator_selection::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type UpdateOrigin = CollatorSelectionUpdateOrigin; - type PotId = PotId; - type MaxCandidates = ConstU32<100>; - type MinEligibleCollators = ConstU32<4>; - type MaxInvulnerables = ConstU32<20>; // should be a multiple of session or things will get inconsistent type KickThreshold = Period; + type MaxCandidates = ConstU32<100>; + type MaxInvulnerables = ConstU32<20>; + type MinEligibleCollators = ConstU32<4>; + type PotId = PotId; + type RuntimeEvent = RuntimeEvent; + type UpdateOrigin = CollatorSelectionUpdateOrigin; type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_collator_selection::IdentityCollator; type ValidatorRegistration = Session; @@ -472,19 +472,19 @@ parameter_types! { } impl pallet_scheduler::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type PalletsOrigin = OriginCaller; - type RuntimeCall = RuntimeCall; - type MaximumWeight = MaximumSchedulerWeight; - type ScheduleOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type MaxScheduledPerBlock = ConstU32<512>; #[cfg(not(feature = "runtime-benchmarks"))] type MaxScheduledPerBlock = ConstU32<50>; - type WeightInfo = pallet_scheduler::weights::SubstrateWeight; + type MaximumWeight = MaximumSchedulerWeight; type OriginPrivilegeCmp = EqualPrivilegeOnly; + type PalletsOrigin = OriginCaller; type Preimages = Preimage; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type ScheduleOrigin = EnsureRoot; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; } parameter_types! { @@ -494,16 +494,16 @@ parameter_types! { } impl pallet_preimage::Config for Runtime { - type WeightInfo = pallet_preimage::weights::SubstrateWeight; - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type ManagerOrigin = EnsureRoot; type Consideration = HoldConsideration< AccountId, Balances, PreimageHoldReason, LinearStoragePrice, >; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_preimage::weights::SubstrateWeight; } parameter_types! { @@ -515,76 +515,115 @@ parameter_types! { } impl pallet_multisig::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_multisig::weights::SubstrateWeight; } impl pallet_utility::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_utility::weights::SubstrateWeight; } -// Create the runtime by composing the FRAME pallets that were previously configured. -construct_runtime!( - pub enum Runtime { - // System support stuff. - System: frame_system = 0, - ParachainSystem: cumulus_pallet_parachain_system = 1, - Timestamp: pallet_timestamp = 2, - ParachainInfo: parachain_info = 3, - - // Monetary stuff. - Balances: pallet_balances = 10, - TransactionPayment: pallet_transaction_payment = 11, - - // Governance - Sudo: pallet_sudo = 15, - - // Collator support. The order of these 4 are important and shall not change. - Authorship: pallet_authorship = 20, - CollatorSelection: pallet_collator_selection = 21, - Session: pallet_session = 22, - Aura: pallet_aura = 23, - AuraExt: cumulus_pallet_aura_ext = 24, - - // Scheduler - Scheduler: pallet_scheduler = 28, - - // Preimage - Preimage: pallet_preimage = 29, - - // XCM helpers. - XcmpQueue: cumulus_pallet_xcmp_queue = 30, - PolkadotXcm: pallet_xcm = 31, - CumulusXcm: cumulus_pallet_xcm = 32, - MessageQueue: pallet_message_queue = 33, - - // Contracts - Contracts: pallet_contracts = 40, - - // Proxy - Proxy: pallet_proxy = 41, - // Multisig - Multisig: pallet_multisig = 42, - // Utility - Utility: pallet_utility = 43, - - // Assets - Nfts: pallet_nfts = 50, - NftFractionalization: pallet_nft_fractionalization = 51, - Assets: pallet_assets:: = 52, - - // Pop API - Fungibles: fungibles = 150, - } -); +#[frame_support::runtime] +mod runtime { + // Create the runtime by composing the FRAME pallets that were previously configured. + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + // System support stuff. + #[runtime::pallet_index(0)] + pub type System = frame_system::Pallet; + #[runtime::pallet_index(1)] + pub type ParachainSystem = cumulus_pallet_parachain_system::Pallet; + #[runtime::pallet_index(2)] + pub type Timestamp = pallet_timestamp::Pallet; + #[runtime::pallet_index(3)] + pub type ParachainInfo = parachain_info::Pallet; + + // Monetary stuff. + #[runtime::pallet_index(10)] + pub type Balances = pallet_balances::Pallet; + #[runtime::pallet_index(11)] + pub type TransactionPayment = pallet_transaction_payment::Pallet; + + // Governance + #[runtime::pallet_index(15)] + pub type Sudo = pallet_sudo; + + // Collator support. The order of these 4 are important and shall not change. + #[runtime::pallet_index(20)] + pub type Authorship = pallet_authorship::Pallet; + #[runtime::pallet_index(21)] + pub type CollatorSelection = pallet_collator_selection::Pallet; + #[runtime::pallet_index(22)] + pub type Session = pallet_session::Pallet; + #[runtime::pallet_index(23)] + pub type Aura = pallet_aura::Pallet; + #[runtime::pallet_index(24)] + pub type AuraExt = cumulus_pallet_aura_ext; + + // Scheduler + #[runtime::pallet_index(28)] + pub type Scheduler = pallet_scheduler; + + // Preimage + #[runtime::pallet_index(29)] + pub type Preimage = pallet_preimage; + + // XCM helpers. + #[runtime::pallet_index(30)] + pub type XcmpQueue = cumulus_pallet_xcmp_queue::Pallet; + #[runtime::pallet_index(31)] + pub type PolkadotXcm = pallet_xcm::Pallet; + #[runtime::pallet_index(32)] + pub type CumulusXcm = cumulus_pallet_xcm::Pallet; + #[runtime::pallet_index(33)] + pub type MessageQueue = pallet_message_queue::Pallet; + + // Contracts + #[runtime::pallet_index(40)] + pub type Contracts = pallet_contracts::Pallet; + + // Proxy + #[runtime::pallet_index(41)] + pub type Proxy = pallet_proxy::Pallet; + // Multisig + #[runtime::pallet_index(42)] + pub type Multisig = pallet_multisig::Pallet; + // Utility + #[runtime::pallet_index(43)] + pub type Utility = pallet_utility::Pallet; + + // Assets + #[runtime::pallet_index(50)] + pub type Nfts = pallet_nfts::Pallet; + #[runtime::pallet_index(51)] + pub type NftFractionalization = pallet_nft_fractionalization::Pallet; + #[runtime::pallet_index(52)] + pub type Assets = pallet_assets::Pallet; + + // Pop API + #[runtime::pallet_index(150)] + pub type Fungibles = fungibles::Pallet; +} #[cfg(feature = "runtime-benchmarks")] mod benches { @@ -610,7 +649,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } @@ -623,7 +662,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> ExtrinsicInclusionMode { Executive::initialize_block(header) } } @@ -637,7 +676,7 @@ impl_runtime_apis! { Runtime::metadata_at_version(version) } - fn metadata_versions() -> sp_std::vec::Vec { + fn metadata_versions() -> Vec { Runtime::metadata_versions() } } @@ -911,7 +950,7 @@ impl_runtime_apis! { use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime { - fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { + fn setup_set_code_requirements(code: &Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); Ok(()) } @@ -937,12 +976,16 @@ impl_runtime_apis! { } impl sp_genesis_builder::GenesisBuilder for Runtime { - fn create_default_config() -> Vec { - create_default_config::() + fn build_state(config: Vec) -> sp_genesis_builder::Result { + build_state::(config) + } + + fn get_preset(id: &Option) -> Option> { + get_preset::(id, |_| None) } - fn build_config(config: Vec) -> sp_genesis_builder::Result { - build_config::(config) + fn preset_names() -> Vec { + Default::default() } } } @@ -954,9 +997,10 @@ cumulus_pallet_parachain_system::register_validate_block! { #[cfg(test)] mod tests { - use crate::Runtime; use std::any::TypeId; + use crate::Runtime; + // Ensures that the account id lookup does not perform any state reads. When this changes, // `pallet_api::fungibles` dispatchables need to be re-evaluated. #[test] diff --git a/runtime/devnet/src/weights/paritydb_weights.rs b/runtime/devnet/src/weights/paritydb_weights.rs index 25679703..27f7f1b0 100644 --- a/runtime/devnet/src/weights/paritydb_weights.rs +++ b/runtime/devnet/src/weights/paritydb_weights.rs @@ -32,9 +32,10 @@ pub mod constants { #[cfg(test)] mod test_db_weights { - use super::constants::ParityDbWeight as W; use frame_support::weights::constants; + use super::constants::ParityDbWeight as W; + /// Checks that all weights exist and have sane values. // NOTE: If this test fails but you are sure that the generated values are fine, // you can delete it. diff --git a/runtime/devnet/src/weights/rocksdb_weights.rs b/runtime/devnet/src/weights/rocksdb_weights.rs index 3dd817aa..bacad98c 100644 --- a/runtime/devnet/src/weights/rocksdb_weights.rs +++ b/runtime/devnet/src/weights/rocksdb_weights.rs @@ -32,9 +32,10 @@ pub mod constants { #[cfg(test)] mod test_db_weights { - use super::constants::RocksDbWeight as W; use frame_support::weights::constants; + use super::constants::RocksDbWeight as W; + /// Checks that all weights exist and have sane values. // NOTE: If this test fails but you are sure that the generated values are fine, // you can delete it. diff --git a/runtime/mainnet/Cargo.toml b/runtime/mainnet/Cargo.toml new file mode 100644 index 00000000..a3ddf745 --- /dev/null +++ b/runtime/mainnet/Cargo.toml @@ -0,0 +1,220 @@ +[package] +authors.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +name = "pop-runtime-mainnet" +repository.workspace = true +version = "0.1.0" + +[package.metadata.docs.rs] +targets = [ "x86_64-unknown-linux-gnu" ] + +[build-dependencies] +substrate-wasm-builder.workspace = true + +[dependencies] +codec.workspace = true +scale-info.workspace = true +smallvec.workspace = true + +# Local +pop-runtime-common = { workspace = true, default-features = false } + +# Substrate +frame-benchmarking.workspace = true +frame-executive.workspace = true +frame-metadata-hash-extension.workspace = true +frame-support.workspace = true +frame-system.workspace = true +frame-system-benchmarking.workspace = true +frame-system-rpc-runtime-api.workspace = true +frame-try-runtime.workspace = true +pallet-aura.workspace = true +pallet-authorship.workspace = true +pallet-balances.workspace = true +pallet-message-queue.workspace = true +pallet-multisig.workspace = true +pallet-preimage.workspace = true +pallet-proxy.workspace = true +pallet-scheduler.workspace = true +pallet-session.workspace = true +pallet-sudo.workspace = true +pallet-timestamp.workspace = true +pallet-transaction-payment.workspace = true +pallet-transaction-payment-rpc-runtime-api.workspace = true +pallet-utility.workspace = true +sp-api.workspace = true +sp-block-builder.workspace = true +sp-consensus-aura.workspace = true +sp-core.workspace = true +sp-genesis-builder.workspace = true +sp-inherents.workspace = true +sp-io.workspace = true +sp-offchain.workspace = true +sp-runtime.workspace = true +sp-session.workspace = true +sp-std.workspace = true +sp-transaction-pool.workspace = true +sp-version.workspace = true + +# Polkadot +pallet-xcm.workspace = true +polkadot-parachain-primitives.workspace = true +polkadot-runtime-common.workspace = true +xcm.workspace = true +xcm-builder.workspace = true +xcm-executor.workspace = true + +# Cumulus +cumulus-pallet-aura-ext.workspace = true +cumulus-pallet-parachain-system.workspace = true +cumulus-pallet-session-benchmarking.workspace = true +cumulus-pallet-xcm.workspace = true +cumulus-pallet-xcmp-queue.workspace = true +cumulus-primitives-aura.workspace = true +cumulus-primitives-core.workspace = true +cumulus-primitives-storage-weight-reclaim.workspace = true +cumulus-primitives-utility.workspace = true +pallet-collator-selection.workspace = true +parachain-info.workspace = true +parachains-common.workspace = true + +[dev-dependencies] +enumflags2 = "0.7.9" +env_logger = "0.11.2" +hex = "0.4.3" + +[features] +default = [ "std" ] +std = [ + "codec/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-session-benchmarking/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-aura/std", + "cumulus-primitives-core/std", + "cumulus-primitives-storage-weight-reclaim/std", + "cumulus-primitives-utility/std", + "frame-benchmarking/std", + "frame-executive/std", + "frame-metadata-hash-extension/std", + "frame-support/std", + "frame-system-benchmarking/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "frame-try-runtime/std", + "pallet-aura/std", + "pallet-authorship/std", + "pallet-balances/std", + "pallet-collator-selection/std", + "pallet-message-queue/std", + "pallet-multisig/std", + "pallet-preimage/std", + "pallet-proxy/std", + "pallet-scheduler/std", + "pallet-session/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-utility/std", + "pallet-xcm/std", + "parachain-info/std", + "parachains-common/std", + "polkadot-parachain-primitives/std", + "polkadot-runtime-common/std", + "pop-runtime-common/std", + "scale-info/std", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-genesis-builder/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm/std", +] + +runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "cumulus-pallet-session-benchmarking/runtime-benchmarks", + "cumulus-pallet-xcmp-queue/runtime-benchmarks", + "cumulus-primitives-core/runtime-benchmarks", + "cumulus-primitives-utility/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-collator-selection/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", + "pallet-sudo/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "parachains-common/runtime-benchmarks", + "polkadot-parachain-primitives/runtime-benchmarks", + "polkadot-runtime-common/runtime-benchmarks", + "pop-runtime-common/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", +] + +try-runtime = [ + "cumulus-pallet-aura-ext/try-runtime", + "cumulus-pallet-parachain-system/try-runtime", + "cumulus-pallet-xcm/try-runtime", + "cumulus-pallet-xcmp-queue/try-runtime", + "frame-executive/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", + "pallet-aura/try-runtime", + "pallet-authorship/try-runtime", + "pallet-balances/try-runtime", + "pallet-collator-selection/try-runtime", + "pallet-message-queue/try-runtime", + "pallet-multisig/try-runtime", + "pallet-preimage/try-runtime", + "pallet-proxy/try-runtime", + "pallet-scheduler/try-runtime", + "pallet-session/try-runtime", + "pallet-sudo/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-transaction-payment/try-runtime", + "pallet-utility/try-runtime", + "pallet-xcm/try-runtime", + "parachain-info/try-runtime", + "polkadot-runtime-common/try-runtime", + "sp-runtime/try-runtime", +] + +# Enable the metadata hash generation. +# +# This is hidden behind a feature because it increases the compile time. +# The wasm binary needs to be compiled twice, once to fetch the metadata, +# generate the metadata hash and then a second time with the +# `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash` +# extension. +metadata-hash = [ "substrate-wasm-builder/metadata-hash" ] + +# A convenience feature for enabling things when doing a build +# for an on-chain release. +on-chain-release-build = [ "metadata-hash" ] diff --git a/runtime/mainnet/build.rs b/runtime/mainnet/build.rs new file mode 100644 index 00000000..ecc5fb01 --- /dev/null +++ b/runtime/mainnet/build.rs @@ -0,0 +1,16 @@ +#[cfg(all(feature = "std", feature = "metadata-hash"))] +fn main() { + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("DOT", 10) + .build() +} + +#[cfg(all(feature = "std", not(feature = "metadata-hash")))] +fn main() { + substrate_wasm_builder::WasmBuilder::build_using_defaults() +} + +/// The wasm builder is deactivated when compiling +/// this crate for wasm to speed up the compilation. +#[cfg(not(feature = "std"))] +fn main() {} diff --git a/runtime/mainnet/src/config/mod.rs b/runtime/mainnet/src/config/mod.rs new file mode 100644 index 00000000..913d0352 --- /dev/null +++ b/runtime/mainnet/src/config/mod.rs @@ -0,0 +1,2 @@ +mod proxy; +pub mod xcm; diff --git a/runtime/mainnet/src/config/proxy.rs b/runtime/mainnet/src/config/proxy.rs new file mode 100644 index 00000000..0b8ab9b9 --- /dev/null +++ b/runtime/mainnet/src/config/proxy.rs @@ -0,0 +1,57 @@ +use frame_support::traits::InstanceFilter; +use pop_runtime_common::proxy::{ + AnnouncementDepositBase, AnnouncementDepositFactor, MaxPending, MaxProxies, ProxyDepositBase, + ProxyDepositFactor, ProxyType, +}; +use sp_runtime::traits::BlakeTwo256; + +use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; + +impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::NonTransfer => !matches!(c, RuntimeCall::Balances { .. }), + ProxyType::CancelProxy => matches!( + c, + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } + ), + ProxyType::Assets => { + matches!(c, RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. }) + }, + ProxyType::AssetOwner => { + matches!(c, RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. }) + }, + ProxyType::AssetManager => { + matches!(c, RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. }) + }, + ProxyType::Collator => matches!( + c, + RuntimeCall::CollatorSelection { .. } | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } + ), + } + } + + fn is_superset(&self, o: &Self) -> bool { + ProxyType::is_superset(self, o) + } +} + +impl pallet_proxy::Config for Runtime { + type AnnouncementDepositBase = AnnouncementDepositBase; + type AnnouncementDepositFactor = AnnouncementDepositFactor; + type CallHasher = BlakeTwo256; + type Currency = Balances; + type MaxPending = MaxPending; + type MaxProxies = MaxProxies; + type ProxyDepositBase = ProxyDepositBase; + type ProxyDepositFactor = ProxyDepositFactor; + type ProxyType = ProxyType; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_proxy::weights::SubstrateWeight; +} diff --git a/runtime/mainnet/src/config/xcm.rs b/runtime/mainnet/src/config/xcm.rs new file mode 100644 index 00000000..0b5863a7 --- /dev/null +++ b/runtime/mainnet/src/config/xcm.rs @@ -0,0 +1,213 @@ +use core::marker::PhantomData; + +use frame_support::{ + parameter_types, + traits::{tokens::imbalance::ResolveTo, ConstU32, ContainsPair, Everything, Get, Nothing}, + weights::Weight, +}; +use frame_system::EnsureRoot; +use pallet_xcm::XcmPassthrough; +use parachains_common::xcm_config::{ + AllSiblingSystemParachains, ParentRelayOrSiblingParachains, RelayOrOtherSystemParachains, +}; +use polkadot_parachain_primitives::primitives::Sibling; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, + FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NativeAsset, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, + XcmFeeManagerFromComponents, XcmFeeToAccount, +}; +use xcm_executor::XcmExecutor; + +use crate::{ + fee::WeightToFee, AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, + PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SudoAddress, XcmpQueue, +}; + +parameter_types! { + pub const RelayLocation: Location = Location::parent(); + pub AssetHub: Location = Location::new(1, [Parachain(1000)]); + pub const RelayNetwork: Option = Some(Polkadot); + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(ParachainInfo::parachain_id().into())].into(); +} + +/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the parent `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// Means for transacting assets on this chain. +pub type LocalAssetTransactor = FungibleAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // Do a simple punn to convert an AccountId32 Location into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports. + (), +>; + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when + // recognized. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognized. + SiblingParachainAsNative, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `RuntimeOrigin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + XcmPassthrough, +); + +parameter_types! { + // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. + pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); + pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; +} + +pub type Barrier = TrailingSetTopicAsId<( + TakeWeightCredit, + AllowKnownQueryResponses, + WithComputedOrigin< + ( + AllowTopLevelPaidExecutionFrom, + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +)>; + +/// Asset filter that allows native/relay asset if coming from a certain location. +// Borrowed from https://github.com/paritytech/polkadot-sdk/blob/ea458d0b95d819d31683a8a09ca7973ae10b49be/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs#L239 for now +pub struct NativeAssetFrom(PhantomData); +impl> ContainsPair for NativeAssetFrom { + fn contains(asset: &Asset, origin: &Location) -> bool { + let loc = T::get(); + &loc == origin && + matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) } + if *asset_loc == Location::from(Parent)) + } +} +pub type TrustedReserves = (NativeAsset, NativeAssetFrom); + +/// Locations that will not be charged fees in the executor, +/// either execution or delivery. +/// We only waive fees for system functions, which these locations represent. +pub type WaivedLocations = (RelayOrOtherSystemParachains,); + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type Aliasers = Nothing; + type AssetClaims = PolkadotXcm; + type AssetExchanger = (); + type AssetLocker = (); + // How to withdraw and deposit an asset. + type AssetTransactor = LocalAssetTransactor; + type AssetTrap = PolkadotXcm; + type Barrier = Barrier; + type CallDispatcher = RuntimeCall; + type FeeManager = XcmFeeManagerFromComponents< + WaivedLocations, + XcmFeeToAccount, + >; + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); + type HrmpNewChannelOpenRequestHandler = (); + type IsReserve = TrustedReserves; + type IsTeleporter = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type MessageExporter = (); + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type PalletInstancesInfo = AllPalletsWithSystem; + type ResponseHandler = PolkadotXcm; + type RuntimeCall = RuntimeCall; + type SafeCallFilter = Everything; + type SubscriptionService = PolkadotXcm; + type Trader = UsingComponents< + WeightToFee, + RelayLocation, + AccountId, + Balances, + ResolveTo, + >; + type TransactionalProcessor = FrameTransactionalProcessor; + type UniversalAliases = Nothing; + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type XcmRecorder = PolkadotXcm; + type XcmSender = XcmRouter; +} + +/// No local origins on this chain are allowed to dispatch XCM sends/executions. +pub type LocalOriginToLocation = SignedToAccountId32; + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = WithUniqueTopic<( + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, +)>; + +impl pallet_xcm::Config for Runtime { + type AdminOrigin = EnsureRoot; + // ^ Override for AdvertisedXcmVersion default. + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type ExecuteXcmOrigin = EnsureXcmOrigin; + type MaxLockers = ConstU32<8>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SendXcmOrigin = EnsureXcmOrigin; + type SovereignAccountOf = LocationToAccountId; + type TrustedLockers = (); + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type WeightInfo = pallet_xcm::TestWeightInfo; + type XcmExecuteFilter = Nothing; + // ^ Disable dispatchable execute on the XCM pallet. + // Needs to be `Everything` for local testing. + type XcmExecutor = XcmExecutor; + // TODO: add filter to only allow reserve transfers of native to relay/asset hub + type XcmReserveTransferFilter = Everything; + type XcmRouter = XcmRouter; + type XcmTeleportFilter = Nothing; + + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} diff --git a/runtime/mainnet/src/lib.rs b/runtime/mainnet/src/lib.rs new file mode 100644 index 00000000..536396af --- /dev/null +++ b/runtime/mainnet/src/lib.rs @@ -0,0 +1,1015 @@ +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +pub mod config; +mod weights; + +use config::xcm::{RelayLocation, XcmOriginToTransactDispatchOrigin}; +use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; +use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; +use frame_support::{ + derive_impl, + dispatch::DispatchClass, + genesis_builder_helper::{build_state, get_preset}, + parameter_types, + traits::{ + fungible::HoldConsideration, tokens::imbalance::ResolveTo, ConstBool, ConstU32, ConstU64, + ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, EverythingBut, LinearStoragePrice, + TransformOrigin, VariantCountOf, + }, + weights::{ConstantMultiplier, Weight}, + PalletId, +}; +use frame_system::{ + limits::{BlockLength, BlockWeights}, + EnsureRoot, +}; +use pallet_balances::Call as BalancesCall; +use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; +use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; +use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; +// Polkadot imports +use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; +pub use pop_runtime_common::{ + AuraId, Balance, BlockNumber, Hash, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, + BLOCK_PROCESSING_VELOCITY, DAYS, EXISTENTIAL_DEPOSIT, HOURS, MAXIMUM_BLOCK_WEIGHT, MICROUNIT, + MILLIUNIT, MINUTES, NORMAL_DISPATCH_RATIO, RELAY_CHAIN_SLOT_DURATION_MILLIS, SLOT_DURATION, + UNINCLUDED_SEGMENT_CAPACITY, UNIT, +}; +use sp_api::impl_runtime_apis; +use sp_core::{ + crypto::{KeyTypeId, Ss58Codec}, + OpaqueMetadata, +}; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, +}; +pub use sp_runtime::{ExtrinsicInclusionMode, MultiAddress, Perbill, Permill}; +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; +use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +// XCM Imports +use xcm::latest::prelude::BodyId; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// The address format for describing accounts. +pub type Address = MultiAddress; + +/// Block header type as expected by this runtime. +pub type Header = generic::Header; + +/// Block type as expected by this runtime. +pub type Block = generic::Block; + +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; + +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; + +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, + cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, + frame_metadata_hash_extension::CheckMetadataHash, +); + +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; + +/// Migrations to apply on runtime upgrade. +pub type Migrations = (); + +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, + Migrations, +>; + +pub const fn deposit(items: u32, bytes: u32) -> Balance { + // src: https://github.com/polkadot-fellows/runtimes/blob/main/system-parachains/constants/src/polkadot.rs#L70 + (items as Balance * 20 * UNIT + (bytes as Balance) * 100 * fee::MILLICENTS) / 100 +} + +/// Constants related to Polkadot fee payment. +/// Source: https://github.com/polkadot-fellows/runtimes/blob/main/system-parachains/constants/src/polkadot.rs#L65C47-L65C58 +pub mod fee { + use frame_support::{ + pallet_prelude::Weight, + weights::{ + constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, + }; + use pop_runtime_common::{Balance, MILLIUNIT}; + use smallvec::smallvec; + pub use sp_runtime::Perbill; + + pub const CENTS: Balance = MILLIUNIT * 10; // 100_000_000 + pub const MILLICENTS: Balance = CENTS / 1_000; // 100_000 + + /// Cost of every transaction byte at Polkadot system parachains. + /// + /// It is the Relay Chain (Polkadot) `TransactionByteFee` / 20. + pub const TRANSACTION_BYTE_FEE: Balance = MILLICENTS / 2; + + /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the + /// node's balance type. + /// + /// This should typically create a mapping between the following ranges: + /// - [0, MAXIMUM_BLOCK_WEIGHT] + /// - [Balance::min, Balance::max] + /// + /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: + /// - Setting it to `0` will essentially disable the weight fee. + /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. + pub struct WeightToFee; + impl frame_support::weights::WeightToFee for WeightToFee { + type Balance = Balance; + + fn weight_to_fee(weight: &Weight) -> Self::Balance { + let time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { + type Balance = Balance; + + fn polynomial() -> WeightToFeeCoefficients { + // In Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + // The standard system parachain configuration is 1/20 of that, as in 1/200 CENT. + let p = CENTS; + let q = 200 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// Maps the proof size component of `Weight` to a fee. + pub struct ProofSizeToFee; + impl WeightToFeePolynomial for ProofSizeToFee { + type Balance = Balance; + + fn polynomial() -> WeightToFeeCoefficients { + // Map 20kb proof to 1 CENT. + let p = CENTS; + let q = 20_000; + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } +} + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + use sp_runtime::{ + generic, + traits::{BlakeTwo256, Hash as HashT}, + }; + + use super::*; + /// Opaque block header type. + pub type Header = generic::Header; + /// Opaque block type. + pub type Block = generic::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; + /// Opaque block hash type. + pub type Hash = ::Output; +} + +impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + } +} + +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("pop"), + impl_name: create_runtime_str!("pop"), + authoring_version: 1, + #[allow(clippy::zero_prefixed_literal)] + spec_version: 00_01_00, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, + state_version: 1, +}; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } +} + +parameter_types! { + pub const Version: RuntimeVersion = VERSION; + + // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. + // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the + // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize + // the lazy contract deletion. + pub RuntimeBlockLength: BlockLength = + BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + pub const SS58Prefix: u16 = 0; +} + +/// A type to identify filtered calls. +pub struct FilteredCalls; +impl Contains for FilteredCalls { + fn contains(c: &RuntimeCall) -> bool { + use BalancesCall::*; + matches!( + c, + RuntimeCall::Balances( + force_adjust_total_issuance { .. } | + force_set_balance { .. } | + force_transfer { .. } | + force_unreserve { .. } + ) + ) + } +} + +/// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from +/// [`ParaChainDefaultConfig`](`struct@frame_system::config_preludes::ParaChainDefaultConfig`), +/// but overridden as needed. +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] +impl frame_system::Config for Runtime { + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The basic call filter to use in dispatchable. Supports everything as the default. + type BaseCallFilter = EverythingBut; + /// The block type. + type Block = Block; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The type for hashing blocks and tries. + type Hash = Hash; + type MaxConsumers = frame_support::traits::ConstU32<16>; + /// The index type for storing how many extrinsics an account has signed. + type Nonce = Nonce; + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// Runtime version. + type Version = Version; +} + +impl pallet_timestamp::Config for Runtime { + type MinimumPeriod = ConstU64<0>; + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type WeightInfo = (); +} + +impl pallet_authorship::Config for Runtime { + type EventHandler = (CollatorSelection,); + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; +} + +parameter_types! { + // increase ED 100 times to match system chains: 1_000_000_000 + pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT * 100; +} + +impl pallet_balances::Config for Runtime { + type AccountStore = System; + /// The type for recording an account's balance. + type Balance = Balance; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = VariantCountOf; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type RuntimeFreezeReason = RuntimeFreezeReason; + type RuntimeHoldReason = RuntimeHoldReason; + type WeightInfo = pallet_balances::weights::SubstrateWeight; +} + +parameter_types! { + /// Relay Chain `TransactionByteFee` / 10 + pub const TransactionByteFee: Balance = fee::TRANSACTION_BYTE_FEE; + pub SudoAddress: AccountId = AccountId::from_ss58check("15NMV2JX1NeMwarQiiZvuJ8ixUcvayFDcu1F9Wz1HNpSc8gP").expect("sudo address is valid SS58"); +} + +impl pallet_transaction_payment::Config for Runtime { + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type LengthToFee = ConstantMultiplier; + type OnChargeTransaction = + pallet_transaction_payment::FungibleAdapter>; + type OperationalFeeMultiplier = ConstU8<5>; + type RuntimeEvent = RuntimeEvent; + type WeightToFee = fee::WeightToFee; +} + +impl pallet_sudo::Config for Runtime { + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; +} + +type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< + Runtime, + RELAY_CHAIN_SLOT_DURATION_MILLIS, + BLOCK_PROCESSING_VELOCITY, + UNINCLUDED_SEGMENT_CAPACITY, +>; + +impl cumulus_pallet_parachain_system::Config for Runtime { + type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases; + type ConsensusHook = ConsensusHook; + type DmpQueue = frame_support::traits::EnqueueWithOrigin; + type OnSystemEvent = (); + type OutboundXcmpMessageSource = XcmpQueue; + type ReservedDmpWeight = ReservedDmpWeight; + type ReservedXcmpWeight = ReservedXcmpWeight; + type RuntimeEvent = RuntimeEvent; + type SelfParaId = parachain_info::Pallet; + type WeightInfo = (); + type XcmpMessageHandler = XcmpQueue; +} + +impl parachain_info::Config for Runtime {} + +parameter_types! { + pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; + pub MessageQueueIdleServiceWeight: Weight = Perbill::from_percent(20) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_message_queue::Config for Runtime { + type HeapSize = ConstU32<{ 64 * 1024 }>; + type IdleMaxServiceWeight = MessageQueueIdleServiceWeight; + type MaxStale = ConstU32<8>; + #[cfg(feature = "runtime-benchmarks")] + type MessageProcessor = + pallet_message_queue::mock_helpers::NoopMessageProcessor; + #[cfg(not(feature = "runtime-benchmarks"))] + type MessageProcessor = xcm_builder::ProcessXcmMessage< + AggregateMessageOrigin, + xcm_executor::XcmExecutor, + RuntimeCall, + >; + // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: + type QueueChangeHandler = NarrowOriginToSibling; + type QueuePausedQuery = NarrowOriginToSibling; + type RuntimeEvent = RuntimeEvent; + type ServiceWeight = MessageQueueServiceWeight; + type Size = u32; + type WeightInfo = (); +} + +impl cumulus_pallet_aura_ext::Config for Runtime {} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type ChannelInfo = ParachainSystem; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + // Limit the number of messages and signals a HRMP channel can have at most + type MaxActiveOutboundChannels = ConstU32<128>; + type MaxInboundSuspended = ConstU32<1_000>; + // Limit the number of HRMP channels + type MaxPageSize = ConstU32<{ 103 * 1024 }>; + type PriceForSiblingDelivery = NoPriceForMessageDelivery; + type RuntimeEvent = RuntimeEvent; + type VersionWrapper = PolkadotXcm; + type WeightInfo = (); + // Enqueue XCMP messages from siblings for later processing. + type XcmpQueue = TransformOrigin; +} + +parameter_types! { + pub const Period: u32 = 6 * HOURS; + pub const Offset: u32 = 0; +} + +impl pallet_session::Config for Runtime { + type Keys = SessionKeys; + type NextSessionRotation = pallet_session::PeriodicSessions; + type RuntimeEvent = RuntimeEvent; + // Essentially just Aura, but let's be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = CollatorSelection; + type ShouldEndSession = pallet_session::PeriodicSessions; + type ValidatorId = ::AccountId; + // we don't have stash and controller, thus we don't need the convert as well. + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type WeightInfo = (); +} + +impl pallet_aura::Config for Runtime { + type AllowMultipleBlocksPerSlot = ConstBool; + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = ConstU32<100_000>; + type SlotDuration = ConstU64; +} + +parameter_types! { + pub const PotId: PalletId = PalletId(*b"PotStake"); + // StakingAdmin pluralistic body. + pub const StakingAdminBodyId: BodyId = BodyId::Defense; +} + +/// We allow root and the StakingAdmin to execute privileged collator selection operations. +pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< + EnsureRoot, + EnsureXcm>, +>; + +impl pallet_collator_selection::Config for Runtime { + type Currency = Balances; + // should be a multiple of session or things will get inconsistent + type KickThreshold = Period; + type MaxCandidates = ConstU32<0>; + type MaxInvulnerables = ConstU32<20>; + type MinEligibleCollators = ConstU32<3>; + type PotId = PotId; + type RuntimeEvent = RuntimeEvent; + type UpdateOrigin = CollatorSelectionUpdateOrigin; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ValidatorRegistration = Session; + type WeightInfo = (); +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(60) * + RuntimeBlockWeights::get().max_block; +} + +impl pallet_scheduler::Config for Runtime { + #[cfg(feature = "runtime-benchmarks")] + type MaxScheduledPerBlock = ConstU32<512>; + #[cfg(not(feature = "runtime-benchmarks"))] + type MaxScheduledPerBlock = ConstU32<50>; + type MaximumWeight = MaximumSchedulerWeight; + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type PalletsOrigin = OriginCaller; + type Preimages = Preimage; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type ScheduleOrigin = EnsureRoot; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; +} + +parameter_types! { + pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage); + pub const PreimageBaseDeposit: Balance = deposit(2, 64); + pub const PreimageByteDeposit: Balance = deposit(0, 1); +} + +impl pallet_preimage::Config for Runtime { + type Consideration = HoldConsideration< + AccountId, + Balances, + PreimageHoldReason, + LinearStoragePrice, + >; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_preimage::weights::SubstrateWeight; +} + +parameter_types! { + // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. + pub const DepositBase: Balance = deposit(1, 88); + // Additional storage item size of 32 bytes. + pub const DepositFactor: Balance = deposit(0, 32); + pub const MaxSignatories: u32 = 100; +} + +impl pallet_multisig::Config for Runtime { + type Currency = Balances; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; + type MaxSignatories = MaxSignatories; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_multisig::weights::SubstrateWeight; +} + +impl pallet_utility::Config for Runtime { + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_utility::weights::SubstrateWeight; +} + +#[frame_support::runtime] +mod runtime { + // Create the runtime by composing the FRAME pallets that were previously configured. + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + // System support stuff. + #[runtime::pallet_index(0)] + pub type System = frame_system::Pallet; + #[runtime::pallet_index(1)] + pub type ParachainSystem = cumulus_pallet_parachain_system::Pallet; + #[runtime::pallet_index(2)] + pub type Timestamp = pallet_timestamp::Pallet; + #[runtime::pallet_index(3)] + pub type ParachainInfo = parachain_info::Pallet; + + // Monetary stuff. + #[runtime::pallet_index(10)] + pub type Balances = pallet_balances::Pallet; + #[runtime::pallet_index(11)] + pub type TransactionPayment = pallet_transaction_payment::Pallet; + + // Governance + #[runtime::pallet_index(15)] + pub type Sudo = pallet_sudo; + + // Collator support. The order of these 4 are important and shall not change. + #[runtime::pallet_index(20)] + pub type Authorship = pallet_authorship::Pallet; + #[runtime::pallet_index(21)] + pub type CollatorSelection = pallet_collator_selection::Pallet; + #[runtime::pallet_index(22)] + pub type Session = pallet_session::Pallet; + #[runtime::pallet_index(23)] + pub type Aura = pallet_aura::Pallet; + #[runtime::pallet_index(24)] + pub type AuraExt = cumulus_pallet_aura_ext; + + // Scheduler + #[runtime::pallet_index(28)] + pub type Scheduler = pallet_scheduler; + + // Preimage + #[runtime::pallet_index(29)] + pub type Preimage = pallet_preimage; + + // XCM helpers. + #[runtime::pallet_index(30)] + pub type XcmpQueue = cumulus_pallet_xcmp_queue::Pallet; + #[runtime::pallet_index(31)] + pub type PolkadotXcm = pallet_xcm::Pallet; + #[runtime::pallet_index(32)] + pub type CumulusXcm = cumulus_pallet_xcm::Pallet; + #[runtime::pallet_index(33)] + pub type MessageQueue = pallet_message_queue::Pallet; + + // Proxy + #[runtime::pallet_index(41)] + pub type Proxy = pallet_proxy::Pallet; + // Multisig + #[runtime::pallet_index(42)] + pub type Multisig = pallet_multisig::Pallet; + // Utility + #[runtime::pallet_index(43)] + pub type Utility = pallet_utility::Pallet; +} + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + [pallet_session, SessionBench::] + [pallet_timestamp, Timestamp] + [pallet_message_queue, MessageQueue] + [pallet_sudo, Sudo] + [pallet_collator_selection, CollatorSelection] + [cumulus_pallet_parachain_system, ParachainSystem] + [cumulus_pallet_xcmp_queue, XcmpQueue] + ); +} + +impl_runtime_apis! { + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION) + } + + fn authorities() -> Vec { + pallet_aura::Authorities::::get().into_inner() + } + } + + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) -> ExtrinsicInclusionMode{ + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + OpaqueMetadata::new(Runtime::metadata().into()) + } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx, block_hash) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + SessionKeys::generate(seed) + } + + fn decode_session_keys( + encoded: Vec, + ) -> Option, KeyTypeId)>> { + SessionKeys::decode_into_raw_public_keys(&encoded) + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Nonce { + System::account_nonce(account) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + fn query_fee_details( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi + for Runtime + { + fn query_call_info( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::RuntimeDispatchInfo { + TransactionPayment::query_call_info(call, len) + } + fn query_call_fee_details( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_call_fee_details(call, len) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + impl cumulus_primitives_aura::AuraUnincludedSegmentApi for Runtime { + fn can_build_upon( + included_hash: ::Hash, + slot: cumulus_primitives_aura::Slot, + ) -> bool { + ConsensusHook::can_build_upon(included_hash, slot) + } + } + + impl cumulus_primitives_core::CollectCollationInfo for Runtime { + fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { + ParachainSystem::collect_collation_info(header) + } + } + + #[cfg(feature = "try-runtime")] + impl frame_try_runtime::TryRuntime for Runtime { + fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { + let weight = Executive::try_runtime_upgrade(checks).unwrap(); + (weight, RuntimeBlockWeights::get().max_block) + } + + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect, + ) -> Weight { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. + Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn benchmark_metadata(extra: bool) -> ( + Vec, + Vec, + ) { + use frame_benchmarking::{Benchmarking, BenchmarkList}; + use frame_support::traits::StorageInfoTrait; + use frame_system_benchmarking::Pallet as SystemBench; + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + + let mut list = Vec::::new(); + list_benchmarks!(list, extra); + + let storage_info = AllPalletsWithSystem::storage_info(); + (list, storage_info) + } + + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{BenchmarkError, Benchmarking, BenchmarkBatch}; + + use frame_system_benchmarking::Pallet as SystemBench; + impl frame_system_benchmarking::Config for Runtime { + fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { + ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); + Ok(()) + } + + fn verify_set_code() { + System::assert_last_event(cumulus_pallet_parachain_system::Event::::ValidationFunctionStored.into()); + } + } + + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + impl cumulus_pallet_session_benchmarking::Config for Runtime {} + + use frame_support::traits::WhitelistedStorageKeys; + let whitelist = AllPalletsWithSystem::whitelisted_storage_keys(); + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + add_benchmarks!(params, batches); + + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } + Ok(batches) + } + } + + impl sp_genesis_builder::GenesisBuilder for Runtime { + fn build_state(config: Vec) -> sp_genesis_builder::Result { + build_state::(config) + } + + fn get_preset(id: &Option) -> Option> { + get_preset::(id, |_| None) + } + + fn preset_names() -> Vec { + Default::default() + } + } +} + +cumulus_pallet_parachain_system::register_validate_block! { + Runtime = Runtime, + BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, +} + +#[cfg(test)] +mod tests { + use std::any::TypeId; + + use pallet_balances::AdjustmentDirection; + use BalancesCall::*; + use RuntimeCall::Balances; + + use super::*; + #[test] + fn filtering_force_adjust_total_issuance_works() { + assert!(FilteredCalls::contains(&Balances(force_adjust_total_issuance { + direction: AdjustmentDirection::Increase, + delta: 0 + }))); + } + + #[test] + fn filtering_force_set_balance_works() { + assert!(FilteredCalls::contains(&Balances(force_set_balance { + who: MultiAddress::Address32([0u8; 32]), + new_free: 0, + }))); + } + + #[test] + fn filtering_force_transfer_works() { + assert!(FilteredCalls::contains(&Balances(force_transfer { + source: MultiAddress::Address32([0u8; 32]), + dest: MultiAddress::Address32([0u8; 32]), + value: 0, + }))); + } + + #[test] + fn filtering_force_unreserve_works() { + assert!(FilteredCalls::contains(&Balances(force_unreserve { + who: MultiAddress::Address32([0u8; 32]), + amount: 0 + }))); + } + + #[test] + fn filtering_configured() { + assert_eq!( + TypeId::of::<::BaseCallFilter>(), + TypeId::of::>(), + ); + } + + #[test] + fn ed_is_correct() { + assert_eq!(ExistentialDeposit::get(), EXISTENTIAL_DEPOSIT * 100); + assert_eq!(ExistentialDeposit::get(), 1_000_000_000); + } + + #[test] + fn units_are_correct() { + // UNIT should have 10 decimals + assert_eq!(UNIT, 10_000_000_000); + assert_eq!(MILLIUNIT, 10_000_000); + assert_eq!(MICROUNIT, 10_000); + + // fee specific units + assert_eq!(fee::CENTS, 100_000_000); + assert_eq!(fee::MILLICENTS, 100_000); + } + + #[test] + fn transaction_byte_fee_is_correct() { + assert_eq!(fee::TRANSACTION_BYTE_FEE, 50_000); + } + + #[test] + fn deposit_works() { + const UNITS: Balance = 10_000_000_000; + const DOLLARS: Balance = UNITS; // 10_000_000_000 + const CENTS: Balance = DOLLARS / 100; // 100_000_000 + const MILLICENTS: Balance = CENTS / 1_000; // 100_000 + + // https://github.com/polkadot-fellows/runtimes/blob/e220854a081f30183999848ce6c11ca62647bcfa/relay/polkadot/constants/src/lib.rs#L36 + fn relay_deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 20 * DOLLARS + (bytes as Balance) * 100 * MILLICENTS + } + + // https://github.com/polkadot-fellows/runtimes/blob/e220854a081f30183999848ce6c11ca62647bcfa/system-parachains/constants/src/polkadot.rs#L70 + fn system_para_deposit(items: u32, bytes: u32) -> Balance { + relay_deposit(items, bytes) / 100 + } + + assert_eq!(deposit(2, 64), system_para_deposit(2, 64)) + } +} diff --git a/runtime/mainnet/src/weights/block_weights.rs b/runtime/mainnet/src/weights/block_weights.rs new file mode 100644 index 00000000..e7fdb2aa --- /dev/null +++ b/runtime/mainnet/src/weights/block_weights.rs @@ -0,0 +1,53 @@ +// 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. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, Weight}, + }; + + parameter_types! { + /// Importing a block with 0 Extrinsics. + pub const BlockExecutionWeight: Weight = + Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000), 0); + } + + #[cfg(test)] + mod test_weights { + use frame_support::weights::constants; + + /// Checks that the weight exists and is sane. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + let w = super::constants::BlockExecutionWeight::get(); + + // At least 100 µs. + assert!( + w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, + "Weight should be at least 100 µs." + ); + // At most 50 ms. + assert!( + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 50 ms." + ); + } + } +} diff --git a/runtime/mainnet/src/weights/extrinsic_weights.rs b/runtime/mainnet/src/weights/extrinsic_weights.rs new file mode 100644 index 00000000..1a4adb96 --- /dev/null +++ b/runtime/mainnet/src/weights/extrinsic_weights.rs @@ -0,0 +1,53 @@ +// 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. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, Weight}, + }; + + parameter_types! { + /// Executing a NO-OP `System::remarks` Extrinsic. + pub const ExtrinsicBaseWeight: Weight = + Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000), 0); + } + + #[cfg(test)] + mod test_weights { + use frame_support::weights::constants; + + /// Checks that the weight exists and is sane. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + let w = super::constants::ExtrinsicBaseWeight::get(); + + // At least 10 µs. + assert!( + w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, + "Weight should be at least 10 µs." + ); + // At most 1 ms. + assert!( + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 1 ms." + ); + } + } +} diff --git a/runtime/mainnet/src/weights/mod.rs b/runtime/mainnet/src/weights/mod.rs new file mode 100644 index 00000000..b473d49e --- /dev/null +++ b/runtime/mainnet/src/weights/mod.rs @@ -0,0 +1,27 @@ +// 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. + +//! Expose the auto generated weight files. + +pub mod block_weights; +pub mod extrinsic_weights; +pub mod paritydb_weights; +pub mod rocksdb_weights; + +pub use block_weights::constants::BlockExecutionWeight; +pub use extrinsic_weights::constants::ExtrinsicBaseWeight; +pub use rocksdb_weights::constants::RocksDbWeight; diff --git a/runtime/mainnet/src/weights/paritydb_weights.rs b/runtime/mainnet/src/weights/paritydb_weights.rs new file mode 100644 index 00000000..27f7f1b0 --- /dev/null +++ b/runtime/mainnet/src/weights/paritydb_weights.rs @@ -0,0 +1,64 @@ +// 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. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, RuntimeDbWeight}, + }; + + parameter_types! { + /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights + /// are available for brave runtime engineers who may want to try this out as default. + pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 8_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 50_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + }; + } + + #[cfg(test)] + mod test_db_weights { + use frame_support::weights::constants; + + use super::constants::ParityDbWeight as W; + + /// Checks that all weights exist and have sane values. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + // At least 1 µs. + assert!( + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/runtime/mainnet/src/weights/rocksdb_weights.rs b/runtime/mainnet/src/weights/rocksdb_weights.rs new file mode 100644 index 00000000..bacad98c --- /dev/null +++ b/runtime/mainnet/src/weights/rocksdb_weights.rs @@ -0,0 +1,64 @@ +// 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. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, RuntimeDbWeight}, + }; + + parameter_types! { + /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout + /// the runtime. + pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 25_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 100_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + }; + } + + #[cfg(test)] + mod test_db_weights { + use frame_support::weights::constants; + + use super::constants::RocksDbWeight as W; + + /// Checks that all weights exist and have sane values. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + // At least 1 µs. + assert!( + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/runtime/testnet/Cargo.toml b/runtime/testnet/Cargo.toml index 53d20552..54fe7632 100644 --- a/runtime/testnet/Cargo.toml +++ b/runtime/testnet/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "pop-runtime-testnet" -version = "0.2.0" authors.workspace = true description.workspace = true -license = "Unlicense" +edition.workspace = true homepage.workspace = true +license = "Unlicense" +name = "pop-runtime-testnet" repository.workspace = true -edition.workspace = true +version = "0.4.1" [package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +targets = [ "x86_64-unknown-linux-gnu" ] [build-dependencies] substrate-wasm-builder.workspace = true @@ -28,14 +28,15 @@ pop-runtime-common.workspace = true # Substrate frame-benchmarking.workspace = true frame-executive.workspace = true +frame-metadata-hash-extension.workspace = true frame-support.workspace = true frame-system.workspace = true frame-system-benchmarking.workspace = true frame-system-rpc-runtime-api.workspace = true frame-try-runtime.workspace = true +pallet-assets.workspace = true pallet-aura.workspace = true pallet-authorship.workspace = true -pallet-assets.workspace = true pallet-balances.workspace = true pallet-contracts.workspace = true pallet-message-queue.workspace = true @@ -43,22 +44,22 @@ pallet-multisig.workspace = true pallet-nft-fractionalization.workspace = true pallet-nfts.workspace = true pallet-nfts-runtime-api.workspace = true +pallet-preimage.workspace = true +pallet-proxy.workspace = true pallet-scheduler.workspace = true pallet-session.workspace = true pallet-sudo.workspace = true -pallet-preimage.workspace = true -pallet-proxy.workspace = true pallet-timestamp.workspace = true pallet-transaction-payment.workspace = true pallet-transaction-payment-rpc-runtime-api.workspace = true pallet-utility.workspace = true sp-api.workspace = true -sp-io.workspace = true sp-block-builder.workspace = true sp-consensus-aura.workspace = true sp-core.workspace = true sp-genesis-builder.workspace = true sp-inherents.workspace = true +sp-io.workspace = true sp-offchain.workspace = true sp-runtime.workspace = true sp-session.workspace = true @@ -82,142 +83,161 @@ cumulus-pallet-xcm.workspace = true cumulus-pallet-xcmp-queue.workspace = true cumulus-primitives-aura.workspace = true cumulus-primitives-core.workspace = true +cumulus-primitives-storage-weight-reclaim.workspace = true cumulus-primitives-utility.workspace = true pallet-collator-selection.workspace = true -parachains-common.workspace = true parachain-info.workspace = true +parachains-common.workspace = true [dev-dependencies] +enumflags2 = "0.7.9" env_logger = "0.11.2" hex = "0.4.3" [features] -default = ["std"] +default = [ "std" ] std = [ - "codec/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-session-benchmarking/std", - "cumulus-pallet-xcm/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-primitives-aura/std", - "cumulus-primitives-core/std", - "cumulus-primitives-utility/std", - "frame-benchmarking/std", - "frame-executive/std", - "frame-support/std", - "frame-system-benchmarking/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "frame-try-runtime/std", - "log/std", - "pallet-aura/std", - "pallet-authorship/std", - "pallet-assets/std", - "pallet-balances/std", - "pallet-collator-selection/std", - "pallet-contracts/std", - "pallet-message-queue/std", - "pallet-multisig/std", - "pallet-nft-fractionalization/std", - "pallet-nfts/std", - "pallet-nfts-runtime-api/std", - "pallet-scheduler/std", - "pallet-session/std", - "pallet-sudo/std", - "pallet-preimage/std", - "pallet-proxy/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-utility/std", - "pallet-xcm/std", - "parachain-info/std", - "parachains-common/std", - "polkadot-parachain-primitives/std", - "polkadot-runtime-common/std", - "pop-primitives/std", - "scale-info/std", - "sp-api/std", - "sp-io/std", - "sp-block-builder/std", - "sp-consensus-aura/std", - "sp-core/std", - "sp-genesis-builder/std", - "sp-inherents/std", - "sp-offchain/std", - "sp-runtime/std", - "sp-session/std", - "sp-std/std", - "sp-transaction-pool/std", - "sp-version/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", + "codec/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-session-benchmarking/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-aura/std", + "cumulus-primitives-core/std", + "cumulus-primitives-storage-weight-reclaim/std", + "cumulus-primitives-utility/std", + "frame-benchmarking/std", + "frame-executive/std", + "frame-metadata-hash-extension/std", + "frame-support/std", + "frame-system-benchmarking/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "frame-try-runtime/std", + "log/std", + "pallet-assets/std", + "pallet-aura/std", + "pallet-authorship/std", + "pallet-balances/std", + "pallet-collator-selection/std", + "pallet-contracts/std", + "pallet-message-queue/std", + "pallet-multisig/std", + "pallet-nft-fractionalization/std", + "pallet-nfts-runtime-api/std", + "pallet-nfts/std", + "pallet-preimage/std", + "pallet-proxy/std", + "pallet-scheduler/std", + "pallet-session/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-utility/std", + "pallet-xcm/std", + "parachain-info/std", + "parachains-common/std", + "polkadot-parachain-primitives/std", + "polkadot-runtime-common/std", + "pop-primitives/std", + "pop-runtime-common/std", + "scale-info/std", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-genesis-builder/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm/std", ] runtime-benchmarks = [ - "cumulus-pallet-parachain-system/runtime-benchmarks", - "cumulus-pallet-session-benchmarking/runtime-benchmarks", - "cumulus-pallet-xcmp-queue/runtime-benchmarks", - "cumulus-primitives-core/runtime-benchmarks", - "cumulus-primitives-utility/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-collator-selection/runtime-benchmarks", - "pallet-contracts/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "pallet-multisig/runtime-benchmarks", - "pallet-nft-fractionalization/runtime-benchmarks", - "pallet-nfts/runtime-benchmarks", - "pallet-scheduler/runtime-benchmarks", - "pallet-sudo/runtime-benchmarks", - "pallet-preimage/runtime-benchmarks", - "pallet-proxy/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks", - "pallet-utility/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "parachains-common/runtime-benchmarks", - "polkadot-parachain-primitives/runtime-benchmarks", - "polkadot-runtime-common/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", + "cumulus-pallet-parachain-system/runtime-benchmarks", + "cumulus-pallet-session-benchmarking/runtime-benchmarks", + "cumulus-pallet-xcmp-queue/runtime-benchmarks", + "cumulus-primitives-core/runtime-benchmarks", + "cumulus-primitives-utility/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-collator-selection/runtime-benchmarks", + "pallet-contracts/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-nft-fractionalization/runtime-benchmarks", + "pallet-nfts/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", + "pallet-sudo/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "parachains-common/runtime-benchmarks", + "polkadot-parachain-primitives/runtime-benchmarks", + "polkadot-runtime-common/runtime-benchmarks", + "pop-runtime-common/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", ] try-runtime = [ - "cumulus-pallet-aura-ext/try-runtime", - "cumulus-pallet-parachain-system/try-runtime", - "cumulus-pallet-xcm/try-runtime", - "cumulus-pallet-xcmp-queue/try-runtime", - "frame-executive/try-runtime", - "frame-support/try-runtime", - "frame-system/try-runtime", - "frame-try-runtime/try-runtime", - "pallet-aura/try-runtime", - "pallet-authorship/try-runtime", - "pallet-assets/try-runtime", - "pallet-balances/try-runtime", - "pallet-collator-selection/try-runtime", - "pallet-contracts/try-runtime", - "pallet-message-queue/try-runtime", - "pallet-multisig/try-runtime", - "pallet-nft-fractionalization/try-runtime", - "pallet-nfts/try-runtime", - "pallet-scheduler/try-runtime", - "pallet-session/try-runtime", - "pallet-sudo/try-runtime", - "pallet-preimage/try-runtime", - "pallet-proxy/try-runtime", - "pallet-timestamp/try-runtime", - "pallet-transaction-payment/try-runtime", - "pallet-utility/try-runtime", - "pallet-xcm/try-runtime", - "parachain-info/try-runtime", - "polkadot-runtime-common/try-runtime", - "sp-runtime/try-runtime", -] \ No newline at end of file + "cumulus-pallet-aura-ext/try-runtime", + "cumulus-pallet-parachain-system/try-runtime", + "cumulus-pallet-xcm/try-runtime", + "cumulus-pallet-xcmp-queue/try-runtime", + "frame-executive/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", + "pallet-assets/try-runtime", + "pallet-aura/try-runtime", + "pallet-authorship/try-runtime", + "pallet-balances/try-runtime", + "pallet-collator-selection/try-runtime", + "pallet-contracts/try-runtime", + "pallet-message-queue/try-runtime", + "pallet-multisig/try-runtime", + "pallet-nft-fractionalization/try-runtime", + "pallet-nfts/try-runtime", + "pallet-preimage/try-runtime", + "pallet-proxy/try-runtime", + "pallet-scheduler/try-runtime", + "pallet-session/try-runtime", + "pallet-sudo/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-transaction-payment/try-runtime", + "pallet-utility/try-runtime", + "pallet-xcm/try-runtime", + "parachain-info/try-runtime", + "polkadot-runtime-common/try-runtime", + "sp-runtime/try-runtime", +] + +# Enable the metadata hash generation. +# +# This is hidden behind a feature because it increases the compile time. +# The wasm binary needs to be compiled twice, once to fetch the metadata, +# generate the metadata hash and then a second time with the +# `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash` +# extension. +metadata-hash = [ "substrate-wasm-builder/metadata-hash" ] + +# A convenience feature for enabling things when doing a build +# for an on-chain release. +on-chain-release-build = [ "metadata-hash" ] diff --git a/runtime/testnet/build.rs b/runtime/testnet/build.rs index 02d6973f..6293cebb 100644 --- a/runtime/testnet/build.rs +++ b/runtime/testnet/build.rs @@ -1,12 +1,15 @@ -#[cfg(feature = "std")] +#[cfg(all(feature = "std", feature = "metadata-hash"))] fn main() { - substrate_wasm_builder::WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("PAS", 10) .build() } +#[cfg(all(feature = "std", not(feature = "metadata-hash")))] +fn main() { + substrate_wasm_builder::WasmBuilder::build_using_defaults() +} + /// The wasm builder is deactivated when compiling /// this crate for wasm to speed up the compilation. #[cfg(not(feature = "std"))] diff --git a/runtime/testnet/src/config/assets.rs b/runtime/testnet/src/config/assets.rs index 2c8ea952..91322ecf 100644 --- a/runtime/testnet/src/config/assets.rs +++ b/runtime/testnet/src/config/assets.rs @@ -1,7 +1,3 @@ -use crate::{ - deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, - RuntimeHoldReason, DAYS, EXISTENTIAL_DEPOSIT, UNIT, -}; use frame_support::{ parameter_types, traits::{AsEnsureOriginWithArg, ConstU32}, @@ -12,6 +8,11 @@ use pallet_nfts::PalletFeatures; use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId, Signature}; use sp_runtime::traits::Verify; +use crate::{ + deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, + RuntimeHoldReason, DAYS, EXISTENTIAL_DEPOSIT, UNIT, +}; + /// We allow root to execute privileged asset operations. pub type AssetsForceOrigin = EnsureRoot; @@ -37,36 +38,36 @@ parameter_types! { } impl pallet_nfts::Config for Runtime { - type RuntimeEvent = RuntimeEvent; // TODO: source from primitives - type CollectionId = CollectionId; + type ApprovalsLimit = ConstU32<20>; + type AttributeDepositBase = NftsAttributeDepositBase; + type CollectionDeposit = NftsCollectionDeposit; // TODO: source from primitives - type ItemId = ItemId; - type Currency = Balances; + type CollectionId = CollectionId; type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type DepositPerByte = NftsDepositPerByte; + type Features = NftsPalletFeatures; type ForceOrigin = AssetsForceOrigin; - type Locker = (); - type CollectionDeposit = NftsCollectionDeposit; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); + type ItemAttributesApprovalsLimit = ConstU32<30>; type ItemDeposit = NftsItemDeposit; - type MetadataDepositBase = NftsMetadataDepositBase; - type AttributeDepositBase = NftsAttributeDepositBase; - type DepositPerByte = NftsDepositPerByte; - type StringLimit = ConstU32<256>; // TODO: source from primitives - type KeyLimit = ConstU32<64>; - type ValueLimit = ConstU32<256>; + type ItemId = ItemId; // TODO: source from primitives - type ApprovalsLimit = ConstU32<20>; - type ItemAttributesApprovalsLimit = ConstU32<30>; - type MaxTips = ConstU32<10>; - type MaxDeadlineDuration = NftsMaxDeadlineDuration; + type KeyLimit = ConstU32<64>; + type Locker = (); type MaxAttributesPerCall = ConstU32<10>; - type Features = NftsPalletFeatures; - type OffchainSignature = Signature; + type MaxDeadlineDuration = NftsMaxDeadlineDuration; + type MaxTips = ConstU32<10>; + type MetadataDepositBase = NftsMetadataDepositBase; type OffchainPublic = ::Signer; + type OffchainSignature = Signature; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<256>; + type ValueLimit = ConstU32<256>; type WeightInfo = pallet_nfts::weights::SubstrateWeight; - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); } parameter_types! { @@ -76,46 +77,46 @@ parameter_types! { } impl pallet_nft_fractionalization::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Deposit = AssetDeposit; + type AssetBalance = >::Balance; + type AssetId = >::AssetId; + type Assets = Assets; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type Currency = Balances; - type NewAssetSymbol = NewAssetSymbol; + type Deposit = AssetDeposit; type NewAssetName = NewAssetName; - type StringLimit = AssetsStringLimit; + type NewAssetSymbol = NewAssetSymbol; type NftCollectionId = ::CollectionId; type NftId = ::ItemId; - type AssetBalance = >::Balance; - type AssetId = >::AssetId; - type Assets = Assets; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; - type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight; + type RuntimeEvent = RuntimeEvent; type RuntimeHoldReason = RuntimeHoldReason; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type StringLimit = AssetsStringLimit; + type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight; } pub type TrustBackedAssetsInstance = pallet_assets::Instance1; -pub(crate) type AssetsCall = pallet_assets::Call; +pub type TrustBackedAssetsCall = pallet_assets::Call; impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; + type ApprovalDeposit = ApprovalDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = AssetIdForTrustBackedAssets; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = AssetsForceOrigin; - type AssetDeposit = AssetDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type RemoveItemsLimit = ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); type WeightInfo = pallet_assets::weights::SubstrateWeight; - type CallbackHandle = (); - type AssetAccountDeposit = AssetAccountDeposit; - type RemoveItemsLimit = ConstU32<1000>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } diff --git a/runtime/testnet/src/config/contracts.rs b/runtime/testnet/src/config/contracts.rs index 36d62f7f..f052b1d3 100644 --- a/runtime/testnet/src/config/contracts.rs +++ b/runtime/testnet/src/config/contracts.rs @@ -1,12 +1,13 @@ -use crate::{ - deposit, extensions, Balance, Balances, BalancesCall, Perbill, Runtime, RuntimeCall, - RuntimeEvent, RuntimeHoldReason, Timestamp, -}; use frame_support::{ parameter_types, traits::{ConstBool, ConstU32, Randomness}, }; -use frame_system::pallet_prelude::BlockNumberFor; +use frame_system::{pallet_prelude::BlockNumberFor, EnsureSigned}; + +use crate::{ + deposit, extensions, Balance, Balances, BalancesCall, Perbill, Runtime, RuntimeCall, + RuntimeEvent, RuntimeHoldReason, Timestamp, +}; pub enum AllowBalancesCall {} @@ -45,12 +46,8 @@ parameter_types! { } impl pallet_contracts::Config for Runtime { - type Time = Timestamp; - type Randomness = DummyRandomness; - type Currency = Balances; - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - + type AddressGenerator = pallet_contracts::DefaultAddressGenerator; + type ApiVersion = (); /// The safest default is to allow no calls at all. /// /// Runtimes should whitelist dispatchables that are allowed to be called from contracts @@ -58,14 +55,16 @@ impl pallet_contracts::Config for Runtime { /// change because that would break already deployed contracts. The `RuntimeCall` structure /// itself is not allowed to change the indices of existing pallets, too. type CallFilter = AllowBalancesCall; - type DepositPerItem = DepositPerItem; - type DepositPerByte = DepositPerByte; type CallStack = [pallet_contracts::Frame; 23]; - type WeightPrice = pallet_transaction_payment::Pallet; - type WeightInfo = pallet_contracts::weights::SubstrateWeight; type ChainExtension = extensions::PopApiExtension; - type Schedule = Schedule; - type AddressGenerator = pallet_contracts::DefaultAddressGenerator; + type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; + type Currency = Balances; + type Debug = (); + type DefaultDepositLimit = DefaultDepositLimit; + type DepositPerByte = DepositPerByte; + type DepositPerItem = DepositPerItem; + type Environment = (); + type InstantiateOrigin = EnsureSigned; // This node is geared towards development and testing of contracts. // We decided to increase the default allowed contract size for this // reason (the default is `128 * 1024`). @@ -75,16 +74,19 @@ impl pallet_contracts::Config for Runtime { // less friction during development when the requirement here is // just more lax. type MaxCodeLen = ConstU32<{ 256 * 1024 }>; - type DefaultDepositLimit = DefaultDepositLimit; - type MaxStorageKeyLen = ConstU32<128>; type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; - type UnsafeUnstableInterface = ConstBool; - type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; type MaxDelegateDependencies = ConstU32<32>; + type MaxStorageKeyLen = ConstU32<128>; + type Migrations = (pallet_contracts::migration::v16::Migration,); + type Randomness = DummyRandomness; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type RuntimeHoldReason = RuntimeHoldReason; - - type Environment = (); - type Debug = (); - type Migrations = (); + type Schedule = Schedule; + type Time = Timestamp; + type UnsafeUnstableInterface = ConstBool; + type UploadOrigin = EnsureSigned; + type WeightInfo = pallet_contracts::weights::SubstrateWeight; + type WeightPrice = pallet_transaction_payment::Pallet; type Xcm = pallet_xcm::Pallet; } diff --git a/runtime/testnet/src/config/proxy.rs b/runtime/testnet/src/config/proxy.rs index c1142126..ff70240e 100644 --- a/runtime/testnet/src/config/proxy.rs +++ b/runtime/testnet/src/config/proxy.rs @@ -1,5 +1,3 @@ -use super::assets::AssetsCall; -use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; use frame_support::traits::InstanceFilter; use pop_runtime_common::proxy::{ AnnouncementDepositBase, AnnouncementDepositFactor, MaxPending, MaxProxies, ProxyDepositBase, @@ -7,6 +5,9 @@ use pop_runtime_common::proxy::{ }; use sp_runtime::traits::BlakeTwo256; +use super::assets::TrustBackedAssetsCall; +use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; + impl InstanceFilter for ProxyType { fn filter(&self, c: &RuntimeCall) -> bool { match self { @@ -34,16 +35,16 @@ impl InstanceFilter for ProxyType { }, ProxyType::AssetOwner => matches!( c, - RuntimeCall::Assets(AssetsCall::create { .. }) | - RuntimeCall::Assets(AssetsCall::start_destroy { .. }) | - RuntimeCall::Assets(AssetsCall::destroy_accounts { .. }) | - RuntimeCall::Assets(AssetsCall::destroy_approvals { .. }) | - RuntimeCall::Assets(AssetsCall::finish_destroy { .. }) | - RuntimeCall::Assets(AssetsCall::transfer_ownership { .. }) | - RuntimeCall::Assets(AssetsCall::set_team { .. }) | - RuntimeCall::Assets(AssetsCall::set_metadata { .. }) | - RuntimeCall::Assets(AssetsCall::clear_metadata { .. }) | - RuntimeCall::Assets(AssetsCall::set_min_balance { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | @@ -56,15 +57,15 @@ impl InstanceFilter for ProxyType { ), ProxyType::AssetManager => matches!( c, - RuntimeCall::Assets(AssetsCall::mint { .. }) | - RuntimeCall::Assets(AssetsCall::burn { .. }) | - RuntimeCall::Assets(AssetsCall::freeze { .. }) | - RuntimeCall::Assets(AssetsCall::block { .. }) | - RuntimeCall::Assets(AssetsCall::thaw { .. }) | - RuntimeCall::Assets(AssetsCall::freeze_asset { .. }) | - RuntimeCall::Assets(AssetsCall::thaw_asset { .. }) | - RuntimeCall::Assets(AssetsCall::touch_other { .. }) | - RuntimeCall::Assets(AssetsCall::refund_other { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | @@ -94,16 +95,16 @@ impl InstanceFilter for ProxyType { } impl pallet_proxy::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; + type AnnouncementDepositBase = AnnouncementDepositBase; + type AnnouncementDepositFactor = AnnouncementDepositFactor; + type CallHasher = BlakeTwo256; type Currency = Balances; - type ProxyType = ProxyType; + type MaxPending = MaxPending; + type MaxProxies = MaxProxies; type ProxyDepositBase = ProxyDepositBase; type ProxyDepositFactor = ProxyDepositFactor; - type MaxProxies = MaxProxies; + type ProxyType = ProxyType; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_proxy::weights::SubstrateWeight; - type MaxPending = MaxPending; - type CallHasher = BlakeTwo256; - type AnnouncementDepositBase = AnnouncementDepositBase; - type AnnouncementDepositFactor = AnnouncementDepositFactor; } diff --git a/runtime/testnet/src/config/xcm.rs b/runtime/testnet/src/config/xcm.rs index a5b7a04d..4fe54a4f 100644 --- a/runtime/testnet/src/config/xcm.rs +++ b/runtime/testnet/src/config/xcm.rs @@ -1,8 +1,5 @@ -use crate::{ - AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, - Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, -}; use core::marker::PhantomData; + use frame_support::{ parameter_types, traits::{ConstU32, Contains, ContainsPair, Everything, Get, Nothing}, @@ -13,24 +10,29 @@ use pallet_xcm::XcmPassthrough; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; use xcm::latest::prelude::*; -#[allow(deprecated)] -use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, - FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, - UsingComponents, WithComputedOrigin, WithUniqueTopic, + FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NativeAsset, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::XcmExecutor; +use crate::{ + AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, + Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, +}; + parameter_types! { pub const RelayLocation: Location = Location::parent(); pub AssetHub: Location = Location::new(1, [Parachain(1000)]); // Note: Paseo currently uses Polkadot https://github.com/paseo-network/runtimes/blob/abc4ae9c5ae8f0166aab7ef2b427b3c2c6d5ce5c/relay/paseo/src/xcm_config.rs#L56 pub const RelayNetwork: Option = Some(Polkadot); pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + // For the real deployment, it is recommended to set `RelayNetwork` according to the relay chain + // and prepend `UniversalLocation` with `GlobalConsensus(RelayNetwork::get())`. pub UniversalLocation: InteriorLocation = Parachain(ParachainInfo::parachain_id().into()).into(); } @@ -48,7 +50,7 @@ pub type LocationToAccountId = ( /// Means for transacting assets on this chain. #[allow(deprecated)] -pub type LocalAssetTransactor = CurrencyAdapter< +pub type LocalAssetTransactor = FungibleAdapter< // Use this currency: Balances, // Use this currency when it is a fungible asset matching the given location or name: @@ -125,33 +127,38 @@ pub type TrustedReserves = (NativeAsset, NativeAssetFrom); pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type Aliasers = Nothing; + type AssetClaims = PolkadotXcm; + type AssetExchanger = (); + type AssetLocker = (); // How to withdraw and deposit an asset. type AssetTransactor = LocalAssetTransactor; - type OriginConverter = XcmOriginToTransactDispatchOrigin; - type IsReserve = TrustedReserves; - type IsTeleporter = (); // Teleporting is disabled. - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = - UsingComponents>; - type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; - type AssetClaims = PolkadotXcm; - type SubscriptionService = PolkadotXcm; - type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); + type Barrier = Barrier; + type CallDispatcher = RuntimeCall; type FeeManager = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); + type HrmpNewChannelOpenRequestHandler = (); + type IsReserve = TrustedReserves; + type IsTeleporter = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type PalletInstancesInfo = AllPalletsWithSystem; + type ResponseHandler = PolkadotXcm; + type RuntimeCall = RuntimeCall; type SafeCallFilter = Everything; - type Aliasers = Nothing; + type SubscriptionService = PolkadotXcm; + type Trader = + UsingComponents>; type TransactionalProcessor = FrameTransactionalProcessor; + type UniversalAliases = Nothing; + // Teleporting is disabled. + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type XcmRecorder = PolkadotXcm; + type XcmSender = XcmRouter; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -167,34 +174,32 @@ pub type XcmRouter = WithUniqueTopic<( )>; impl pallet_xcm::Config for Runtime { + type AdminOrigin = EnsureRoot; + // ^ Override for AdvertisedXcmVersion default. + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type ExecuteXcmOrigin = EnsureXcmOrigin; + type MaxLockers = ConstU32<8>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Nothing; - // ^ Disable dispatchable execute on the XCM pallet. - // Needs to be `Everything` for local testing. + type SovereignAccountOf = LocationToAccountId; + type TrustedLockers = (); + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type WeightInfo = pallet_xcm::TestWeightInfo; + type XcmExecuteFilter = Everything; type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Nothing; // TODO: add filter to only allow reserve transfers of native to relay/asset hub type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; + type XcmRouter = XcmRouter; + type XcmTeleportFilter = Everything; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - // ^ Override for AdvertisedXcmVersion default - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = LocationToAccountId; - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index fc228b03..084778eb 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -3,8 +3,11 @@ use frame_support::{ pallet_prelude::*, traits::{Contains, OriginTrait}, }; -use pallet_contracts::chain_extension::{ - BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, +use pallet_contracts::{ + chain_extension::{ + BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, + }, + WeightInfo, }; use sp_core::crypto::UncheckedFrom; use sp_runtime::{traits::Dispatchable, DispatchError}; @@ -14,8 +17,6 @@ use crate::{AccountId, AllowedApiCalls, RuntimeCall, RuntimeOrigin}; const LOG_TARGET: &str = "pop-api::extension"; -type ContractSchedule = ::Schedule; - #[derive(Default)] pub struct PopApiExtension; @@ -29,10 +30,10 @@ where >, T::AccountId: UncheckedFrom + AsRef<[u8]>, { - fn call(&mut self, env: Environment) -> Result - where - E: Ext, - { + fn call>( + &mut self, + env: Environment, + ) -> Result { log::debug!(target:LOG_TARGET, " extension called "); match v0::FuncId::try_from(env.func_id())? { v0::FuncId::Dispatch => { @@ -123,16 +124,14 @@ where T: pallet_contracts::Config, E: Ext, { - let contract_host_weight = ContractSchedule::::get().host_fn_weights; - // calculate weight for reading bytes of `len` // reference: https://github.com/paritytech/polkadot-sdk/blob/117a9433dac88d5ac00c058c9b39c511d47749d2/substrate/frame/contracts/src/wasm/runtime.rs#L267 - let base_weight: Weight = contract_host_weight.return_per_byte.saturating_mul(len.into()); + let base_weight: Weight = T::WeightInfo::seal_return(len); // debug_message weight is a good approximation of the additional overhead of going // from contract layer to substrate layer. // reference: https://github.com/paritytech/ink-examples/blob/b8d2caa52cf4691e0ddd7c919e4462311deb5ad0/psp22-extension/runtime/psp22-extension-example.rs#L236 - let overhead = contract_host_weight.debug_message; + let overhead: Weight = T::WeightInfo::seal_debug_message(len); let charged_weight = env.charge_weight(base_weight.saturating_add(overhead))?; log::debug!(target: LOG_TARGET, "{} charged weight: {:?}", log_prefix, charged_weight); @@ -172,10 +171,7 @@ where let mut env = env.buf_in_buf_out(); // To be conservative, we charge the weight for reading the input bytes of a fixed-size type. - let base_weight: Weight = ContractSchedule::::get() - .host_fn_weights - .return_per_byte - .saturating_mul(env.in_len().into()); + let base_weight: Weight = T::WeightInfo::seal_return(env.in_len()); let charged_weight = env.charge_weight(base_weight)?; log::debug!(target:LOG_TARGET, "{} charged weight: {:?}", LOG_PREFIX, charged_weight); diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index 700257fa..c39d9928 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -10,34 +10,18 @@ mod config; mod extensions; mod weights; -use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; -use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; -use smallvec::smallvec; -use sp_api::impl_runtime_apis; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, - transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, -}; - -use sp_std::prelude::*; -#[cfg(feature = "std")] -use sp_version::NativeVersion; -use sp_version::RuntimeVersion; - use config::xcm::{RelayLocation, XcmOriginToTransactDispatchOrigin}; +use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; use frame_support::{ - construct_runtime, derive_impl, + derive_impl, dispatch::DispatchClass, - genesis_builder_helper::{build_config, create_default_config}, + genesis_builder_helper::{build_state, get_preset}, parameter_types, traits::{ fungible::HoldConsideration, tokens::nonfungibles_v2::Inspect, ConstBool, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, EverythingBut, - LinearStoragePrice, TransformOrigin, + LinearStoragePrice, TransformOrigin, VariantCountOf, }, weights::{ ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, @@ -49,26 +33,35 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, }; +use pallet_balances::Call as BalancesCall; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; +use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; +// Polkadot imports +use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; pub use pop_runtime_common::{ deposit, AuraId, Balance, BlockNumber, Hash, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, BLOCK_PROCESSING_VELOCITY, DAYS, EXISTENTIAL_DEPOSIT, HOURS, MAXIMUM_BLOCK_WEIGHT, MICROUNIT, MILLIUNIT, MINUTES, NORMAL_DISPATCH_RATIO, RELAY_CHAIN_SLOT_DURATION_MILLIS, SLOT_DURATION, UNINCLUDED_SEGMENT_CAPACITY, UNIT, }; -pub use sp_runtime::{MultiAddress, Perbill, Permill}; - +use smallvec::smallvec; +use sp_api::impl_runtime_apis; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; - -use pallet_balances::Call as BalancesCall; - -// Polkadot imports -use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; - +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, +}; +pub use sp_runtime::{ExtrinsicInclusionMode, MultiAddress, Perbill, Permill}; +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; - // XCM Imports use xcm::latest::prelude::BodyId; @@ -101,6 +94,8 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, + frame_metadata_hash_extension::CheckMetadataHash, ); /// Unchecked extrinsic type as expected by this runtime. @@ -108,7 +103,11 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. -pub type Migrations = (pallet_collator_selection::migration::v2::MigrationToV2,); +pub type Migrations = ( + pallet_contracts::Migration, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, + pallet_xcm::migration::MigrateToLatestXcmVersion, +); /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< @@ -133,6 +132,7 @@ pub type Executive = frame_executive::Executive< pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: // we map to 1/10 of that, or 1/10 MILLIUNIT @@ -152,13 +152,13 @@ impl WeightToFeePolynomial for WeightToFee { /// of data like extrinsics, allowing for them to continue syncing the network through upgrades /// to even the core data structures. pub mod opaque { - use super::*; + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; use sp_runtime::{ generic, traits::{BlakeTwo256, Hash as HashT}, }; - pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + use super::*; /// Opaque block header type. pub type Header = generic::Header; /// Opaque block type. @@ -181,7 +181,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_name: create_runtime_str!("pop"), authoring_version: 1, #[allow(clippy::zero_prefixed_literal)] - spec_version: 00_02_00, + spec_version: 00_04_01, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -233,7 +233,7 @@ parameter_types! { }) .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); - pub const SS58Prefix: u16 = 42; + pub const SS58Prefix: u16 = 0; } /// A type to identify filtered calls. @@ -264,48 +264,48 @@ impl Contains for AllowedApiCalls { /// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from /// [`ParaChainDefaultConfig`](`struct@frame_system::config_preludes::ParaChainDefaultConfig`), /// but overridden as needed. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; /// The identifier used to distinguish between accounts. type AccountId = AccountId; - /// The index type for storing how many extrinsics an account has signed. - type Nonce = Nonce; - /// The type for hashing blocks and tries. - type Hash = Hash; + /// The basic call filter to use in dispatchable. Supports everything as the default. + type BaseCallFilter = EverythingBut; /// The block type. type Block = Block; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount = BlockHashCount; - /// Runtime version. - type Version = Version; - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). type BlockLength = RuntimeBlockLength; - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; - /// The basic call filter to use in dispatchable. Supports everything as the default. - type BaseCallFilter = EverythingBut; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The type for hashing blocks and tries. + type Hash = Hash; + type MaxConsumers = frame_support::traits::ConstU32<16>; + /// The index type for storing how many extrinsics an account has signed. + type Nonce = Nonce; /// The action to take on a Runtime Upgrade type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = frame_support::traits::ConstU32<16>; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// Runtime version. + type Version = Version; } impl pallet_timestamp::Config for Runtime { + type MinimumPeriod = ConstU64<0>; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<0>; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type EventHandler = (CollatorSelection,); + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; } parameter_types! { @@ -313,21 +313,21 @@ parameter_types! { } impl pallet_balances::Config for Runtime { - type MaxLocks = ConstU32<50>; + type AccountStore = System; /// The type for recording an account's balance. type Balance = Balance; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = VariantCountOf; + type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; type RuntimeFreezeReason = RuntimeFreezeReason; - type FreezeIdentifier = (); - type MaxFreezes = ConstU32<0>; + type RuntimeHoldReason = RuntimeHoldReason; + type WeightInfo = pallet_balances::weights::SubstrateWeight; } parameter_types! { @@ -336,17 +336,17 @@ parameter_types! { } impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type LengthToFee = ConstantMultiplier; + type OnChargeTransaction = pallet_transaction_payment::FungibleAdapter; type OperationalFeeMultiplier = ConstU8<5>; + type RuntimeEvent = RuntimeEvent; + type WeightToFee = WeightToFee; } impl pallet_sudo::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -364,17 +364,17 @@ type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< >; impl cumulus_pallet_parachain_system::Config for Runtime { - type WeightInfo = (); - type RuntimeEvent = RuntimeEvent; + type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases; + type ConsensusHook = ConsensusHook; + type DmpQueue = frame_support::traits::EnqueueWithOrigin; type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; type OutboundXcmpMessageSource = XcmpQueue; - type DmpQueue = frame_support::traits::EnqueueWithOrigin; type ReservedDmpWeight = ReservedDmpWeight; - type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases; - type ConsensusHook = ConsensusHook; + type RuntimeEvent = RuntimeEvent; + type SelfParaId = parachain_info::Pallet; + type WeightInfo = (); + type XcmpMessageHandler = XcmpQueue; } impl parachain_info::Config for Runtime {} @@ -384,8 +384,9 @@ parameter_types! { } impl pallet_message_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; + type IdleMaxServiceWeight = (); + type MaxStale = sp_core::ConstU32<8>; #[cfg(feature = "runtime-benchmarks")] type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor< cumulus_primitives_core::AggregateMessageOrigin, @@ -396,28 +397,37 @@ impl pallet_message_queue::Config for Runtime { xcm_executor::XcmExecutor, RuntimeCall, >; - type Size = u32; // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; - type MaxStale = sp_core::ConstU32<8>; + type RuntimeEvent = RuntimeEvent; type ServiceWeight = MessageQueueServiceWeight; + type Size = u32; + type WeightInfo = (); } impl cumulus_pallet_aura_ext::Config for Runtime {} impl cumulus_pallet_xcmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type ChannelInfo = ParachainSystem; - type VersionWrapper = (); - // Enqueue XCMP messages from siblings for later processing. - type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type WeightInfo = (); + // Limit the number of messages and signals a HRML channel can have at most + type MaxActiveOutboundChannels = ConstU32<128>; + type MaxInboundSuspended = sp_core::ConstU32<1_000>; + // Limit the number of HRML channels + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type PriceForSiblingDelivery = NoPriceForMessageDelivery; + type RuntimeEvent = RuntimeEvent; + type VersionWrapper = (); + type WeightInfo = (); + // Enqueue XCMP messages from siblings for later processing. + type XcmpQueue = TransformOrigin; +} + +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; } parameter_types! { @@ -426,24 +436,24 @@ parameter_types! { } impl pallet_session::Config for Runtime { + type Keys = SessionKeys; + type NextSessionRotation = pallet_session::PeriodicSessions; type RuntimeEvent = RuntimeEvent; + // Essentially just Aura, but let's be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = CollatorSelection; + type ShouldEndSession = pallet_session::PeriodicSessions; type ValidatorId = ::AccountId; // we don't have stash and controller, thus we don't need the convert as well. type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = CollatorSelection; - // Essentially just Aura, but let's be pedantic. - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; type WeightInfo = (); } impl pallet_aura::Config for Runtime { + type AllowMultipleBlocksPerSlot = ConstBool; type AuthorityId = AuraId; type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; - type AllowMultipleBlocksPerSlot = ConstBool; type SlotDuration = ConstU64; } @@ -461,15 +471,15 @@ pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< >; impl pallet_collator_selection::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type UpdateOrigin = CollatorSelectionUpdateOrigin; - type PotId = PotId; - type MaxCandidates = ConstU32<100>; - type MinEligibleCollators = ConstU32<4>; - type MaxInvulnerables = ConstU32<20>; // should be a multiple of session or things will get inconsistent type KickThreshold = Period; + type MaxCandidates = ConstU32<100>; + type MaxInvulnerables = ConstU32<20>; + type MinEligibleCollators = ConstU32<4>; + type PotId = PotId; + type RuntimeEvent = RuntimeEvent; + type UpdateOrigin = CollatorSelectionUpdateOrigin; type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_collator_selection::IdentityCollator; type ValidatorRegistration = Session; @@ -482,19 +492,19 @@ parameter_types! { } impl pallet_scheduler::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type PalletsOrigin = OriginCaller; - type RuntimeCall = RuntimeCall; - type MaximumWeight = MaximumSchedulerWeight; - type ScheduleOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type MaxScheduledPerBlock = ConstU32<512>; #[cfg(not(feature = "runtime-benchmarks"))] type MaxScheduledPerBlock = ConstU32<50>; - type WeightInfo = pallet_scheduler::weights::SubstrateWeight; + type MaximumWeight = MaximumSchedulerWeight; type OriginPrivilegeCmp = EqualPrivilegeOnly; + type PalletsOrigin = OriginCaller; type Preimages = Preimage; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type ScheduleOrigin = EnsureRoot; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; } parameter_types! { @@ -504,16 +514,16 @@ parameter_types! { } impl pallet_preimage::Config for Runtime { - type WeightInfo = pallet_preimage::weights::SubstrateWeight; - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type ManagerOrigin = EnsureRoot; type Consideration = HoldConsideration< AccountId, Balances, PreimageHoldReason, LinearStoragePrice, >; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_preimage::weights::SubstrateWeight; } parameter_types! { @@ -525,73 +535,111 @@ parameter_types! { } impl pallet_multisig::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_multisig::weights::SubstrateWeight; } impl pallet_utility::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_utility::weights::SubstrateWeight; } -// Create the runtime by composing the FRAME pallets that were previously configured. -construct_runtime!( - pub enum Runtime { - // System support stuff. - System: frame_system = 0, - ParachainSystem: cumulus_pallet_parachain_system = 1, - Timestamp: pallet_timestamp = 2, - ParachainInfo: parachain_info = 3, - - // Monetary stuff. - Balances: pallet_balances = 10, - TransactionPayment: pallet_transaction_payment = 11, - - // Governance - Sudo: pallet_sudo = 15, - - // Collator support. The order of these 4 are important and shall not change. - Authorship: pallet_authorship = 20, - CollatorSelection: pallet_collator_selection = 21, - Session: pallet_session = 22, - Aura: pallet_aura = 23, - AuraExt: cumulus_pallet_aura_ext = 24, - - // Scheduler - Scheduler: pallet_scheduler = 28, - - // Preimage - Preimage: pallet_preimage = 29, - - // XCM helpers. - XcmpQueue: cumulus_pallet_xcmp_queue = 30, - PolkadotXcm: pallet_xcm = 31, - CumulusXcm: cumulus_pallet_xcm = 32, - MessageQueue: pallet_message_queue = 33, - - // Contracts - Contracts: pallet_contracts = 40, - - // Proxy - Proxy: pallet_proxy = 41, - // Multisig - Multisig: pallet_multisig = 42, - // Utility - Utility: pallet_utility = 43, - - // Assets - Nfts: pallet_nfts = 50, - NftFractionalization: pallet_nft_fractionalization = 51, - Assets: pallet_assets:: = 52, - } -); +#[frame_support::runtime] +mod runtime { + // Create the runtime by composing the FRAME pallets that were previously configured. + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + // System support stuff. + #[runtime::pallet_index(0)] + pub type System = frame_system::Pallet; + #[runtime::pallet_index(1)] + pub type ParachainSystem = cumulus_pallet_parachain_system::Pallet; + #[runtime::pallet_index(2)] + pub type Timestamp = pallet_timestamp::Pallet; + #[runtime::pallet_index(3)] + pub type ParachainInfo = parachain_info::Pallet; + + // Monetary stuff. + #[runtime::pallet_index(10)] + pub type Balances = pallet_balances::Pallet; + #[runtime::pallet_index(11)] + pub type TransactionPayment = pallet_transaction_payment::Pallet; + + // Governance + #[runtime::pallet_index(15)] + pub type Sudo = pallet_sudo; + + // Collator support. The order of these 4 are important and shall not change. + #[runtime::pallet_index(20)] + pub type Authorship = pallet_authorship::Pallet; + #[runtime::pallet_index(21)] + pub type CollatorSelection = pallet_collator_selection::Pallet; + #[runtime::pallet_index(22)] + pub type Session = pallet_session::Pallet; + #[runtime::pallet_index(23)] + pub type Aura = pallet_aura::Pallet; + #[runtime::pallet_index(24)] + pub type AuraExt = cumulus_pallet_aura_ext; + + // Scheduler + #[runtime::pallet_index(28)] + pub type Scheduler = pallet_scheduler; + + // Preimage + #[runtime::pallet_index(29)] + pub type Preimage = pallet_preimage; + + // XCM helpers. + #[runtime::pallet_index(30)] + pub type XcmpQueue = cumulus_pallet_xcmp_queue::Pallet; + #[runtime::pallet_index(31)] + pub type PolkadotXcm = pallet_xcm::Pallet; + #[runtime::pallet_index(32)] + pub type CumulusXcm = cumulus_pallet_xcm::Pallet; + #[runtime::pallet_index(33)] + pub type MessageQueue = pallet_message_queue::Pallet; + + // Contracts + #[runtime::pallet_index(40)] + pub type Contracts = pallet_contracts::Pallet; + + // Proxy + #[runtime::pallet_index(41)] + pub type Proxy = pallet_proxy::Pallet; + // Multisig + #[runtime::pallet_index(42)] + pub type Multisig = pallet_multisig::Pallet; + // Utility + #[runtime::pallet_index(43)] + pub type Utility = pallet_utility::Pallet; + + // Assets + #[runtime::pallet_index(50)] + pub type Nfts = pallet_nfts::Pallet; + #[runtime::pallet_index(51)] + pub type NftFractionalization = pallet_nft_fractionalization::Pallet; + #[runtime::pallet_index(52)] + pub type Assets = pallet_assets::Pallet; +} #[cfg(feature = "runtime-benchmarks")] mod benches { @@ -616,7 +664,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } @@ -629,7 +677,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> ExtrinsicInclusionMode{ Executive::initialize_block(header) } } @@ -943,12 +991,16 @@ impl_runtime_apis! { } impl sp_genesis_builder::GenesisBuilder for Runtime { - fn create_default_config() -> Vec { - create_default_config::() + fn build_state(config: Vec) -> sp_genesis_builder::Result { + build_state::(config) + } + + fn get_preset(id: &Option) -> Option> { + get_preset::(id, |_| None) } - fn build_config(config: Vec) -> sp_genesis_builder::Result { - build_config::(config) + fn preset_names() -> Vec { + Default::default() } } } diff --git a/runtime/testnet/src/weights/paritydb_weights.rs b/runtime/testnet/src/weights/paritydb_weights.rs index 25679703..27f7f1b0 100644 --- a/runtime/testnet/src/weights/paritydb_weights.rs +++ b/runtime/testnet/src/weights/paritydb_weights.rs @@ -32,9 +32,10 @@ pub mod constants { #[cfg(test)] mod test_db_weights { - use super::constants::ParityDbWeight as W; use frame_support::weights::constants; + use super::constants::ParityDbWeight as W; + /// Checks that all weights exist and have sane values. // NOTE: If this test fails but you are sure that the generated values are fine, // you can delete it. diff --git a/runtime/testnet/src/weights/rocksdb_weights.rs b/runtime/testnet/src/weights/rocksdb_weights.rs index 3dd817aa..bacad98c 100644 --- a/runtime/testnet/src/weights/rocksdb_weights.rs +++ b/runtime/testnet/src/weights/rocksdb_weights.rs @@ -32,9 +32,10 @@ pub mod constants { #[cfg(test)] mod test_db_weights { - use super::constants::RocksDbWeight as W; use frame_support::weights::constants; + use super::constants::RocksDbWeight as W; + /// Checks that all weights exist and have sane values. // NOTE: If this test fails but you are sure that the generated values are fine, // you can delete it. diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 12d44b03..a7445512 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] channel = "stable" -components = ["rust-src", "rustfmt", "clippy"] -targets = ["wasm32-unknown-unknown"] +components = [ "clippy", "rust-src", "rustfmt" ] +targets = [ "wasm32-unknown-unknown" ] diff --git a/tests/contracts/filtered-call/Cargo.toml b/tests/contracts/filtered-call/Cargo.toml index 53148822..091beabe 100755 --- a/tests/contracts/filtered-call/Cargo.toml +++ b/tests/contracts/filtered-call/Cargo.toml @@ -1,21 +1,21 @@ [package] -name = "pop_api_filtered_call" edition = "2021" +name = "pop_api_filtered_call" [dependencies] ink = { version = "5.0.0", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } [lib] path = "lib.rs" [features] -default = ["std"] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "scale/std", - "scale-info/std", + "ink/std", + "scale-info/std", + "scale/std", ] -ink-as-dependency = [] -e2e-tests = [] From d92a4c5f2aa6c3e0350948b900864178858acac3 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Sat, 7 Sep 2024 15:08:32 +0100 Subject: [PATCH 051/161] chore(runtime): use workspace dependencies --- Cargo.toml | 2 ++ runtime/devnet/Cargo.toml | 6 +++--- runtime/testnet/Cargo.toml | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3c2f5a1c..09fe0b0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,8 +34,10 @@ codec = { package = "parity-scale-codec", version = "3.6.12", default-features = "derive", ] } contract-build = "4.1.1" +enumflags2 = "0.7.9" env_logger = "0.11.5" futures = "0.3.28" +hex = "0.4.3" hex-literal = "0.4.1" impl-trait-for-tuples = "0.2.2" jsonrpsee = { version = "0.23.2", features = [ "server" ] } diff --git a/runtime/devnet/Cargo.toml b/runtime/devnet/Cargo.toml index b0eec2c2..a94e2831 100644 --- a/runtime/devnet/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -92,9 +92,9 @@ parachain-info.workspace = true parachains-common.workspace = true [dev-dependencies] -enumflags2 = "0.7.9" -env_logger = "0.11.2" -hex = "0.4.3" +enumflags2.workspace = true +env_logger.workspace = true +hex.workspace = true [features] default = [ "std" ] diff --git a/runtime/testnet/Cargo.toml b/runtime/testnet/Cargo.toml index 54fe7632..6dc58e18 100644 --- a/runtime/testnet/Cargo.toml +++ b/runtime/testnet/Cargo.toml @@ -90,9 +90,9 @@ parachain-info.workspace = true parachains-common.workspace = true [dev-dependencies] -enumflags2 = "0.7.9" -env_logger = "0.11.2" -hex = "0.4.3" +enumflags2.workspace = true +env_logger.workspace = true +hex.workspace = true [features] default = [ "std" ] From d7cba0ad6b786b6556edd68d9a72837c142979ef Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Sat, 7 Sep 2024 18:56:31 +0100 Subject: [PATCH 052/161] chore: resolve merge issues --- Cargo.lock | 117 ------------------------------------------ primitives/Cargo.toml | 1 - 2 files changed, 118 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 379b1f32..960e68f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1281,25 +1281,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "bp-polkadot-bulletin" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb5b3cd885b40b52bf96e52ffbec92d0c435f7303fc11374ccfcfa5bebfbc4f" -dependencies = [ - "bp-header-chain", - "bp-messages", - "bp-polkadot-core", - "bp-runtime", - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", - "sp-api", - "sp-runtime", - "sp-std", -] - [[package]] name = "bp-polkadot-core" version = "0.15.0" @@ -7086,15 +7067,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "object" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" -dependencies = [ - "memchr", -] - [[package]] name = "oid-registry" version = "0.6.1" @@ -8228,25 +8200,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-parameters" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d9a81a93202105a660e6aa3d3f81638bdd109ca0497f3e528529cd52d034db" -dependencies = [ - "docify", - "frame-benchmarking", - "frame-support", - "frame-system", - "parity-scale-codec", - "paste", - "scale-info", - "serde", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-preimage" version = "36.0.0" @@ -10474,37 +10427,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26e85d3456948e650dff0cfc85603915847faf893ed1e66b020bb82ef4557120" -[[package]] -name = "polkavm-derive-impl-macro" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" -dependencies = [ - "polkavm-derive-impl", - "syn 2.0.66", -] - -[[package]] -name = "polkavm-linker" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7be503e60cf56c0eb785f90aaba4b583b36bff00e93997d93fef97f9553c39" -dependencies = [ - "gimli 0.28.1", - "hashbrown 0.14.5", - "log", - "object 0.32.2", - "polkavm-common", - "regalloc2 0.9.3", - "rustc-demangle", -] - -[[package]] -name = "polkavm-linux-raw" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26e85d3456948e650dff0cfc85603915847faf893ed1e66b020bb82ef4557120" - [[package]] name = "polling" version = "2.8.0" @@ -11170,27 +11092,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "prost-build" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" -dependencies = [ - "bytes", - "heck 0.5.0", - "itertools 0.11.0", - "log", - "multimap 0.10.0", - "once_cell", - "petgraph", - "prettyplease 0.2.20", - "prost 0.12.6", - "prost-types 0.12.6", - "regex", - "syn 2.0.66", - "tempfile", -] - [[package]] name = "prost-derive" version = "0.11.9" @@ -16310,24 +16211,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 24566240..0cb46198 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -1,7 +1,6 @@ [package] description = "Primitives crate for Pop" edition = "2021" -name = "pop-primitives" license = "GPL-3.0-only" name = "pop-primitives" version = "0.0.0" From a2726574e4c49db3e077736b20e105950c343d5b Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Sat, 7 Sep 2024 21:36:27 +0100 Subject: [PATCH 053/161] ci: clear more space Required due to failure or coverage CI job. --- .github/actions/init/action.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/actions/init/action.yml b/.github/actions/init/action.yml index 69bb346b..f82d4fcc 100644 --- a/.github/actions/init/action.yml +++ b/.github/actions/init/action.yml @@ -14,9 +14,14 @@ runs: - name: Free up space on runner shell: bash run: | - sudo rm -rf /usr/share/dotnet sudo rm -rf /opt/ghc - sudo rm -rf "/usr/local/share/boost" + sudo rm -rf /opt/hostedtoolcache/CodeQL + sudo rm -rf /usr/local/.ghcup + sudo rm -rf /usr/local/lib/android + sudo rm -rf /usr/local/share/boost + sudo rm -rf /usr/local/share/powershell + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/share/swift sudo rm -rf "$AGENT_TOOLSDIRECTORY" - name: Rust Cache From c0ea3ed1ad6f3d07cc8e156cfc310f43ae2e946d Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Sat, 7 Sep 2024 21:38:21 +0100 Subject: [PATCH 054/161] ci: disable debug info for coverage Required due to failure or coverage CI job. --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 953aa723..ee041702 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -110,6 +110,8 @@ jobs: coverage: needs: lint runs-on: ubuntu-latest + env: + RUSTFLAGS: "-C debuginfo=0" steps: - uses: actions/checkout@v4 From 206757bb660679af83c8a4a3bf060eecbb1b855f Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:34:45 +0200 Subject: [PATCH 055/161] style: token terminology (#215) Co-authored-by: Tin Chung <56880684+chungquantin@users.noreply.github.com> Co-authored-by: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> --- pallets/api/src/fungibles/benchmarking.rs | 18 +- pallets/api/src/fungibles/mod.rs | 215 ++++++------- pallets/api/src/fungibles/tests.rs | 234 +++++++------- pallets/api/src/mock.rs | 5 +- pop-api/Cargo.toml | 3 +- .../create_token_in_constructor/lib.rs | 23 +- .../contracts/fungibles/lib.rs | 85 +++-- .../integration-tests/src/fungibles/mod.rs | 115 +++---- .../integration-tests/src/fungibles/utils.rs | 4 +- pop-api/src/lib.rs | 3 +- pop-api/src/v0/assets/mod.rs | 3 - pop-api/src/v0/{assets => }/fungibles.rs | 290 +++++++++--------- pop-api/src/v0/mod.rs | 6 +- primitives/src/lib.rs | 4 +- runtime/devnet/src/config/api/mod.rs | 22 +- 15 files changed, 510 insertions(+), 520 deletions(-) delete mode 100644 pop-api/src/v0/assets/mod.rs rename pop-api/src/v0/{assets => }/fungibles.rs (66%) diff --git a/pallets/api/src/fungibles/benchmarking.rs b/pallets/api/src/fungibles/benchmarking.rs index f346df1a..e143ae47 100644 --- a/pallets/api/src/fungibles/benchmarking.rs +++ b/pallets/api/src/fungibles/benchmarking.rs @@ -1,4 +1,4 @@ -//! Benchmarking setup for pallet-api::fungibles +//! Benchmarking setup for pallet_api::fungibles use frame_benchmarking::{account, v2::*}; use frame_support::{ @@ -14,7 +14,7 @@ use frame_support::{ use frame_system::RawOrigin; use sp_runtime::traits::Zero; -use super::{AccountIdOf, AssetIdOf, AssetsInstanceOf, AssetsOf, BalanceOf, Call, Config, Pallet}; +use super::{AccountIdOf, AssetsInstanceOf, AssetsOf, BalanceOf, Call, Config, Pallet, TokenIdOf}; const SEED: u32 = 1; @@ -37,7 +37,7 @@ mod benchmarks { // - 'c': whether `cancel_approval` is required. #[benchmark] fn approve(a: Linear<0, 1>, c: Linear<0, 1>) -> Result<(), BenchmarkError> { - let asset_id = AssetIdOf::::zero(); + let token_id = TokenIdOf::::zero(); let min_balance = >::from(1u32); let owner: AccountIdOf = account("Alice", 0, SEED); let spender: AccountIdOf = account("Bob", 0, SEED); @@ -45,13 +45,13 @@ mod benchmarks { T::Currency::make_free_balance_be(&owner, u32::MAX.into()); // Set the `current_allowance`. assert_ok!( as Create>>::create( - asset_id.clone(), + token_id.clone(), owner.clone(), true, min_balance )); assert_ok!( as Mutate>>::approve( - asset_id.clone(), + token_id.clone(), &owner, &spender, current_allowance, @@ -69,13 +69,13 @@ mod benchmarks { }; #[extrinsic_call] - _(RawOrigin::Signed(owner.clone()), asset_id.clone(), spender.clone(), approval_value); + _(RawOrigin::Signed(owner.clone()), token_id.clone(), spender.clone(), approval_value); - assert_eq!(AssetsOf::::allowance(asset_id.clone(), &owner, &spender), approval_value); + assert_eq!(AssetsOf::::allowance(token_id.clone(), &owner, &spender), approval_value); if c == 1 { assert_has_event::( pallet_assets::Event::ApprovalCancelled { - asset_id: asset_id.clone(), + asset_id: token_id.clone(), owner: owner.clone(), delegate: spender.clone(), } @@ -92,7 +92,7 @@ mod benchmarks { }; assert_has_event::( pallet_assets::Event::ApprovedTransfer { - asset_id, + asset_id: token_id, source: owner, delegate: spender, amount, diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index 76f3b28a..311b717e 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -1,4 +1,4 @@ -//! The fungibles pallet offers a streamlined interface for interacting with fungible assets. The +//! The fungibles pallet offers a streamlined interface for interacting with fungible tokens. The //! goal is to provide a simplified, consistent API that adheres to standards in the smart contract //! space. @@ -14,10 +14,10 @@ mod tests; pub mod weights; type AccountIdOf = ::AccountId; -type AssetIdOf = > as Inspect< +type TokenIdOf = > as Inspect< ::AccountId, >>::AssetId; -type AssetIdParameterOf = >>::AssetIdParameter; +type TokenIdParameterOf = >>::AssetIdParameter; type AssetsOf = pallet_assets::Pallet>; type AssetsInstanceOf = ::AssetsInstance; type AssetsWeightInfoOf = >>::WeightInfo; @@ -48,58 +48,58 @@ pub mod pallet { #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { - /// Total token supply for a specified asset. + /// Total token supply for a specified token. #[codec(index = 0)] - TotalSupply(AssetIdOf), - /// Account balance for a specified `asset` and `owner`. + TotalSupply(TokenIdOf), + /// Account balance for a specified `token` and `owner`. #[codec(index = 1)] BalanceOf { - /// The asset. - asset: AssetIdOf, - /// The owner of the asset. + /// The token. + token: TokenIdOf, + /// The owner of the token. owner: AccountIdOf, }, - /// Allowance for a `spender` approved by an `owner`, for a specified `asset`. + /// Allowance for a `spender` approved by an `owner`, for a specified `token`. #[codec(index = 2)] Allowance { - /// The asset. - asset: AssetIdOf, - /// The owner of the asset. + /// The token. + token: TokenIdOf, + /// The owner of the token. owner: AccountIdOf, /// The spender with an allowance. spender: AccountIdOf, }, - /// Name of the specified asset. + /// Name of the specified token. #[codec(index = 8)] - TokenName(AssetIdOf), - /// Symbol for the specified asset. + TokenName(TokenIdOf), + /// Symbol for the specified token. #[codec(index = 9)] - TokenSymbol(AssetIdOf), - /// Decimals for the specified asset. + TokenSymbol(TokenIdOf), + /// Decimals for the specified token. #[codec(index = 10)] - TokenDecimals(AssetIdOf), - /// Check if a specified asset exists. + TokenDecimals(TokenIdOf), + /// Check if a specified token exists. #[codec(index = 18)] - AssetExists(AssetIdOf), + TokenExists(TokenIdOf), } /// Results of state reads for the fungibles API. #[derive(Debug)] pub enum ReadResult { - /// Total token supply for a specified asset. + /// Total token supply for a specified token. TotalSupply(BalanceOf), - /// Account balance for a specified `asset` and `owner`. + /// Account balance for a specified token and owner. BalanceOf(BalanceOf), - /// Allowance for a `spender` approved by an `owner`, for a specified `asset`. + /// Allowance for a spender approved by an owner, for a specified token. Allowance(BalanceOf), - /// Name of the specified asset. + /// Name of the specified token. TokenName(Vec), - /// Symbol for the specified asset. + /// Symbol for the specified token. TokenSymbol(Vec), - /// Decimals for the specified asset. + /// Decimals for the specified token. TokenDecimals(u8), - /// Whether the specified asset exists. - AssetExists(bool), + /// Whether the specified token exists. + TokenExists(bool), } impl ReadResult { @@ -113,7 +113,7 @@ pub mod pallet { TokenName(result) => result.encode(), TokenSymbol(result) => result.encode(), TokenDecimals(result) => result.encode(), - AssetExists(result) => result.encode(), + TokenExists(result) => result.encode(), } } } @@ -138,8 +138,8 @@ pub mod pallet { pub enum Event { /// Event emitted when allowance by `owner` to `spender` changes. Approval { - /// The asset. - asset: AssetIdOf, + /// The token. + token: TokenIdOf, /// The owner providing the allowance. owner: AccountIdOf, /// The beneficiary of the allowance. @@ -147,10 +147,10 @@ pub mod pallet { /// The new allowance amount. value: BalanceOf, }, - /// Event emitted when an asset transfer occurs. + /// Event emitted when a token transfer occurs. Transfer { - /// The asset. - asset: AssetIdOf, + /// The token. + token: TokenIdOf, /// The source of the transfer. `None` when minting. from: Option>, /// The recipient of the transfer. `None` when burning. @@ -158,13 +158,13 @@ pub mod pallet { /// The amount transferred (or minted/burned). value: BalanceOf, }, - /// Event emitted when an asset is created. + /// Event emitted when an token is created. Create { - /// The asset identifier. - id: AssetIdOf, - /// The creator of the asset. + /// The token identifier. + id: TokenIdOf, + /// The creator of the token. creator: AccountIdOf, - /// The administrator of the asset. + /// The administrator of the token. admin: AccountIdOf, }, } @@ -174,72 +174,73 @@ pub mod pallet { /// Transfers `value` amount of tokens from the caller's account to account `to`. /// /// # Parameters - /// - `asset` - The asset to transfer. + /// - `token` - The token to transfer. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[pallet::call_index(3)] #[pallet::weight(AssetsWeightInfoOf::::transfer_keep_alive())] pub fn transfer( origin: OriginFor, - asset: AssetIdOf, + token: TokenIdOf, to: AccountIdOf, value: BalanceOf, ) -> DispatchResult { let from = ensure_signed(origin.clone())?; AssetsOf::::transfer_keep_alive( origin, - asset.clone().into(), + token.clone().into(), T::Lookup::unlookup(to.clone()), value, )?; - Self::deposit_event(Event::Transfer { asset, from: Some(from), to: Some(to), value }); + Self::deposit_event(Event::Transfer { token, from: Some(from), to: Some(to), value }); Ok(()) } - /// Transfers `value` amount tokens on behalf of `from` to account `to`. + /// Transfers `value` amount tokens on behalf of `from` to account `to` with additional + /// `data` in unspecified format. /// /// # Parameters - /// - `asset` - The asset to transfer. - /// - `from` - The account from which the asset balance will be withdrawn. + /// - `token` - The token to transfer. + /// - `from` - The account from which the token balance will be withdrawn. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[pallet::call_index(4)] #[pallet::weight(AssetsWeightInfoOf::::transfer_approved())] pub fn transfer_from( origin: OriginFor, - asset: AssetIdOf, + token: TokenIdOf, from: AccountIdOf, to: AccountIdOf, value: BalanceOf, ) -> DispatchResult { AssetsOf::::transfer_approved( origin, - asset.clone().into(), + token.clone().into(), T::Lookup::unlookup(from.clone()), T::Lookup::unlookup(to.clone()), value, )?; - Self::deposit_event(Event::Transfer { asset, from: Some(from), to: Some(to), value }); + Self::deposit_event(Event::Transfer { token, from: Some(from), to: Some(to), value }); Ok(()) } /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. /// /// # Parameters - /// - `asset` - The asset to approve. + /// - `token` - The token to approve. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[pallet::call_index(5)] #[pallet::weight(::WeightInfo::approve(1, 1))] pub fn approve( origin: OriginFor, - asset: AssetIdOf, + token: TokenIdOf, spender: AccountIdOf, value: BalanceOf, ) -> DispatchResultWithPostInfo { let owner = ensure_signed(origin.clone()) .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; - let current_allowance = AssetsOf::::allowance(asset.clone(), &owner, &spender); + let current_allowance = AssetsOf::::allowance(token.clone(), &owner, &spender); let weight = match value.cmp(¤t_allowance) { // If the new value is equal to the current allowance, do nothing. @@ -249,7 +250,7 @@ pub mod pallet { Greater => { AssetsOf::::approve_transfer( origin, - asset.clone().into(), + token.clone().into(), T::Lookup::unlookup(spender.clone()), value.saturating_sub(current_allowance), ) @@ -259,11 +260,11 @@ pub mod pallet { // If the new value is less than the current allowance, cancel the approval and // set the new value. Less => { - let asset_param: AssetIdParameterOf = asset.clone().into(); + let token_param: TokenIdParameterOf = token.clone().into(); let spender_source = T::Lookup::unlookup(spender.clone()); AssetsOf::::cancel_approval( origin.clone(), - asset_param.clone(), + token_param.clone(), spender_source.clone(), ) .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; @@ -272,7 +273,7 @@ pub mod pallet { } else { AssetsOf::::approve_transfer( origin, - asset_param, + token_param, spender_source, value, )?; @@ -280,21 +281,21 @@ pub mod pallet { } }, }; - Self::deposit_event(Event::Approval { asset, owner, spender, value }); + Self::deposit_event(Event::Approval { token, owner, spender, value }); Ok(Some(weight).into()) } /// Increases the allowance of `spender` by `value` amount of tokens. /// /// # Parameters - /// - `asset` - The asset to have an allowance increased. + /// - `token` - The token to have an allowance increased. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[pallet::call_index(6)] #[pallet::weight(::WeightInfo::approve(1, 0))] pub fn increase_allowance( origin: OriginFor, - asset: AssetIdOf, + token: TokenIdOf, spender: AccountIdOf, value: BalanceOf, ) -> DispatchResultWithPostInfo { @@ -302,27 +303,27 @@ pub mod pallet { .map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?; AssetsOf::::approve_transfer( origin, - asset.clone().into(), + token.clone().into(), T::Lookup::unlookup(spender.clone()), value, ) .map_err(|e| e.with_weight(AssetsWeightInfoOf::::approve_transfer()))?; - let value = AssetsOf::::allowance(asset.clone(), &owner, &spender); - Self::deposit_event(Event::Approval { asset, owner, spender, value }); + let value = AssetsOf::::allowance(token.clone(), &owner, &spender); + Self::deposit_event(Event::Approval { token, owner, spender, value }); Ok(().into()) } - /// Decreases the allowance of a `spender` by `value` amount of tokens. + /// Decreases the allowance of `spender` by `value` amount of tokens. /// /// # Parameters - /// - `asset` - The asset to have an allowance decreased. + /// - `token` - The token to have an allowance decreased. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[pallet::call_index(7)] #[pallet::weight(::WeightInfo::approve(1, 1))] pub fn decrease_allowance( origin: OriginFor, - asset: AssetIdOf, + token: TokenIdOf, spender: AccountIdOf, value: BalanceOf, ) -> DispatchResultWithPostInfo { @@ -331,14 +332,14 @@ pub mod pallet { if value.is_zero() { return Ok(Some(Self::weight_approve(0, 0)).into()); } - let current_allowance = AssetsOf::::allowance(asset.clone(), &owner, &spender); + let current_allowance = AssetsOf::::allowance(token.clone(), &owner, &spender); let spender_source = T::Lookup::unlookup(spender.clone()); - let asset_param: AssetIdParameterOf = asset.clone().into(); + let token_param: TokenIdParameterOf = token.clone().into(); // Cancel the approval and set the new value if `new_allowance` is more than zero. AssetsOf::::cancel_approval( origin.clone(), - asset_param.clone(), + token_param.clone(), spender_source.clone(), ) .map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?; @@ -348,27 +349,27 @@ pub mod pallet { } else { AssetsOf::::approve_transfer( origin, - asset_param, + token_param, spender_source, new_allowance, )?; Self::weight_approve(1, 1) }; - Self::deposit_event(Event::Approval { asset, owner, spender, value: new_allowance }); + Self::deposit_event(Event::Approval { token, owner, spender, value: new_allowance }); Ok(Some(weight).into()) } /// Create a new token with a given identifier. /// /// # Parameters - /// - `id` - The identifier of the asset. - /// - `admin` - The account that will administer the asset. - /// - `min_balance` - The minimum balance required for accounts holding this asset. + /// - `id` - The identifier of the token. + /// - `admin` - The account that will administer the token. + /// - `min_balance` - The minimum balance required for accounts holding this token. #[pallet::call_index(11)] #[pallet::weight(AssetsWeightInfoOf::::create())] pub fn create( origin: OriginFor, - id: AssetIdOf, + id: TokenIdOf, admin: AccountIdOf, min_balance: BalanceOf, ) -> DispatchResult { @@ -386,88 +387,88 @@ pub mod pallet { /// Start the process of destroying a token. /// /// # Parameters - /// - `asset` - The asset to be destroyed. + /// - `token` - The token to be destroyed. #[pallet::call_index(12)] #[pallet::weight(AssetsWeightInfoOf::::start_destroy())] - pub fn start_destroy(origin: OriginFor, asset: AssetIdOf) -> DispatchResult { - AssetsOf::::start_destroy(origin, asset.into()) + pub fn start_destroy(origin: OriginFor, token: TokenIdOf) -> DispatchResult { + AssetsOf::::start_destroy(origin, token.into()) } /// Set the metadata for a token. /// /// # Parameters - /// - `asset`: The asset to update. - /// - `name`: The user friendly name of this asset. - /// - `symbol`: The exchange symbol for this asset. - /// - `decimals`: The number of decimals this asset uses to represent one unit. + /// - `token`: The token to update. + /// - `name`: The user friendly name of this token. + /// - `symbol`: The exchange symbol for this token. + /// - `decimals`: The number of decimals this token uses to represent one unit. #[pallet::call_index(16)] #[pallet::weight(AssetsWeightInfoOf::::set_metadata(name.len() as u32, symbol.len() as u32))] pub fn set_metadata( origin: OriginFor, - asset: AssetIdOf, + token: TokenIdOf, name: Vec, symbol: Vec, decimals: u8, ) -> DispatchResult { - AssetsOf::::set_metadata(origin, asset.into(), name, symbol, decimals) + AssetsOf::::set_metadata(origin, token.into(), name, symbol, decimals) } /// Clear the metadata for a token. /// /// # Parameters - /// - `asset` - The asset to update. + /// - `token` - The token to update. #[pallet::call_index(17)] #[pallet::weight(AssetsWeightInfoOf::::clear_metadata())] - pub fn clear_metadata(origin: OriginFor, asset: AssetIdOf) -> DispatchResult { - AssetsOf::::clear_metadata(origin, asset.into()) + pub fn clear_metadata(origin: OriginFor, token: TokenIdOf) -> DispatchResult { + AssetsOf::::clear_metadata(origin, token.into()) } /// Creates `value` amount of tokens and assigns them to `account`, increasing the total /// supply. /// /// # Parameters - /// - `asset` - The asset to mint. + /// - `token` - The token to mint. /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[pallet::call_index(19)] #[pallet::weight(AssetsWeightInfoOf::::mint())] pub fn mint( origin: OriginFor, - asset: AssetIdOf, + token: TokenIdOf, account: AccountIdOf, value: BalanceOf, ) -> DispatchResult { AssetsOf::::mint( origin, - asset.clone().into(), + token.clone().into(), T::Lookup::unlookup(account.clone()), value, )?; - Self::deposit_event(Event::Transfer { asset, from: None, to: Some(account), value }); + Self::deposit_event(Event::Transfer { token, from: None, to: Some(account), value }); Ok(()) } /// Destroys `value` amount of tokens from `account`, reducing the total supply. /// /// # Parameters - /// - `asset` - the asset to burn. + /// - `token` - the token to burn. /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[pallet::call_index(20)] #[pallet::weight(AssetsWeightInfoOf::::burn())] pub fn burn( origin: OriginFor, - asset: AssetIdOf, + token: TokenIdOf, account: AccountIdOf, value: BalanceOf, ) -> DispatchResult { AssetsOf::::burn( origin, - asset.clone().into(), + token.clone().into(), T::Lookup::unlookup(account.clone()), value, )?; - Self::deposit_event(Event::Transfer { asset, from: Some(account), to: None, value }); + Self::deposit_event(Event::Transfer { token, from: Some(account), to: None, value }); Ok(()) } } @@ -501,21 +502,21 @@ pub mod pallet { fn read(request: Self::Read) -> Self::Result { use Read::*; match request { - TotalSupply(asset) => ReadResult::TotalSupply(AssetsOf::::total_supply(asset)), - BalanceOf { asset, owner } => - ReadResult::BalanceOf(AssetsOf::::balance(asset, owner)), - Allowance { asset, owner, spender } => - ReadResult::Allowance(AssetsOf::::allowance(asset, &owner, &spender)), - TokenName(asset) => ReadResult::TokenName( as MetadataInspect< + TotalSupply(token) => ReadResult::TotalSupply(AssetsOf::::total_supply(token)), + BalanceOf { token, owner } => + ReadResult::BalanceOf(AssetsOf::::balance(token, owner)), + Allowance { token, owner, spender } => + ReadResult::Allowance(AssetsOf::::allowance(token, &owner, &spender)), + TokenName(token) => ReadResult::TokenName( as MetadataInspect< AccountIdOf, - >>::name(asset)), - TokenSymbol(asset) => ReadResult::TokenSymbol( as MetadataInspect< + >>::name(token)), + TokenSymbol(token) => ReadResult::TokenSymbol( as MetadataInspect< AccountIdOf, - >>::symbol(asset)), - TokenDecimals(asset) => ReadResult::TokenDecimals( - as MetadataInspect>>::decimals(asset), + >>::symbol(token)), + TokenDecimals(token) => ReadResult::TokenDecimals( + as MetadataInspect>>::decimals(token), ), - AssetExists(asset) => ReadResult::AssetExists(AssetsOf::::asset_exists(asset)), + TokenExists(token) => ReadResult::TokenExists(AssetsOf::::asset_exists(token)), } } } diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index d850474b..c57c753c 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -9,7 +9,7 @@ use frame_support::{ use crate::{fungibles::Read::*, mock::*, Read}; -const ASSET: u32 = 42; +const TOKEN: u32 = 42; type Event = crate::fungibles::Event; @@ -17,16 +17,16 @@ type Event = crate::fungibles::Event; fn transfer_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let asset = ASSET; + let token = TOKEN; let from = Some(ALICE); let to = Some(BOB); - create_asset_and_mint_to(ALICE, asset, ALICE, value * 2); - let balance_before_transfer = Assets::balance(asset, &BOB); - assert_ok!(Fungibles::transfer(signed(ALICE), asset, BOB, value)); - let balance_after_transfer = Assets::balance(asset, &BOB); + create_token_and_mint_to(ALICE, token, ALICE, value * 2); + let balance_before_transfer = Assets::balance(token, &BOB); + assert_ok!(Fungibles::transfer(signed(ALICE), token, BOB, value)); + let balance_after_transfer = Assets::balance(token, &BOB); assert_eq!(balance_after_transfer, balance_before_transfer + value); - System::assert_last_event(Event::Transfer { asset, from, to, value }.into()); + System::assert_last_event(Event::Transfer { token, from, to, value }.into()); }); } @@ -34,22 +34,22 @@ fn transfer_works() { fn transfer_from_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let asset = ASSET; + let token = TOKEN; let from = Some(ALICE); let to = Some(BOB); // Approve CHARLIE to transfer up to `value` to BOB. - create_asset_mint_and_approve(ALICE, asset, ALICE, value * 2, CHARLIE, value); + create_token_mint_and_approve(ALICE, token, ALICE, value * 2, CHARLIE, value); // Successfully call transfer from. - let alice_balance_before_transfer = Assets::balance(asset, &ALICE); - let bob_balance_before_transfer = Assets::balance(asset, &BOB); - assert_ok!(Fungibles::transfer_from(signed(CHARLIE), asset, ALICE, BOB, value)); - let alice_balance_after_transfer = Assets::balance(asset, &ALICE); - let bob_balance_after_transfer = Assets::balance(asset, &BOB); + let alice_balance_before_transfer = Assets::balance(token, &ALICE); + let bob_balance_before_transfer = Assets::balance(token, &BOB); + assert_ok!(Fungibles::transfer_from(signed(CHARLIE), token, ALICE, BOB, value)); + let alice_balance_after_transfer = Assets::balance(token, &ALICE); + let bob_balance_after_transfer = Assets::balance(token, &BOB); // Check that BOB receives the `value` and ALICE `amount` is spent successfully by CHARLIE. assert_eq!(bob_balance_after_transfer, bob_balance_before_transfer + value); assert_eq!(alice_balance_after_transfer, alice_balance_before_transfer - value); - System::assert_last_event(Event::Transfer { asset, from, to, value }.into()); + System::assert_last_event(Event::Transfer { token, from, to, value }.into()); }); } @@ -58,37 +58,37 @@ fn transfer_from_works() { fn approve_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let asset = ASSET; + let token = TOKEN; let owner = ALICE; let spender = BOB; - create_asset_and_mint_to(ALICE, asset, ALICE, value); - assert_eq!(0, Assets::allowance(asset, &ALICE, &BOB)); - assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, value)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value); - System::assert_last_event(Event::Approval { asset, owner, spender, value }.into()); + create_token_and_mint_to(ALICE, token, ALICE, value); + assert_eq!(0, Assets::allowance(token, &ALICE, &BOB)); + assert_ok!(Fungibles::approve(signed(ALICE), token, BOB, value)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), value); + System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); // Approves an value to spend that is lower than the current allowance. - assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, value / 2)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value / 2); + assert_ok!(Fungibles::approve(signed(ALICE), token, BOB, value / 2)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), value / 2); System::assert_last_event( - Event::Approval { asset, owner, spender, value: value / 2 }.into(), + Event::Approval { token, owner, spender, value: value / 2 }.into(), ); // Approves an value to spend that is higher than the current allowance. - assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, value * 2)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value * 2); + assert_ok!(Fungibles::approve(signed(ALICE), token, BOB, value * 2)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), value * 2); System::assert_last_event( - Event::Approval { asset, owner, spender, value: value * 2 }.into(), + Event::Approval { token, owner, spender, value: value * 2 }.into(), ); // Approves an value to spend that is equal to the current allowance. - assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, value * 2)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value * 2); + assert_ok!(Fungibles::approve(signed(ALICE), token, BOB, value * 2)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), value * 2); System::assert_last_event( - Event::Approval { asset, owner, spender, value: value * 2 }.into(), + Event::Approval { token, owner, spender, value: value * 2 }.into(), ); // Sets allowance to zero. - assert_ok!(Fungibles::approve(signed(ALICE), asset, BOB, 0)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), 0); - System::assert_last_event(Event::Approval { asset, owner, spender, value: 0 }.into()); + assert_ok!(Fungibles::approve(signed(ALICE), token, BOB, 0)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), 0); + System::assert_last_event(Event::Approval { token, owner, spender, value: 0 }.into()); }); } @@ -96,20 +96,20 @@ fn approve_works() { fn increase_allowance_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let asset = ASSET; + let token = TOKEN; let owner = ALICE; let spender = BOB; - create_asset_and_mint_to(ALICE, asset, ALICE, value); - assert_eq!(0, Assets::allowance(asset, &ALICE, &BOB)); - assert_ok!(Fungibles::increase_allowance(signed(ALICE), asset, BOB, value)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value); - System::assert_last_event(Event::Approval { asset, owner, spender, value }.into()); + create_token_and_mint_to(ALICE, token, ALICE, value); + assert_eq!(0, Assets::allowance(token, &ALICE, &BOB)); + assert_ok!(Fungibles::increase_allowance(signed(ALICE), token, BOB, value)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), value); + System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); // Additive. - assert_ok!(Fungibles::increase_allowance(signed(ALICE), asset, BOB, value)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value * 2); + assert_ok!(Fungibles::increase_allowance(signed(ALICE), token, BOB, value)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), value * 2); System::assert_last_event( - Event::Approval { asset, owner, spender, value: value * 2 }.into(), + Event::Approval { token, owner, spender, value: value * 2 }.into(), ); }); } @@ -118,32 +118,32 @@ fn increase_allowance_works() { fn decrease_allowance_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let asset = ASSET; + let token = TOKEN; let owner = ALICE; let spender = BOB; - create_asset_mint_and_approve(ALICE, asset, ALICE, value, BOB, value); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value); + create_token_mint_and_approve(ALICE, token, ALICE, value, BOB, value); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), value); // Owner balance is not changed if decreased by zero. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), asset, BOB, 0)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value); + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), token, BOB, 0)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), value); // Decrease allowance successfully. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), asset, BOB, value / 2)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), value / 2); + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), token, BOB, value / 2)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), value / 2); System::assert_last_event( - Event::Approval { asset, owner, spender, value: value / 2 }.into(), + Event::Approval { token, owner, spender, value: value / 2 }.into(), ); // Saturating if current allowance is decreased more than the owner balance. - assert_ok!(Fungibles::decrease_allowance(signed(ALICE), asset, BOB, value)); - assert_eq!(Assets::allowance(asset, &ALICE, &BOB), 0); - System::assert_last_event(Event::Approval { asset, owner, spender, value: 0 }.into()); + assert_ok!(Fungibles::decrease_allowance(signed(ALICE), token, BOB, value)); + assert_eq!(Assets::allowance(token, &ALICE, &BOB), 0); + System::assert_last_event(Event::Approval { token, owner, spender, value: 0 }.into()); }); } #[test] fn create_works() { new_test_ext().execute_with(|| { - let id = ASSET; + let id = TOKEN; let creator = ALICE; let admin = ALICE; @@ -157,45 +157,45 @@ fn create_works() { #[test] fn start_destroy_works() { new_test_ext().execute_with(|| { - let asset = ASSET; + let token = TOKEN; - create_asset(ALICE, asset); - assert_ok!(Fungibles::start_destroy(signed(ALICE), asset)); + create_token(ALICE, token); + assert_ok!(Fungibles::start_destroy(signed(ALICE), token)); }); } #[test] fn set_metadata_works() { new_test_ext().execute_with(|| { - let asset = ASSET; + let token = TOKEN; let name = vec![42]; let symbol = vec![42]; let decimals = 42; - create_asset(ALICE, asset); + create_token(ALICE, token); assert_ok!(Fungibles::set_metadata( signed(ALICE), - asset, + token, name.clone(), symbol.clone(), decimals )); - assert_eq!(Assets::name(asset), name); - assert_eq!(Assets::symbol(asset), symbol); - assert_eq!(Assets::decimals(asset), decimals); + assert_eq!(Assets::name(token), name); + assert_eq!(Assets::symbol(token), symbol); + assert_eq!(Assets::decimals(token), decimals); }); } #[test] fn clear_metadata_works() { new_test_ext().execute_with(|| { - let asset = ASSET; + let token = TOKEN; - create_asset_and_set_metadata(ALICE, asset, vec![42], vec![42], 42); - assert_ok!(Fungibles::clear_metadata(signed(ALICE), asset)); - assert!(Assets::name(asset).is_empty()); - assert!(Assets::symbol(asset).is_empty()); - assert!(Assets::decimals(asset).is_zero()); + create_token_and_set_metadata(ALICE, token, vec![42], vec![42], 42); + assert_ok!(Fungibles::clear_metadata(signed(ALICE), token)); + assert!(Assets::name(token).is_empty()); + assert!(Assets::symbol(token).is_empty()); + assert!(Assets::decimals(token).is_zero()); }); } @@ -203,16 +203,16 @@ fn clear_metadata_works() { fn mint_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let asset = ASSET; + let token = TOKEN; let from = None; let to = Some(BOB); - create_asset(ALICE, asset); - let balance_before_mint = Assets::balance(asset, &BOB); - assert_ok!(Fungibles::mint(signed(ALICE), asset, BOB, value)); - let balance_after_mint = Assets::balance(asset, &BOB); + create_token(ALICE, token); + let balance_before_mint = Assets::balance(token, &BOB); + assert_ok!(Fungibles::mint(signed(ALICE), token, BOB, value)); + let balance_after_mint = Assets::balance(token, &BOB); assert_eq!(balance_after_mint, balance_before_mint + value); - System::assert_last_event(Event::Transfer { asset, from, to, value }.into()); + System::assert_last_event(Event::Transfer { token, from, to, value }.into()); }); } @@ -220,26 +220,26 @@ fn mint_works() { fn burn_works() { new_test_ext().execute_with(|| { let value: Balance = 100 * UNIT; - let asset = ASSET; + let token = TOKEN; let from = Some(BOB); let to = None; - create_asset_and_mint_to(ALICE, asset, BOB, value); - let balance_before_burn = Assets::balance(asset, &BOB); - assert_ok!(Fungibles::burn(signed(ALICE), asset, BOB, value)); - let balance_after_burn = Assets::balance(asset, &BOB); + create_token_and_mint_to(ALICE, token, BOB, value); + let balance_before_burn = Assets::balance(token, &BOB); + assert_ok!(Fungibles::burn(signed(ALICE), token, BOB, value)); + let balance_after_burn = Assets::balance(token, &BOB); assert_eq!(balance_after_burn, balance_before_burn - value); - System::assert_last_event(Event::Transfer { asset, from, to, value }.into()); + System::assert_last_event(Event::Transfer { token, from, to, value }.into()); }); } #[test] fn total_supply_works() { new_test_ext().execute_with(|| { - create_asset_and_mint_to(ALICE, ASSET, ALICE, 100); + create_token_and_mint_to(ALICE, TOKEN, ALICE, 100); assert_eq!( - Assets::total_supply(ASSET).encode(), - Fungibles::read(TotalSupply(ASSET)).encode() + Assets::total_supply(TOKEN).encode(), + Fungibles::read(TotalSupply(TOKEN)).encode() ); }); } @@ -247,10 +247,10 @@ fn total_supply_works() { #[test] fn balance_of_works() { new_test_ext().execute_with(|| { - create_asset_and_mint_to(ALICE, ASSET, ALICE, 100); + create_token_and_mint_to(ALICE, TOKEN, ALICE, 100); assert_eq!( - Assets::balance(ASSET, ALICE).encode(), - Fungibles::read(BalanceOf { asset: ASSET, owner: ALICE }).encode() + Assets::balance(TOKEN, ALICE).encode(), + Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }).encode() ); }); } @@ -258,10 +258,10 @@ fn balance_of_works() { #[test] fn allowance_works() { new_test_ext().execute_with(|| { - create_asset_mint_and_approve(ALICE, ASSET, BOB, 100, ALICE, 50); + create_token_mint_and_approve(ALICE, TOKEN, BOB, 100, ALICE, 50); assert_eq!( - Assets::allowance(ASSET, &ALICE, &BOB).encode(), - Fungibles::read(Allowance { asset: ASSET, owner: ALICE, spender: BOB }).encode() + Assets::allowance(TOKEN, &ALICE, &BOB).encode(), + Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }).encode() ); }); } @@ -272,23 +272,23 @@ fn token_metadata_works() { let name: Vec = vec![11, 12, 13]; let symbol: Vec = vec![21, 22, 23]; let decimals: u8 = 69; - create_asset_and_set_metadata(ALICE, ASSET, name.clone(), symbol.clone(), decimals); - assert_eq!(Assets::name(ASSET).encode(), Fungibles::read(TokenName(ASSET)).encode()); - assert_eq!(Assets::symbol(ASSET).encode(), Fungibles::read(TokenSymbol(ASSET)).encode()); + create_token_and_set_metadata(ALICE, TOKEN, name.clone(), symbol.clone(), decimals); + assert_eq!(Assets::name(TOKEN).encode(), Fungibles::read(TokenName(TOKEN)).encode()); + assert_eq!(Assets::symbol(TOKEN).encode(), Fungibles::read(TokenSymbol(TOKEN)).encode()); assert_eq!( - Assets::decimals(ASSET).encode(), - Fungibles::read(TokenDecimals(ASSET)).encode() + Assets::decimals(TOKEN).encode(), + Fungibles::read(TokenDecimals(TOKEN)).encode() ); }); } #[test] -fn asset_exists_works() { +fn token_exists_works() { new_test_ext().execute_with(|| { - create_asset(ALICE, ASSET); + create_token(ALICE, TOKEN); assert_eq!( - Assets::asset_exists(ASSET).encode(), - Fungibles::read(AssetExists(ASSET)).encode() + Assets::asset_exists(TOKEN).encode(), + Fungibles::read(TokenExists(TOKEN)).encode() ); }); } @@ -297,48 +297,48 @@ fn signed(account: AccountId) -> RuntimeOrigin { RuntimeOrigin::signed(account) } -fn create_asset(owner: AccountId, asset: AssetId) { - assert_ok!(Assets::create(signed(owner), asset, owner, 1)); +fn create_token(owner: AccountId, token: TokenId) { + assert_ok!(Assets::create(signed(owner), token, owner, 1)); } -fn mint_asset(owner: AccountId, asset: AssetId, to: AccountId, value: Balance) { - assert_ok!(Assets::mint(signed(owner), asset, to, value)); +fn mint_token(owner: AccountId, token: TokenId, to: AccountId, value: Balance) { + assert_ok!(Assets::mint(signed(owner), token, to, value)); } -fn create_asset_and_mint_to(owner: AccountId, asset: AssetId, to: AccountId, value: Balance) { - create_asset(owner, asset); - mint_asset(owner, asset, to, value) +fn create_token_and_mint_to(owner: AccountId, token: TokenId, to: AccountId, value: Balance) { + create_token(owner, token); + mint_token(owner, token, to, value) } -fn create_asset_mint_and_approve( +fn create_token_mint_and_approve( owner: AccountId, - asset: AssetId, + token: TokenId, to: AccountId, mint: Balance, spender: AccountId, approve: Balance, ) { - create_asset_and_mint_to(owner, asset, to, mint); - assert_ok!(Assets::approve_transfer(signed(to), asset, spender, approve,)); + create_token_and_mint_to(owner, token, to, mint); + assert_ok!(Assets::approve_transfer(signed(to), token, spender, approve,)); } -fn create_asset_and_set_metadata( +fn create_token_and_set_metadata( owner: AccountId, - asset: AssetId, + token: TokenId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::create(signed(owner), asset, owner, 100)); - set_metadata_asset(owner, asset, name, symbol, decimals); + assert_ok!(Assets::create(signed(owner), token, owner, 100)); + set_metadata_token(owner, token, name, symbol, decimals); } -fn set_metadata_asset( +fn set_metadata_token( owner: AccountId, - asset: AssetId, + token: TokenId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::set_metadata(signed(owner), asset, name, symbol, decimals)); + assert_ok!(Assets::set_metadata(signed(owner), token, name, symbol, decimals)); } diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index fe2b2c9a..b736656f 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -11,8 +11,9 @@ use sp_runtime::{ type Block = frame_system::mocking::MockBlock; pub(crate) type AccountId = u64; -pub(crate) type AssetId = u32; pub(crate) type Balance = u128; +// For terminology in tests. +pub(crate) type TokenId = u32; // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( @@ -78,7 +79,7 @@ impl pallet_assets::Config for Test { type ApprovalDeposit = ConstU128<1>; type AssetAccountDeposit = ConstU128<10>; type AssetDeposit = ConstU128<1>; - type AssetId = AssetId; + type AssetId = TokenId; type AssetIdParameter = u32; type Balance = Balance; #[cfg(feature = "runtime-benchmarks")] diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 8296569a..ae381d08 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -20,7 +20,6 @@ name = "pop_api" path = "src/lib.rs" [features] -assets = [ ] default = [ "std" ] -fungibles = [ "assets" ] +fungibles = [ ] std = [ "ink/std", "pop-primitives/std", "sp-io/std" ] diff --git a/pop-api/integration-tests/contracts/create_token_in_constructor/lib.rs b/pop-api/integration-tests/contracts/create_token_in_constructor/lib.rs index e9e5d127..93838f3c 100755 --- a/pop-api/integration-tests/contracts/create_token_in_constructor/lib.rs +++ b/pop-api/integration-tests/contracts/create_token_in_constructor/lib.rs @@ -1,9 +1,8 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::prelude::vec::Vec; use pop_api::{ - assets::fungibles::{self as api}, - primitives::AssetId, + fungibles::{self as api}, + primitives::TokenId, StatusCode, }; @@ -15,12 +14,12 @@ mod create_token_in_constructor { #[ink(storage)] pub struct Fungible { - id: AssetId, + id: TokenId, } impl Fungible { #[ink(constructor, payable)] - pub fn new(id: AssetId, min_balance: Balance) -> Result { + pub fn new(id: TokenId, min_balance: Balance) -> Result { let contract = Self { id }; // AccountId of the contract which will be set to the owner of the fungible token. let owner = contract.env().account_id(); @@ -29,18 +28,8 @@ mod create_token_in_constructor { } #[ink(message)] - pub fn asset_exists(&self) -> Result { - api::asset_exists(self.id) - } - } - - #[cfg(test)] - mod tests { - use super::*; - - #[ink::test] - fn default_works() { - PopApiFungiblesExample::new(); + pub fn token_exists(&self) -> Result { + api::token_exists(self.id) } } } diff --git a/pop-api/integration-tests/contracts/fungibles/lib.rs b/pop-api/integration-tests/contracts/fungibles/lib.rs index 2b33ce04..6530968a 100755 --- a/pop-api/integration-tests/contracts/fungibles/lib.rs +++ b/pop-api/integration-tests/contracts/fungibles/lib.rs @@ -1,14 +1,13 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -/// Local Fungibles: -/// 1. PSP-22 Interface -/// 2. PSP-22 Metadata Interface -/// 3. Asset Management -/// +/// 1. PSP-22 +/// 2. PSP-22 Metadata +/// 3. Management +/// 4. PSP-22 Mintable & Burnable use ink::prelude::vec::Vec; use pop_api::{ - assets::fungibles::{self as api}, - primitives::AssetId, + fungibles::{self as api}, + primitives::TokenId, StatusCode, }; @@ -40,66 +39,66 @@ mod fungibles { /// - decrease_allowance #[ink(message)] - pub fn total_supply(&self, id: AssetId) -> Result { - api::total_supply(id) + pub fn total_supply(&self, token: TokenId) -> Result { + api::total_supply(token) } #[ink(message)] - pub fn balance_of(&self, id: AssetId, owner: AccountId) -> Result { - api::balance_of(id, owner) + pub fn balance_of(&self, token: TokenId, owner: AccountId) -> Result { + api::balance_of(token, owner) } #[ink(message)] pub fn allowance( &self, - id: AssetId, + token: TokenId, owner: AccountId, spender: AccountId, ) -> Result { - api::allowance(id, owner, spender) + api::allowance(token, owner, spender) } #[ink(message)] - pub fn transfer(&mut self, id: AssetId, to: AccountId, value: Balance) -> Result<()> { - api::transfer(id, to, value) + pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> Result<()> { + api::transfer(token, to, value) } #[ink(message)] pub fn transfer_from( &mut self, - id: AssetId, + token: TokenId, from: AccountId, to: AccountId, value: Balance, // In the PSP-22 standard a `[u8]`, but the size needs to be known at compile time. _data: Vec, ) -> Result<()> { - api::transfer_from(id, from, to, value) + api::transfer_from(token, from, to, value) } #[ink(message)] - pub fn approve(&mut self, id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - api::approve(id, spender, value) + pub fn approve(&mut self, token: TokenId, spender: AccountId, value: Balance) -> Result<()> { + api::approve(token, spender, value) } #[ink(message)] pub fn increase_allowance( &mut self, - id: AssetId, + token: TokenId, spender: AccountId, value: Balance, ) -> Result<()> { - api::increase_allowance(id, spender, value) + api::increase_allowance(token, spender, value) } #[ink(message)] pub fn decrease_allowance( &mut self, - id: AssetId, + token: TokenId, spender: AccountId, value: Balance, ) -> Result<()> { - api::decrease_allowance(id, spender, value) + api::decrease_allowance(token, spender, value) } /// 2. PSP-22 Metadata Interface: @@ -108,18 +107,18 @@ mod fungibles { /// - token_decimals #[ink(message)] - pub fn token_name(&self, id: AssetId) -> Result> { - api::token_name(id) + pub fn token_name(&self, token: TokenId) -> Result> { + api::token_name(token) } #[ink(message)] - pub fn token_symbol(&self, id: AssetId) -> Result> { - api::token_symbol(id) + pub fn token_symbol(&self, token: TokenId) -> Result> { + api::token_symbol(token) } #[ink(message)] - pub fn token_decimals(&self, id: AssetId) -> Result { - api::token_decimals(id) + pub fn token_decimals(&self, token: TokenId) -> Result { + api::token_decimals(token) } /// 3. Asset Management: @@ -127,12 +126,12 @@ mod fungibles { /// - start_destroy /// - set_metadata /// - clear_metadata - /// - asset_exists + /// - token_exists #[ink(message)] pub fn create( &mut self, - id: AssetId, + id: TokenId, admin: AccountId, min_balance: Balance, ) -> Result<()> { @@ -140,29 +139,29 @@ mod fungibles { } #[ink(message)] - pub fn start_destroy(&mut self, id: AssetId) -> Result<()> { - api::start_destroy(id) + pub fn start_destroy(&mut self, token: TokenId) -> Result<()> { + api::start_destroy(token) } #[ink(message)] pub fn set_metadata( &mut self, - id: AssetId, + token: TokenId, name: Vec, symbol: Vec, decimals: u8, ) -> Result<()> { - api::set_metadata(id, name, symbol, decimals) + api::set_metadata(token, name, symbol, decimals) } #[ink(message)] - pub fn clear_metadata(&self, id: AssetId) -> Result<()> { - api::clear_metadata(id) + pub fn clear_metadata(&self, token: TokenId) -> Result<()> { + api::clear_metadata(token) } #[ink(message)] - pub fn asset_exists(&self, id: AssetId) -> Result { - api::asset_exists(id) + pub fn token_exists(&self, token: TokenId) -> Result { + api::token_exists(token) } /// 4. PSP-22 Mintable & Burnable Interface: @@ -170,13 +169,13 @@ mod fungibles { /// - burn #[ink(message)] - pub fn mint(&mut self, id: AssetId, account: AccountId, amount: Balance) -> Result<()> { - api::mint(id, account, amount) + pub fn mint(&mut self, token: TokenId, account: AccountId, amount: Balance) -> Result<()> { + api::mint(token, account, amount) } #[ink(message)] - pub fn burn(&mut self, id: AssetId, account: AccountId, amount: Balance) -> Result<()> { - api::burn(id, account, amount) + pub fn burn(&mut self, token: TokenId, account: AccountId, amount: Balance) -> Result<()> { + api::burn(token, account, amount) } } diff --git a/pop-api/integration-tests/src/fungibles/mod.rs b/pop-api/integration-tests/src/fungibles/mod.rs index 0d895aa3..bfea0b45 100644 --- a/pop-api/integration-tests/src/fungibles/mod.rs +++ b/pop-api/integration-tests/src/fungibles/mod.rs @@ -1,10 +1,11 @@ -use super::*; -use pop_primitives::{ArithmeticError::*, AssetId, Error::*, TokenError::*, *}; +use pop_primitives::{ArithmeticError::*, Error::*, TokenError::*, TokenId, *}; use utils::*; +use super::*; + mod utils; -const ASSET_ID: AssetId = 1; +const TOKEN_ID: TokenId = 1; const CONTRACT: &str = "contracts/fungibles/target/ink/fungibles.wasm"; /// 1. PSP-22 Interface: @@ -24,13 +25,13 @@ fn total_supply_works() { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); // No tokens in circulation. - assert_eq!(total_supply(addr.clone(), ASSET_ID), Ok(Assets::total_supply(ASSET_ID))); - assert_eq!(total_supply(addr.clone(), ASSET_ID), Ok(0)); + assert_eq!(total_supply(addr.clone(), TOKEN_ID), Ok(Assets::total_supply(TOKEN_ID))); + assert_eq!(total_supply(addr.clone(), TOKEN_ID), Ok(0)); // Tokens in circulation. - create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); - assert_eq!(total_supply(addr.clone(), ASSET_ID), Ok(Assets::total_supply(ASSET_ID))); - assert_eq!(total_supply(addr, ASSET_ID), Ok(100)); + create_asset_and_mint_to(addr.clone(), TOKEN_ID, BOB, 100); + assert_eq!(total_supply(addr.clone(), TOKEN_ID), Ok(Assets::total_supply(TOKEN_ID))); + assert_eq!(total_supply(addr, TOKEN_ID), Ok(100)); }); } @@ -41,13 +42,13 @@ fn balance_of_works() { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); // No tokens in circulation. - assert_eq!(balance_of(addr.clone(), ASSET_ID, BOB), Ok(Assets::balance(ASSET_ID, BOB))); - assert_eq!(balance_of(addr.clone(), ASSET_ID, BOB), Ok(0)); + assert_eq!(balance_of(addr.clone(), TOKEN_ID, BOB), Ok(Assets::balance(TOKEN_ID, BOB))); + assert_eq!(balance_of(addr.clone(), TOKEN_ID, BOB), Ok(0)); // Tokens in circulation. - create_asset_and_mint_to(addr.clone(), ASSET_ID, BOB, 100); - assert_eq!(balance_of(addr.clone(), ASSET_ID, BOB), Ok(Assets::balance(ASSET_ID, BOB))); - assert_eq!(balance_of(addr, ASSET_ID, BOB), Ok(100)); + create_asset_and_mint_to(addr.clone(), TOKEN_ID, BOB, 100); + assert_eq!(balance_of(addr.clone(), TOKEN_ID, BOB), Ok(Assets::balance(TOKEN_ID, BOB))); + assert_eq!(balance_of(addr, TOKEN_ID, BOB), Ok(100)); }); } @@ -59,18 +60,18 @@ fn allowance_works() { // No tokens in circulation. assert_eq!( - allowance(addr.clone(), ASSET_ID, BOB, ALICE), - Ok(Assets::allowance(ASSET_ID, &BOB, &ALICE)) + allowance(addr.clone(), TOKEN_ID, BOB, ALICE), + Ok(Assets::allowance(TOKEN_ID, &BOB, &ALICE)) ); - assert_eq!(allowance(addr.clone(), ASSET_ID, BOB, ALICE), Ok(0)); + assert_eq!(allowance(addr.clone(), TOKEN_ID, BOB, ALICE), Ok(0)); // Tokens in circulation. - create_asset_mint_and_approve(addr.clone(), ASSET_ID, BOB, 100, ALICE, 50); + create_asset_mint_and_approve(addr.clone(), TOKEN_ID, BOB, 100, ALICE, 50); assert_eq!( - allowance(addr.clone(), ASSET_ID, BOB, ALICE), - Ok(Assets::allowance(ASSET_ID, &BOB, &ALICE)) + allowance(addr.clone(), TOKEN_ID, BOB, ALICE), + Ok(Assets::allowance(TOKEN_ID, &BOB, &ALICE)) ); - assert_eq!(allowance(addr, ASSET_ID, BOB, ALICE), Ok(50)); + assert_eq!(allowance(addr, TOKEN_ID, BOB, ALICE), Ok(50)); }); } @@ -296,26 +297,26 @@ fn token_metadata_works() { let decimals: u8 = 69; // Token does not exist. - assert_eq!(token_name(addr.clone(), ASSET_ID), Ok(token_name_asset(ASSET_ID))); - assert_eq!(token_name(addr.clone(), ASSET_ID), Ok(Vec::::new())); - assert_eq!(token_symbol(addr.clone(), ASSET_ID), Ok(token_symbol_asset(ASSET_ID))); - assert_eq!(token_symbol(addr.clone(), ASSET_ID), Ok(Vec::::new())); - assert_eq!(token_decimals(addr.clone(), ASSET_ID), Ok(token_decimals_asset(ASSET_ID))); - assert_eq!(token_decimals(addr.clone(), ASSET_ID), Ok(0)); + assert_eq!(token_name(addr.clone(), TOKEN_ID), Ok(token_name_asset(TOKEN_ID))); + assert_eq!(token_name(addr.clone(), TOKEN_ID), Ok(Vec::::new())); + assert_eq!(token_symbol(addr.clone(), TOKEN_ID), Ok(token_symbol_asset(TOKEN_ID))); + assert_eq!(token_symbol(addr.clone(), TOKEN_ID), Ok(Vec::::new())); + assert_eq!(token_decimals(addr.clone(), TOKEN_ID), Ok(token_decimals_asset(TOKEN_ID))); + assert_eq!(token_decimals(addr.clone(), TOKEN_ID), Ok(0)); // Create Token. create_asset_and_set_metadata( addr.clone(), - ASSET_ID, + TOKEN_ID, name.clone(), symbol.clone(), decimals, ); - assert_eq!(token_name(addr.clone(), ASSET_ID), Ok(token_name_asset(ASSET_ID))); - assert_eq!(token_name(addr.clone(), ASSET_ID), Ok(name)); - assert_eq!(token_symbol(addr.clone(), ASSET_ID), Ok(token_symbol_asset(ASSET_ID))); - assert_eq!(token_symbol(addr.clone(), ASSET_ID), Ok(symbol)); - assert_eq!(token_decimals(addr.clone(), ASSET_ID), Ok(token_decimals_asset(ASSET_ID))); - assert_eq!(token_decimals(addr.clone(), ASSET_ID), Ok(decimals)); + assert_eq!(token_name(addr.clone(), TOKEN_ID), Ok(token_name_asset(TOKEN_ID))); + assert_eq!(token_name(addr.clone(), TOKEN_ID), Ok(name)); + assert_eq!(token_symbol(addr.clone(), TOKEN_ID), Ok(token_symbol_asset(TOKEN_ID))); + assert_eq!(token_symbol(addr.clone(), TOKEN_ID), Ok(symbol)); + assert_eq!(token_decimals(addr.clone(), TOKEN_ID), Ok(token_decimals_asset(TOKEN_ID))); + assert_eq!(token_decimals(addr.clone(), TOKEN_ID), Ok(decimals)); }); } @@ -324,7 +325,7 @@ fn token_metadata_works() { /// - start_destroy /// - set_metadata /// - clear_metadata -/// - asset_exists +/// - token_exists #[test] fn create_works() { @@ -334,7 +335,7 @@ fn create_works() { let addr = instantiate(CONTRACT, 0, vec![0]); // No balance to pay for fees. assert_eq!( - create(addr.clone(), ASSET_ID, addr.clone(), 1), + create(addr.clone(), TOKEN_ID, addr.clone(), 1), Err(Module { index: 10, error: [2, 0] }), ); @@ -342,26 +343,26 @@ fn create_works() { let addr = instantiate(CONTRACT, 100, vec![1]); // No balance to pay the deposit. assert_eq!( - create(addr.clone(), ASSET_ID, addr.clone(), 1), + create(addr.clone(), TOKEN_ID, addr.clone(), 1), Err(Module { index: 10, error: [2, 0] }), ); // Instantiate a contract with enough balance. let addr = instantiate(CONTRACT, INIT_VALUE, vec![2]); assert_eq!( - create(addr.clone(), ASSET_ID, BOB, 0), + create(addr.clone(), TOKEN_ID, BOB, 0), Err(Module { index: 52, error: [7, 0] }), ); // The minimal balance for an asset must be non zero. assert_eq!( - create(addr.clone(), ASSET_ID, BOB, 0), + create(addr.clone(), TOKEN_ID, BOB, 0), Err(Module { index: 52, error: [7, 0] }), ); // Create asset successfully. - assert_ok!(create(addr.clone(), ASSET_ID, BOB, 1)); + assert_ok!(create(addr.clone(), TOKEN_ID, BOB, 1)); // Asset ID is already taken. assert_eq!( - create(addr.clone(), ASSET_ID, BOB, 1), + create(addr.clone(), TOKEN_ID, BOB, 1), Err(Module { index: 52, error: [5, 0] }), ); }); @@ -381,8 +382,8 @@ fn instantiate_and_create_fungible_works() { Err(Module { index: 52, error: [5, 0] }) ); // Successfully create an asset when instantiating the contract. - assert_ok!(instantiate_and_create_fungible(contract, ASSET_ID, 1)); - assert!(Assets::asset_exists(ASSET_ID)); + assert_ok!(instantiate_and_create_fungible(contract, TOKEN_ID, 1)); + assert!(Assets::asset_exists(TOKEN_ID)); }); } @@ -393,12 +394,12 @@ fn start_destroy_works() { let addr = instantiate(CONTRACT, INIT_VALUE, vec![2]); // Asset does not exist. - assert_eq!(start_destroy(addr.clone(), ASSET_ID), Err(Module { index: 52, error: [3, 0] }),); + assert_eq!(start_destroy(addr.clone(), TOKEN_ID), Err(Module { index: 52, error: [3, 0] }),); // Create assets where contract is not the owner. let asset = create_asset(ALICE, 0, 1); // No Permission. assert_eq!(start_destroy(addr.clone(), asset), Err(Module { index: 52, error: [2, 0] }),); - let asset = create_asset(addr.clone(), ASSET_ID, 1); + let asset = create_asset(addr.clone(), TOKEN_ID, 1); assert_ok!(start_destroy(addr.clone(), asset)); }); } @@ -414,7 +415,7 @@ fn set_metadata_works() { // Asset does not exist. assert_eq!( - set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], 0u8), + set_metadata(addr.clone(), TOKEN_ID, vec![0], vec![0], 0u8), Err(Module { index: 52, error: [3, 0] }), ); // Create assets where contract is not the owner. @@ -424,11 +425,11 @@ fn set_metadata_works() { set_metadata(addr.clone(), asset, vec![0], vec![0], 0u8), Err(Module { index: 52, error: [2, 0] }), ); - let asset = create_asset(addr.clone(), ASSET_ID, 1); + let asset = create_asset(addr.clone(), TOKEN_ID, 1); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(addr.clone(), asset); assert_eq!( - set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], 0u8), + set_metadata(addr.clone(), TOKEN_ID, vec![0], vec![0], 0u8), Err(Module { index: 52, error: [16, 0] }), ); thaw_asset(addr.clone(), asset); @@ -436,15 +437,15 @@ fn set_metadata_works() { // `OutputBufferTooSmall. Added to security analysis issue #131 to revisit. // Set bad metadata - too large values. assert_eq!( - set_metadata(addr.clone(), ASSET_ID, vec![0; 1000], vec![0; 1000], 0u8), + set_metadata(addr.clone(), TOKEN_ID, vec![0; 1000], vec![0; 1000], 0u8), Err(Module { index: 52, error: [9, 0] }), ); // Set metadata successfully. - assert_ok!(set_metadata(addr.clone(), ASSET_ID, name, symbol, decimals)); + assert_ok!(set_metadata(addr.clone(), TOKEN_ID, name, symbol, decimals)); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(addr.clone(), asset); assert_eq!( - set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], 0), + set_metadata(addr.clone(), TOKEN_ID, vec![0], vec![0], 0), Err(Module { index: 52, error: [16, 0] }), ); }); @@ -465,7 +466,7 @@ fn clear_metadata_works() { let asset = create_asset_and_set_metadata(ALICE, 0, vec![0], vec![0], 0); // No Permission. assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: [2, 0] }),); - let asset = create_asset(addr.clone(), ASSET_ID, 1); + let asset = create_asset(addr.clone(), TOKEN_ID, 1); // Asset is not live, i.e. frozen or being destroyed. freeze_asset(addr.clone(), asset); assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: [16, 0] }),); @@ -474,28 +475,28 @@ fn clear_metadata_works() { assert_eq!(clear_metadata(addr.clone(), asset), Err(Module { index: 52, error: [3, 0] }),); set_metadata_asset(addr.clone(), asset, name, symbol, decimals); // Clear metadata successfully. - assert_ok!(clear_metadata(addr.clone(), ASSET_ID)); + assert_ok!(clear_metadata(addr.clone(), TOKEN_ID)); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(addr.clone(), asset); assert_eq!( - set_metadata(addr.clone(), ASSET_ID, vec![0], vec![0], decimals), + set_metadata(addr.clone(), TOKEN_ID, vec![0], vec![0], decimals), Err(Module { index: 52, error: [16, 0] }), ); }); } #[test] -fn asset_exists_works() { +fn token_exists_works() { new_test_ext().execute_with(|| { let _ = env_logger::try_init(); let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); // No tokens in circulation. - assert_eq!(asset_exists(addr.clone(), ASSET_ID), Ok(Assets::asset_exists(ASSET_ID))); + assert_eq!(token_exists(addr.clone(), TOKEN_ID), Ok(Assets::asset_exists(TOKEN_ID))); // Tokens in circulation. - create_asset(addr.clone(), ASSET_ID, 1); - assert_eq!(asset_exists(addr.clone(), ASSET_ID), Ok(Assets::asset_exists(ASSET_ID))); + create_asset(addr.clone(), TOKEN_ID, 1); + assert_eq!(token_exists(addr.clone(), TOKEN_ID), Ok(Assets::asset_exists(TOKEN_ID))); }); } diff --git a/pop-api/integration-tests/src/fungibles/utils.rs b/pop-api/integration-tests/src/fungibles/utils.rs index 33a25f7a..35761673 100644 --- a/pop-api/integration-tests/src/fungibles/utils.rs +++ b/pop-api/integration-tests/src/fungibles/utils.rs @@ -57,8 +57,8 @@ pub(super) fn token_decimals(addr: AccountId32, asset_id: AssetId) -> Result Result { - let result = do_bare_call("asset_exists", addr, asset_id.encode()); +pub(super) fn token_exists(addr: AccountId32, asset_id: AssetId) -> Result { + let result = do_bare_call("token_exists", addr, asset_id.encode()); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index cc785c14..0a080c56 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -9,8 +9,7 @@ use constants::DECODING_FAILED; use ink::env::chain_extension::{ChainExtensionMethod, FromStatusCode}; -#[cfg(feature = "assets")] -pub use v0::assets; +pub use v0::*; /// Module providing primitives types. pub mod primitives; diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs deleted file mode 100644 index 2d5ae236..00000000 --- a/pop-api/src/v0/assets/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -/// APIs for fungible assets. -#[cfg(feature = "fungibles")] -pub mod fungibles; diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/fungibles.rs similarity index 66% rename from pop-api/src/v0/assets/fungibles.rs rename to pop-api/src/v0/fungibles.rs index 56d2f9af..5c9b9a30 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/fungibles.rs @@ -1,21 +1,22 @@ -//! The `fungibles` module provides an API for interacting and managing fungible assets on Pop Network. +//! The `fungibles` module provides an API for interacting and managing fungible tokens. //! //! The API includes the following interfaces: //! 1. PSP-22 //! 2. PSP-22 Metadata -//! 3. Asset Management +//! 3. Management //! 4. PSP-22 Mintable & Burnable -use crate::{ - constants::{ASSETS, BALANCES, FUNGIBLES}, - primitives::{AccountId, AssetId, Balance}, - Result, StatusCode, -}; use constants::*; use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec}; pub use management::*; pub use metadata::*; +use crate::{ + constants::{ASSETS, BALANCES, FUNGIBLES}, + primitives::{AccountId, Balance, TokenId}, + Result, StatusCode, +}; + // Helper method to build a dispatch call. // // Parameters: @@ -53,7 +54,7 @@ mod constants { pub(super) const START_DESTROY: u8 = 12; pub(super) const SET_METADATA: u8 = 16; pub(super) const CLEAR_METADATA: u8 = 17; - pub(super) const ASSET_EXISTS: u8 = 18; + pub(super) const TOKEN_EXISTS: u8 = 18; /// 4. PSP-22 Mintable & Burnable interface: pub(super) const MINT: u8 = 19; @@ -66,7 +67,7 @@ mod constants { /// (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. /// /// These events are not emitted by the API itself but can be used in your contracts to -/// track asset operations. Be mindful of the costs associated with emitting events. +/// track token operations. Be mindful of the costs associated with emitting events. /// /// For more details, refer to [ink! events](https://use.ink/basics/events). pub mod events { @@ -75,354 +76,357 @@ pub mod events { /// Event emitted when allowance by `owner` to `spender` changes. #[ink::event] pub struct Approval { - /// Account providing allowance. + /// The owner providing the allowance. #[ink(topic)] pub owner: AccountId, - /// Allowance beneficiary. + /// The beneficiary of the allowance. #[ink(topic)] pub spender: AccountId, - /// New allowance amount. + /// The new allowance amount. pub value: u128, } /// Event emitted when transfer of tokens occurs. #[ink::event] pub struct Transfer { - /// Transfer sender. `None` in case of minting new tokens. + /// The source of the transfer. `None` when minting. #[ink(topic)] pub from: Option, - /// Transfer recipient. `None` in case of burning tokens. + /// The recipient of the transfer. `None` when burning. #[ink(topic)] pub to: Option, - /// Amount of tokens transferred (or minted/burned). + /// The amount transferred (or minted/burned). pub value: u128, } - /// Event emitted when a token class is created. + /// Event emitted when an token is created. #[ink::event] pub struct Create { - /// The ID of the asset. + /// The token identifier. #[ink(topic)] - pub id: AssetId, - /// Creator of the asset. + pub id: TokenId, + /// The creator of the token. #[ink(topic)] pub creator: AccountId, - /// Admin of the asset. + /// The administrator of the token. #[ink(topic)] pub admin: AccountId, } - /// Event emitted when a asset is in the process of being destroyed. + /// Event emitted when a token is in the process of being destroyed. #[ink::event] pub struct StartDestroy { - /// The ID of the asset. + /// The token. #[ink(topic)] - pub id: AssetId, + pub token: TokenId, } - /// Event emitted when new metadata is set for an asset. + /// Event emitted when new metadata is set for a token. #[ink::event] pub struct SetMetadata { - /// The ID of the asset created. + /// The token. #[ink(topic)] - pub id: AssetId, - /// The name of the asset. + pub token: TokenId, + /// The name of the token. #[ink(topic)] pub name: Vec, - /// The symbol of the asset. + /// The symbol of the token. #[ink(topic)] pub symbol: Vec, - /// The decimals of the asset. + /// The decimals of the token. pub decimals: u8, } /// Event emitted when metadata is cleared for a token. #[ink::event] pub struct ClearMetadata { - /// The ID of the asset. + /// The token. #[ink(topic)] - pub id: AssetId, + pub token: TokenId, } } -/// Returns the total token supply for a given asset ID. +/// Returns the total token supply for a specified token. /// /// # Parameters -/// - `id` - The ID of the asset. +/// - `token` - The token. #[inline] -pub fn total_supply(id: AssetId) -> Result { +pub fn total_supply(token: TokenId) -> Result { build_read_state(TOTAL_SUPPLY) - .input::() + .input::() .output::, true>() .handle_error_code::() - .call(&(id)) + .call(&(token)) } -/// Returns the account balance for the specified `owner` for a given asset ID. Returns `0` if +/// Returns the account balance for a specified `token` and `owner`. Returns `0` if /// the account is non-existent. /// /// # Parameters -/// - `id` - The ID of the asset. +/// - `token` - The token. /// - `owner` - The account whose balance is being queried. #[inline] -pub fn balance_of(id: AssetId, owner: AccountId) -> Result { +pub fn balance_of(token: TokenId, owner: AccountId) -> Result { build_read_state(BALANCE_OF) - .input::<(AssetId, AccountId)>() + .input::<(TokenId, AccountId)>() .output::, true>() .handle_error_code::() - .call(&(id, owner)) + .call(&(token, owner)) } -/// Returns the amount which `spender` is still allowed to withdraw from `owner` for a given -/// asset ID. Returns `0` if no allowance has been set. +/// Returns the allowance for a `spender` approved by an `owner`, for a specified `token`. Returns +/// `0` if no allowance has been set. /// /// # Parameters -/// - `id` - The ID of the asset. +/// - `token` - The token. /// - `owner` - The account that owns the tokens. /// - `spender` - The account that is allowed to spend the tokens. #[inline] -pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { +pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result { build_read_state(ALLOWANCE) - .input::<(AssetId, AccountId, AccountId)>() + .input::<(TokenId, AccountId, AccountId)>() .output::, true>() .handle_error_code::() - .call(&(id, owner, spender)) + .call(&(token, owner, spender)) } -/// Transfers `value` amount of tokens from the caller's account to account `to`, with additional -/// `data` in unspecified format. +/// Transfers `value` amount of tokens from the caller's account to account `to`. /// /// # Parameters -/// - `id` - The ID of the asset. +/// - `token` - The token to transfer. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer(id: AssetId, to: AccountId, value: Balance) -> Result<()> { +pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { build_dispatch(TRANSFER) - .input::<(AssetId, AccountId, Balance)>() + .input::<(TokenId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, to, value)) + .call(&(token, to, value)) } -/// Transfers `value` amount tokens on behalf of `from` to account `to` with additional `data` -/// in unspecified format. +/// Transfers `value` amount tokens on behalf of `from` to account `to`. /// /// # Parameters -/// - `id` - The ID of the asset. -/// - `from` - The account from which the tokens are transferred. +/// - `token` - The token to transfer. +/// - `from` - The account from which the token balance will be withdrawn. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { +pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { build_dispatch(TRANSFER_FROM) - .input::<(AssetId, AccountId, AccountId, Balance)>() + .input::<(TokenId, AccountId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, from, to, value)) + .call(&(token, from, to, value)) } -/// Approves an account to spend a specified number of tokens on behalf of the caller. +/// Approves `spender` to spend `value` amount of tokens on behalf of the caller. /// /// # Parameters -/// - `id` - The ID of the asset. +/// - `token` - The token to approve. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[inline] -pub fn approve(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { +pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(APPROVE) - .input::<(AssetId, AccountId, Balance)>() + .input::<(TokenId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, spender, value)) + .call(&(token, spender, value)) } -/// Increases the allowance of a spender. +/// Increases the allowance of `spender` by `value` amount of tokens. /// /// # Parameters -/// - `id` - The ID of the asset. +/// - `token` - The token to have an allowance increased. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[inline] -pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { +pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(INCREASE_ALLOWANCE) - .input::<(AssetId, AccountId, Balance)>() + .input::<(TokenId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, spender, value)) + .call(&(token, spender, value)) } -/// Decreases the allowance of a spender. +/// Decreases the allowance of `spender` by `value` amount of tokens. /// /// # Parameters -/// - `id` - The ID of the asset. +/// - `token` - The token to have an allowance decreased. /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[inline] -pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { +pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(DECREASE_ALLOWANCE) - .input::<(AssetId, AccountId, Balance)>() + .input::<(TokenId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, spender, value)) + .call(&(token, spender, value)) } -/// Creates `value` amount tokens and assigns them to `account`, increasing the total supply. +/// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. /// /// # Parameters -/// - `id` - The ID of the asset. +/// - `token` - The token to mint. /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[inline] -pub fn mint(id: AssetId, account: AccountId, value: Balance) -> Result<()> { +pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { build_dispatch(MINT) - .input::<(AssetId, AccountId, Balance)>() + .input::<(TokenId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, account, value)) + .call(&(token, account, value)) } -/// Destroys `value` amount tokens from `account`, reducing the total supply. +/// Destroys `value` amount of tokens from `account`, reducing the total supply. /// /// # Parameters -/// - `id` - The ID of the asset. +/// - `token` - the token to burn. /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[inline] -pub fn burn(id: AssetId, account: AccountId, value: Balance) -> Result<()> { +pub fn burn(token: TokenId, account: AccountId, value: Balance) -> Result<()> { build_dispatch(BURN) - .input::<(AssetId, AccountId, Balance)>() + .input::<(TokenId, AccountId, Balance)>() .output::, true>() .handle_error_code::() - .call(&(id, account, value)) + .call(&(token, account, value)) } /// The PSP-22 Metadata interface for querying metadata. pub mod metadata { use super::*; - /// Returns the token name for a given asset ID. + /// Returns the name of the specified token. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `token` - The token. #[inline] - pub fn token_name(id: AssetId) -> Result> { + pub fn token_name(token: TokenId) -> Result> { build_read_state(TOKEN_NAME) - .input::() + .input::() .output::>, true>() .handle_error_code::() - .call(&(id)) + .call(&(token)) } - /// Returns the token symbol for a given asset ID. + /// Returns the symbol for the specified token. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `token` - The token. #[inline] - pub fn token_symbol(id: AssetId) -> Result> { + pub fn token_symbol(token: TokenId) -> Result> { build_read_state(TOKEN_SYMBOL) - .input::() + .input::() .output::>, true>() .handle_error_code::() - .call(&(id)) + .call(&(token)) } - /// Returns the token decimals for a given asset ID. + /// Returns the decimals for the specified token. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `token` - The token. #[inline] - pub fn token_decimals(id: AssetId) -> Result { + pub fn token_decimals(token: TokenId) -> Result { build_read_state(TOKEN_DECIMALS) - .input::() + .input::() .output::, true>() .handle_error_code::() - .call(&(id)) + .call(&(token)) } } -/// The interface for creating, managing and destroying fungible assets. +/// The interface for creating, managing and destroying fungible tokens. pub mod management { use super::*; - /// Create a new token with a given asset ID. + /// Create a new token with a given identifier. /// /// # Parameters - /// - `id` - The ID of the asset. - /// - `admin` - The account that will administer the asset. - /// - `min_balance` - The minimum balance required for accounts holding this asset. + /// - `id` - The identifier of the token. + /// - `admin` - The account that will administer the token. + /// - `min_balance` - The minimum balance required for accounts holding this token. #[inline] - pub fn create(id: AssetId, admin: AccountId, min_balance: Balance) -> Result<()> { + pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()> { build_dispatch(CREATE) - .input::<(AssetId, AccountId, Balance)>() + .input::<(TokenId, AccountId, Balance)>() .output::, true>() .handle_error_code::() .call(&(id, admin, min_balance)) } - /// Start the process of destroying a token with a given asset ID. + /// Start the process of destroying a token. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `token` - The token to be destroyed. #[inline] - pub fn start_destroy(id: AssetId) -> Result<()> { + pub fn start_destroy(token: TokenId) -> Result<()> { build_dispatch(START_DESTROY) - .input::() + .input::() .output::, true>() .handle_error_code::() - .call(&(id)) + .call(&(token)) } - /// Set the metadata for a token with a given asset ID. + /// Set the metadata for a token. /// /// # Parameters - /// - `id`: The identifier of the asset to update. - /// - `name`: The user friendly name of this asset. Limited in length by `StringLimit`. - /// - `symbol`: The exchange symbol for this asset. Limited in length by `StringLimit`. - /// - `decimals`: The number of decimals this asset uses to represent one unit. + /// - `token`: The token to update. + /// - `name`: The user friendly name of this token. + /// - `symbol`: The exchange symbol for this token. + /// - `decimals`: The number of decimals this token uses to represent one unit. #[inline] - pub fn set_metadata(id: AssetId, name: Vec, symbol: Vec, decimals: u8) -> Result<()> { + pub fn set_metadata( + token: TokenId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()> { build_dispatch(SET_METADATA) - .input::<(AssetId, Vec, Vec, u8)>() + .input::<(TokenId, Vec, Vec, u8)>() .output::, true>() .handle_error_code::() - .call(&(id, name, symbol, decimals)) + .call(&(token, name, symbol, decimals)) } - /// Clear the metadata for a token with a given asset ID. + /// Clear the metadata for a token. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `token` - The token to update #[inline] - pub fn clear_metadata(id: AssetId) -> Result<()> { + pub fn clear_metadata(token: TokenId) -> Result<()> { build_dispatch(CLEAR_METADATA) - .input::() + .input::() .output::, true>() .handle_error_code::() - .call(&(id)) + .call(&(token)) } - /// Checks if token with a given asset ID exists. + /// Checks if a specified token exists. /// /// # Parameters - /// - `id` - The ID of the asset. + /// - `token` - The token. #[inline] - pub fn asset_exists(id: AssetId) -> Result { - build_read_state(ASSET_EXISTS) - .input::() + pub fn token_exists(token: TokenId) -> Result { + build_read_state(TOKEN_EXISTS) + .input::() .output::, true>() .handle_error_code::() - .call(&(id)) + .call(&(token)) } } -/// Represents various errors related to local fungible assets in the Pop API. +/// Represents various errors related to fungible tokens. /// /// The `FungiblesError` provides a detailed and specific set of error types that can occur when -/// interacting with fungible assets through the Pop API. Each variant signifies a particular error +/// interacting with fungible tokens. Each variant signifies a particular error /// condition, facilitating precise error handling and debugging. /// -/// It is designed to be lightweight, including only the essential errors relevant to fungible asset +/// It is designed to be lightweight, including only the essential errors relevant to fungible token /// operations. The `Other` variant serves as a catch-all for any unexpected errors. For more /// detailed debugging, the `Other` variant can be converted into the richer `Error` type defined in /// the primitives crate. @@ -431,13 +435,13 @@ pub mod management { pub enum FungiblesError { /// An unspecified or unknown error occurred. Other(StatusCode), - /// The asset is not live; either frozen or being destroyed. - AssetNotLive, + /// The token is not live; either frozen or being destroyed. + NotLive, /// Not enough allowance to fulfill a request is available. InsufficientAllowance, /// Not enough balance to fulfill a request is available. InsufficientBalance, - /// The asset ID is already taken. + /// The token ID is already taken. InUse, /// Minimum balance should be non-zero. MinBalanceZero, @@ -445,12 +449,12 @@ pub enum FungiblesError { NoAccount, /// The signing account has no permission to do the operation. NoPermission, - /// The given asset ID is unknown. + /// The given token ID is unknown. Unknown, - /// No balance for creation of assets or fees. + /// No balance for creation of tokens or fees. // TODO: Originally `pallet_balances::Error::InsufficientBalance` but collides with the - // `InsufficientBalance` error that is used for `pallet_assets::Error::BalanceLow` to adhere to - // standard. This deserves a second look. + // `InsufficientBalance` error that is used for `pallet_assets::Error::BalanceLow` to adhere + // to the standard. This deserves a second look. NoBalance, } @@ -472,7 +476,7 @@ impl From for FungiblesError { [_, ASSETS, 3, _] => FungiblesError::InUse, [_, ASSETS, 5, _] => FungiblesError::MinBalanceZero, [_, ASSETS, 7, _] => FungiblesError::InsufficientAllowance, - [_, ASSETS, 10, _] => FungiblesError::AssetNotLive, + [_, ASSETS, 10, _] => FungiblesError::NotLive, _ => FungiblesError::Other(value), } } @@ -578,7 +582,7 @@ mod tests { ); assert_eq!( into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), - FungiblesError::AssetNotLive + FungiblesError::NotLive ); } } diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 55732e2d..8ed35058 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -6,9 +6,9 @@ use crate::{ }; use ink::env::chain_extension::ChainExtensionMethod; -/// APIs for asset-related use cases. -#[cfg(feature = "assets")] -pub mod assets; +/// APIs for fungible tokens. +#[cfg(feature = "fungibles")] +pub mod fungibles; pub(crate) const V0: u8 = 0; diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index ef6ae3a9..e6942432 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -5,8 +5,8 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; pub use v0::*; -/// Identifier for the class of asset. -pub type AssetId = u32; +/// The identifier of a token. +pub type TokenId = u32; pub mod v0 { pub use error::*; diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 16ea92fb..6d27fcde 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -157,7 +157,7 @@ impl Contains for Filter { Allowance { .. } | TokenName(..) | TokenSymbol(..) | TokenDecimals(..) | - AssetExists(..) + TokenExists(..) ) ) } @@ -196,17 +196,17 @@ fn filter_allows_fungibles_calls() { const ACCOUNT: AccountId32 = AccountId32::new([0u8; 32]); const CALLS: [RuntimeCall; 11] = [ - Fungibles(transfer { asset: 0, to: ACCOUNT, value: 0 }), - Fungibles(transfer_from { asset: 0, from: ACCOUNT, to: ACCOUNT, value: 0 }), - Fungibles(approve { asset: 0, spender: ACCOUNT, value: 0 }), - Fungibles(increase_allowance { asset: 0, spender: ACCOUNT, value: 0 }), - Fungibles(decrease_allowance { asset: 0, spender: ACCOUNT, value: 0 }), + Fungibles(transfer { token: 0, to: ACCOUNT, value: 0 }), + Fungibles(transfer_from { token: 0, from: ACCOUNT, to: ACCOUNT, value: 0 }), + Fungibles(approve { token: 0, spender: ACCOUNT, value: 0 }), + Fungibles(increase_allowance { token: 0, spender: ACCOUNT, value: 0 }), + Fungibles(decrease_allowance { token: 0, spender: ACCOUNT, value: 0 }), Fungibles(create { id: 0, admin: ACCOUNT, min_balance: 0 }), - Fungibles(set_metadata { asset: 0, name: vec![], symbol: vec![], decimals: 0 }), - Fungibles(start_destroy { asset: 0 }), - Fungibles(clear_metadata { asset: 0 }), - Fungibles(mint { asset: 0, account: ACCOUNT, value: 0 }), - Fungibles(burn { asset: 0, account: ACCOUNT, value: 0 }), + Fungibles(set_metadata { token: 0, name: vec![], symbol: vec![], decimals: 0 }), + Fungibles(start_destroy { token: 0 }), + Fungibles(clear_metadata { token: 0 }), + Fungibles(mint { token: 0, account: ACCOUNT, value: 0 }), + Fungibles(burn { token: 0, account: ACCOUNT, value: 0 }), ]; for call in CALLS { From 07a07311af26553cdecca0fb159e5b0a8c4dc96b Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 11 Sep 2024 15:40:05 +0700 Subject: [PATCH 056/161] chore: add sandbox crate --- Cargo.toml | 7 +- pop-sandbox/Cargo.toml | 57 ++++++ pop-sandbox/examples/.gitignore | 9 + pop-sandbox/examples/flipper/.gitignore | 9 + pop-sandbox/examples/flipper/Cargo.toml | 27 +++ pop-sandbox/examples/flipper/lib.rs | 167 ++++++++++++++++ pop-sandbox/examples/fungibles/Cargo.toml | 36 ++++ pop-sandbox/examples/fungibles/lib.rs | 57 ++++++ pop-sandbox/examples/proxy/Cargo.toml | 38 ++++ pop-sandbox/examples/proxy/lib.rs | 76 ++++++++ pop-sandbox/src/api/mod.rs | 159 ++++++++++++++++ pop-sandbox/src/api/versioning.rs | 220 ++++++++++++++++++++++ pop-sandbox/src/lib.rs | 158 ++++++++++++++++ 13 files changed, 1019 insertions(+), 1 deletion(-) create mode 100644 pop-sandbox/Cargo.toml create mode 100644 pop-sandbox/examples/.gitignore create mode 100644 pop-sandbox/examples/flipper/.gitignore create mode 100644 pop-sandbox/examples/flipper/Cargo.toml create mode 100644 pop-sandbox/examples/flipper/lib.rs create mode 100644 pop-sandbox/examples/fungibles/Cargo.toml create mode 100644 pop-sandbox/examples/fungibles/lib.rs create mode 100644 pop-sandbox/examples/proxy/Cargo.toml create mode 100644 pop-sandbox/examples/proxy/lib.rs create mode 100644 pop-sandbox/src/api/mod.rs create mode 100644 pop-sandbox/src/api/versioning.rs create mode 100644 pop-sandbox/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 0c44755a..5699915b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,12 @@ license = "Unlicense" repository = "https://github.com/r0gue-io/pop-node/" [workspace] -exclude = [ "extension/contract", "pop-api", "tests/contracts" ] +exclude = [ + "extension/contract", + "pop-api", + "pop-sandbox", + "tests/contracts", +] members = [ "integration-tests", "node", diff --git a/pop-sandbox/Cargo.toml b/pop-sandbox/Cargo.toml new file mode 100644 index 00000000..6debda40 --- /dev/null +++ b/pop-sandbox/Cargo.toml @@ -0,0 +1,57 @@ +[package] +description = "Sandboxing environment for contract quasi testing with Pop Network runtimes." +edition = "2021" +license = "GPL-3.0-only" +name = "pop-sandbox" +version = "0.0.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.11", default-features = false } + +# Local +drink = { path = "../../pop-drink/drink", default-features = false } +pallet-api = { path = "../pallets/api", default-features = false } +pop-chain-extension = { path = "../extension", default-features = false } +pop-primitives = { path = "../primitives", default-features = false } + +# Substrate +cumulus-primitives-core = { version = "0.14.0", default-features = false } +frame-support = { version = "36.0.0", default-features = false } +frame-system = { version = "36.1.0", default-features = false } +pallet-assets = { version = "37.0.0", default-features = false } +pallet-balances = { version = "37.0.0", default-features = false } +pallet-contracts = { version = "35.0.0", default-features = false } +pallet-timestamp = { version = "35.0.0", default-features = false } +sp-core = { version = "34.0.0", default-features = false } +sp-runtime = { version = "38.0.0", default-features = false } +sp-std = { version = "14.0.0", default-features = false } + +[lib] +crate-type = [ "rlib" ] +name = "pop_sandbox" +path = "src/lib.rs" + +[features] +default = [ "std" ] +std = [ + "codec/std", + "cumulus-primitives-core/std", + "drink/std", + "frame-support/std", + "frame-system/std", + "pallet-api/std", + "pallet-api/std", + "pallet-assets/std", + "pallet-balances/std", + "pallet-contracts/std", + "pallet-timestamp/std", + "pop-chain-extension/std", + "pop-primitives/std", + "scale-info/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/pop-sandbox/examples/.gitignore b/pop-sandbox/examples/.gitignore new file mode 100644 index 00000000..d60800c8 --- /dev/null +++ b/pop-sandbox/examples/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +**/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +**/Cargo.lock diff --git a/pop-sandbox/examples/flipper/.gitignore b/pop-sandbox/examples/flipper/.gitignore new file mode 100644 index 00000000..8de8f877 --- /dev/null +++ b/pop-sandbox/examples/flipper/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/pop-sandbox/examples/flipper/Cargo.toml b/pop-sandbox/examples/flipper/Cargo.toml new file mode 100644 index 00000000..3ce7c90d --- /dev/null +++ b/pop-sandbox/examples/flipper/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "api_example_flipper" +edition = "2021" +version = "0.1.0" +authors = ["R0GUE "] + +[dependencies] +ink = { version = "=5.0.0", default-features = false, features = ["ink-debug"] } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.6", default-features = false, features = [ + "derive", +], optional = true } + +[dev-dependencies] +drink = { path = "../../../../pop-drink/drink" } +pop-sandbox = { path = "../../../pop-sandbox", default-features = false } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = ["ink/std", "scale/std", "scale-info/std", "pop-sandbox/std"] +ink-as-dependency = [] diff --git a/pop-sandbox/examples/flipper/lib.rs b/pop-sandbox/examples/flipper/lib.rs new file mode 100644 index 00000000..4efd4edf --- /dev/null +++ b/pop-sandbox/examples/flipper/lib.rs @@ -0,0 +1,167 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +/// This is the classical flipper contract. It stores a single `bool` value in its storage. The +/// contract exposes: +/// - a constructor (`new`) that initializes the `bool` value to the given value, +/// - a message `flip` that flips the stored `bool` value from `true` to `false` or vice versa, +/// - a getter message `get` that returns the current `bool` value. +/// +/// Additionally, we use the `debug_println` macro from the `ink_env` crate to produce some debug +/// logs from the contract. +#[ink::contract] +mod flipper { + use ink::env::debug_println; + + #[ink(storage)] + pub struct Flipper { + value: bool, + } + + impl Flipper { + #[ink(constructor)] + pub fn new(init: bool) -> Self { + debug_println!("Initializing contract with: `{init}`"); + Self { value: init } + } + + #[ink(message)] + pub fn flip(&mut self) { + debug_println!("Previous value: `{}`", self.value); + self.value = !self.value; + debug_println!("Flipped to: `{}`", self.value); + } + + #[ink(message)] + pub fn get(&self) -> bool { + debug_println!("Reading value from storage"); + self.value + } + } +} + +/// We put `drink`-based tests as usual unit tests, into a test module. +#[cfg(test)] +mod tests { + use drink::{ + sandbox_api::contracts_api::decode_debug_buffer, + session::{Session, NO_ARGS, NO_SALT}, + }; + + /// `drink` automatically discovers all the contract projects that your tests will need. For + /// every such dependency (including the contract from the current crate), it will generate a + /// [`ContractBundle`](drink::session::ContractBundle) object that contains the compiled contract's code + /// and a special transcoder, which is used to encode and decode the contract's message + /// arguments. Such a bundle will be useful when deploying a contract. + /// + /// To get a convenient way for obtaining such bundles, we can define an empty enum and mark + /// it with the [`drink::contract_bundle_provider`](drink::contract_bundle_provider) attribute. + /// From now on, we can use it in all testcases in this module. + #[drink::contract_bundle_provider] + enum BundleProvider {} + + /// Now we write the simplest contract test, that will: + /// 1. Deploy the contract. + /// 2. Call its `flip` method. + /// 3. Call its `get` method and ensure that the stored value has been flipped. + /// + /// We can use the [`drink::test`](drink::test) attribute to mark a function as a `drink` test. + /// This way we ensure that all the required contracts are compiled and built, so that we don't + /// have to run `cargo contract build` manually for every contract dependency. + /// + /// For convenience of using `?` operator, we mark the test function as returning a `Result`. + /// + /// `drink::test` will already provide us with a `Session` object. It is a wrapper around a runtime and it exposes + /// a broad API for interacting with it. Session is generic over the runtime type, but usually and by default, we + /// use `MinimalSandbox`, which is a minimalistic runtime that allows using smart contracts. + #[drink::test(sandbox = pop_sandbox::PopSandbox)] + fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { + // Now we get the contract bundle from the `BundleProvider` enum. Since the current crate + // comes with a contract, we can use the `local` method to get the bundle for it. + let contract_bundle = BundleProvider::local()?; + + // We can now deploy the contract. + let _contract_address = session.deploy_bundle( + // The bundle that we want to deploy. + contract_bundle, + // The constructor that we want to call. + "new", + // The constructor arguments (as stringish objects). + &["true"], + // Salt for the contract address derivation. + NO_SALT, + // Initial endowment (the amount of tokens that we want to transfer to the contract). + None, + )?; + + // Once the contract is instantiated, we can call the `flip` method on the contract. + session.call( + // The message that we want to call. + "flip", + // The message arguments (as stringish objects). If none, then we can use the `NO_ARGS` + // constant, which spares us from typing `&[]`. + NO_ARGS, + // Endowment (the amount of tokens that we want to transfer to the contract). + None, + )??; + + // Finally, we can call the `get` method on the contract and ensure that the value has been + // flipped. + // + // `Session::call` returns a `Result, SessionError>`, where `T` is the + // type of the message result. In this case, the `get` message returns a `bool`, and we have + // to explicitly hint the compiler about it. + let result: bool = session.call("get", NO_ARGS, None)??; + assert_eq!(result, false); + + Ok(()) + } + + /// In this testcase we will see how to get and read debug logs from the contract. + #[drink::test(sandbox = pop_sandbox::PopSandbox)] + fn get_debug_logs(mut session: Session) -> Result<(), Box> { + session.deploy_bundle(BundleProvider::local()?, "new", &["true"], NO_SALT, None)?; + + // `deploy_bundle` returns just a contract address. If we are interested in more details + // about last operation (either deploy or call), we can get a `Record` object and use its + // `last_deploy_result` (or analogously `last_call_result`) method, which will provide us + // with a full report from the last contract interaction. + // + // In particular, we can get the decoded debug buffer from the contract. The buffer is + // just a vector of bytes, which we can decode using the `decode_debug_buffer` function. + let decoded_buffer = &session.record().last_deploy_result().debug_message; + let encoded_buffer = decode_debug_buffer(decoded_buffer); + + assert_eq!(encoded_buffer, vec!["Initializing contract with: `true`"]); + + Ok(()) + } + + /// In this testcase we will see how to work with multiple contracts. + #[drink::test(sandbox = pop_sandbox::PopSandbox)] + fn work_with_multiple_contracts( + mut session: Session, + ) -> Result<(), Box> { + let bundle = BundleProvider::local()?; + + // We can deploy the same contract multiple times. However, we have to ensure that the + // derived contract addresses are different. We can do this by providing using different + // arguments for the constructor or by providing a different salt. + let first_address = + session.deploy_bundle(bundle.clone(), "new", &["true"], NO_SALT, None)?; + let _second_address = + session.deploy_bundle(bundle.clone(), "new", &["true"], vec![0], None)?; + let _third_address = session.deploy_bundle(bundle, "new", &["false"], NO_SALT, None)?; + + // By default, when we run `session.call`, `drink` will interact with the last deployed + // contract. + let value_at_third_contract: bool = session.call("get", NO_ARGS, None)??; + assert_eq!(value_at_third_contract, false); + + // However, we can also call a specific contract by providing its address. + let value_at_first_contract: bool = + session.call_with_address(first_address, "get", NO_ARGS, None)??; + assert_eq!(value_at_first_contract, true); + + Ok(()) + } +} diff --git a/pop-sandbox/examples/fungibles/Cargo.toml b/pop-sandbox/examples/fungibles/Cargo.toml new file mode 100644 index 00000000..326a1755 --- /dev/null +++ b/pop-sandbox/examples/fungibles/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "api_example_fungibles" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { version = "=5.0.0", default-features = false, features = ["ink-debug"] } +pop-api = { path = "../../../pop-api", default-features = false, features = [ + "fungibles", +] } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.6", default-features = false, features = [ + "derive", +], optional = true } + +[dev-dependencies] +drink = { path = "../../../../pop-drink/drink" } +pop-sandbox = { path = "../../../pop-sandbox", default-features = false } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +e2e-tests = [] +ink-as-dependency = [] +std = [ + "ink/std", + "pop-api/std", + "pop-sandbox/std", + "scale/std", + "scale-info/std", +] diff --git a/pop-sandbox/examples/fungibles/lib.rs b/pop-sandbox/examples/fungibles/lib.rs new file mode 100644 index 00000000..59d0ea7e --- /dev/null +++ b/pop-sandbox/examples/fungibles/lib.rs @@ -0,0 +1,57 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +#[ink::contract] +mod create_token_in_constructor { + use pop_api::{ + primitives::AssetId, + v0::assets::fungibles::{self as api}, + StatusCode, + }; + + pub type Result = core::result::Result; + + #[ink(storage)] + pub struct Fungible { + id: AssetId, + } + + impl Fungible { + #[ink(constructor)] + pub fn new(id: AssetId, min_balance: Balance) -> Result { + ink::env::debug_println!("Fungible::call() asset_id={id}, min_balance={min_balance}"); + let contract = Self { id }; + // AccountId of the contract which will be set to the owner of the fungible token. + let owner = contract.env().account_id(); + // TODO: Calling POP API caused DeploymentReverted + api::create(id, owner, min_balance)?; + Ok(contract) + } + + #[ink(message)] + pub fn asset_exists(&self) -> Result { + api::asset_exists(self.id) + } + } +} + +/// We put `drink`-based tests as usual unit tests, into a test module. +#[cfg(test)] +mod tests { + use drink::session::{Session, NO_ARGS, NO_SALT}; + + #[drink::contract_bundle_provider] + enum BundleProvider {} + + #[drink::test(sandbox = pop_sandbox::PopSandbox)] + fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { + let contract_bundle = BundleProvider::local()?; + let _contract_address = session.deploy_bundle( + contract_bundle, + "new", + &[1.to_string(), 1_000.to_string()], + NO_SALT, + None, + )?; + Ok(()) + } +} diff --git a/pop-sandbox/examples/proxy/Cargo.toml b/pop-sandbox/examples/proxy/Cargo.toml new file mode 100644 index 00000000..918de444 --- /dev/null +++ b/pop-sandbox/examples/proxy/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "api_example_proxy" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { version = "=5.0.0", default-features = false, features = ["ink-debug"] } +pop-api = { path = "../../../pop-api", default-features = false, features = [ + "fungibles", +] } +codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.6", default-features = false, features = [ + "derive", +], optional = true } +frame-system = { version = "29.0.0", default-features = false } + +[dev-dependencies] +drink = { path = "../../../../pop-drink/drink" } +pop-sandbox = { path = "../../../pop-sandbox", default-features = false } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +e2e-tests = [] +ink-as-dependency = [] +std = [ + "ink/std", + "pop-api/std", + "pop-sandbox/std", + "frame-system/std", + "codec/std", + "scale-info/std", +] diff --git a/pop-sandbox/examples/proxy/lib.rs b/pop-sandbox/examples/proxy/lib.rs new file mode 100644 index 00000000..b0116301 --- /dev/null +++ b/pop-sandbox/examples/proxy/lib.rs @@ -0,0 +1,76 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +use ink::{ + env::chain_extension::{ChainExtensionMethod, FromStatusCode}, + prelude::vec::Vec, +}; + +#[ink::contract] +mod proxy_contract { + use super::*; + + // Simple contract for proxying a call to a chain extension. + #[ink(storage)] + #[derive(Default)] + pub struct Proxy; + + impl Proxy { + #[ink(constructor)] + pub fn new() -> Self { + ink::env::debug_println!("Proxy::new()"); + Default::default() + } + + #[ink(message)] + pub fn call(&self, func_id: u32, input: Vec) -> Result, StatusCode> { + ink::env::debug_println!("Proxy::call() func_id={func_id}, input={input:?}"); + ChainExtensionMethod::build(func_id) + .input::>() + .output::, StatusCode>, true>() + .handle_error_code::() + .call(&input) + } + } + + #[ink::scale_derive(Encode, Decode, TypeInfo)] + pub struct StatusCode(u32); + impl FromStatusCode for StatusCode { + fn from_status_code(status_code: u32) -> Result<(), Self> { + match status_code { + 0 => Ok(()), + _ => Err(StatusCode(status_code)), + } + } + } + + impl From for StatusCode { + fn from(_: ink::scale::Error) -> Self { + StatusCode(u32::MAX) + } + } +} + +/// We put `drink`-based tests as usual unit tests, into a test module. +#[cfg(test)] +mod tests { + use codec::Encode; + use core::fmt::Debug; + use drink::session::{Session, NO_ARGS, NO_SALT}; + + #[drink::contract_bundle_provider] + enum BundleProvider {} + + #[drink::test(sandbox = pop_sandbox::PopSandbox)] + fn deploy_contract_and_call(mut session: Session) -> Result<(), Box> { + let contract_bundle = BundleProvider::local()?; + let contract_address = + session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, None)?; + + let input : Vec = vec![0, 7, 112, 111, 112].encode(); + let converted_input : Vec = input.into_iter().map(|b| b.to_string()).collect::>(); + // DispatchCall::RuntimeSystem::Remark + session.call_with_address(contract_address, "call", &[vec![0u32.to_string()], converted_input].concat(), None)??; + + Ok(()) + } +} diff --git a/pop-sandbox/src/api/mod.rs b/pop-sandbox/src/api/mod.rs new file mode 100644 index 00000000..ad4f8491 --- /dev/null +++ b/pop-sandbox/src/api/mod.rs @@ -0,0 +1,159 @@ +use core::marker::PhantomData; + +use codec::Decode; +use cumulus_primitives_core::Weight; +use frame_support::traits::Contains; +pub(crate) use pallet_api::Extension; +use pallet_api::{extension::*, Read}; +use sp_core::ConstU8; +use sp_runtime::DispatchError; +use sp_std::vec::Vec; +use versioning::*; + +use crate::{fungibles, Runtime, RuntimeCall, RuntimeEvent}; + +mod versioning; + +type DecodingFailedError = DecodingFailed; +type DecodesAs = pallet_api::extension::DecodesAs< + Output, + ContractWeightsOf, + DecodingFailedError, + Logger, +>; + +/// A query of runtime state. +#[derive(Decode, Debug)] +#[repr(u8)] +pub enum RuntimeRead { + /// Fungible token queries. + #[codec(index = 150)] + Fungibles(fungibles::Read), +} + +impl Readable for RuntimeRead { + /// The corresponding type carrying the result of the query for runtime state. + type Result = RuntimeResult; + + /// Determines the weight of the read, used to charge the appropriate weight before the read is + /// performed. + fn weight(&self) -> Weight { + match self { + RuntimeRead::Fungibles(key) => fungibles::Pallet::weight(key), + } + } + + /// Performs the read and returns the result. + fn read(self) -> Self::Result { + match self { + RuntimeRead::Fungibles(key) => RuntimeResult::Fungibles(fungibles::Pallet::read(key)), + } + } +} + +/// The result of a runtime state read. +#[derive(Debug)] +pub enum RuntimeResult { + /// Fungible token read results. + Fungibles(fungibles::ReadResult), +} + +impl RuntimeResult { + /// Encodes the result. + fn encode(&self) -> Vec { + match self { + RuntimeResult::Fungibles(result) => result.encode(), + } + } +} + +impl fungibles::Config for Runtime { + type AssetsInstance = (); + type RuntimeEvent = RuntimeEvent; + type WeightInfo = fungibles::weights::SubstrateWeight; +} + +#[derive(Default)] +pub struct Config; +impl pallet_api::extension::Config for Config { + /// Functions used by the Pop API. + /// + /// Each function corresponds to specific functionality provided by the API, facilitating the + /// interaction between smart contracts and the runtime. + type Functions = ( + // Dispatching calls + DispatchCall< + // Function ID: 0. + IdentifiedByFirstByteOfFunctionId>, + // The runtime configuration. + Runtime, + // Decode as a versioned runtime call. + DecodesAs, + // Apply any filtering. + Filter, + // Ensure errors are versioned. + VersionedErrorConverter, + // Logging with a specific target. + DispatchCallLogTarget, + >, + // Reading state + ReadState< + // Function ID: 1. + IdentifiedByFirstByteOfFunctionId>, + // The runtime configuration. + Runtime, + // The runtime state reads available. + RuntimeRead, + // Decode as a versioned runtime read. + DecodesAs, + // Apply any filtering. + Filter, + // Convert the result of a read into the expected versioned result + VersionedResultConverter, + // Ensure errors are versioned. + VersionedErrorConverter, + // Logging with a specific target. + ReadStateLogTarget, + >, + ); + + /// The log target. + const LOG_TARGET: &'static str = LOG_TARGET; +} + +/// Filters used by the chain extension. +pub struct Filter(PhantomData); + +impl> Contains for Filter { + fn contains(c: &RuntimeCall) -> bool { + use fungibles::Call::*; + T::BaseCallFilter::contains(c) + && matches!( + c, + RuntimeCall::Fungibles( + transfer { .. } + | transfer_from { .. } | approve { .. } + | increase_allowance { .. } + | decrease_allowance { .. } + | create { .. } | set_metadata { .. } + | start_destroy { .. } | clear_metadata { .. } + | mint { .. } | burn { .. } + ) + ) + } +} + +impl Contains for Filter { + fn contains(r: &RuntimeRead) -> bool { + use fungibles::Read::*; + matches!( + r, + RuntimeRead::Fungibles( + TotalSupply(..) + | BalanceOf { .. } | Allowance { .. } + | TokenName(..) | TokenSymbol(..) + | TokenDecimals(..) | TokenExists(..) + ) + ) + } +} diff --git a/pop-sandbox/src/api/versioning.rs b/pop-sandbox/src/api/versioning.rs new file mode 100644 index 00000000..317496df --- /dev/null +++ b/pop-sandbox/src/api/versioning.rs @@ -0,0 +1,220 @@ +use sp_runtime::ModuleError; + +use super::*; + +type Version = u8; + +/// Versioned runtime calls. +#[derive(Decode, Debug)] +pub enum VersionedRuntimeCall { + /// Version zero of runtime calls. + #[codec(index = 0)] + V0(RuntimeCall), +} + +impl From for RuntimeCall { + fn from(value: VersionedRuntimeCall) -> Self { + // Allows mapping from some previous runtime call shape to a current valid runtime call + match value { + VersionedRuntimeCall::V0(call) => call, + } + } +} + +/// Versioned runtime state reads. +#[derive(Decode, Debug)] +pub enum VersionedRuntimeRead { + /// Version zero of runtime state reads. + #[codec(index = 0)] + V0(RuntimeRead), +} + +impl From for RuntimeRead { + fn from(value: VersionedRuntimeRead) -> Self { + // Allows mapping from some previous runtime read shape to a current valid runtime read + match value { + VersionedRuntimeRead::V0(read) => read, + } + } +} + +/// Versioned runtime state read results. +#[derive(Debug)] +pub enum VersionedRuntimeResult { + /// Version zero of runtime read results. + V0(RuntimeResult), +} + +impl From<(RuntimeResult, Version)> for VersionedRuntimeResult { + fn from(value: (RuntimeResult, Version)) -> Self { + let (result, version) = value; + match version { + // Allows mapping from current `RuntimeResult` to a specific/prior version + 0 => VersionedRuntimeResult::V0(result), + // TODO: should never occur due to version processing/validation when request received + _ => unimplemented!(), + } + } +} + +impl From for Vec { + fn from(result: VersionedRuntimeResult) -> Self { + match result { + // Simply unwrap and return the encoded result + VersionedRuntimeResult::V0(result) => result.encode(), + } + } +} + +/// Versioned errors. +#[derive(Debug)] +pub enum VersionedError { + /// Version zero of errors. + V0(pop_primitives::v0::Error), +} + +impl From<(DispatchError, Version)> for VersionedError { + fn from(value: (DispatchError, Version)) -> Self { + let (error, version) = value; + match version { + // Allows mapping from current `DispatchError` to a specific/prior version of `Error` + 0 => VersionedError::V0(V0Error::from(error).0), + // TODO: should never occur due to version processing/validation when request received + _ => unimplemented!(), + } + } +} + +impl From for u32 { + fn from(value: VersionedError) -> Self { + match value { + VersionedError::V0(error) => error.into(), + } + } +} + +struct V0Error(pop_primitives::v0::Error); +impl From for V0Error { + fn from(error: DispatchError) -> Self { + use pop_primitives::v0::*; + use sp_runtime::{ArithmeticError::*, TokenError::*, TransactionalError::*}; + use DispatchError::*; + // Mappings exist here to avoid taking a dependency of sp_runtime on pop-primitives + Self(match error { + Other(_message) => { + // Note: lossy conversion: message not used due to returned contract status code + // size limitation + Error::Other + }, + CannotLookup => Error::CannotLookup, + BadOrigin => Error::BadOrigin, + Module(error) => { + // Note: message not used + let ModuleError { index, error, message: _message } = error; + // Map `pallet-contracts::Error::DecodingFailed` to `Error::DecodingFailed` + if index as usize == + ::index() && + error == DECODING_FAILED_ERROR + { + Error::DecodingFailed + } else { + // Note: lossy conversion of error value due to returned contract status code + // size limitation + Error::Module { index, error: [error[0], error[1]] } + } + }, + ConsumerRemaining => Error::ConsumerRemaining, + NoProviders => Error::NoProviders, + TooManyConsumers => Error::TooManyConsumers, + Token(error) => Error::Token(match error { + FundsUnavailable => TokenError::FundsUnavailable, + OnlyProvider => TokenError::OnlyProvider, + BelowMinimum => TokenError::BelowMinimum, + CannotCreate => TokenError::CannotCreate, + UnknownAsset => TokenError::UnknownAsset, + Frozen => TokenError::Frozen, + Unsupported => TokenError::Unsupported, + CannotCreateHold => TokenError::CannotCreateHold, + NotExpendable => TokenError::NotExpendable, + Blocked => TokenError::Blocked, + }), + Arithmetic(error) => Error::Arithmetic(match error { + Underflow => ArithmeticError::Underflow, + Overflow => ArithmeticError::Overflow, + DivisionByZero => ArithmeticError::DivisionByZero, + }), + Transactional(error) => Error::Transactional(match error { + LimitReached => TransactionalError::LimitReached, + NoLayer => TransactionalError::NoLayer, + }), + Exhausted => Error::Exhausted, + Corruption => Error::Corruption, + Unavailable => Error::Unavailable, + RootNotAllowed => Error::RootNotAllowed, + }) + } +} + +#[cfg(test)] +mod tests { + use pop_primitives::{ArithmeticError::*, Error, TokenError::*, TransactionalError::*}; + use sp_runtime::ModuleError; + use DispatchError::*; + + use super::*; + + // Compare all the different `DispatchError` variants with the expected `Error`. + #[test] + fn dispatch_error_to_error() { + let test_cases = vec![ + (Other(""), (Error::Other)), + (Other("UnknownCall"), Error::Other), + (Other("DecodingFailed"), Error::Other), + (Other("Random"), (Error::Other)), + (CannotLookup, Error::CannotLookup), + (BadOrigin, Error::BadOrigin), + ( + Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: Some("hallo") }), + Error::Module { index: 1, error: [2, 0] }, + ), + ( + Module(ModuleError { index: 1, error: [2, 2, 0, 0], message: Some("hallo") }), + Error::Module { index: 1, error: [2, 2] }, + ), + ( + Module(ModuleError { index: 1, error: [2, 2, 2, 0], message: Some("hallo") }), + Error::Module { index: 1, error: [2, 2] }, + ), + ( + Module(ModuleError { index: 1, error: [2, 2, 2, 4], message: Some("hallo") }), + Error::Module { index: 1, error: [2, 2] }, + ), + (pallet_contracts::Error::::DecodingFailed.into(), Error::DecodingFailed), + (ConsumerRemaining, Error::ConsumerRemaining), + (NoProviders, Error::NoProviders), + (TooManyConsumers, Error::TooManyConsumers), + (Token(sp_runtime::TokenError::BelowMinimum), Error::Token(BelowMinimum)), + (Arithmetic(sp_runtime::ArithmeticError::Overflow), Error::Arithmetic(Overflow)), + ( + Transactional(sp_runtime::TransactionalError::LimitReached), + Error::Transactional(LimitReached), + ), + (Exhausted, Error::Exhausted), + (Corruption, Error::Corruption), + (Unavailable, Error::Unavailable), + (RootNotAllowed, Error::RootNotAllowed), + ]; + for (dispatch_error, expected) in test_cases { + let error = V0Error::from(dispatch_error).0; + assert_eq!(error, expected); + } + } + + #[test] + fn decoding_failed_error_encoding_works() { + let Module(error) = pallet_contracts::Error::::DecodingFailed.into() else { + unreachable!() + }; + assert_eq!(error.error, DECODING_FAILED_ERROR) + } +} diff --git a/pop-sandbox/src/lib.rs b/pop-sandbox/src/lib.rs new file mode 100644 index 00000000..f2abacd3 --- /dev/null +++ b/pop-sandbox/src/lib.rs @@ -0,0 +1,158 @@ +use crate::api::Config; +use frame_support::{ + construct_runtime, derive_impl, parameter_types, + sp_runtime::{testing::H256, Perbill}, + traits::{AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, Randomness}, + weights::Weight, +}; +use frame_system::{EnsureRoot, EnsureSigned}; +use pallet_api::fungibles; +use pallet_contracts::{DefaultAddressGenerator, Frame, Schedule}; +use sp_runtime::traits::{AccountIdLookup, Convert}; +use sp_std::vec::Vec; + +mod api; + +pub(crate) type AccountId = AccountId32; +pub(crate) type AssetId = u32; +pub(crate) type Balance = u128; + +// Define the runtime type as a collection of pallets +construct_runtime!( + pub enum Runtime { + System: frame_system, + Assets: pallet_assets, + Balances: pallet_balances, + Timestamp: pallet_timestamp, + Contracts: pallet_contracts, + Fungibles: fungibles = 150, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Runtime { + type AccountData = pallet_balances::AccountData<::Balance>; + type AccountId = AccountId; + type Block = frame_system::mocking::MockBlock; + type Lookup = AccountIdLookup; +} + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +impl pallet_balances::Config for Runtime { + type AccountStore = System; + type Balance = Balance; + type ExistentialDeposit = ConstU128<1>; + type ReserveIdentifier = [u8; 8]; +} + +parameter_types! { + pub const AssetDeposit: u128 = 1; + pub const AssetAccountDeposit: u128 = 10; + pub const ApprovalDeposit: u128 = 1; + pub const AssetsStringLimit: u32 = 50; + pub const MetadataDepositBase: u128 = 1; + pub const MetadataDepositPerByte: u128 = 1; +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type RemoveItemsLimit = ConstU32<5>; + type AssetId = AssetId; + type AssetIdParameter = u32; + type Currency = Balances; + type CreateOrigin = AsEnsureOriginWithArg>; + type ForceOrigin = EnsureRoot; + type AssetDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; + type MetadataDepositBase = ConstU128<1>; + type MetadataDepositPerByte = ConstU128<1>; + type ApprovalDeposit = ConstU128<1>; + type StringLimit = ConstU32<50>; + type Freezer = (); + type Extra = (); + type CallbackHandle = (); + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + +#[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig as pallet_timestamp::DefaultConfig)] +impl pallet_timestamp::Config for Runtime {} + +// Configure pallet contracts +impl Randomness for Runtime { + fn random(_subject: &[u8]) -> (H256, u64) { + (Default::default(), Default::default()) + } +} + +// Configure pallet contracts +pub enum SandboxRandomness {} +impl Randomness for SandboxRandomness { + fn random(_subject: &[u8]) -> (H256, u64) { + unreachable!("No randomness") + } +} + +type BalanceOf = ::Balance; +impl Convert for Runtime { + fn convert(w: Weight) -> BalanceOf { + w.ref_time().into() + } +} + +parameter_types! { + pub SandboxSchedule: Schedule = { + let schedule = >::default(); + schedule + }; + pub DeletionWeightLimit: Weight = Weight::zero(); + pub DefaultDepositLimit: BalanceOf = 10_000_000; + pub CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); + pub MaxDelegateDependencies: u32 = 32; +} + +impl pallet_contracts::Config for Runtime { + type AddressGenerator = DefaultAddressGenerator; + type ApiVersion = (); + type CallFilter = (); + // TestFilter; + type CallStack = [Frame; 5]; + type ChainExtension = api::Extension; + type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; + type Currency = Balances; + type Debug = drink::pallet_contracts_debugging::DrinkDebug; + // TestDebug; + type DefaultDepositLimit = DefaultDepositLimit; + type DepositPerByte = ConstU128<1>; + type DepositPerItem = ConstU128<1>; + type Environment = (); + type InstantiateOrigin = EnsureSigned; + type MaxCodeLen = ConstU32<{ 123 * 1024 }>; + type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; + type MaxDelegateDependencies = MaxDelegateDependencies; + type MaxStorageKeyLen = ConstU32<128>; + type Migrations = (); + // crate::migration::codegen::BenchMigrations; + type Randomness = SandboxRandomness; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; + type Schedule = SandboxSchedule; + type Time = Timestamp; + type UnsafeUnstableInterface = ConstBool; + // UnstableInterface; + type UploadOrigin = EnsureSigned; + type WeightInfo = (); + type WeightPrice = Self; + // Self; + type Xcm = (); +} + +drink::create_sandbox!(PopSandbox, Runtime); From 7f04779a0cac28dfa82a182c35c3b7c425883a97 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 11 Sep 2024 15:49:29 +0700 Subject: [PATCH 057/161] fix: taplo formatting --- pop-sandbox/examples/flipper/Cargo.toml | 16 +++++----- pop-sandbox/examples/fungibles/Cargo.toml | 28 +++++++++--------- pop-sandbox/examples/proxy/Cargo.toml | 36 +++++++++++------------ 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/pop-sandbox/examples/flipper/Cargo.toml b/pop-sandbox/examples/flipper/Cargo.toml index 3ce7c90d..c0694808 100644 --- a/pop-sandbox/examples/flipper/Cargo.toml +++ b/pop-sandbox/examples/flipper/Cargo.toml @@ -1,17 +1,17 @@ [package] -name = "api_example_flipper" +authors = [ "R0GUE " ] edition = "2021" +name = "api_example_flipper" version = "0.1.0" -authors = ["R0GUE "] [dependencies] -ink = { version = "=5.0.0", default-features = false, features = ["ink-debug"] } +ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", + "derive", ] } scale-info = { version = "2.6", default-features = false, features = [ - "derive", + "derive", ], optional = true } [dev-dependencies] @@ -22,6 +22,6 @@ pop-sandbox = { path = "../../../pop-sandbox", default-features = false } path = "lib.rs" [features] -default = ["std"] -std = ["ink/std", "scale/std", "scale-info/std", "pop-sandbox/std"] -ink-as-dependency = [] +default = [ "std" ] +ink-as-dependency = [ ] +std = [ "ink/std", "pop-sandbox/std", "scale-info/std", "scale/std" ] diff --git a/pop-sandbox/examples/fungibles/Cargo.toml b/pop-sandbox/examples/fungibles/Cargo.toml index 326a1755..f151f376 100644 --- a/pop-sandbox/examples/fungibles/Cargo.toml +++ b/pop-sandbox/examples/fungibles/Cargo.toml @@ -1,19 +1,19 @@ [package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" name = "api_example_fungibles" version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" [dependencies] -ink = { version = "=5.0.0", default-features = false, features = ["ink-debug"] } +ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } pop-api = { path = "../../../pop-api", default-features = false, features = [ - "fungibles", + "fungibles", ] } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", + "derive", ] } scale-info = { version = "2.6", default-features = false, features = [ - "derive", + "derive", ], optional = true } [dev-dependencies] @@ -24,13 +24,13 @@ pop-sandbox = { path = "../../../pop-sandbox", default-features = false } path = "lib.rs" [features] -default = ["std"] -e2e-tests = [] -ink-as-dependency = [] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "pop-api/std", - "pop-sandbox/std", - "scale/std", - "scale-info/std", + "ink/std", + "pop-api/std", + "pop-sandbox/std", + "scale-info/std", + "scale/std", ] diff --git a/pop-sandbox/examples/proxy/Cargo.toml b/pop-sandbox/examples/proxy/Cargo.toml index 918de444..0dd7b249 100644 --- a/pop-sandbox/examples/proxy/Cargo.toml +++ b/pop-sandbox/examples/proxy/Cargo.toml @@ -1,21 +1,21 @@ [package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" name = "api_example_proxy" version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" [dependencies] -ink = { version = "=5.0.0", default-features = false, features = ["ink-debug"] } -pop-api = { path = "../../../pop-api", default-features = false, features = [ - "fungibles", -] } codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", + "derive", +] } +frame-system = { version = "29.0.0", default-features = false } +ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } +pop-api = { path = "../../../pop-api", default-features = false, features = [ + "fungibles", ] } scale-info = { version = "2.6", default-features = false, features = [ - "derive", + "derive", ], optional = true } -frame-system = { version = "29.0.0", default-features = false } [dev-dependencies] drink = { path = "../../../../pop-drink/drink" } @@ -25,14 +25,14 @@ pop-sandbox = { path = "../../../pop-sandbox", default-features = false } path = "lib.rs" [features] -default = ["std"] -e2e-tests = [] -ink-as-dependency = [] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] std = [ - "ink/std", - "pop-api/std", - "pop-sandbox/std", - "frame-system/std", - "codec/std", - "scale-info/std", + "codec/std", + "frame-system/std", + "ink/std", + "pop-api/std", + "pop-sandbox/std", + "scale-info/std", ] From 8a1095bb71df44d0a26b6d05355772ad205abb08 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:28:36 +0700 Subject: [PATCH 058/161] fix: update tests --- pop-sandbox/examples/fungibles/lib.rs | 14 ++++---- pop-sandbox/examples/proxy/Cargo.toml | 3 +- pop-sandbox/examples/proxy/lib.rs | 25 ++++++++++---- pop-sandbox/src/lib.rs | 2 ++ pop-sandbox/src/utils.rs | 38 +++++++++++++++++++++ runtime/devnet/src/config/api/versioning.rs | 6 ++-- 6 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 pop-sandbox/src/utils.rs diff --git a/pop-sandbox/examples/fungibles/lib.rs b/pop-sandbox/examples/fungibles/lib.rs index 59d0ea7e..d31786db 100644 --- a/pop-sandbox/examples/fungibles/lib.rs +++ b/pop-sandbox/examples/fungibles/lib.rs @@ -3,8 +3,8 @@ #[ink::contract] mod create_token_in_constructor { use pop_api::{ - primitives::AssetId, - v0::assets::fungibles::{self as api}, + primitives::TokenId, + v0::fungibles::{self as api}, StatusCode, }; @@ -12,13 +12,13 @@ mod create_token_in_constructor { #[ink(storage)] pub struct Fungible { - id: AssetId, + id: TokenId, } impl Fungible { #[ink(constructor)] - pub fn new(id: AssetId, min_balance: Balance) -> Result { - ink::env::debug_println!("Fungible::call() asset_id={id}, min_balance={min_balance}"); + pub fn new(id: TokenId, min_balance: Balance) -> Result { + ink::env::debug_println!("Fungible::call() asset_id={id}, min_balance={min_balance}"); let contract = Self { id }; // AccountId of the contract which will be set to the owner of the fungible token. let owner = contract.env().account_id(); @@ -28,8 +28,8 @@ mod create_token_in_constructor { } #[ink(message)] - pub fn asset_exists(&self) -> Result { - api::asset_exists(self.id) + pub fn token_exists(&self) -> Result { + api::token_exists(self.id) } } } diff --git a/pop-sandbox/examples/proxy/Cargo.toml b/pop-sandbox/examples/proxy/Cargo.toml index 0dd7b249..f937145a 100644 --- a/pop-sandbox/examples/proxy/Cargo.toml +++ b/pop-sandbox/examples/proxy/Cargo.toml @@ -8,7 +8,7 @@ version = "0.1.0" codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive", ] } -frame-system = { version = "29.0.0", default-features = false } +frame-system = { version = "36.1.0", default-features = false } ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } pop-api = { path = "../../../pop-api", default-features = false, features = [ "fungibles", @@ -20,6 +20,7 @@ scale-info = { version = "2.6", default-features = false, features = [ [dev-dependencies] drink = { path = "../../../../pop-drink/drink" } pop-sandbox = { path = "../../../pop-sandbox", default-features = false } +serde_json = "1.0.108" [lib] path = "lib.rs" diff --git a/pop-sandbox/examples/proxy/lib.rs b/pop-sandbox/examples/proxy/lib.rs index b0116301..e91ea6fe 100644 --- a/pop-sandbox/examples/proxy/lib.rs +++ b/pop-sandbox/examples/proxy/lib.rs @@ -55,21 +55,34 @@ mod proxy_contract { mod tests { use codec::Encode; use core::fmt::Debug; - use drink::session::{Session, NO_ARGS, NO_SALT}; + use drink::{ + session::{Session, NO_ARGS, NO_SALT}, + AccountId32, + }; + use frame_system::Call; + use pop_sandbox::{utils::call_function, PopSandbox, RuntimeCall}; #[drink::contract_bundle_provider] enum BundleProvider {} - #[drink::test(sandbox = pop_sandbox::PopSandbox)] + #[drink::test(sandbox = PopSandbox)] fn deploy_contract_and_call(mut session: Session) -> Result<(), Box> { let contract_bundle = BundleProvider::local()?; let contract_address = session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, None)?; - let input : Vec = vec![0, 7, 112, 111, 112].encode(); - let converted_input : Vec = input.into_iter().map(|b| b.to_string()).collect::>(); - // DispatchCall::RuntimeSystem::Remark - session.call_with_address(contract_address, "call", &[vec![0u32.to_string()], converted_input].concat(), None)??; + let alice = AccountId32::new([1u8; 32]); + let call = + RuntimeCall::System(Call::remark_with_event { remark: "pop".as_bytes().to_vec() }); + call_function( + session, + &contract_address, + &alice, + "call".to_string(), + // DispatchCall::System::Call::remark_with_event. + Some(vec![0.to_string(), serde_json::to_string(&call.encode()).unwrap()]), + None, + )?; Ok(()) } diff --git a/pop-sandbox/src/lib.rs b/pop-sandbox/src/lib.rs index f2abacd3..9d2d2cd8 100644 --- a/pop-sandbox/src/lib.rs +++ b/pop-sandbox/src/lib.rs @@ -12,6 +12,8 @@ use sp_runtime::traits::{AccountIdLookup, Convert}; use sp_std::vec::Vec; mod api; +// Provides utlity methods to interact with the sandbox. +pub mod utils; pub(crate) type AccountId = AccountId32; pub(crate) type AssetId = u32; diff --git a/pop-sandbox/src/utils.rs b/pop-sandbox/src/utils.rs new file mode 100644 index 00000000..f315897e --- /dev/null +++ b/pop-sandbox/src/utils.rs @@ -0,0 +1,38 @@ +use drink::{ + session::{Session, NO_ARGS}, + AccountId32, +}; +use std::error::Error; + +use super::*; + +// TODO: Convert this method to accept generic runtime instead of `PopSandbox`. +pub fn call_function( + mut sess: Session, + contract: &AccountId32, + sender: &AccountId32, + func_name: String, + args: Option>, + value: Option, +) -> Result, Box> { + sess.set_actor(sender.clone()); + if let Some(args) = args { + println!("Calling function: {}() | Input: {:?}", func_name, args); + sess.call_with_address(contract.clone(), &func_name, &args, value)??; + } else { + println!("Calling function: {}() | Input: None", func_name); + sess.call_with_address(contract.clone(), &func_name, NO_ARGS, value)??; + } + + let encoded = &sess.record().last_call_result().result.clone().unwrap().data; + let decoded = encoded.iter().map(|b| *b as char).collect::(); + let messages: Vec = decoded.split('\n').map(|s| s.to_string()).collect(); + // Print debug logs + for line in messages { + if line.len() > 0 { + println!("LOG: {}", line); + } + } + + Ok(sess) +} diff --git a/runtime/devnet/src/config/api/versioning.rs b/runtime/devnet/src/config/api/versioning.rs index 317496df..7c3d9ee5 100644 --- a/runtime/devnet/src/config/api/versioning.rs +++ b/runtime/devnet/src/config/api/versioning.rs @@ -112,9 +112,9 @@ impl From for V0Error { // Note: message not used let ModuleError { index, error, message: _message } = error; // Map `pallet-contracts::Error::DecodingFailed` to `Error::DecodingFailed` - if index as usize == - ::index() && - error == DECODING_FAILED_ERROR + if index as usize + == ::index() + && error == DECODING_FAILED_ERROR { Error::DecodingFailed } else { From d23c2b315e0d5469df9c95bfa248c29fb024a2ef Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:33:56 +0700 Subject: [PATCH 059/161] fix: test with logger --- pop-sandbox/examples/flipper/Cargo.toml | 1 + pop-sandbox/examples/flipper/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pop-sandbox/examples/flipper/Cargo.toml b/pop-sandbox/examples/flipper/Cargo.toml index c0694808..1080f85e 100644 --- a/pop-sandbox/examples/flipper/Cargo.toml +++ b/pop-sandbox/examples/flipper/Cargo.toml @@ -16,6 +16,7 @@ scale-info = { version = "2.6", default-features = false, features = [ [dev-dependencies] drink = { path = "../../../../pop-drink/drink" } +env_logger = { version = "0.11.3" } pop-sandbox = { path = "../../../pop-sandbox", default-features = false } [lib] diff --git a/pop-sandbox/examples/flipper/lib.rs b/pop-sandbox/examples/flipper/lib.rs index 4efd4edf..3d72c2cb 100644 --- a/pop-sandbox/examples/flipper/lib.rs +++ b/pop-sandbox/examples/flipper/lib.rs @@ -75,6 +75,7 @@ mod tests { /// use `MinimalSandbox`, which is a minimalistic runtime that allows using smart contracts. #[drink::test(sandbox = pop_sandbox::PopSandbox)] fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); // Now we get the contract bundle from the `BundleProvider` enum. Since the current crate // comes with a contract, we can use the `local` method to get the bundle for it. let contract_bundle = BundleProvider::local()?; @@ -90,7 +91,7 @@ mod tests { // Salt for the contract address derivation. NO_SALT, // Initial endowment (the amount of tokens that we want to transfer to the contract). - None, + Some(1000), )?; // Once the contract is instantiated, we can call the `flip` method on the contract. From 0ab510f3d366a379ead74c6fe6bcd3c6f72cedf6 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:34:11 +0700 Subject: [PATCH 060/161] fix: test with logger --- pop-sandbox/examples/fungibles/Cargo.toml | 1 + pop-sandbox/examples/fungibles/lib.rs | 8 +-- pop-sandbox/examples/proxy/Cargo.toml | 1 + pop-sandbox/examples/proxy/lib.rs | 11 +++-- pop-sandbox/src/lib.rs | 59 +++++++++++++++-------- pop-sandbox/src/utils.rs | 2 + 6 files changed, 55 insertions(+), 27 deletions(-) diff --git a/pop-sandbox/examples/fungibles/Cargo.toml b/pop-sandbox/examples/fungibles/Cargo.toml index f151f376..075ea943 100644 --- a/pop-sandbox/examples/fungibles/Cargo.toml +++ b/pop-sandbox/examples/fungibles/Cargo.toml @@ -18,6 +18,7 @@ scale-info = { version = "2.6", default-features = false, features = [ [dev-dependencies] drink = { path = "../../../../pop-drink/drink" } +env_logger = { version = "0.11.3" } pop-sandbox = { path = "../../../pop-sandbox", default-features = false } [lib] diff --git a/pop-sandbox/examples/fungibles/lib.rs b/pop-sandbox/examples/fungibles/lib.rs index d31786db..f8328800 100644 --- a/pop-sandbox/examples/fungibles/lib.rs +++ b/pop-sandbox/examples/fungibles/lib.rs @@ -20,9 +20,7 @@ mod create_token_in_constructor { pub fn new(id: TokenId, min_balance: Balance) -> Result { ink::env::debug_println!("Fungible::call() asset_id={id}, min_balance={min_balance}"); let contract = Self { id }; - // AccountId of the contract which will be set to the owner of the fungible token. let owner = contract.env().account_id(); - // TODO: Calling POP API caused DeploymentReverted api::create(id, owner, min_balance)?; Ok(contract) } @@ -37,20 +35,22 @@ mod create_token_in_constructor { /// We put `drink`-based tests as usual unit tests, into a test module. #[cfg(test)] mod tests { - use drink::session::{Session, NO_ARGS, NO_SALT}; + use drink::session::{Session, NO_SALT}; #[drink::contract_bundle_provider] enum BundleProvider {} #[drink::test(sandbox = pop_sandbox::PopSandbox)] fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); let contract_bundle = BundleProvider::local()?; + // TODO: utility method for deploy_contract let _contract_address = session.deploy_bundle( contract_bundle, "new", &[1.to_string(), 1_000.to_string()], NO_SALT, - None, + Some(100_000_000), )?; Ok(()) } diff --git a/pop-sandbox/examples/proxy/Cargo.toml b/pop-sandbox/examples/proxy/Cargo.toml index f937145a..95adf32c 100644 --- a/pop-sandbox/examples/proxy/Cargo.toml +++ b/pop-sandbox/examples/proxy/Cargo.toml @@ -19,6 +19,7 @@ scale-info = { version = "2.6", default-features = false, features = [ [dev-dependencies] drink = { path = "../../../../pop-drink/drink" } +env_logger = { version = "0.11.3" } pop-sandbox = { path = "../../../pop-sandbox", default-features = false } serde_json = "1.0.108" diff --git a/pop-sandbox/examples/proxy/lib.rs b/pop-sandbox/examples/proxy/lib.rs index e91ea6fe..d5299045 100644 --- a/pop-sandbox/examples/proxy/lib.rs +++ b/pop-sandbox/examples/proxy/lib.rs @@ -60,29 +60,34 @@ mod tests { AccountId32, }; use frame_system::Call; - use pop_sandbox::{utils::call_function, PopSandbox, RuntimeCall}; + use pop_sandbox::{ + utils::{call_function, ALICE}, + PopSandbox, RuntimeCall, + }; #[drink::contract_bundle_provider] enum BundleProvider {} #[drink::test(sandbox = PopSandbox)] fn deploy_contract_and_call(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + let contract_bundle = BundleProvider::local()?; let contract_address = session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, None)?; - let alice = AccountId32::new([1u8; 32]); let call = RuntimeCall::System(Call::remark_with_event { remark: "pop".as_bytes().to_vec() }); call_function( session, &contract_address, - &alice, + &ALICE, "call".to_string(), // DispatchCall::System::Call::remark_with_event. Some(vec![0.to_string(), serde_json::to_string(&call.encode()).unwrap()]), None, )?; + // TOOD: Return CallFiltered Ok(()) } diff --git a/pop-sandbox/src/lib.rs b/pop-sandbox/src/lib.rs index 9d2d2cd8..118ebaa6 100644 --- a/pop-sandbox/src/lib.rs +++ b/pop-sandbox/src/lib.rs @@ -7,7 +7,7 @@ use frame_support::{ }; use frame_system::{EnsureRoot, EnsureSigned}; use pallet_api::fungibles; -use pallet_contracts::{DefaultAddressGenerator, Frame, Schedule}; +use pallet_contracts::{DefaultAddressGenerator, Frame}; use sp_runtime::traits::{AccountIdLookup, Convert}; use sp_std::vec::Vec; @@ -19,6 +19,12 @@ pub(crate) type AccountId = AccountId32; pub(crate) type AssetId = u32; pub(crate) type Balance = u128; +pub const MILLIUNIT: Balance = UNIT / 1_000; // 10_000_000 + +pub const fn deposit(items: u32, bytes: u32) -> Balance { + (items as Balance * UNIT + (bytes as Balance) * (5 * MILLIUNIT / 100)) / 10 +} + // Define the runtime type as a collection of pallets construct_runtime!( pub enum Runtime { @@ -109,51 +115,64 @@ impl Convert for Runtime { } } +fn schedule() -> pallet_contracts::Schedule { + pallet_contracts::Schedule { + limits: pallet_contracts::Limits { + runtime_memory: 1024 * 1024 * 1024, + ..Default::default() + }, + ..Default::default() + } +} + parameter_types! { - pub SandboxSchedule: Schedule = { - let schedule = >::default(); - schedule - }; - pub DeletionWeightLimit: Weight = Weight::zero(); - pub DefaultDepositLimit: BalanceOf = 10_000_000; - pub CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); - pub MaxDelegateDependencies: u32 = 32; + pub const DepositPerItem: Balance = deposit(1, 0); + pub const DepositPerByte: Balance = deposit(0, 1); + pub Schedule: pallet_contracts::Schedule = schedule::(); + pub const DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024); + pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); } impl pallet_contracts::Config for Runtime { type AddressGenerator = DefaultAddressGenerator; type ApiVersion = (); + // C type CallFilter = (); - // TestFilter; - type CallStack = [Frame; 5]; + type CallStack = [Frame; 23]; type ChainExtension = api::Extension; type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; type Currency = Balances; + // D type Debug = drink::pallet_contracts_debugging::DrinkDebug; - // TestDebug; type DefaultDepositLimit = DefaultDepositLimit; - type DepositPerByte = ConstU128<1>; - type DepositPerItem = ConstU128<1>; + type DepositPerByte = DepositPerByte; + type DepositPerItem = DepositPerItem; + // E type Environment = (); + // I type InstantiateOrigin = EnsureSigned; - type MaxCodeLen = ConstU32<{ 123 * 1024 }>; + // M + type MaxCodeLen = ConstU32<{ 256 * 1024 }>; type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; - type MaxDelegateDependencies = MaxDelegateDependencies; + type MaxDelegateDependencies = ConstU32<32>; type MaxStorageKeyLen = ConstU32<128>; type Migrations = (); - // crate::migration::codegen::BenchMigrations; + // R type Randomness = SandboxRandomness; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; type RuntimeHoldReason = RuntimeHoldReason; - type Schedule = SandboxSchedule; + // S + type Schedule = Schedule; + // T type Time = Timestamp; + // U type UnsafeUnstableInterface = ConstBool; - // UnstableInterface; type UploadOrigin = EnsureSigned; + // W type WeightInfo = (); type WeightPrice = Self; - // Self; + // X type Xcm = (); } diff --git a/pop-sandbox/src/utils.rs b/pop-sandbox/src/utils.rs index f315897e..8a8085ac 100644 --- a/pop-sandbox/src/utils.rs +++ b/pop-sandbox/src/utils.rs @@ -6,6 +6,8 @@ use std::error::Error; use super::*; +pub const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); + // TODO: Convert this method to accept generic runtime instead of `PopSandbox`. pub fn call_function( mut sess: Session, From 1c0604321e87af52a9dc17e83fd1088bd35ea142 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:35:31 +0700 Subject: [PATCH 061/161] fix: revert flipper example changes --- pop-sandbox/examples/flipper/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pop-sandbox/examples/flipper/lib.rs b/pop-sandbox/examples/flipper/lib.rs index 3d72c2cb..9e97465a 100644 --- a/pop-sandbox/examples/flipper/lib.rs +++ b/pop-sandbox/examples/flipper/lib.rs @@ -91,7 +91,7 @@ mod tests { // Salt for the contract address derivation. NO_SALT, // Initial endowment (the amount of tokens that we want to transfer to the contract). - Some(1000), + None, )?; // Once the contract is instantiated, we can call the `flip` method on the contract. From f6976b082e9065bd933cf3093588c969ad402128 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:13:39 +0700 Subject: [PATCH 062/161] fix: fungibles contract --- pop-sandbox/examples/fungibles/lib.rs | 44 +++++++++++++++++++-------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/pop-sandbox/examples/fungibles/lib.rs b/pop-sandbox/examples/fungibles/lib.rs index f8328800..2e976376 100644 --- a/pop-sandbox/examples/fungibles/lib.rs +++ b/pop-sandbox/examples/fungibles/lib.rs @@ -1,14 +1,16 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] +use pop_api::{ + primitives::TokenId, + v0::fungibles::{self as api}, + StatusCode, +}; + +type PopApiResult = core::result::Result; + #[ink::contract] mod create_token_in_constructor { - use pop_api::{ - primitives::TokenId, - v0::fungibles::{self as api}, - StatusCode, - }; - - pub type Result = core::result::Result; + use super::*; #[ink(storage)] pub struct Fungible { @@ -16,8 +18,8 @@ mod create_token_in_constructor { } impl Fungible { - #[ink(constructor)] - pub fn new(id: TokenId, min_balance: Balance) -> Result { + #[ink(constructor, payable)] + pub fn new(id: TokenId, min_balance: Balance) -> PopApiResult { ink::env::debug_println!("Fungible::call() asset_id={id}, min_balance={min_balance}"); let contract = Self { id }; let owner = contract.env().account_id(); @@ -26,8 +28,8 @@ mod create_token_in_constructor { } #[ink(message)] - pub fn token_exists(&self) -> Result { - api::token_exists(self.id) + pub fn token_exists(&self, id: TokenId) -> PopApiResult { + api::token_exists(id) } } } @@ -35,7 +37,9 @@ mod create_token_in_constructor { /// We put `drink`-based tests as usual unit tests, into a test module. #[cfg(test)] mod tests { + use super::*; use drink::session::{Session, NO_SALT}; + use pop_sandbox::utils::{call_function, ALICE}; #[drink::contract_bundle_provider] enum BundleProvider {} @@ -44,14 +48,28 @@ mod tests { fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); let contract_bundle = BundleProvider::local()?; - // TODO: utility method for deploy_contract - let _contract_address = session.deploy_bundle( + + const ASSET_ID: TokenId = 1; + // Deploy a contract and create a new token with ASSET_ID = 1 + let contract_address = session.deploy_bundle( contract_bundle, "new", &[1.to_string(), 1_000.to_string()], NO_SALT, Some(100_000_000), )?; + // Calling the method in the contract. + let session = call_function( + session, + &contract_address, + &ALICE, + "token_exists".to_string(), + Some(vec![ASSET_ID.to_string()]), + None, + )?; + // Check that the token is created successfully. + let result = session.record().last_call_return_decoded::>()??; + assert_eq!(result, Ok(true)); Ok(()) } } From d6408da5636bfbbf9a12ae975e67bab0c1160818 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:14:49 +0700 Subject: [PATCH 063/161] refactor: create sandbox for devnet runtime --- pop-api/examples/balance-transfer/Cargo.toml | 28 -- pop-api/examples/balance-transfer/lib.rs | 135 --------- pop-api/examples/fungibles/Cargo.toml | 22 +- pop-api/examples/fungibles/lib.rs | 180 ++++++------ pop-api/examples/nfts/Cargo.toml | 25 -- pop-api/examples/nfts/lib.rs | 117 -------- pop-api/examples/place-spot-order/Cargo.toml | 25 -- pop-api/examples/place-spot-order/lib.rs | 43 --- .../examples/read-runtime-state/Cargo.toml | 25 -- pop-api/examples/read-runtime-state/lib.rs | 36 --- pop-sandbox/Cargo.toml | 38 +-- pop-sandbox/examples/flipper/lib.rs | 15 +- pop-sandbox/examples/fungibles/Cargo.toml | 37 --- pop-sandbox/examples/fungibles/lib.rs | 75 ----- pop-sandbox/examples/proxy/Cargo.toml | 40 --- pop-sandbox/examples/proxy/lib.rs | 94 ------- pop-sandbox/src/api/mod.rs | 159 ----------- pop-sandbox/src/api/versioning.rs | 220 --------------- pop-sandbox/src/lib.rs | 261 ++++++++---------- pop-sandbox/src/utils.rs | 5 +- runtime/devnet/src/config/api/versioning.rs | 6 +- 21 files changed, 242 insertions(+), 1344 deletions(-) delete mode 100755 pop-api/examples/balance-transfer/Cargo.toml delete mode 100755 pop-api/examples/balance-transfer/lib.rs mode change 100755 => 100644 pop-api/examples/fungibles/Cargo.toml mode change 100755 => 100644 pop-api/examples/fungibles/lib.rs delete mode 100755 pop-api/examples/nfts/Cargo.toml delete mode 100755 pop-api/examples/nfts/lib.rs delete mode 100755 pop-api/examples/place-spot-order/Cargo.toml delete mode 100755 pop-api/examples/place-spot-order/lib.rs delete mode 100755 pop-api/examples/read-runtime-state/Cargo.toml delete mode 100755 pop-api/examples/read-runtime-state/lib.rs delete mode 100644 pop-sandbox/examples/fungibles/Cargo.toml delete mode 100644 pop-sandbox/examples/fungibles/lib.rs delete mode 100644 pop-sandbox/examples/proxy/Cargo.toml delete mode 100644 pop-sandbox/examples/proxy/lib.rs delete mode 100644 pop-sandbox/src/api/mod.rs delete mode 100644 pop-sandbox/src/api/versioning.rs diff --git a/pop-api/examples/balance-transfer/Cargo.toml b/pop-api/examples/balance-transfer/Cargo.toml deleted file mode 100755 index 2a12e532..00000000 --- a/pop-api/examples/balance-transfer/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "balance_transfer" -version = "0.1.0" - -[dependencies] -ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } - -[dev-dependencies] -ink_e2e = "5.0.0" - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "ink/std", - "pop-api/std", - "scale-info/std", - "scale/std", -] diff --git a/pop-api/examples/balance-transfer/lib.rs b/pop-api/examples/balance-transfer/lib.rs deleted file mode 100755 index e75c15b9..00000000 --- a/pop-api/examples/balance-transfer/lib.rs +++ /dev/null @@ -1,135 +0,0 @@ -// DEPRECATED -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -use pop_api::balances::*; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum ContractError { - BalancesError(Error), -} - -impl From for ContractError { - fn from(value: Error) -> Self { - ContractError::BalancesError(value) - } -} - -#[ink::contract] -mod balance_transfer { - use super::*; - - #[ink(storage)] - #[derive(Default)] - pub struct BalanceTransfer; - - impl BalanceTransfer { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("BalanceTransfer::new"); - Default::default() - } - - #[ink(message)] - pub fn transfer( - &mut self, - receiver: AccountId, - value: Balance, - ) -> Result<(), ContractError> { - ink::env::debug_println!( - "BalanceTransfer::transfer: \nreceiver: {:?}, \nvalue: {:?}", - receiver, - value - ); - - transfer_keep_alive(receiver, value)?; - - ink::env::debug_println!("BalanceTransfer::transfer end"); - Ok(()) - } - } - - #[cfg(all(test, feature = "e2e-tests"))] - mod e2e_tests { - use super::*; - use ink_e2e::{ChainBackend, ContractsBackend}; - - use ink::{ - env::{test::default_accounts, DefaultEnvironment}, - primitives::AccountId, - }; - - type E2EResult = Result>; - - /// The base number of indivisible units for balances on the - /// `substrate-contracts-node`. - const UNIT: Balance = 1_000_000_000_000; - - /// The contract will be given 1000 tokens during instantiation. - const CONTRACT_BALANCE: Balance = 1_000 * UNIT; - - /// The receiver will get enough funds to have the required existential deposit. - /// - /// If your chain has this threshold higher, increase the transfer value. - const TRANSFER_VALUE: Balance = 1 / 10 * UNIT; - - /// An amount that is below the existential deposit, so that a transfer to an - /// empty account fails. - /// - /// Must not be zero, because such an operation would be a successful no-op. - const INSUFFICIENT_TRANSFER_VALUE: Balance = 1; - - /// Positive case scenario: - /// - the call is valid - /// - the call execution succeeds - #[ink_e2e::test] - async fn transfer_with_call_runtime_works( - mut client: Client, - ) -> E2EResult<()> { - // given - let mut constructor = RuntimeCallerRef::new(); - let contract = client - .instantiate("call-runtime", &ink_e2e::alice(), &mut constructor) - .value(CONTRACT_BALANCE) - .submit() - .await - .expect("instantiate failed"); - let mut call_builder = contract.call_builder::(); - - let accounts = default_accounts::(); - - let receiver: AccountId = accounts.bob; - - let sender_balance_before = client - .free_balance(accounts.alice) - .await - .expect("Failed to get account balance"); - let receiver_balance_before = - client.free_balance(receiver).await.expect("Failed to get account balance"); - - // when - let transfer_message = call_builder.transfer(receiver, TRANSFER_VALUE); - - let call_res = client - .call(&ink_e2e::alice(), &transfer_message) - .submit() - .await - .expect("call failed"); - - assert!(call_res.return_value().is_ok()); - - // then - let sender_balance_after = client - .free_balance(accounts.alice) - .await - .expect("Failed to get account balance"); - let receiver_balance_after = - client.free_balance(receiver).await.expect("Failed to get account balance"); - - assert_eq!(contract_balance_before, contract_balance_after + TRANSFER_VALUE); - assert_eq!(receiver_balance_before, receiver_balance_after - TRANSFER_VALUE); - - Ok(()) - } - } -} diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml old mode 100755 new mode 100644 index 0b79e1b2..075ea943 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -1,12 +1,25 @@ [package] authors = [ "[your_name] <[your_email]>" ] edition = "2021" -name = "fungibles" +name = "api_example_fungibles" version = "0.1.0" [dependencies] -ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false, features = [ "fungibles" ] } +ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } +pop-api = { path = "../../../pop-api", default-features = false, features = [ + "fungibles", +] } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.6", default-features = false, features = [ + "derive", +], optional = true } + +[dev-dependencies] +drink = { path = "../../../../pop-drink/drink" } +env_logger = { version = "0.11.3" } +pop-sandbox = { path = "../../../pop-sandbox", default-features = false } [lib] path = "lib.rs" @@ -18,4 +31,7 @@ ink-as-dependency = [ ] std = [ "ink/std", "pop-api/std", + "pop-sandbox/std", + "scale-info/std", + "scale/std", ] diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs old mode 100755 new mode 100644 index 1ad36de0..00f02914 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -1,185 +1,161 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -/// Local Fungibles: -/// 1. PSP-22 Interface -/// 2. PSP-22 Metadata Interface -/// 3. Asset Management -/// use ink::prelude::vec::Vec; use pop_api::{ - assets::fungibles::{self as api}, - primitives::AssetId, + primitives::TokenId, + v0::fungibles::{self as api}, StatusCode, }; -pub type Result = core::result::Result; +type PopApiResult = core::result::Result; #[ink::contract] -mod fungibles { +mod create_token_in_constructor { use super::*; #[ink(storage)] - #[derive(Default)] - pub struct Fungibles; + pub struct Fungible { + id: TokenId, + } - impl Fungibles { + impl Fungible { #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("PopApiFungiblesExample::new"); - Default::default() + pub fn new(id: TokenId, min_balance: Balance) -> PopApiResult { + ink::env::debug_println!("Fungible::call() asset_id={id}, min_balance={min_balance}"); + let contract = Self { id }; + let owner = contract.env().account_id(); + api::create(id, owner, min_balance)?; + Ok(contract) } - /// 1. PSP-22 Interface: - /// - total_supply - /// - balance_of - /// - allowance - /// - transfer - /// - transfer_from - /// - approve - /// - increase_allowance - /// - decrease_allowance + #[ink(message)] + pub fn token_exists(&self, id: TokenId) -> PopApiResult { + api::token_exists(id) + } #[ink(message)] - pub fn total_supply(&self, id: AssetId) -> Result { + pub fn total_supply(&self, id: TokenId) -> PopApiResult { api::total_supply(id) } #[ink(message)] - pub fn balance_of(&self, id: AssetId, owner: AccountId) -> Result { + pub fn balance_of(&self, id: TokenId, owner: AccountId) -> PopApiResult { api::balance_of(id, owner) } #[ink(message)] pub fn allowance( &self, - id: AssetId, + id: TokenId, owner: AccountId, spender: AccountId, - ) -> Result { + ) -> PopApiResult { api::allowance(id, owner, spender) } #[ink(message)] - pub fn transfer(&mut self, id: AssetId, to: AccountId, value: Balance) -> Result<()> { + pub fn transfer(&mut self, id: TokenId, to: AccountId, value: Balance) -> PopApiResult<()> { api::transfer(id, to, value) } #[ink(message)] pub fn transfer_from( &mut self, - id: AssetId, + id: TokenId, from: AccountId, to: AccountId, value: Balance, // In the PSP-22 standard a `[u8]`, but the size needs to be known at compile time. _data: Vec, - ) -> Result<()> { + ) -> PopApiResult<()> { api::transfer_from(id, from, to, value) } #[ink(message)] - pub fn approve(&mut self, id: AssetId, spender: AccountId, value: Balance) -> Result<()> { + pub fn approve( + &mut self, + id: TokenId, + spender: AccountId, + value: Balance, + ) -> PopApiResult<()> { api::approve(id, spender, value) } #[ink(message)] pub fn increase_allowance( &mut self, - id: AssetId, + id: TokenId, spender: AccountId, value: Balance, - ) -> Result<()> { + ) -> PopApiResult<()> { api::increase_allowance(id, spender, value) } #[ink(message)] pub fn decrease_allowance( &mut self, - id: AssetId, + id: TokenId, spender: AccountId, value: Balance, - ) -> Result<()> { + ) -> PopApiResult<()> { api::decrease_allowance(id, spender, value) } - /// 2. PSP-22 Metadata Interface: - /// - token_name - /// - token_symbol - /// - token_decimals - #[ink(message)] - pub fn token_name(&self, id: AssetId) -> Result> { + pub fn token_name(&self, id: TokenId) -> PopApiResult> { api::token_name(id) } #[ink(message)] - pub fn token_symbol(&self, id: AssetId) -> Result> { + pub fn token_symbol(&self, id: TokenId) -> PopApiResult> { api::token_symbol(id) } #[ink(message)] - pub fn token_decimals(&self, id: AssetId) -> Result { + pub fn token_decimals(&self, id: TokenId) -> PopApiResult { api::token_decimals(id) } - - // 3. Asset Management: - // - create - // - start_destroy - // - destroy_accounts - // - destroy_approvals - // - finish_destroy - // - set_metadata - // - clear_metadata - - // #[ink(message)] - // pub fn create(&self, id: AssetId, admin: AccountId, min_balance: Balance) -> Result<()> { - // ink::env::debug_println!( - // "PopApiFungiblesExample::create: id: {:?} admin: {:?} min_balance: {:?}", - // id, - // admin, - // min_balance, - // ); - // let result = api::create(id, admin, min_balance); - // ink::env::debug_println!("Result: {:?}", result); - // result.map_err(|e| e.into()) - // result - // } - - // #[ink(message)] - // pub fn set_metadata( - // &self, - // id: AssetId, - // name: Vec, - // symbol: Vec, - // decimals: u8, - // ) -> Result<()> { - // ink::env::debug_println!( - // "PopApiFungiblesExample::set_metadata: id: {:?} name: {:?} symbol: {:?}, decimals: {:?}", - // id, - // name, - // symbol, - // decimals, - // ); - // let result = api::set_metadata(id, name, symbol, decimals); - // ink::env::debug_println!("Result: {:?}", result); - // // result.map_err(|e| e.into()) - // result - // } - // - // #[ink(message)] - // pub fn asset_exists(&self, id: AssetId) -> Result { - // // api::asset_exists(id).map_err(|e| e.into()) - // api::asset_exists(id) - // } } +} - #[cfg(test)] - mod tests { - use super::*; +/// We put `drink`-based tests as usual unit tests, into a test module. +#[cfg(test)] +mod tests { + use drink::session::{Session, NO_SALT}; + use pop_sandbox::{utils::call_function, ALICE, INIT_VALUE}; - #[ink::test] - fn default_works() { - PopApiFungiblesExample::new(); - } + use super::*; + + #[drink::contract_bundle_provider] + enum BundleProvider {} + + #[drink::test(sandbox = pop_sandbox::PopSandbox)] + fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + let contract_bundle = BundleProvider::local()?; + + const ASSET_ID: TokenId = 1; + + // Deploy a contract and create a new token with ASSET_ID = 1 + let contract_address = session.deploy_bundle( + contract_bundle, + "new", + &[ASSET_ID.to_string(), 1.to_string()], + NO_SALT, + Some(INIT_VALUE), + )?; + // Calling the method in the contract. + let session = call_function( + session, + &contract_address, + &ALICE, + "token_exists".to_string(), + Some(vec![ASSET_ID.to_string()]), + None, + )?; + // Check that the token is created successfully. + let result = session.record().last_call_return_decoded::>()??; + assert_eq!(result, Ok(true)); + Ok(()) } -} \ No newline at end of file +} diff --git a/pop-api/examples/nfts/Cargo.toml b/pop-api/examples/nfts/Cargo.toml deleted file mode 100755 index ef50b7ec..00000000 --- a/pop-api/examples/nfts/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "nfts" -version = "0.1.0" - -[dependencies] -ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "ink/std", - "pop-api/std", - "scale-info/std", - "scale/std", -] diff --git a/pop-api/examples/nfts/lib.rs b/pop-api/examples/nfts/lib.rs deleted file mode 100755 index 0cd0f313..00000000 --- a/pop-api/examples/nfts/lib.rs +++ /dev/null @@ -1,117 +0,0 @@ -// DEPRECATED -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -use pop_api::nfts::*; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum ContractError { - InvalidCollection, - ItemAlreadyExists, - NftsError(Error), - NotOwner, -} - -impl From for ContractError { - fn from(value: Error) -> Self { - ContractError::NftsError(value) - } -} - -#[ink::contract] -mod nfts { - use super::*; - - #[ink(storage)] - #[derive(Default)] - pub struct Nfts; - - impl Nfts { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("Nfts::new"); - Default::default() - } - - #[ink(message)] - pub fn create_nft_collection(&self) -> Result<(), ContractError> { - ink::env::debug_println!("Nfts::create_nft_collection: collection creation started."); - let admin = Self::env().caller(); - let item_settings = ItemSettings(BitFlags::from(ItemSetting::Transferable)); - - let mint_settings = MintSettings { - mint_type: MintType::Issuer, - price: Some(0), - start_block: Some(0), - end_block: Some(0), - default_item_settings: item_settings, - }; - - let config = CollectionConfig { - settings: CollectionSettings(BitFlags::from(CollectionSetting::TransferableItems)), - max_supply: None, - mint_settings, - }; - pop_api::nfts::create(admin, config)?; - ink::env::debug_println!( - "Nfts::create_nft_collection: collection created successfully." - ); - Ok(()) - } - - #[ink(message)] - pub fn mint_nft( - &mut self, - collection_id: u32, - item_id: u32, - receiver: AccountId, - ) -> Result<(), ContractError> { - ink::env::debug_println!( - "Nfts::mint: collection_id: {:?} item_id {:?} receiver: {:?}", - collection_id, - item_id, - receiver - ); - - // Check if item already exists (demo purposes only, unnecessary as would expect check in mint call) - if item(collection_id, item_id)?.is_some() { - return Err(ContractError::ItemAlreadyExists); - } - - // mint api - mint(collection_id, item_id, receiver)?; - ink::env::debug_println!("Nfts::mint: item minted successfully"); - - // check owner - match owner(collection_id, item_id)? { - Some(owner) if owner == receiver => { - ink::env::debug_println!("Nfts::mint success: minted item belongs to receiver"); - }, - _ => { - return Err(ContractError::NotOwner); - }, - } - - ink::env::debug_println!("Nfts::mint end"); - Ok(()) - } - - #[ink(message)] - pub fn read_collection(&self, collection_id: u32) -> Result<(), ContractError> { - ink::env::debug_println!("Nfts::read_collection: collection_id: {:?}", collection_id); - let collection = pop_api::nfts::collection(collection_id)?; - ink::env::debug_println!("Nfts::read_collection: collection: {:?}", collection); - Ok(()) - } - } - - #[cfg(test)] - mod tests { - use super::*; - - #[ink::test] - fn default_works() { - Nfts::new(); - } - } -} diff --git a/pop-api/examples/place-spot-order/Cargo.toml b/pop-api/examples/place-spot-order/Cargo.toml deleted file mode 100755 index f523bea7..00000000 --- a/pop-api/examples/place-spot-order/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "spot_order" -version = "0.1.0" - -[dependencies] -ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "ink/std", - "pop-api/std", - "scale-info/std", - "scale/std", -] diff --git a/pop-api/examples/place-spot-order/lib.rs b/pop-api/examples/place-spot-order/lib.rs deleted file mode 100755 index 965917d1..00000000 --- a/pop-api/examples/place-spot-order/lib.rs +++ /dev/null @@ -1,43 +0,0 @@ -// DEPRECATED -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -#[ink::contract] -mod spot_order { - - #[ink(storage)] - #[derive(Default)] - pub struct SpotOrder; - - impl SpotOrder { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("SpotOrder::new"); - Default::default() - } - - #[ink(message)] - pub fn place_spot_order(&mut self, max_amount: Balance, para_id: u32) { - ink::env::debug_println!( - "SpotOrder::place_spot_order: max_amount {:?} para_id: {:?} ", - max_amount, - para_id, - ); - - #[allow(unused_variables)] - let res = pop_api::cross_chain::coretime::place_spot_order(max_amount, para_id); - ink::env::debug_println!("SpotOrder::place_spot_order: res {:?} ", res,); - - ink::env::debug_println!("SpotOrder::place_spot_order end"); - } - } - - #[cfg(test)] - mod tests { - use super::*; - - #[ink::test] - fn default_works() { - SpotOrder::new(); - } - } -} diff --git a/pop-api/examples/read-runtime-state/Cargo.toml b/pop-api/examples/read-runtime-state/Cargo.toml deleted file mode 100755 index f5464730..00000000 --- a/pop-api/examples/read-runtime-state/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "read_relay_blocknumber" -version = "0.1.0" - -[dependencies] -ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "ink/std", - "pop-api/std", - "scale-info/std", - "scale/std", -] diff --git a/pop-api/examples/read-runtime-state/lib.rs b/pop-api/examples/read-runtime-state/lib.rs deleted file mode 100755 index 092e9f2f..00000000 --- a/pop-api/examples/read-runtime-state/lib.rs +++ /dev/null @@ -1,36 +0,0 @@ -// DEPRECATED -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -#[ink::contract] -mod read_relay_blocknumber { - use pop_api::primitives::storage_keys::{ - ParachainSystemKeys::LastRelayChainBlockNumber, RuntimeStateKeys::ParachainSystem, - }; - - #[ink(event)] - pub struct RelayBlockNumberRead { - value: BlockNumber, - } - - #[ink(storage)] - #[derive(Default)] - pub struct ReadRelayBlockNumber; - - impl ReadRelayBlockNumber { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("ReadRelayBlockNumber::new"); - Default::default() - } - - #[ink(message)] - pub fn read_relay_block_number(&self) { - let result = - pop_api::state::read::(ParachainSystem(LastRelayChainBlockNumber)); - ink::env::debug_println!("Last relay block number read by contract: {:?}", result); - self.env().emit_event(RelayBlockNumberRead { - value: result.expect("Failed to read relay block number."), - }); - } - } -} diff --git a/pop-sandbox/Cargo.toml b/pop-sandbox/Cargo.toml index 6debda40..d2309173 100644 --- a/pop-sandbox/Cargo.toml +++ b/pop-sandbox/Cargo.toml @@ -9,25 +9,28 @@ version = "0.0.0" codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive", ] } +log = { version = "0.4.21", default-features = false } scale-info = { version = "2.11", default-features = false } -# Local -drink = { path = "../../pop-drink/drink", default-features = false } -pallet-api = { path = "../pallets/api", default-features = false } -pop-chain-extension = { path = "../extension", default-features = false } -pop-primitives = { path = "../primitives", default-features = false } +drink = { path = "../../pop-drink/drink", default-features = true } -# Substrate -cumulus-primitives-core = { version = "0.14.0", default-features = false } +# Substrate +frame-metadata = { version = "16.0.0", default-features = false } frame-support = { version = "36.0.0", default-features = false } +frame-support-procedural = { version = "=30.0.1", default-features = false } frame-system = { version = "36.1.0", default-features = false } pallet-assets = { version = "37.0.0", default-features = false } +pallet-aura = { version = "35.0.0", default-features = false } +pallet-authorship = { version = "36.0.0", default-features = false } pallet-balances = { version = "37.0.0", default-features = false } pallet-contracts = { version = "35.0.0", default-features = false } +pallet-scheduler = { version = "37.0.0", default-features = false } +pallet-session = { version = "36.0.0", default-features = false } pallet-timestamp = { version = "35.0.0", default-features = false } -sp-core = { version = "34.0.0", default-features = false } -sp-runtime = { version = "38.0.0", default-features = false } -sp-std = { version = "14.0.0", default-features = false } +pallet-transaction-payment = { version = "36.0.0", default-features = false } +pop-runtime-devnet = { path = "../runtime/devnet", default-features = false } +sp-io = { version = "37.0.0", default-features = false } +sp-runtime = { version = "=38.0.0", default-features = false } [lib] crate-type = [ "rlib" ] @@ -38,20 +41,19 @@ path = "src/lib.rs" default = [ "std" ] std = [ "codec/std", - "cumulus-primitives-core/std", - "drink/std", "frame-support/std", "frame-system/std", - "pallet-api/std", - "pallet-api/std", "pallet-assets/std", + "pallet-aura/std", + "pallet-authorship/std", "pallet-balances/std", "pallet-contracts/std", + "pallet-scheduler/std", + "pallet-session/std", "pallet-timestamp/std", - "pop-chain-extension/std", - "pop-primitives/std", + "pallet-transaction-payment/std", + "pop-runtime-devnet/std", "scale-info/std", - "sp-core/std", + "sp-io/std", "sp-runtime/std", - "sp-std/std", ] diff --git a/pop-sandbox/examples/flipper/lib.rs b/pop-sandbox/examples/flipper/lib.rs index 9e97465a..cf0352a9 100644 --- a/pop-sandbox/examples/flipper/lib.rs +++ b/pop-sandbox/examples/flipper/lib.rs @@ -18,7 +18,7 @@ mod flipper { } impl Flipper { - #[ink(constructor)] + #[ink(constructor, payable)] pub fn new(init: bool) -> Self { debug_println!("Initializing contract with: `{init}`"); Self { value: init } @@ -49,9 +49,9 @@ mod tests { /// `drink` automatically discovers all the contract projects that your tests will need. For /// every such dependency (including the contract from the current crate), it will generate a - /// [`ContractBundle`](drink::session::ContractBundle) object that contains the compiled contract's code - /// and a special transcoder, which is used to encode and decode the contract's message - /// arguments. Such a bundle will be useful when deploying a contract. + /// [`ContractBundle`](drink::session::ContractBundle) object that contains the compiled + /// contract's code and a special transcoder, which is used to encode and decode the contract's + /// message arguments. Such a bundle will be useful when deploying a contract. /// /// To get a convenient way for obtaining such bundles, we can define an empty enum and mark /// it with the [`drink::contract_bundle_provider`](drink::contract_bundle_provider) attribute. @@ -70,9 +70,10 @@ mod tests { /// /// For convenience of using `?` operator, we mark the test function as returning a `Result`. /// - /// `drink::test` will already provide us with a `Session` object. It is a wrapper around a runtime and it exposes - /// a broad API for interacting with it. Session is generic over the runtime type, but usually and by default, we - /// use `MinimalSandbox`, which is a minimalistic runtime that allows using smart contracts. + /// `drink::test` will already provide us with a `Session` object. It is a wrapper around a + /// runtime and it exposes a broad API for interacting with it. Session is generic over the + /// runtime type, but usually and by default, we use `MinimalSandbox`, which is a minimalistic + /// runtime that allows using smart contracts. #[drink::test(sandbox = pop_sandbox::PopSandbox)] fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); diff --git a/pop-sandbox/examples/fungibles/Cargo.toml b/pop-sandbox/examples/fungibles/Cargo.toml deleted file mode 100644 index 075ea943..00000000 --- a/pop-sandbox/examples/fungibles/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "api_example_fungibles" -version = "0.1.0" - -[dependencies] -ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } -pop-api = { path = "../../../pop-api", default-features = false, features = [ - "fungibles", -] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", -] } -scale-info = { version = "2.6", default-features = false, features = [ - "derive", -], optional = true } - -[dev-dependencies] -drink = { path = "../../../../pop-drink/drink" } -env_logger = { version = "0.11.3" } -pop-sandbox = { path = "../../../pop-sandbox", default-features = false } - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "ink/std", - "pop-api/std", - "pop-sandbox/std", - "scale-info/std", - "scale/std", -] diff --git a/pop-sandbox/examples/fungibles/lib.rs b/pop-sandbox/examples/fungibles/lib.rs deleted file mode 100644 index 2e976376..00000000 --- a/pop-sandbox/examples/fungibles/lib.rs +++ /dev/null @@ -1,75 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -use pop_api::{ - primitives::TokenId, - v0::fungibles::{self as api}, - StatusCode, -}; - -type PopApiResult = core::result::Result; - -#[ink::contract] -mod create_token_in_constructor { - use super::*; - - #[ink(storage)] - pub struct Fungible { - id: TokenId, - } - - impl Fungible { - #[ink(constructor, payable)] - pub fn new(id: TokenId, min_balance: Balance) -> PopApiResult { - ink::env::debug_println!("Fungible::call() asset_id={id}, min_balance={min_balance}"); - let contract = Self { id }; - let owner = contract.env().account_id(); - api::create(id, owner, min_balance)?; - Ok(contract) - } - - #[ink(message)] - pub fn token_exists(&self, id: TokenId) -> PopApiResult { - api::token_exists(id) - } - } -} - -/// We put `drink`-based tests as usual unit tests, into a test module. -#[cfg(test)] -mod tests { - use super::*; - use drink::session::{Session, NO_SALT}; - use pop_sandbox::utils::{call_function, ALICE}; - - #[drink::contract_bundle_provider] - enum BundleProvider {} - - #[drink::test(sandbox = pop_sandbox::PopSandbox)] - fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - - const ASSET_ID: TokenId = 1; - // Deploy a contract and create a new token with ASSET_ID = 1 - let contract_address = session.deploy_bundle( - contract_bundle, - "new", - &[1.to_string(), 1_000.to_string()], - NO_SALT, - Some(100_000_000), - )?; - // Calling the method in the contract. - let session = call_function( - session, - &contract_address, - &ALICE, - "token_exists".to_string(), - Some(vec![ASSET_ID.to_string()]), - None, - )?; - // Check that the token is created successfully. - let result = session.record().last_call_return_decoded::>()??; - assert_eq!(result, Ok(true)); - Ok(()) - } -} diff --git a/pop-sandbox/examples/proxy/Cargo.toml b/pop-sandbox/examples/proxy/Cargo.toml deleted file mode 100644 index 95adf32c..00000000 --- a/pop-sandbox/examples/proxy/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "api_example_proxy" -version = "0.1.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", -] } -frame-system = { version = "36.1.0", default-features = false } -ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } -pop-api = { path = "../../../pop-api", default-features = false, features = [ - "fungibles", -] } -scale-info = { version = "2.6", default-features = false, features = [ - "derive", -], optional = true } - -[dev-dependencies] -drink = { path = "../../../../pop-drink/drink" } -env_logger = { version = "0.11.3" } -pop-sandbox = { path = "../../../pop-sandbox", default-features = false } -serde_json = "1.0.108" - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "codec/std", - "frame-system/std", - "ink/std", - "pop-api/std", - "pop-sandbox/std", - "scale-info/std", -] diff --git a/pop-sandbox/examples/proxy/lib.rs b/pop-sandbox/examples/proxy/lib.rs deleted file mode 100644 index d5299045..00000000 --- a/pop-sandbox/examples/proxy/lib.rs +++ /dev/null @@ -1,94 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -use ink::{ - env::chain_extension::{ChainExtensionMethod, FromStatusCode}, - prelude::vec::Vec, -}; - -#[ink::contract] -mod proxy_contract { - use super::*; - - // Simple contract for proxying a call to a chain extension. - #[ink(storage)] - #[derive(Default)] - pub struct Proxy; - - impl Proxy { - #[ink(constructor)] - pub fn new() -> Self { - ink::env::debug_println!("Proxy::new()"); - Default::default() - } - - #[ink(message)] - pub fn call(&self, func_id: u32, input: Vec) -> Result, StatusCode> { - ink::env::debug_println!("Proxy::call() func_id={func_id}, input={input:?}"); - ChainExtensionMethod::build(func_id) - .input::>() - .output::, StatusCode>, true>() - .handle_error_code::() - .call(&input) - } - } - - #[ink::scale_derive(Encode, Decode, TypeInfo)] - pub struct StatusCode(u32); - impl FromStatusCode for StatusCode { - fn from_status_code(status_code: u32) -> Result<(), Self> { - match status_code { - 0 => Ok(()), - _ => Err(StatusCode(status_code)), - } - } - } - - impl From for StatusCode { - fn from(_: ink::scale::Error) -> Self { - StatusCode(u32::MAX) - } - } -} - -/// We put `drink`-based tests as usual unit tests, into a test module. -#[cfg(test)] -mod tests { - use codec::Encode; - use core::fmt::Debug; - use drink::{ - session::{Session, NO_ARGS, NO_SALT}, - AccountId32, - }; - use frame_system::Call; - use pop_sandbox::{ - utils::{call_function, ALICE}, - PopSandbox, RuntimeCall, - }; - - #[drink::contract_bundle_provider] - enum BundleProvider {} - - #[drink::test(sandbox = PopSandbox)] - fn deploy_contract_and_call(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - - let contract_bundle = BundleProvider::local()?; - let contract_address = - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, None)?; - - let call = - RuntimeCall::System(Call::remark_with_event { remark: "pop".as_bytes().to_vec() }); - call_function( - session, - &contract_address, - &ALICE, - "call".to_string(), - // DispatchCall::System::Call::remark_with_event. - Some(vec![0.to_string(), serde_json::to_string(&call.encode()).unwrap()]), - None, - )?; - // TOOD: Return CallFiltered - - Ok(()) - } -} diff --git a/pop-sandbox/src/api/mod.rs b/pop-sandbox/src/api/mod.rs deleted file mode 100644 index ad4f8491..00000000 --- a/pop-sandbox/src/api/mod.rs +++ /dev/null @@ -1,159 +0,0 @@ -use core::marker::PhantomData; - -use codec::Decode; -use cumulus_primitives_core::Weight; -use frame_support::traits::Contains; -pub(crate) use pallet_api::Extension; -use pallet_api::{extension::*, Read}; -use sp_core::ConstU8; -use sp_runtime::DispatchError; -use sp_std::vec::Vec; -use versioning::*; - -use crate::{fungibles, Runtime, RuntimeCall, RuntimeEvent}; - -mod versioning; - -type DecodingFailedError = DecodingFailed; -type DecodesAs = pallet_api::extension::DecodesAs< - Output, - ContractWeightsOf, - DecodingFailedError, - Logger, ->; - -/// A query of runtime state. -#[derive(Decode, Debug)] -#[repr(u8)] -pub enum RuntimeRead { - /// Fungible token queries. - #[codec(index = 150)] - Fungibles(fungibles::Read), -} - -impl Readable for RuntimeRead { - /// The corresponding type carrying the result of the query for runtime state. - type Result = RuntimeResult; - - /// Determines the weight of the read, used to charge the appropriate weight before the read is - /// performed. - fn weight(&self) -> Weight { - match self { - RuntimeRead::Fungibles(key) => fungibles::Pallet::weight(key), - } - } - - /// Performs the read and returns the result. - fn read(self) -> Self::Result { - match self { - RuntimeRead::Fungibles(key) => RuntimeResult::Fungibles(fungibles::Pallet::read(key)), - } - } -} - -/// The result of a runtime state read. -#[derive(Debug)] -pub enum RuntimeResult { - /// Fungible token read results. - Fungibles(fungibles::ReadResult), -} - -impl RuntimeResult { - /// Encodes the result. - fn encode(&self) -> Vec { - match self { - RuntimeResult::Fungibles(result) => result.encode(), - } - } -} - -impl fungibles::Config for Runtime { - type AssetsInstance = (); - type RuntimeEvent = RuntimeEvent; - type WeightInfo = fungibles::weights::SubstrateWeight; -} - -#[derive(Default)] -pub struct Config; -impl pallet_api::extension::Config for Config { - /// Functions used by the Pop API. - /// - /// Each function corresponds to specific functionality provided by the API, facilitating the - /// interaction between smart contracts and the runtime. - type Functions = ( - // Dispatching calls - DispatchCall< - // Function ID: 0. - IdentifiedByFirstByteOfFunctionId>, - // The runtime configuration. - Runtime, - // Decode as a versioned runtime call. - DecodesAs, - // Apply any filtering. - Filter, - // Ensure errors are versioned. - VersionedErrorConverter, - // Logging with a specific target. - DispatchCallLogTarget, - >, - // Reading state - ReadState< - // Function ID: 1. - IdentifiedByFirstByteOfFunctionId>, - // The runtime configuration. - Runtime, - // The runtime state reads available. - RuntimeRead, - // Decode as a versioned runtime read. - DecodesAs, - // Apply any filtering. - Filter, - // Convert the result of a read into the expected versioned result - VersionedResultConverter, - // Ensure errors are versioned. - VersionedErrorConverter, - // Logging with a specific target. - ReadStateLogTarget, - >, - ); - - /// The log target. - const LOG_TARGET: &'static str = LOG_TARGET; -} - -/// Filters used by the chain extension. -pub struct Filter(PhantomData); - -impl> Contains for Filter { - fn contains(c: &RuntimeCall) -> bool { - use fungibles::Call::*; - T::BaseCallFilter::contains(c) - && matches!( - c, - RuntimeCall::Fungibles( - transfer { .. } - | transfer_from { .. } | approve { .. } - | increase_allowance { .. } - | decrease_allowance { .. } - | create { .. } | set_metadata { .. } - | start_destroy { .. } | clear_metadata { .. } - | mint { .. } | burn { .. } - ) - ) - } -} - -impl Contains for Filter { - fn contains(r: &RuntimeRead) -> bool { - use fungibles::Read::*; - matches!( - r, - RuntimeRead::Fungibles( - TotalSupply(..) - | BalanceOf { .. } | Allowance { .. } - | TokenName(..) | TokenSymbol(..) - | TokenDecimals(..) | TokenExists(..) - ) - ) - } -} diff --git a/pop-sandbox/src/api/versioning.rs b/pop-sandbox/src/api/versioning.rs deleted file mode 100644 index 317496df..00000000 --- a/pop-sandbox/src/api/versioning.rs +++ /dev/null @@ -1,220 +0,0 @@ -use sp_runtime::ModuleError; - -use super::*; - -type Version = u8; - -/// Versioned runtime calls. -#[derive(Decode, Debug)] -pub enum VersionedRuntimeCall { - /// Version zero of runtime calls. - #[codec(index = 0)] - V0(RuntimeCall), -} - -impl From for RuntimeCall { - fn from(value: VersionedRuntimeCall) -> Self { - // Allows mapping from some previous runtime call shape to a current valid runtime call - match value { - VersionedRuntimeCall::V0(call) => call, - } - } -} - -/// Versioned runtime state reads. -#[derive(Decode, Debug)] -pub enum VersionedRuntimeRead { - /// Version zero of runtime state reads. - #[codec(index = 0)] - V0(RuntimeRead), -} - -impl From for RuntimeRead { - fn from(value: VersionedRuntimeRead) -> Self { - // Allows mapping from some previous runtime read shape to a current valid runtime read - match value { - VersionedRuntimeRead::V0(read) => read, - } - } -} - -/// Versioned runtime state read results. -#[derive(Debug)] -pub enum VersionedRuntimeResult { - /// Version zero of runtime read results. - V0(RuntimeResult), -} - -impl From<(RuntimeResult, Version)> for VersionedRuntimeResult { - fn from(value: (RuntimeResult, Version)) -> Self { - let (result, version) = value; - match version { - // Allows mapping from current `RuntimeResult` to a specific/prior version - 0 => VersionedRuntimeResult::V0(result), - // TODO: should never occur due to version processing/validation when request received - _ => unimplemented!(), - } - } -} - -impl From for Vec { - fn from(result: VersionedRuntimeResult) -> Self { - match result { - // Simply unwrap and return the encoded result - VersionedRuntimeResult::V0(result) => result.encode(), - } - } -} - -/// Versioned errors. -#[derive(Debug)] -pub enum VersionedError { - /// Version zero of errors. - V0(pop_primitives::v0::Error), -} - -impl From<(DispatchError, Version)> for VersionedError { - fn from(value: (DispatchError, Version)) -> Self { - let (error, version) = value; - match version { - // Allows mapping from current `DispatchError` to a specific/prior version of `Error` - 0 => VersionedError::V0(V0Error::from(error).0), - // TODO: should never occur due to version processing/validation when request received - _ => unimplemented!(), - } - } -} - -impl From for u32 { - fn from(value: VersionedError) -> Self { - match value { - VersionedError::V0(error) => error.into(), - } - } -} - -struct V0Error(pop_primitives::v0::Error); -impl From for V0Error { - fn from(error: DispatchError) -> Self { - use pop_primitives::v0::*; - use sp_runtime::{ArithmeticError::*, TokenError::*, TransactionalError::*}; - use DispatchError::*; - // Mappings exist here to avoid taking a dependency of sp_runtime on pop-primitives - Self(match error { - Other(_message) => { - // Note: lossy conversion: message not used due to returned contract status code - // size limitation - Error::Other - }, - CannotLookup => Error::CannotLookup, - BadOrigin => Error::BadOrigin, - Module(error) => { - // Note: message not used - let ModuleError { index, error, message: _message } = error; - // Map `pallet-contracts::Error::DecodingFailed` to `Error::DecodingFailed` - if index as usize == - ::index() && - error == DECODING_FAILED_ERROR - { - Error::DecodingFailed - } else { - // Note: lossy conversion of error value due to returned contract status code - // size limitation - Error::Module { index, error: [error[0], error[1]] } - } - }, - ConsumerRemaining => Error::ConsumerRemaining, - NoProviders => Error::NoProviders, - TooManyConsumers => Error::TooManyConsumers, - Token(error) => Error::Token(match error { - FundsUnavailable => TokenError::FundsUnavailable, - OnlyProvider => TokenError::OnlyProvider, - BelowMinimum => TokenError::BelowMinimum, - CannotCreate => TokenError::CannotCreate, - UnknownAsset => TokenError::UnknownAsset, - Frozen => TokenError::Frozen, - Unsupported => TokenError::Unsupported, - CannotCreateHold => TokenError::CannotCreateHold, - NotExpendable => TokenError::NotExpendable, - Blocked => TokenError::Blocked, - }), - Arithmetic(error) => Error::Arithmetic(match error { - Underflow => ArithmeticError::Underflow, - Overflow => ArithmeticError::Overflow, - DivisionByZero => ArithmeticError::DivisionByZero, - }), - Transactional(error) => Error::Transactional(match error { - LimitReached => TransactionalError::LimitReached, - NoLayer => TransactionalError::NoLayer, - }), - Exhausted => Error::Exhausted, - Corruption => Error::Corruption, - Unavailable => Error::Unavailable, - RootNotAllowed => Error::RootNotAllowed, - }) - } -} - -#[cfg(test)] -mod tests { - use pop_primitives::{ArithmeticError::*, Error, TokenError::*, TransactionalError::*}; - use sp_runtime::ModuleError; - use DispatchError::*; - - use super::*; - - // Compare all the different `DispatchError` variants with the expected `Error`. - #[test] - fn dispatch_error_to_error() { - let test_cases = vec![ - (Other(""), (Error::Other)), - (Other("UnknownCall"), Error::Other), - (Other("DecodingFailed"), Error::Other), - (Other("Random"), (Error::Other)), - (CannotLookup, Error::CannotLookup), - (BadOrigin, Error::BadOrigin), - ( - Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: Some("hallo") }), - Error::Module { index: 1, error: [2, 0] }, - ), - ( - Module(ModuleError { index: 1, error: [2, 2, 0, 0], message: Some("hallo") }), - Error::Module { index: 1, error: [2, 2] }, - ), - ( - Module(ModuleError { index: 1, error: [2, 2, 2, 0], message: Some("hallo") }), - Error::Module { index: 1, error: [2, 2] }, - ), - ( - Module(ModuleError { index: 1, error: [2, 2, 2, 4], message: Some("hallo") }), - Error::Module { index: 1, error: [2, 2] }, - ), - (pallet_contracts::Error::::DecodingFailed.into(), Error::DecodingFailed), - (ConsumerRemaining, Error::ConsumerRemaining), - (NoProviders, Error::NoProviders), - (TooManyConsumers, Error::TooManyConsumers), - (Token(sp_runtime::TokenError::BelowMinimum), Error::Token(BelowMinimum)), - (Arithmetic(sp_runtime::ArithmeticError::Overflow), Error::Arithmetic(Overflow)), - ( - Transactional(sp_runtime::TransactionalError::LimitReached), - Error::Transactional(LimitReached), - ), - (Exhausted, Error::Exhausted), - (Corruption, Error::Corruption), - (Unavailable, Error::Unavailable), - (RootNotAllowed, Error::RootNotAllowed), - ]; - for (dispatch_error, expected) in test_cases { - let error = V0Error::from(dispatch_error).0; - assert_eq!(error, expected); - } - } - - #[test] - fn decoding_failed_error_encoding_works() { - let Module(error) = pallet_contracts::Error::::DecodingFailed.into() else { - unreachable!() - }; - assert_eq!(error.error, DECODING_FAILED_ERROR) - } -} diff --git a/pop-sandbox/src/lib.rs b/pop-sandbox/src/lib.rs index 118ebaa6..5a083c4a 100644 --- a/pop-sandbox/src/lib.rs +++ b/pop-sandbox/src/lib.rs @@ -1,179 +1,142 @@ -use crate::api::Config; +use core::any::Any; + +use frame_metadata::RuntimeMetadataPrefixed; use frame_support::{ - construct_runtime, derive_impl, parameter_types, - sp_runtime::{testing::H256, Perbill}, - traits::{AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, Randomness}, - weights::Weight, + sp_runtime::{traits::Header, AccountId32}, + traits::Hooks, }; -use frame_system::{EnsureRoot, EnsureSigned}; -use pallet_api::fungibles; -use pallet_contracts::{DefaultAddressGenerator, Frame}; -use sp_runtime::traits::{AccountIdLookup, Convert}; -use sp_std::vec::Vec; +use frame_system::pallet_prelude::BlockNumberFor; +use pop_runtime_devnet::{BuildStorage, Runtime}; +use sp_io::TestExternalities; +use frame_support::sp_runtime::traits::One; +use pop_runtime_devnet::Balance; -mod api; // Provides utlity methods to interact with the sandbox. pub mod utils; -pub(crate) type AccountId = AccountId32; -pub(crate) type AssetId = u32; -pub(crate) type Balance = u128; +/// Alias for the account ID type. +pub type AccountIdFor = ::AccountId; -pub const MILLIUNIT: Balance = UNIT / 1_000; // 10_000_000 +/// Default initial balance for the default account. +pub const UNIT: Balance = 10_000_000_000; +pub const INIT_AMOUNT: Balance = 100_000_000 * UNIT; +pub const INIT_VALUE: Balance = 100 * UNIT; +pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); -pub const fn deposit(items: u32, bytes: u32) -> Balance { - (items as Balance * UNIT + (bytes as Balance) * (5 * MILLIUNIT / 100)) / 10 -} +/// A helper struct for initializing and finalizing blocks. +pub struct BlockBuilder(std::marker::PhantomData); + +impl< + T: pallet_balances::Config + pallet_timestamp::Config + pallet_contracts::Config + pallet_aura::Config, + > BlockBuilder +{ + /// Create a new externalities with the given balances. + pub fn new_ext(balances: Vec<(T::AccountId, T::Balance)>) -> TestExternalities { + log::debug!("new externalities: balances={:?}", balances); + let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); -// Define the runtime type as a collection of pallets -construct_runtime!( - pub enum Runtime { - System: frame_system, - Assets: pallet_assets, - Balances: pallet_balances, - Timestamp: pallet_timestamp, - Contracts: pallet_contracts, - Fungibles: fungibles = 150, + pallet_balances::GenesisConfig:: { balances } + .assimilate_storage(&mut storage) + .unwrap(); + + let mut ext = TestExternalities::new(storage); + + ext.execute_with(|| Self::initialize_block(BlockNumberFor::::one(), Default::default())); + ext } -); -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; -} + /// Initialize a new block at particular height. + pub fn initialize_block( + height: frame_system::pallet_prelude::BlockNumberFor, + parent_hash: ::Hash, + ) { + frame_system::Pallet::::reset_events(); + frame_system::Pallet::::initialize(&height, &parent_hash, &Default::default()); + pallet_balances::Pallet::::on_initialize(height); + pallet_aura::Pallet::::on_initialize(height); + // TODO: Resolve an issue with pallet-aura to simulate the time. + // pallet_timestamp::Pallet::::set_timestamp( + // SystemTime::now() + // .duration_since(SystemTime::UNIX_EPOCH) + // .expect("Time went backwards") + // .as_secs(), + // ); + pallet_timestamp::Pallet::::on_initialize(height); + pallet_contracts::Pallet::::on_initialize(height); + frame_system::Pallet::::note_finished_initialize(); + } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] -impl frame_system::Config for Runtime { - type AccountData = pallet_balances::AccountData<::Balance>; - type AccountId = AccountId; - type Block = frame_system::mocking::MockBlock; - type Lookup = AccountIdLookup; + /// Finalize a block at particular height. + pub fn finalize_block( + height: frame_system::pallet_prelude::BlockNumberFor, + ) -> ::Hash { + pallet_contracts::Pallet::::on_finalize(height); + pallet_timestamp::Pallet::::on_finalize(height); + pallet_balances::Pallet::::on_finalize(height); + frame_system::Pallet::::finalize().hash() + } } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] -impl pallet_balances::Config for Runtime { - type AccountStore = System; - type Balance = Balance; - type ExistentialDeposit = ConstU128<1>; - type ReserveIdentifier = [u8; 8]; +pub struct PopSandbox { + ext: TestExternalities, } -parameter_types! { - pub const AssetDeposit: u128 = 1; - pub const AssetAccountDeposit: u128 = 10; - pub const ApprovalDeposit: u128 = 1; - pub const AssetsStringLimit: u32 = 50; - pub const MetadataDepositBase: u128 = 1; - pub const MetadataDepositPerByte: u128 = 1; +impl Default for PopSandbox { + fn default() -> Self { + let balances : Vec<(AccountId32, u128)> = vec![(ALICE, INIT_AMOUNT)]; + let ext = BlockBuilder::::new_ext(balances); + Self { ext } + } } -impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type RemoveItemsLimit = ConstU32<5>; - type AssetId = AssetId; - type AssetIdParameter = u32; - type Currency = Balances; - type CreateOrigin = AsEnsureOriginWithArg>; - type ForceOrigin = EnsureRoot; - type AssetDeposit = ConstU128<1>; - type AssetAccountDeposit = ConstU128<10>; - type MetadataDepositBase = ConstU128<1>; - type MetadataDepositPerByte = ConstU128<1>; - type ApprovalDeposit = ConstU128<1>; - type StringLimit = ConstU32<50>; - type Freezer = (); - type Extra = (); - type CallbackHandle = (); - type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); -} +impl drink::Sandbox for PopSandbox { + type Runtime = Runtime; -#[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig as pallet_timestamp::DefaultConfig)] -impl pallet_timestamp::Config for Runtime {} + fn execute_with(&mut self, execute: impl FnOnce() -> T) -> T { + self.ext.execute_with(execute) + } -// Configure pallet contracts -impl Randomness for Runtime { - fn random(_subject: &[u8]) -> (H256, u64) { - (Default::default(), Default::default()) + fn dry_run(&mut self, action: impl FnOnce(&mut Self) -> T) -> T { + // Make a backup of the backend. + let backend_backup = self.ext.as_backend(); + // Run the action, potentially modifying storage. Ensure, that there are no pending changes + // that would affect the reverted backend. + let result = action(self); + self.ext.commit_all().expect("Failed to commit changes"); + + // Restore the backend. + self.ext.backend = backend_backup; + result } -} -// Configure pallet contracts -pub enum SandboxRandomness {} -impl Randomness for SandboxRandomness { - fn random(_subject: &[u8]) -> (H256, u64) { - unreachable!("No randomness") + fn register_extension(&mut self, ext: E) { + self.ext.register_extension(ext); } -} -type BalanceOf = ::Balance; -impl Convert for Runtime { - fn convert(w: Weight) -> BalanceOf { - w.ref_time().into() + fn initialize_block( + height: frame_system::pallet_prelude::BlockNumberFor, + parent_hash: ::Hash, + ) { + BlockBuilder::::initialize_block(height, parent_hash) } -} -fn schedule() -> pallet_contracts::Schedule { - pallet_contracts::Schedule { - limits: pallet_contracts::Limits { - runtime_memory: 1024 * 1024 * 1024, - ..Default::default() - }, - ..Default::default() + fn finalize_block( + height: frame_system::pallet_prelude::BlockNumberFor, + ) -> ::Hash { + BlockBuilder::::finalize_block(height) } -} -parameter_types! { - pub const DepositPerItem: Balance = deposit(1, 0); - pub const DepositPerByte: Balance = deposit(0, 1); - pub Schedule: pallet_contracts::Schedule = schedule::(); - pub const DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024); - pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); -} + fn default_actor() -> AccountIdFor { + ALICE + } -impl pallet_contracts::Config for Runtime { - type AddressGenerator = DefaultAddressGenerator; - type ApiVersion = (); - // C - type CallFilter = (); - type CallStack = [Frame; 23]; - type ChainExtension = api::Extension; - type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; - type Currency = Balances; - // D - type Debug = drink::pallet_contracts_debugging::DrinkDebug; - type DefaultDepositLimit = DefaultDepositLimit; - type DepositPerByte = DepositPerByte; - type DepositPerItem = DepositPerItem; - // E - type Environment = (); - // I - type InstantiateOrigin = EnsureSigned; - // M - type MaxCodeLen = ConstU32<{ 256 * 1024 }>; - type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; - type MaxDelegateDependencies = ConstU32<32>; - type MaxStorageKeyLen = ConstU32<128>; - type Migrations = (); - // R - type Randomness = SandboxRandomness; - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; - type RuntimeHoldReason = RuntimeHoldReason; - // S - type Schedule = Schedule; - // T - type Time = Timestamp; - // U - type UnsafeUnstableInterface = ConstBool; - type UploadOrigin = EnsureSigned; - // W - type WeightInfo = (); - type WeightPrice = Self; - // X - type Xcm = (); -} + fn get_metadata() -> RuntimeMetadataPrefixed { + Self::Runtime::metadata() + } -drink::create_sandbox!(PopSandbox, Runtime); + fn convert_account_to_origin( + account: AccountIdFor, + ) -> <::RuntimeCall as frame_support::sp_runtime::traits::Dispatchable>::RuntimeOrigin{ + Some(account).into() + } +} diff --git a/pop-sandbox/src/utils.rs b/pop-sandbox/src/utils.rs index 8a8085ac..3d67da8b 100644 --- a/pop-sandbox/src/utils.rs +++ b/pop-sandbox/src/utils.rs @@ -1,13 +1,12 @@ +use std::error::Error; + use drink::{ session::{Session, NO_ARGS}, AccountId32, }; -use std::error::Error; use super::*; -pub const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); - // TODO: Convert this method to accept generic runtime instead of `PopSandbox`. pub fn call_function( mut sess: Session, diff --git a/runtime/devnet/src/config/api/versioning.rs b/runtime/devnet/src/config/api/versioning.rs index 7c3d9ee5..317496df 100644 --- a/runtime/devnet/src/config/api/versioning.rs +++ b/runtime/devnet/src/config/api/versioning.rs @@ -112,9 +112,9 @@ impl From for V0Error { // Note: message not used let ModuleError { index, error, message: _message } = error; // Map `pallet-contracts::Error::DecodingFailed` to `Error::DecodingFailed` - if index as usize - == ::index() - && error == DECODING_FAILED_ERROR + if index as usize == + ::index() && + error == DECODING_FAILED_ERROR { Error::DecodingFailed } else { From 0399d46429d99a3c3aa6debefee82db165832ba5 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:18:08 +0700 Subject: [PATCH 064/161] refactor: fungible example contract --- pop-api/examples/fungibles/lib.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 00f02914..f1171ffe 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -10,22 +10,20 @@ use pop_api::{ type PopApiResult = core::result::Result; #[ink::contract] -mod create_token_in_constructor { +mod fungibles { use super::*; #[ink(storage)] - pub struct Fungible { - id: TokenId, - } + #[derive(Default)] + pub struct Fungibles; - impl Fungible { + impl Fungibles { #[ink(constructor, payable)] pub fn new(id: TokenId, min_balance: Balance) -> PopApiResult { ink::env::debug_println!("Fungible::call() asset_id={id}, min_balance={min_balance}"); - let contract = Self { id }; - let owner = contract.env().account_id(); + let owner = Self::env().account_id(); api::create(id, owner, min_balance)?; - Ok(contract) + Ok(Default::default()) } #[ink(message)] From 5fdf406e7e056b8a3ac2b94033147b3a451f1409 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:35:14 +0700 Subject: [PATCH 065/161] refactor: fungible test --- pop-api/examples/fungibles/lib.rs | 72 +++++++++++++++++++------------ pop-sandbox/src/lib.rs | 3 -- pop-sandbox/src/utils.rs | 39 ----------------- 3 files changed, 45 insertions(+), 69 deletions(-) delete mode 100644 pop-sandbox/src/utils.rs diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index f1171ffe..7977e58d 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -19,16 +19,8 @@ mod fungibles { impl Fungibles { #[ink(constructor, payable)] - pub fn new(id: TokenId, min_balance: Balance) -> PopApiResult { - ink::env::debug_println!("Fungible::call() asset_id={id}, min_balance={min_balance}"); - let owner = Self::env().account_id(); - api::create(id, owner, min_balance)?; - Ok(Default::default()) - } - - #[ink(message)] - pub fn token_exists(&self, id: TokenId) -> PopApiResult { - api::token_exists(id) + pub fn new() -> Self { + Default::default() } #[ink(message)] @@ -113,14 +105,40 @@ mod fungibles { pub fn token_decimals(&self, id: TokenId) -> PopApiResult { api::token_decimals(id) } + + #[ink(message, payable)] + pub fn create( + &self, + id: TokenId, + admin: AccountId, + min_balance: Balance, + ) -> PopApiResult<()> { + api::create(id, admin, min_balance) + } + + #[ink(message)] + pub fn set_metadata( + &self, + id: TokenId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> PopApiResult<()> { + api::set_metadata(id, name, symbol, decimals) + } + + #[ink(message)] + pub fn token_exists(&self, id: TokenId) -> PopApiResult { + api::token_exists(id) + } } } /// We put `drink`-based tests as usual unit tests, into a test module. #[cfg(test)] mod tests { - use drink::session::{Session, NO_SALT}; - use pop_sandbox::{utils::call_function, ALICE, INIT_VALUE}; + use drink::session::{Session, NO_ARGS, NO_SALT}; + use pop_sandbox::{ALICE, INIT_VALUE}; use super::*; @@ -134,23 +152,23 @@ mod tests { const ASSET_ID: TokenId = 1; - // Deploy a contract and create a new token with ASSET_ID = 1 - let contract_address = session.deploy_bundle( - contract_bundle, - "new", - &[ASSET_ID.to_string(), 1.to_string()], - NO_SALT, - Some(INIT_VALUE), - )?; + // Deploy a contract. + let contract_address = + session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; + // Calling the method in the contract. + session.call_with_address( + contract_address.clone(), + "create", + &vec![ASSET_ID.to_string(), ALICE.to_string(), 10_000.to_string()], + None, + )??; // Calling the method in the contract. - let session = call_function( - session, - &contract_address, - &ALICE, - "token_exists".to_string(), - Some(vec![ASSET_ID.to_string()]), + session.call_with_address( + contract_address.clone(), + "token_exists", + &vec![ASSET_ID.to_string()], None, - )?; + )??; // Check that the token is created successfully. let result = session.record().last_call_return_decoded::>()??; assert_eq!(result, Ok(true)); diff --git a/pop-sandbox/src/lib.rs b/pop-sandbox/src/lib.rs index 5a083c4a..4b7e47f5 100644 --- a/pop-sandbox/src/lib.rs +++ b/pop-sandbox/src/lib.rs @@ -11,9 +11,6 @@ use sp_io::TestExternalities; use frame_support::sp_runtime::traits::One; use pop_runtime_devnet::Balance; -// Provides utlity methods to interact with the sandbox. -pub mod utils; - /// Alias for the account ID type. pub type AccountIdFor = ::AccountId; diff --git a/pop-sandbox/src/utils.rs b/pop-sandbox/src/utils.rs deleted file mode 100644 index 3d67da8b..00000000 --- a/pop-sandbox/src/utils.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::error::Error; - -use drink::{ - session::{Session, NO_ARGS}, - AccountId32, -}; - -use super::*; - -// TODO: Convert this method to accept generic runtime instead of `PopSandbox`. -pub fn call_function( - mut sess: Session, - contract: &AccountId32, - sender: &AccountId32, - func_name: String, - args: Option>, - value: Option, -) -> Result, Box> { - sess.set_actor(sender.clone()); - if let Some(args) = args { - println!("Calling function: {}() | Input: {:?}", func_name, args); - sess.call_with_address(contract.clone(), &func_name, &args, value)??; - } else { - println!("Calling function: {}() | Input: None", func_name); - sess.call_with_address(contract.clone(), &func_name, NO_ARGS, value)??; - } - - let encoded = &sess.record().last_call_result().result.clone().unwrap().data; - let decoded = encoded.iter().map(|b| *b as char).collect::(); - let messages: Vec = decoded.split('\n').map(|s| s.to_string()).collect(); - // Print debug logs - for line in messages { - if line.len() > 0 { - println!("LOG: {}", line); - } - } - - Ok(sess) -} From ed7146bc56d9a9173e8d8e28a9e2bf6afd4fb0fa Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:41:50 +0700 Subject: [PATCH 066/161] fix: fungible contract --- pop-api/examples/fungibles/lib.rs | 47 +++++++++++-------- pop-sandbox/Cargo.toml | 11 +---- pop-sandbox/src/lib.rs | 76 +++++-------------------------- 3 files changed, 40 insertions(+), 94 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 7977e58d..6ba396f4 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -138,39 +138,48 @@ mod fungibles { #[cfg(test)] mod tests { use drink::session::{Session, NO_ARGS, NO_SALT}; - use pop_sandbox::{ALICE, INIT_VALUE}; + use pop_sandbox::{Balance, PopSandbox, ALICE, INIT_VALUE}; + use scale::Decode; use super::*; #[drink::contract_bundle_provider] enum BundleProvider {} - #[drink::test(sandbox = pop_sandbox::PopSandbox)] - fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { + fn decoded_call( + session: &mut Session, + func_name: &str, + input: Vec, + endowment: Option, + ) -> Result> { + session.call(func_name, &input, endowment)??; + Ok(session.record().last_call_return_decoded::()??) + } + + #[drink::test(sandbox = PopSandbox)] + fn test_create_token_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); let contract_bundle = BundleProvider::local()?; - const ASSET_ID: TokenId = 1; - // Deploy a contract. - let contract_address = - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - // Calling the method in the contract. - session.call_with_address( - contract_address.clone(), + session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; + + const TOKEN_ID: TokenId = 1; + // Create a new token. + let _ = decoded_call::>( + &mut session, "create", - &vec![ASSET_ID.to_string(), ALICE.to_string(), 10_000.to_string()], + vec![TOKEN_ID.to_string(), ALICE.to_string(), 10_000.to_string()], None, - )??; - // Calling the method in the contract. - session.call_with_address( - contract_address.clone(), + )?; + + // Check that the token is created successfully. + let result = decoded_call::>( + &mut session, "token_exists", - &vec![ASSET_ID.to_string()], + vec![TOKEN_ID.to_string()], None, - )??; - // Check that the token is created successfully. - let result = session.record().last_call_return_decoded::>()??; + )?; assert_eq!(result, Ok(true)); Ok(()) } diff --git a/pop-sandbox/Cargo.toml b/pop-sandbox/Cargo.toml index d2309173..7a65f593 100644 --- a/pop-sandbox/Cargo.toml +++ b/pop-sandbox/Cargo.toml @@ -1,4 +1,5 @@ [package] +authors = [ "[your_name] <[your_email]>" ] description = "Sandboxing environment for contract quasi testing with Pop Network runtimes." edition = "2021" license = "GPL-3.0-only" @@ -20,14 +21,9 @@ frame-support = { version = "36.0.0", default-features = false } frame-support-procedural = { version = "=30.0.1", default-features = false } frame-system = { version = "36.1.0", default-features = false } pallet-assets = { version = "37.0.0", default-features = false } -pallet-aura = { version = "35.0.0", default-features = false } -pallet-authorship = { version = "36.0.0", default-features = false } pallet-balances = { version = "37.0.0", default-features = false } pallet-contracts = { version = "35.0.0", default-features = false } -pallet-scheduler = { version = "37.0.0", default-features = false } -pallet-session = { version = "36.0.0", default-features = false } pallet-timestamp = { version = "35.0.0", default-features = false } -pallet-transaction-payment = { version = "36.0.0", default-features = false } pop-runtime-devnet = { path = "../runtime/devnet", default-features = false } sp-io = { version = "37.0.0", default-features = false } sp-runtime = { version = "=38.0.0", default-features = false } @@ -44,14 +40,9 @@ std = [ "frame-support/std", "frame-system/std", "pallet-assets/std", - "pallet-aura/std", - "pallet-authorship/std", "pallet-balances/std", "pallet-contracts/std", - "pallet-scheduler/std", - "pallet-session/std", "pallet-timestamp/std", - "pallet-transaction-payment/std", "pop-runtime-devnet/std", "scale-info/std", "sp-io/std", diff --git a/pop-sandbox/src/lib.rs b/pop-sandbox/src/lib.rs index 4b7e47f5..285c5774 100644 --- a/pop-sandbox/src/lib.rs +++ b/pop-sandbox/src/lib.rs @@ -1,15 +1,13 @@ -use core::any::Any; - -use frame_metadata::RuntimeMetadataPrefixed; use frame_support::{ - sp_runtime::{traits::Header, AccountId32}, + sp_runtime::{ + traits::{Header, One}, + AccountId32, + }, traits::Hooks, }; use frame_system::pallet_prelude::BlockNumberFor; +pub use pop_runtime_devnet::Balance; use pop_runtime_devnet::{BuildStorage, Runtime}; -use sp_io::TestExternalities; -use frame_support::sp_runtime::traits::One; -use pop_runtime_devnet::Balance; /// Alias for the account ID type. pub type AccountIdFor = ::AccountId; @@ -24,19 +22,18 @@ pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); pub struct BlockBuilder(std::marker::PhantomData); impl< - T: pallet_balances::Config + pallet_timestamp::Config + pallet_contracts::Config + pallet_aura::Config, + T: pallet_balances::Config + pallet_timestamp::Config + pallet_contracts::Config, > BlockBuilder { /// Create a new externalities with the given balances. - pub fn new_ext(balances: Vec<(T::AccountId, T::Balance)>) -> TestExternalities { - log::debug!("new externalities: balances={:?}", balances); + pub fn new_ext(balances: Vec<(T::AccountId, T::Balance)>) -> sp_io::TestExternalities { let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); pallet_balances::GenesisConfig:: { balances } .assimilate_storage(&mut storage) .unwrap(); - let mut ext = TestExternalities::new(storage); + let mut ext = sp_io::TestExternalities::new(storage); ext.execute_with(|| Self::initialize_block(BlockNumberFor::::one(), Default::default())); ext @@ -50,7 +47,6 @@ impl< frame_system::Pallet::::reset_events(); frame_system::Pallet::::initialize(&height, &parent_hash, &Default::default()); pallet_balances::Pallet::::on_initialize(height); - pallet_aura::Pallet::::on_initialize(height); // TODO: Resolve an issue with pallet-aura to simulate the time. // pallet_timestamp::Pallet::::set_timestamp( // SystemTime::now() @@ -75,65 +71,15 @@ impl< } pub struct PopSandbox { - ext: TestExternalities, + ext: sp_io::TestExternalities, } impl Default for PopSandbox { fn default() -> Self { - let balances : Vec<(AccountId32, u128)> = vec![(ALICE, INIT_AMOUNT)]; + let balances: Vec<(AccountId32, u128)> = vec![(ALICE, INIT_AMOUNT)]; let ext = BlockBuilder::::new_ext(balances); Self { ext } } } -impl drink::Sandbox for PopSandbox { - type Runtime = Runtime; - - fn execute_with(&mut self, execute: impl FnOnce() -> T) -> T { - self.ext.execute_with(execute) - } - - fn dry_run(&mut self, action: impl FnOnce(&mut Self) -> T) -> T { - // Make a backup of the backend. - let backend_backup = self.ext.as_backend(); - // Run the action, potentially modifying storage. Ensure, that there are no pending changes - // that would affect the reverted backend. - let result = action(self); - self.ext.commit_all().expect("Failed to commit changes"); - - // Restore the backend. - self.ext.backend = backend_backup; - result - } - - fn register_extension(&mut self, ext: E) { - self.ext.register_extension(ext); - } - - fn initialize_block( - height: frame_system::pallet_prelude::BlockNumberFor, - parent_hash: ::Hash, - ) { - BlockBuilder::::initialize_block(height, parent_hash) - } - - fn finalize_block( - height: frame_system::pallet_prelude::BlockNumberFor, - ) -> ::Hash { - BlockBuilder::::finalize_block(height) - } - - fn default_actor() -> AccountIdFor { - ALICE - } - - fn get_metadata() -> RuntimeMetadataPrefixed { - Self::Runtime::metadata() - } - - fn convert_account_to_origin( - account: AccountIdFor, - ) -> <::RuntimeCall as frame_support::sp_runtime::traits::Dispatchable>::RuntimeOrigin{ - Some(account).into() - } -} +drink::impl_sandbox!(PopSandbox, Runtime, BlockBuilder, ALICE); From 7ce06746b468ddf2ed667f6bb45d28b6cdc063be Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:22:23 +0700 Subject: [PATCH 067/161] test: drink tests for fungible use case --- pop-api/examples/fungibles/lib.rs | 132 +++++++---------- pop-api/examples/fungibles/tests.rs | 211 ++++++++++++++++++++++++++++ pop-api/src/primitives.rs | 6 + pop-sandbox/README.md | 46 ++++++ pop-sandbox/src/lib.rs | 14 +- 5 files changed, 324 insertions(+), 85 deletions(-) create mode 100644 pop-api/examples/fungibles/tests.rs create mode 100644 pop-sandbox/README.md diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 6ba396f4..649a8b64 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -7,6 +7,9 @@ use pop_api::{ StatusCode, }; +#[cfg(test)] +mod tests; + type PopApiResult = core::result::Result; #[ink::contract] @@ -24,23 +27,23 @@ mod fungibles { } #[ink(message)] - pub fn total_supply(&self, id: TokenId) -> PopApiResult { - api::total_supply(id) - } - - #[ink(message)] - pub fn balance_of(&self, id: TokenId, owner: AccountId) -> PopApiResult { - api::balance_of(id, owner) + pub fn mint( + &mut self, + token: TokenId, + account: AccountId, + amount: Balance, + ) -> PopApiResult<()> { + api::mint(token, account, amount) } #[ink(message)] - pub fn allowance( - &self, - id: TokenId, - owner: AccountId, - spender: AccountId, - ) -> PopApiResult { - api::allowance(id, owner, spender) + pub fn burn( + &mut self, + token: TokenId, + account: AccountId, + amount: Balance, + ) -> PopApiResult<()> { + api::burn(token, account, amount) } #[ink(message)] @@ -91,21 +94,6 @@ mod fungibles { api::decrease_allowance(id, spender, value) } - #[ink(message)] - pub fn token_name(&self, id: TokenId) -> PopApiResult> { - api::token_name(id) - } - - #[ink(message)] - pub fn token_symbol(&self, id: TokenId) -> PopApiResult> { - api::token_symbol(id) - } - - #[ink(message)] - pub fn token_decimals(&self, id: TokenId) -> PopApiResult { - api::token_decimals(id) - } - #[ink(message, payable)] pub fn create( &self, @@ -113,7 +101,9 @@ mod fungibles { admin: AccountId, min_balance: Balance, ) -> PopApiResult<()> { - api::create(id, admin, min_balance) + api::create(id, admin, min_balance)?; + self.env().emit_event(api::events::Create { id, creator: admin, admin }); + Ok(()) } #[ink(message)] @@ -128,59 +118,43 @@ mod fungibles { } #[ink(message)] - pub fn token_exists(&self, id: TokenId) -> PopApiResult { - api::token_exists(id) + pub fn total_supply(&self, id: TokenId) -> PopApiResult { + api::total_supply(id) } - } -} -/// We put `drink`-based tests as usual unit tests, into a test module. -#[cfg(test)] -mod tests { - use drink::session::{Session, NO_ARGS, NO_SALT}; - use pop_sandbox::{Balance, PopSandbox, ALICE, INIT_VALUE}; - use scale::Decode; + #[ink(message)] + pub fn balance_of(&self, id: TokenId, owner: AccountId) -> PopApiResult { + api::balance_of(id, owner) + } - use super::*; + #[ink(message)] + pub fn allowance( + &self, + id: TokenId, + owner: AccountId, + spender: AccountId, + ) -> PopApiResult { + api::allowance(id, owner, spender) + } - #[drink::contract_bundle_provider] - enum BundleProvider {} - - fn decoded_call( - session: &mut Session, - func_name: &str, - input: Vec, - endowment: Option, - ) -> Result> { - session.call(func_name, &input, endowment)??; - Ok(session.record().last_call_return_decoded::()??) - } + #[ink(message)] + pub fn token_name(&self, id: TokenId) -> PopApiResult> { + api::token_name(id) + } + + #[ink(message)] + pub fn token_symbol(&self, id: TokenId) -> PopApiResult> { + api::token_symbol(id) + } - #[drink::test(sandbox = PopSandbox)] - fn test_create_token_works(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - - // Deploy a contract. - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - - const TOKEN_ID: TokenId = 1; - // Create a new token. - let _ = decoded_call::>( - &mut session, - "create", - vec![TOKEN_ID.to_string(), ALICE.to_string(), 10_000.to_string()], - None, - )?; - - // Check that the token is created successfully. - let result = decoded_call::>( - &mut session, - "token_exists", - vec![TOKEN_ID.to_string()], - None, - )?; - assert_eq!(result, Ok(true)); - Ok(()) + #[ink(message)] + pub fn token_decimals(&self, id: TokenId) -> PopApiResult { + api::token_decimals(id) + } + + #[ink(message)] + pub fn token_exists(&self, id: TokenId) -> PopApiResult { + api::token_exists(id) + } } } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs new file mode 100644 index 00000000..bca7b64f --- /dev/null +++ b/pop-api/examples/fungibles/tests.rs @@ -0,0 +1,211 @@ +use drink::session::{Session, NO_ARGS, NO_SALT}; +use pop_api::{ + primitives::{account_id_from_slice, TokenId}, + v0::fungibles::{self as api}, +}; +use pop_sandbox::{AccountId32, Balance, Sandbox, ALICE, BOB, INIT_VALUE}; +use scale::{Decode, Encode}; + +use super::*; + +const TOKEN_A_ID: TokenId = 1; +const TOKEN_B_ID: TokenId = 2; + +#[drink::contract_bundle_provider] +enum BundleProvider {} + +use test_methods::*; +// Utility methods to test the contract calls. +mod test_methods { + use super::*; + + // Call a contract method and decode the returned data. + pub(super) fn decoded_call( + session: &mut Session, + func_name: &str, + input: Vec, + endowment: Option, + ) -> Result> { + session.call(func_name, &input, endowment)??; + Ok(session.record().last_call_return_decoded::()??) + } + + // Check if the event emitted correctly. + pub(super) fn assert_event(session: &mut Session, event: Vec) { + let contract_events = session.record().last_event_batch().contract_events(); + let last_event = contract_events.last().unwrap().to_vec(); + assert_eq!(last_event, event.as_slice()); + } + + pub(super) fn mint( + session: &mut Session, + token: TokenId, + account: AccountId32, + amount: Balance, + ) -> Result<(), Box> { + Ok(session.call( + "mint", + &vec![token.to_string(), account.to_string(), amount.to_string()], + None, + )??) + } + + pub(super) fn burn( + session: &mut Session, + token: TokenId, + account: AccountId32, + amount: Balance, + ) -> Result<(), Box> { + Ok(session.call( + "burn", + &vec![token.to_string(), account.to_string(), amount.to_string()], + None, + )??) + } + + pub(super) fn transfer( + session: &mut Session, + token: TokenId, + to: AccountId32, + amount: Balance, + ) -> Result<(), Box> { + Ok(session.call( + "transfer", + &vec![token.to_string(), to.to_string(), amount.to_string()], + None, + )??) + } + + pub(super) fn create( + session: &mut Session, + id: TokenId, + admin: AccountId32, + min_balance: Balance, + ) -> Result<(), Box> { + Ok(session.call( + "create", + &vec![id.to_string(), admin.to_string(), min_balance.to_string()], + None, + )??) + } + + pub(super) fn token_exist( + session: &mut Session, + id: TokenId, + ) -> Result, Box> { + Ok(decoded_call::>(session, "token_exists", vec![id.to_string()], None)?) + } + + pub(super) fn total_supply( + session: &mut Session, + id: TokenId, + ) -> Result, Box> { + Ok(decoded_call::>( + session, + "total_supply", + vec![id.to_string()], + None, + )?) + } + + pub(super) fn balance_of( + session: &mut Session, + id: TokenId, + owner: AccountId32, + ) -> Result, Box> { + Ok(decoded_call::>( + session, + "balance_of", + vec![id.to_string(), owner.to_string()], + None, + )?) + } +} + +#[drink::test(sandbox = Sandbox)] +fn test_create_multiple_token_works( + mut session: Session, +) -> Result<(), Box> { + let _ = env_logger::try_init(); + let contract_bundle = BundleProvider::local()?; + // Deploy a contract. + session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; + // Create new tokens. + create(&mut session, TOKEN_A_ID, ALICE, 1_000)?; + + assert_event( + &mut session, + api::events::Create { + id: TOKEN_A_ID, + admin: account_id_from_slice(ALICE.as_ref()), + creator: account_id_from_slice(ALICE.as_ref()), + } + .encode(), + ); + + create(&mut session, TOKEN_B_ID, ALICE, 2_000)?; + // Check that the token is created successfully. + assert_eq!(token_exist(&mut session, TOKEN_A_ID)?, Ok(true)); + assert_eq!(token_exist(&mut session, TOKEN_B_ID)?, Ok(true)); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn test_mint_token_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + let contract_bundle = BundleProvider::local()?; + // Deploy a contract. + let contract_address = + session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; + // Create a new token. + create(&mut session, TOKEN_A_ID, contract_address, 10_000)?; + // Mint tokens. + const AMOUNT: Balance = 12_000; + mint(&mut session, TOKEN_A_ID, ALICE, AMOUNT)?; + mint(&mut session, TOKEN_A_ID, BOB, AMOUNT)?; + // Check if the tokens were minted with the right amount. + assert_eq!(total_supply(&mut session, TOKEN_A_ID)?, Ok(AMOUNT * 2)); + assert_eq!(balance_of(&mut session, TOKEN_A_ID, ALICE)?, Ok(AMOUNT)); + assert_eq!(balance_of(&mut session, TOKEN_A_ID, BOB)?, Ok(AMOUNT)); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn test_burn_token_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + let contract_bundle = BundleProvider::local()?; + // Deploy a contract. + let contract_address = + session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; + // Create a new token. + create(&mut session, TOKEN_A_ID, contract_address, 10_000)?; + // Mint tokens. + const AMOUNT: Balance = 12_000; + mint(&mut session, TOKEN_A_ID, ALICE, AMOUNT)?; + // Burn tokens. + burn(&mut session, TOKEN_A_ID, ALICE, 1)?; + assert_eq!(total_supply(&mut session, TOKEN_A_ID)?, Ok(AMOUNT - 1)); + assert_eq!(balance_of(&mut session, TOKEN_A_ID, ALICE)?, Ok(AMOUNT - 1)); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn test_transfer_token_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + let contract_bundle = BundleProvider::local()?; + // Deploy a contract. + let contract_address = + session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; + // Create a new token. + create(&mut session, TOKEN_A_ID, contract_address.clone(), 10_000)?; + // Mint tokens. + const AMOUNT: Balance = 12_000; + const TRANSFERED: Balance = 500; + mint(&mut session, TOKEN_A_ID, contract_address.clone(), AMOUNT)?; + mint(&mut session, TOKEN_A_ID, BOB, AMOUNT)?; + // Transfer tokens. + transfer(&mut session, TOKEN_A_ID, BOB, TRANSFERED)?; + assert_eq!(balance_of(&mut session, TOKEN_A_ID, contract_address)?, Ok(AMOUNT - TRANSFERED)); + assert_eq!(balance_of(&mut session, TOKEN_A_ID, BOB)?, Ok(AMOUNT + TRANSFERED)); + Ok(()) +} diff --git a/pop-api/src/primitives.rs b/pop-api/src/primitives.rs index a3d596a5..9fec4dd3 100644 --- a/pop-api/src/primitives.rs +++ b/pop-api/src/primitives.rs @@ -1,5 +1,11 @@ use ink::env::{DefaultEnvironment, Environment}; +use ink::scale::Decode; pub use pop_primitives::*; pub(crate) type AccountId = ::AccountId; pub(crate) type Balance = ::Balance; + +/// Decode slice of bytes to environment associated type AccountId. +pub fn account_id_from_slice(s: &[u8; 32]) -> AccountId { + AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") +} diff --git a/pop-sandbox/README.md b/pop-sandbox/README.md new file mode 100644 index 00000000..b911cd17 --- /dev/null +++ b/pop-sandbox/README.md @@ -0,0 +1,46 @@ +# Pop Sandbox + +Implementation of the `pop_drink::Sandbox` struct for the Pop Network runtimes required for the quasi testing with `drink`. + +## Getting Started + +### Installation + +```toml +pop_drink = { version = "1.0.0", package = "pop-drink" } +``` + +### Import Sandbox for the specific runtime + +For mainnet + +```rs +use pop_sandbox::MainnetSandbox; +``` + +For devnet + +```rs +use pop_sandbox::DevnetSandbox; +``` + +For testnet + +```rs +use pop_sandbox::TestnetSandbox; +``` + +### Setup test environment for your contract + +```rs +use drink::session::Session; +use pop_sandbox::DevnetSandbox as Sandbox; + +#[drink::contract_bundle_provider] +enum BundleProvider {} + +#[drink::test(sandbox = Sandbox)] +fn test(mut session: Session) { + // Your test case +} +``` diff --git a/pop-sandbox/src/lib.rs b/pop-sandbox/src/lib.rs index 285c5774..dbdb9a06 100644 --- a/pop-sandbox/src/lib.rs +++ b/pop-sandbox/src/lib.rs @@ -1,13 +1,13 @@ use frame_support::{ sp_runtime::{ traits::{Header, One}, - AccountId32, }, traits::Hooks, }; use frame_system::pallet_prelude::BlockNumberFor; -pub use pop_runtime_devnet::Balance; use pop_runtime_devnet::{BuildStorage, Runtime}; +pub use pop_runtime_devnet::Balance; +pub use frame_support::sp_runtime::AccountId32; /// Alias for the account ID type. pub type AccountIdFor = ::AccountId; @@ -17,6 +17,8 @@ pub const UNIT: Balance = 10_000_000_000; pub const INIT_AMOUNT: Balance = 100_000_000 * UNIT; pub const INIT_VALUE: Balance = 100 * UNIT; pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); +pub const BOB: AccountId32 = AccountId32::new([2_u8; 32]); +pub const CHARLIE: AccountId32 = AccountId32::new([3_u8; 32]); /// A helper struct for initializing and finalizing blocks. pub struct BlockBuilder(std::marker::PhantomData); @@ -70,16 +72,16 @@ impl< } } -pub struct PopSandbox { +pub struct Sandbox { ext: sp_io::TestExternalities, } -impl Default for PopSandbox { +impl Default for Sandbox { fn default() -> Self { - let balances: Vec<(AccountId32, u128)> = vec![(ALICE, INIT_AMOUNT)]; + let balances: Vec<(AccountId32, u128)> = vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)]; let ext = BlockBuilder::::new_ext(balances); Self { ext } } } -drink::impl_sandbox!(PopSandbox, Runtime, BlockBuilder, ALICE); +drink::impl_sandbox!(Sandbox, Runtime, BlockBuilder, ALICE); From 7c4c470851c7e47a60ea06a03425d9c748dd5b7b Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Mon, 16 Sep 2024 15:43:13 +0200 Subject: [PATCH 068/161] style: token terminology --- pop-api/examples/fungibles/lib.rs | 52 ++++++++++++++--------------- pop-api/examples/fungibles/tests.rs | 12 +++---- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index e99bfd60..2148e967 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -47,50 +47,50 @@ mod fungibles { } #[ink(message)] - pub fn transfer(&mut self, id: TokenId, to: AccountId, value: Balance) -> PopApiResult<()> { - api::transfer(id, to, value) + pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> PopApiResult<()> { + api::transfer(token, to, value) } #[ink(message)] pub fn transfer_from( &mut self, - id: TokenId, + token: TokenId, from: AccountId, to: AccountId, value: Balance, _data: Vec, ) -> PopApiResult<()> { - api::transfer_from(id, from, to, value) + api::transfer_from(token, from, to, value) } #[ink(message)] pub fn approve( &mut self, - id: TokenId, + token: TokenId, spender: AccountId, value: Balance, ) -> PopApiResult<()> { - api::approve(id, spender, value) + api::approve(token, spender, value) } #[ink(message)] pub fn increase_allowance( &mut self, - id: TokenId, + token: TokenId, spender: AccountId, value: Balance, ) -> PopApiResult<()> { - api::increase_allowance(id, spender, value) + api::increase_allowance(token, spender, value) } #[ink(message)] pub fn decrease_allowance( &mut self, - id: TokenId, + token: TokenId, spender: AccountId, value: Balance, ) -> PopApiResult<()> { - api::decrease_allowance(id, spender, value) + api::decrease_allowance(token, spender, value) } #[ink(message, payable)] @@ -108,52 +108,52 @@ mod fungibles { #[ink(message)] pub fn set_metadata( &self, - id: TokenId, + token: TokenId, name: Vec, symbol: Vec, decimals: u8, ) -> PopApiResult<()> { - api::set_metadata(id, name, symbol, decimals) + api::set_metadata(token, name, symbol, decimals) } #[ink(message)] - pub fn total_supply(&self, id: TokenId) -> PopApiResult { - api::total_supply(id) + pub fn total_supply(&self, token: TokenId) -> PopApiResult { + api::total_supply(token) } #[ink(message)] - pub fn balance_of(&self, id: TokenId, owner: AccountId) -> PopApiResult { - api::balance_of(id, owner) + pub fn balance_of(&self, token: TokenId, owner: AccountId) -> PopApiResult { + api::balance_of(token, owner) } #[ink(message)] pub fn allowance( &self, - id: TokenId, + token: TokenId, owner: AccountId, spender: AccountId, ) -> PopApiResult { - api::allowance(id, owner, spender) + api::allowance(token, owner, spender) } #[ink(message)] - pub fn token_name(&self, id: TokenId) -> PopApiResult> { - api::token_name(id) + pub fn token_name(&self, token: TokenId) -> PopApiResult> { + api::token_name(token) } #[ink(message)] - pub fn token_symbol(&self, id: TokenId) -> PopApiResult> { - api::token_symbol(id) + pub fn token_symbol(&self, token: TokenId) -> PopApiResult> { + api::token_symbol(token) } #[ink(message)] - pub fn token_decimals(&self, id: TokenId) -> PopApiResult { - api::token_decimals(id) + pub fn token_decimals(&self, token: TokenId) -> PopApiResult { + api::token_decimals(token) } #[ink(message)] - pub fn token_exists(&self, id: TokenId) -> PopApiResult { - api::token_exists(id) + pub fn token_exists(&self, token: TokenId) -> PopApiResult { + api::token_exists(token) } } } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 4284f733..216b9de3 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -96,32 +96,32 @@ mod test_methods { pub(super) fn token_exist( session: &mut Session, - id: TokenId, + token: TokenId, ) -> Result, Box> { - Ok(decoded_call::>(session, "token_exists", vec![id.to_string()], None)?) + Ok(decoded_call::>(session, "token_exists", vec![token.to_string()], None)?) } pub(super) fn total_supply( session: &mut Session, - id: TokenId, + token: TokenId, ) -> Result, Box> { Ok(decoded_call::>( session, "total_supply", - vec![id.to_string()], + vec![token.to_string()], None, )?) } pub(super) fn balance_of( session: &mut Session, - id: TokenId, + token: TokenId, owner: AccountId32, ) -> Result, Box> { Ok(decoded_call::>( session, "balance_of", - vec![id.to_string(), owner.to_string()], + vec![token.to_string(), owner.to_string()], None, )?) } From 4e44fba9d662535fb568ef8ea00cd57ead2747f6 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 12:48:36 +0800 Subject: [PATCH 069/161] feat: add interfaces for psp22 --- pop-api/src/v0/fungibles.rs | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/pop-api/src/v0/fungibles.rs b/pop-api/src/v0/fungibles.rs index 99c1261a..9ab53957 100644 --- a/pop-api/src/v0/fungibles.rs +++ b/pop-api/src/v0/fungibles.rs @@ -420,6 +420,93 @@ pub mod management { } } +pub mod interfaces { + use super::*; + + pub type Result = core::result::Result; + + #[ink::trait_definition] + pub trait Psp22Impl { + #[ink(message)] + fn total_supply(&self) -> Balance; + + #[ink(message)] + fn balance_of(&self, owner: AccountId) -> Balance; + + #[ink(message)] + fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; + + #[ink(message)] + fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; + + #[ink(message)] + fn transfer_from( + &mut self, + from: AccountId, + to: AccountId, + value: Balance, + data: Vec, + ) -> Result<()>; + + #[ink(message)] + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; + + #[ink(message)] + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + + #[ink(message)] + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + } + + #[ink::trait_definition] + pub trait Psp2ManagableImpl { + #[ink(message)] + fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; + + #[ink(message)] + fn start_destroy(&mut self, token: TokenId) -> Result<()>; + + #[ink(message)] + fn set_metadata( + &mut self, + token: TokenId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()>; + + #[ink(message)] + fn clear_metadata(&mut self, token: TokenId) -> Result<()>; + + #[ink(message)] + fn token_exists(&self, token: TokenId) -> Result; + } + + #[ink::trait_definition] + pub trait Psp22MetadataImpl { + #[ink(message)] + fn token_name(&self) -> Option>; + + #[ink(message)] + fn token_symbol(&self) -> Option>; + + #[ink(message)] + fn token_decimals(&self, id: TokenId) -> u8; + } + + #[ink::trait_definition] + pub trait Psp22MintableImpl { + #[ink(message)] + fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; + } + + #[ink::trait_definition] + pub trait Psp22BurnableImpl { + #[ink(message)] + fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; + } +} + /// Represents various errors related to fungible tokens. /// /// The `FungiblesError` provides a detailed and specific set of error types that can occur when From a32f0021b95555607db113dd4cd3fa5f4292d2a0 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:03:39 +0800 Subject: [PATCH 070/161] chore: add comments --- pop-api/src/v0/fungibles.rs | 143 ++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 6 deletions(-) diff --git a/pop-api/src/v0/fungibles.rs b/pop-api/src/v0/fungibles.rs index 9ab53957..096017c6 100644 --- a/pop-api/src/v0/fungibles.rs +++ b/pop-api/src/v0/fungibles.rs @@ -426,19 +426,78 @@ pub mod interfaces { pub type Result = core::result::Result; #[ink::trait_definition] - pub trait Psp22Impl { + pub trait Psp22 { + /// Returns the total token supply. #[ink(message)] fn total_supply(&self) -> Balance; + /// Returns the account balance for the specified `owner`. + /// + /// # Parameters + /// - `owner` - The account whose balance is being queried. + /// + /// Returns `0` if the account is non-existent. #[ink(message)] fn balance_of(&self, owner: AccountId) -> Balance; + /// Returns the allowance for a `spender` approved by an `owner`. + /// + /// # Parameters + /// - `owner` - The account that owns the tokens. + /// - `spender` - The account that is allowed to spend the tokens. + /// + /// Returns `0` if no allowance has been set. #[ink(message)] fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; + /// Transfers `value` amount of tokens from the caller's account to account `to` + /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// - `data` - Additional data in unspecified format. + /// + /// # Events + /// On success a `Transfer` event is emitted. + /// + /// No-op if the caller and `to` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. #[ink(message)] fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; + /// Transfers `value` tokens on behalf of `from` to the account `to` + /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `from` - The account from which the token balance will be withdrawn. + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// + /// If `from` and the caller are different addresses, the caller must be allowed + /// by `from` to spend at least `value` tokens. + /// + /// # Events + /// On success a `Transfer` event is emitted. + /// + /// No-op if `from` and `to` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// If `from` and the caller are different addresses, a successful transfer results + /// in decreased allowance by `from` to the caller and an `Approval` event with + /// the new allowance amount is emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account `from`. + /// + /// Reverts with `InsufficientAllowance` if `from` and the caller are different addresses and + /// the `value` exceeds the allowance granted by `from` to the caller. + /// + /// If conditions for both `InsufficientBalance` and `InsufficientAllowance` errors are met, + /// reverts with `InsufficientAllowance`. #[ink(message)] fn transfer_from( &mut self, @@ -448,18 +507,57 @@ pub mod interfaces { data: Vec, ) -> Result<()>; + /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. + /// + /// Successive calls of this method overwrite previous values. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to approve. + /// + /// # Events + /// An `Approval` event is emitted. + /// + /// No-op if the caller and `spender` is the same address, returns success and no events are emitted. #[ink(message)] fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; + /// Increases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to increase the allowance by. + /// + /// # Events + /// An `Approval` event with the new allowance amount is emitted. + /// + /// No-op if the caller and `spender` is the same address or `value` is zero, returns success + /// and no events are emitted. #[ink(message)] fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + /// Decreases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to decrease the allowance by. + /// + /// # Events + /// An `Approval` event with the new allowance amount is emitted. + /// + /// No-op if the caller and `spender` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and + /// the `value` exceeds the allowance granted by the caller to `spender`. #[ink(message)] fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; } + /// The PSP22 Metadata trait. #[ink::trait_definition] - pub trait Psp2ManagableImpl { + pub trait Psp22Managable { #[ink(message)] fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; @@ -482,26 +580,59 @@ pub mod interfaces { fn token_exists(&self, token: TokenId) -> Result; } + /// The PSP22 Metadata trait. #[ink::trait_definition] - pub trait Psp22MetadataImpl { + pub trait Psp22Metadata { + /// Returns the token name. #[ink(message)] fn token_name(&self) -> Option>; + /// Returns the token symbol. #[ink(message)] fn token_symbol(&self) -> Option>; + /// Returns the token decimals. #[ink(message)] - fn token_decimals(&self, id: TokenId) -> u8; + fn token_decimals(&self) -> u8; } + /// The PSP22 Mintable trait. #[ink::trait_definition] - pub trait Psp22MintableImpl { + pub trait Psp22Mintable { + /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. + /// + /// # Parameters + /// - `account` - The account to be credited with the created tokens. + /// - `value` - The number of tokens to mint. + /// + /// # Events + /// On success a `Transfer` event is emitted with `None` sender. + /// + /// No-op if `value` is zero, returns success and no events are emitted. + /// + /// # Errors + /// Reverts with `Custom (max supply exceeded)` if the total supply increased by + /// `value` exceeds maximal value of `u128` type. #[ink(message)] fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; } + /// The PSP22 Burnable trait. #[ink::trait_definition] - pub trait Psp22BurnableImpl { + pub trait Psp22Burnable { + /// Destroys `value` amount of tokens from `account`, reducing the total supply. + /// + /// # Parameters + /// - `account` - The account from which the tokens will be destroyed. + /// - `value` - The number of tokens to destroy. + /// + /// # Events + /// On success a `Transfer` event is emitted with `None` recipient. + /// + /// No-op if `value` is zero, returns success and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. #[ink(message)] fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; } From bf4062d6d4e4b97165ecb134259cb00d8698aebd Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:30:18 +0800 Subject: [PATCH 071/161] refactor: separate modules into files --- pop-api/src/v0/fungibles.rs | 806 ------------------------- pop-api/src/v0/fungibles/errors.rs | 63 ++ pop-api/src/v0/fungibles/events.rs | 82 +++ pop-api/src/v0/fungibles/interfaces.rs | 215 +++++++ pop-api/src/v0/fungibles/mod.rs | 343 +++++++++++ pop-api/src/v0/fungibles/tests.rs | 99 +++ 6 files changed, 802 insertions(+), 806 deletions(-) delete mode 100644 pop-api/src/v0/fungibles.rs create mode 100644 pop-api/src/v0/fungibles/errors.rs create mode 100644 pop-api/src/v0/fungibles/events.rs create mode 100644 pop-api/src/v0/fungibles/interfaces.rs create mode 100644 pop-api/src/v0/fungibles/mod.rs create mode 100644 pop-api/src/v0/fungibles/tests.rs diff --git a/pop-api/src/v0/fungibles.rs b/pop-api/src/v0/fungibles.rs deleted file mode 100644 index 096017c6..00000000 --- a/pop-api/src/v0/fungibles.rs +++ /dev/null @@ -1,806 +0,0 @@ -//! The `fungibles` module provides an API for interacting and managing fungible tokens. -//! -//! The API includes the following interfaces: -//! 1. PSP-22 -//! 2. PSP-22 Metadata -//! 3. Management -//! 4. PSP-22 Mintable & Burnable - -use constants::*; -use ink::prelude::vec::Vec; -pub use management::*; -pub use metadata::*; - -use crate::{ - constants::{ASSETS, BALANCES, FUNGIBLES}, - primitives::{AccountId, Balance, TokenId}, - ChainExtensionMethodApi, Result, StatusCode, -}; - -// Helper method to build a dispatch call. -// -// Parameters: -// - 'dispatchable': The index of the dispatchable function within the module. -fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { - crate::v0::build_dispatch(FUNGIBLES, dispatchable) -} - -// Helper method to build a call to read state. -// -// Parameters: -// - 'state_query': The index of the runtime state query. -fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { - crate::v0::build_read_state(FUNGIBLES, state_query) -} - -mod constants { - /// 1. PSP-22 Interface: - pub(super) const TOTAL_SUPPLY: u8 = 0; - pub(super) const BALANCE_OF: u8 = 1; - pub(super) const ALLOWANCE: u8 = 2; - pub(super) const TRANSFER: u8 = 3; - pub(super) const TRANSFER_FROM: u8 = 4; - pub(super) const APPROVE: u8 = 5; - pub(super) const INCREASE_ALLOWANCE: u8 = 6; - pub(super) const DECREASE_ALLOWANCE: u8 = 7; - - /// 2. PSP-22 Metadata Interface: - pub(super) const TOKEN_NAME: u8 = 8; - pub(super) const TOKEN_SYMBOL: u8 = 9; - pub(super) const TOKEN_DECIMALS: u8 = 10; - - /// 3. Asset Management: - pub(super) const CREATE: u8 = 11; - pub(super) const START_DESTROY: u8 = 12; - pub(super) const SET_METADATA: u8 = 16; - pub(super) const CLEAR_METADATA: u8 = 17; - pub(super) const TOKEN_EXISTS: u8 = 18; - - /// 4. PSP-22 Mintable & Burnable interface: - pub(super) const MINT: u8 = 19; - pub(super) const BURN: u8 = 20; -} - -/// A set of events for use in smart contracts interacting with the fungibles API. -/// -/// The `Transfer` and `Approval` events conform to the PSP-22 standard. The other events -/// (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. -/// -/// These events are not emitted by the API itself but can be used in your contracts to -/// track token operations. Be mindful of the costs associated with emitting events. -/// -/// For more details, refer to [ink! events](https://use.ink/basics/events). -pub mod events { - use super::*; - - /// Event emitted when allowance by `owner` to `spender` changes. - #[ink::event] - pub struct Approval { - /// The owner providing the allowance. - #[ink(topic)] - pub owner: AccountId, - /// The beneficiary of the allowance. - #[ink(topic)] - pub spender: AccountId, - /// The new allowance amount. - pub value: u128, - } - - /// Event emitted when transfer of tokens occurs. - #[ink::event] - pub struct Transfer { - /// The source of the transfer. `None` when minting. - #[ink(topic)] - pub from: Option, - /// The recipient of the transfer. `None` when burning. - #[ink(topic)] - pub to: Option, - /// The amount transferred (or minted/burned). - pub value: u128, - } - - /// Event emitted when a token is created. - #[ink::event] - pub struct Created { - /// The token identifier. - #[ink(topic)] - pub id: TokenId, - /// The creator of the token. - #[ink(topic)] - pub creator: AccountId, - /// The administrator of the token. - #[ink(topic)] - pub admin: AccountId, - } - - /// Event emitted when a token is in the process of being destroyed. - #[ink::event] - pub struct DestroyStarted { - /// The token. - #[ink(topic)] - pub token: TokenId, - } - - /// Event emitted when new metadata is set for a token. - #[ink::event] - pub struct MetadataSet { - /// The token. - #[ink(topic)] - pub token: TokenId, - /// The name of the token. - #[ink(topic)] - pub name: Vec, - /// The symbol of the token. - #[ink(topic)] - pub symbol: Vec, - /// The decimals of the token. - pub decimals: u8, - } - - /// Event emitted when metadata is cleared for a token. - #[ink::event] - pub struct MetadataCleared { - /// The token. - #[ink(topic)] - pub token: TokenId, - } -} - -/// Returns the total token supply for a specified token. -/// -/// # Parameters -/// - `token` - The token. -#[inline] -pub fn total_supply(token: TokenId) -> Result { - build_read_state(TOTAL_SUPPLY) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) -} - -/// Returns the account balance for a specified `token` and `owner`. Returns `0` if -/// the account is non-existent. -/// -/// # Parameters -/// - `token` - The token. -/// - `owner` - The account whose balance is being queried. -#[inline] -pub fn balance_of(token: TokenId, owner: AccountId) -> Result { - build_read_state(BALANCE_OF) - .input::<(TokenId, AccountId)>() - .output::, true>() - .handle_error_code::() - .call(&(token, owner)) -} - -/// Returns the allowance for a `spender` approved by an `owner`, for a specified `token`. Returns -/// `0` if no allowance has been set. -/// -/// # Parameters -/// - `token` - The token. -/// - `owner` - The account that owns the tokens. -/// - `spender` - The account that is allowed to spend the tokens. -#[inline] -pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result { - build_read_state(ALLOWANCE) - .input::<(TokenId, AccountId, AccountId)>() - .output::, true>() - .handle_error_code::() - .call(&(token, owner, spender)) -} - -/// Transfers `value` amount of tokens from the caller's account to account `to`. -/// -/// # Parameters -/// - `token` - The token to transfer. -/// - `to` - The recipient account. -/// - `value` - The number of tokens to transfer. -#[inline] -pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { - build_dispatch(TRANSFER) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, to, value)) -} - -/// Transfers `value` amount tokens on behalf of `from` to account `to`. -/// -/// # Parameters -/// - `token` - The token to transfer. -/// - `from` - The account from which the token balance will be withdrawn. -/// - `to` - The recipient account. -/// - `value` - The number of tokens to transfer. -#[inline] -pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { - build_dispatch(TRANSFER_FROM) - .input::<(TokenId, AccountId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, from, to, value)) -} - -/// Approves `spender` to spend `value` amount of tokens on behalf of the caller. -/// -/// # Parameters -/// - `token` - The token to approve. -/// - `spender` - The account that is allowed to spend the tokens. -/// - `value` - The number of tokens to approve. -#[inline] -pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { - build_dispatch(APPROVE) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, spender, value)) -} - -/// Increases the allowance of `spender` by `value` amount of tokens. -/// -/// # Parameters -/// - `token` - The token to have an allowance increased. -/// - `spender` - The account that is allowed to spend the tokens. -/// - `value` - The number of tokens to increase the allowance by. -#[inline] -pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { - build_dispatch(INCREASE_ALLOWANCE) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, spender, value)) -} - -/// Decreases the allowance of `spender` by `value` amount of tokens. -/// -/// # Parameters -/// - `token` - The token to have an allowance decreased. -/// - `spender` - The account that is allowed to spend the tokens. -/// - `value` - The number of tokens to decrease the allowance by. -#[inline] -pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { - build_dispatch(DECREASE_ALLOWANCE) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, spender, value)) -} - -/// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. -/// -/// # Parameters -/// - `token` - The token to mint. -/// - `account` - The account to be credited with the created tokens. -/// - `value` - The number of tokens to mint. -#[inline] -pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { - build_dispatch(MINT) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, account, value)) -} - -/// Destroys `value` amount of tokens from `account`, reducing the total supply. -/// -/// # Parameters -/// - `token` - the token to burn. -/// - `account` - The account from which the tokens will be destroyed. -/// - `value` - The number of tokens to destroy. -#[inline] -pub fn burn(token: TokenId, account: AccountId, value: Balance) -> Result<()> { - build_dispatch(BURN) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, account, value)) -} - -/// The PSP-22 compliant interface for querying metadata. -pub mod metadata { - use super::*; - - /// Returns the name of the specified token. - /// - /// # Parameters - /// - `token` - The token. - #[inline] - pub fn token_name(token: TokenId) -> Result> { - build_read_state(TOKEN_NAME) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(token)) - } - - /// Returns the symbol for the specified token. - /// - /// # Parameters - /// - `token` - The token. - #[inline] - pub fn token_symbol(token: TokenId) -> Result> { - build_read_state(TOKEN_SYMBOL) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(token)) - } - - /// Returns the decimals for the specified token. - /// - /// # Parameters - /// - `token` - The token. - #[inline] - pub fn token_decimals(token: TokenId) -> Result { - build_read_state(TOKEN_DECIMALS) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) - } -} - -/// The interface for creating, managing and destroying fungible tokens. -pub mod management { - use super::*; - - /// Create a new token with a given identifier. - /// - /// # Parameters - /// - `id` - The identifier of the token. - /// - `admin` - The account that will administer the token. - /// - `min_balance` - The minimum balance required for accounts holding this token. - #[inline] - pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()> { - build_dispatch(CREATE) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, admin, min_balance)) - } - - /// Start the process of destroying a token. - /// - /// # Parameters - /// - `token` - The token to be destroyed. - #[inline] - pub fn start_destroy(token: TokenId) -> Result<()> { - build_dispatch(START_DESTROY) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) - } - - /// Set the metadata for a token. - /// - /// # Parameters - /// - `token`: The token to update. - /// - `name`: The user friendly name of this token. - /// - `symbol`: The exchange symbol for this token. - /// - `decimals`: The number of decimals this token uses to represent one unit. - #[inline] - pub fn set_metadata( - token: TokenId, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> Result<()> { - build_dispatch(SET_METADATA) - .input::<(TokenId, Vec, Vec, u8)>() - .output::, true>() - .handle_error_code::() - .call(&(token, name, symbol, decimals)) - } - - /// Clear the metadata for a token. - /// - /// # Parameters - /// - `token` - The token to update - #[inline] - pub fn clear_metadata(token: TokenId) -> Result<()> { - build_dispatch(CLEAR_METADATA) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) - } - - /// Checks if a specified token exists. - /// - /// # Parameters - /// - `token` - The token. - #[inline] - pub fn token_exists(token: TokenId) -> Result { - build_read_state(TOKEN_EXISTS) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) - } -} - -pub mod interfaces { - use super::*; - - pub type Result = core::result::Result; - - #[ink::trait_definition] - pub trait Psp22 { - /// Returns the total token supply. - #[ink(message)] - fn total_supply(&self) -> Balance; - - /// Returns the account balance for the specified `owner`. - /// - /// # Parameters - /// - `owner` - The account whose balance is being queried. - /// - /// Returns `0` if the account is non-existent. - #[ink(message)] - fn balance_of(&self, owner: AccountId) -> Balance; - - /// Returns the allowance for a `spender` approved by an `owner`. - /// - /// # Parameters - /// - `owner` - The account that owns the tokens. - /// - `spender` - The account that is allowed to spend the tokens. - /// - /// Returns `0` if no allowance has been set. - #[ink(message)] - fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; - - /// Transfers `value` amount of tokens from the caller's account to account `to` - /// with additional `data` in unspecified format. - /// - /// # Parameters - /// - `to` - The recipient account. - /// - `value` - The number of tokens to transfer. - /// - `data` - Additional data in unspecified format. - /// - /// # Events - /// On success a `Transfer` event is emitted. - /// - /// No-op if the caller and `to` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. - #[ink(message)] - fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; - - /// Transfers `value` tokens on behalf of `from` to the account `to` - /// with additional `data` in unspecified format. - /// - /// # Parameters - /// - `from` - The account from which the token balance will be withdrawn. - /// - `to` - The recipient account. - /// - `value` - The number of tokens to transfer. - /// - /// If `from` and the caller are different addresses, the caller must be allowed - /// by `from` to spend at least `value` tokens. - /// - /// # Events - /// On success a `Transfer` event is emitted. - /// - /// No-op if `from` and `to` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// If `from` and the caller are different addresses, a successful transfer results - /// in decreased allowance by `from` to the caller and an `Approval` event with - /// the new allowance amount is emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account `from`. - /// - /// Reverts with `InsufficientAllowance` if `from` and the caller are different addresses and - /// the `value` exceeds the allowance granted by `from` to the caller. - /// - /// If conditions for both `InsufficientBalance` and `InsufficientAllowance` errors are met, - /// reverts with `InsufficientAllowance`. - #[ink(message)] - fn transfer_from( - &mut self, - from: AccountId, - to: AccountId, - value: Balance, - data: Vec, - ) -> Result<()>; - - /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. - /// - /// Successive calls of this method overwrite previous values. - /// - /// # Parameters - /// - `spender` - The account that is allowed to spend the tokens. - /// - `value` - The number of tokens to approve. - /// - /// # Events - /// An `Approval` event is emitted. - /// - /// No-op if the caller and `spender` is the same address, returns success and no events are emitted. - #[ink(message)] - fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; - - /// Increases the allowance of `spender` by `value` amount of tokens. - /// - /// # Parameters - /// - `spender` - The account that is allowed to spend the tokens. - /// - `value` - The number of tokens to increase the allowance by. - /// - /// # Events - /// An `Approval` event with the new allowance amount is emitted. - /// - /// No-op if the caller and `spender` is the same address or `value` is zero, returns success - /// and no events are emitted. - #[ink(message)] - fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; - - /// Decreases the allowance of `spender` by `value` amount of tokens. - /// - /// # Parameters - /// - `spender` - The account that is allowed to spend the tokens. - /// - `value` - The number of tokens to decrease the allowance by. - /// - /// # Events - /// An `Approval` event with the new allowance amount is emitted. - /// - /// No-op if the caller and `spender` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and - /// the `value` exceeds the allowance granted by the caller to `spender`. - #[ink(message)] - fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; - } - - /// The PSP22 Metadata trait. - #[ink::trait_definition] - pub trait Psp22Managable { - #[ink(message)] - fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; - - #[ink(message)] - fn start_destroy(&mut self, token: TokenId) -> Result<()>; - - #[ink(message)] - fn set_metadata( - &mut self, - token: TokenId, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> Result<()>; - - #[ink(message)] - fn clear_metadata(&mut self, token: TokenId) -> Result<()>; - - #[ink(message)] - fn token_exists(&self, token: TokenId) -> Result; - } - - /// The PSP22 Metadata trait. - #[ink::trait_definition] - pub trait Psp22Metadata { - /// Returns the token name. - #[ink(message)] - fn token_name(&self) -> Option>; - - /// Returns the token symbol. - #[ink(message)] - fn token_symbol(&self) -> Option>; - - /// Returns the token decimals. - #[ink(message)] - fn token_decimals(&self) -> u8; - } - - /// The PSP22 Mintable trait. - #[ink::trait_definition] - pub trait Psp22Mintable { - /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. - /// - /// # Parameters - /// - `account` - The account to be credited with the created tokens. - /// - `value` - The number of tokens to mint. - /// - /// # Events - /// On success a `Transfer` event is emitted with `None` sender. - /// - /// No-op if `value` is zero, returns success and no events are emitted. - /// - /// # Errors - /// Reverts with `Custom (max supply exceeded)` if the total supply increased by - /// `value` exceeds maximal value of `u128` type. - #[ink(message)] - fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; - } - - /// The PSP22 Burnable trait. - #[ink::trait_definition] - pub trait Psp22Burnable { - /// Destroys `value` amount of tokens from `account`, reducing the total supply. - /// - /// # Parameters - /// - `account` - The account from which the tokens will be destroyed. - /// - `value` - The number of tokens to destroy. - /// - /// # Events - /// On success a `Transfer` event is emitted with `None` recipient. - /// - /// No-op if `value` is zero, returns success and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. - #[ink(message)] - fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; - } -} - -/// Represents various errors related to fungible tokens. -/// -/// The `FungiblesError` provides a detailed and specific set of error types that can occur when -/// interacting with fungible tokens. Each variant signifies a particular error -/// condition, facilitating precise error handling and debugging. -/// -/// It is designed to be lightweight, including only the essential errors relevant to fungible token -/// operations. The `Other` variant serves as a catch-all for any unexpected errors. For more -/// detailed debugging, the `Other` variant can be converted into the richer `Error` type defined in -/// the primitives crate. -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub enum FungiblesError { - /// An unspecified or unknown error occurred. - Other(StatusCode), - /// The token is not live; either frozen or being destroyed. - NotLive, - /// Not enough allowance to fulfill a request is available. - InsufficientAllowance, - /// Not enough balance to fulfill a request is available. - InsufficientBalance, - /// The token ID is already taken. - InUse, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// The account to alter does not exist. - NoAccount, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given token ID is unknown. - Unknown, - /// No balance for creation of tokens or fees. - // TODO: Originally `pallet_balances::Error::InsufficientBalance` but collides with the - // `InsufficientBalance` error that is used for `pallet_assets::Error::BalanceLow` to adhere - // to the standard. This deserves a second look. - NoBalance, -} - -impl From for FungiblesError { - /// Converts a `StatusCode` to a `FungiblesError`. - /// - /// This conversion maps a `StatusCode`, returned by the runtime, to a more descriptive - /// `FungiblesError`. This provides better context and understanding of the error, allowing - /// developers to handle the most important errors effectively. - fn from(value: StatusCode) -> Self { - let encoded = value.0.to_le_bytes(); - match encoded { - // Balances. - [_, BALANCES, 2, _] => FungiblesError::NoBalance, - // Assets. - [_, ASSETS, 0, _] => FungiblesError::NoAccount, - [_, ASSETS, 1, _] => FungiblesError::NoPermission, - [_, ASSETS, 2, _] => FungiblesError::Unknown, - [_, ASSETS, 3, _] => FungiblesError::InUse, - [_, ASSETS, 5, _] => FungiblesError::MinBalanceZero, - [_, ASSETS, 7, _] => FungiblesError::InsufficientAllowance, - [_, ASSETS, 10, _] => FungiblesError::NotLive, - _ => FungiblesError::Other(value), - } - } -} - -#[cfg(test)] -mod tests { - use ink::scale::{Decode, Encode}; - - use super::FungiblesError; - use crate::{ - constants::{ASSETS, BALANCES}, - primitives::{ - ArithmeticError::*, - Error::{self, *}, - TokenError::*, - TransactionalError::*, - }, - StatusCode, - }; - - fn error_into_status_code(error: Error) -> StatusCode { - let mut encoded_error = error.encode(); - encoded_error.resize(4, 0); - let value = u32::from_le_bytes( - encoded_error.try_into().expect("qed, resized to 4 bytes line above"), - ); - value.into() - } - - fn into_fungibles_error(error: Error) -> FungiblesError { - let status_code: StatusCode = error_into_status_code(error); - status_code.into() - } - - // If we ever want to change the conversion from bytes to `u32`. - #[test] - fn status_code_vs_encoded() { - assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 0, 0][..]).unwrap(), 13315u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 1, 0][..]).unwrap(), 78851u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 2, 0][..]).unwrap(), 144387u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 3, 0][..]).unwrap(), 209923u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 5, 0][..]).unwrap(), 340995u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 7, 0][..]).unwrap(), 472067u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 10, 0][..]).unwrap(), 668675u32); - } - - #[test] - fn converting_status_code_into_fungibles_error_works() { - let other_errors = vec![ - Other, - CannotLookup, - BadOrigin, - // `ModuleError` other than assets module. - Module { index: 2, error: [5, 0] }, - ConsumerRemaining, - NoProviders, - TooManyConsumers, - Token(OnlyProvider), - Arithmetic(Overflow), - Transactional(NoLayer), - Exhausted, - Corruption, - Unavailable, - RootNotAllowed, - Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, - DecodingFailed, - ]; - for error in other_errors { - let status_code: StatusCode = error_into_status_code(error); - let fungibles_error: FungiblesError = status_code.into(); - assert_eq!(fungibles_error, FungiblesError::Other(status_code)) - } - - assert_eq!( - into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), - FungiblesError::NoBalance - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), - FungiblesError::NoAccount - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), - FungiblesError::NoPermission - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), - FungiblesError::Unknown - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), - FungiblesError::InUse - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), - FungiblesError::MinBalanceZero - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), - FungiblesError::InsufficientAllowance - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), - FungiblesError::NotLive - ); - } -} diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs new file mode 100644 index 00000000..b29127e5 --- /dev/null +++ b/pop-api/src/v0/fungibles/errors.rs @@ -0,0 +1,63 @@ +use super::*; + +/// Represents various errors related to fungible tokens. +/// +/// The `FungiblesError` provides a detailed and specific set of error types that can occur when +/// interacting with fungible tokens. Each variant signifies a particular error +/// condition, facilitating precise error handling and debugging. +/// +/// It is designed to be lightweight, including only the essential errors relevant to fungible token +/// operations. The `Other` variant serves as a catch-all for any unexpected errors. For more +/// detailed debugging, the `Other` variant can be converted into the richer `Error` type defined in +/// the primitives crate. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum FungiblesError { + /// An unspecified or unknown error occurred. + Other(StatusCode), + /// The token is not live; either frozen or being destroyed. + NotLive, + /// Not enough allowance to fulfill a request is available. + InsufficientAllowance, + /// Not enough balance to fulfill a request is available. + InsufficientBalance, + /// The token ID is already taken. + InUse, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// The account to alter does not exist. + NoAccount, + /// The signing account has no permission to do the operation. + NoPermission, + /// The given token ID is unknown. + Unknown, + /// No balance for creation of tokens or fees. + // TODO: Originally `pallet_balances::Error::InsufficientBalance` but collides with the + // `InsufficientBalance` error that is used for `pallet_assets::Error::BalanceLow` to adhere + // to the standard. This deserves a second look. + NoBalance, +} + +impl From for FungiblesError { + /// Converts a `StatusCode` to a `FungiblesError`. + /// + /// This conversion maps a `StatusCode`, returned by the runtime, to a more descriptive + /// `FungiblesError`. This provides better context and understanding of the error, allowing + /// developers to handle the most important errors effectively. + fn from(value: StatusCode) -> Self { + let encoded = value.0.to_le_bytes(); + match encoded { + // Balances. + [_, BALANCES, 2, _] => FungiblesError::NoBalance, + // Assets. + [_, ASSETS, 0, _] => FungiblesError::NoAccount, + [_, ASSETS, 1, _] => FungiblesError::NoPermission, + [_, ASSETS, 2, _] => FungiblesError::Unknown, + [_, ASSETS, 3, _] => FungiblesError::InUse, + [_, ASSETS, 5, _] => FungiblesError::MinBalanceZero, + [_, ASSETS, 7, _] => FungiblesError::InsufficientAllowance, + [_, ASSETS, 10, _] => FungiblesError::NotLive, + _ => FungiblesError::Other(value), + } + } +} diff --git a/pop-api/src/v0/fungibles/events.rs b/pop-api/src/v0/fungibles/events.rs new file mode 100644 index 00000000..b0639e10 --- /dev/null +++ b/pop-api/src/v0/fungibles/events.rs @@ -0,0 +1,82 @@ +/// A set of events for use in smart contracts interacting with the fungibles API. +/// +/// The `Transfer` and `Approval` events conform to the PSP-22 standard. The other events +/// (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. +/// +/// These events are not emitted by the API itself but can be used in your contracts to +/// track token operations. Be mindful of the costs associated with emitting events. +/// +/// For more details, refer to [ink! events](https://use.ink/basics/events). +use super::*; + +/// Event emitted when allowance by `owner` to `spender` changes. +#[ink::event] +pub struct Approval { + /// The owner providing the allowance. + #[ink(topic)] + pub owner: AccountId, + /// The beneficiary of the allowance. + #[ink(topic)] + pub spender: AccountId, + /// The new allowance amount. + pub value: u128, +} + +/// Event emitted when transfer of tokens occurs. +#[ink::event] +pub struct Transfer { + /// The source of the transfer. `None` when minting. + #[ink(topic)] + pub from: Option, + /// The recipient of the transfer. `None` when burning. + #[ink(topic)] + pub to: Option, + /// The amount transferred (or minted/burned). + pub value: u128, +} + +/// Event emitted when a token is created. +#[ink::event] +pub struct Created { + /// The token identifier. + #[ink(topic)] + pub id: TokenId, + /// The creator of the token. + #[ink(topic)] + pub creator: AccountId, + /// The administrator of the token. + #[ink(topic)] + pub admin: AccountId, +} + +/// Event emitted when a token is in the process of being destroyed. +#[ink::event] +pub struct DestroyStarted { + /// The token. + #[ink(topic)] + pub token: TokenId, +} + +/// Event emitted when new metadata is set for a token. +#[ink::event] +pub struct MetadataSet { + /// The token. + #[ink(topic)] + pub token: TokenId, + /// The name of the token. + #[ink(topic)] + pub name: Vec, + /// The symbol of the token. + #[ink(topic)] + pub symbol: Vec, + /// The decimals of the token. + pub decimals: u8, +} + +/// Event emitted when metadata is cleared for a token. +#[ink::event] +pub struct MetadataCleared { + /// The token. + #[ink(topic)] + pub token: TokenId, +} diff --git a/pop-api/src/v0/fungibles/interfaces.rs b/pop-api/src/v0/fungibles/interfaces.rs new file mode 100644 index 00000000..6023ce37 --- /dev/null +++ b/pop-api/src/v0/fungibles/interfaces.rs @@ -0,0 +1,215 @@ +use super::*; + +pub type Result = core::result::Result; + +#[ink::trait_definition] +pub trait Psp22 { + /// Returns the total token supply. + #[ink(message)] + fn total_supply(&self) -> Balance; + + /// Returns the account balance for the specified `owner`. + /// + /// # Parameters + /// - `owner` - The account whose balance is being queried. + /// + /// Returns `0` if the account is non-existent. + #[ink(message)] + fn balance_of(&self, owner: AccountId) -> Balance; + + /// Returns the allowance for a `spender` approved by an `owner`. + /// + /// # Parameters + /// - `owner` - The account that owns the tokens. + /// - `spender` - The account that is allowed to spend the tokens. + /// + /// Returns `0` if no allowance has been set. + #[ink(message)] + fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; + + /// Transfers `value` amount of tokens from the caller's account to account `to` + /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// - `data` - Additional data in unspecified format. + /// + /// # Events + /// On success a `Transfer` event is emitted. + /// + /// No-op if the caller and `to` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. + #[ink(message)] + fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; + + /// Transfers `value` tokens on behalf of `from` to the account `to` + /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `from` - The account from which the token balance will be withdrawn. + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// + /// If `from` and the caller are different addresses, the caller must be allowed + /// by `from` to spend at least `value` tokens. + /// + /// # Events + /// On success a `Transfer` event is emitted. + /// + /// No-op if `from` and `to` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// If `from` and the caller are different addresses, a successful transfer results + /// in decreased allowance by `from` to the caller and an `Approval` event with + /// the new allowance amount is emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account `from`. + /// + /// Reverts with `InsufficientAllowance` if `from` and the caller are different addresses and + /// the `value` exceeds the allowance granted by `from` to the caller. + /// + /// If conditions for both `InsufficientBalance` and `InsufficientAllowance` errors are met, + /// reverts with `InsufficientAllowance`. + #[ink(message)] + fn transfer_from( + &mut self, + from: AccountId, + to: AccountId, + value: Balance, + data: Vec, + ) -> Result<()>; + + /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. + /// + /// Successive calls of this method overwrite previous values. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to approve. + /// + /// # Events + /// An `Approval` event is emitted. + /// + /// No-op if the caller and `spender` is the same address, returns success and no events are emitted. + #[ink(message)] + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; + + /// Increases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to increase the allowance by. + /// + /// # Events + /// An `Approval` event with the new allowance amount is emitted. + /// + /// No-op if the caller and `spender` is the same address or `value` is zero, returns success + /// and no events are emitted. + #[ink(message)] + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + + /// Decreases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to decrease the allowance by. + /// + /// # Events + /// An `Approval` event with the new allowance amount is emitted. + /// + /// No-op if the caller and `spender` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and + /// the `value` exceeds the allowance granted by the caller to `spender`. + #[ink(message)] + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; +} + +/// The PSP22 Metadata trait. +#[ink::trait_definition] +pub trait Psp22Managable { + #[ink(message)] + fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; + + #[ink(message)] + fn start_destroy(&mut self, token: TokenId) -> Result<()>; + + #[ink(message)] + fn set_metadata( + &mut self, + token: TokenId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()>; + + #[ink(message)] + fn clear_metadata(&mut self, token: TokenId) -> Result<()>; + + #[ink(message)] + fn token_exists(&self, token: TokenId) -> Result; +} + +/// The PSP22 Metadata trait. +#[ink::trait_definition] +pub trait Psp22Metadata { + /// Returns the token name. + #[ink(message)] + fn token_name(&self) -> Option>; + + /// Returns the token symbol. + #[ink(message)] + fn token_symbol(&self) -> Option>; + + /// Returns the token decimals. + #[ink(message)] + fn token_decimals(&self) -> u8; +} + +/// The PSP22 Mintable trait. +#[ink::trait_definition] +pub trait Psp22Mintable { + /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. + /// + /// # Parameters + /// - `account` - The account to be credited with the created tokens. + /// - `value` - The number of tokens to mint. + /// + /// # Events + /// On success a `Transfer` event is emitted with `None` sender. + /// + /// No-op if `value` is zero, returns success and no events are emitted. + /// + /// # Errors + /// Reverts with `Custom (max supply exceeded)` if the total supply increased by + /// `value` exceeds maximal value of `u128` type. + #[ink(message)] + fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; +} + +/// The PSP22 Burnable trait. +#[ink::trait_definition] +pub trait Psp22Burnable { + /// Destroys `value` amount of tokens from `account`, reducing the total supply. + /// + /// # Parameters + /// - `account` - The account from which the tokens will be destroyed. + /// - `value` - The number of tokens to destroy. + /// + /// # Events + /// On success a `Transfer` event is emitted with `None` recipient. + /// + /// No-op if `value` is zero, returns success and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. + #[ink(message)] + fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; +} diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs new file mode 100644 index 00000000..e8d4e81d --- /dev/null +++ b/pop-api/src/v0/fungibles/mod.rs @@ -0,0 +1,343 @@ +//! The `fungibles` module provides an API for interacting and managing fungible tokens. +//! +//! The API includes the following interfaces: +//! 1. PSP-22 +//! 2. PSP-22 Metadata +//! 3. Management +//! 4. PSP-22 Mintable & Burnable +pub mod errors; +pub mod events; +pub mod interfaces; +#[cfg(test)] +mod tests; + +use crate::{ + constants::{ASSETS, BALANCES, FUNGIBLES}, + primitives::{AccountId, Balance, TokenId}, + ChainExtensionMethodApi, StatusCode, +}; +use constants::*; +pub use errors::*; +pub use events::*; +use ink::prelude::vec::Vec; +pub use interfaces::*; +pub use management::*; +pub use metadata::*; + +// Helper method to build a dispatch call. +// +// Parameters: +// - 'dispatchable': The index of the dispatchable function within the module. +fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { + crate::v0::build_dispatch(FUNGIBLES, dispatchable) +} + +// Helper method to build a call to read state. +// +// Parameters: +// - 'state_query': The index of the runtime state query. +fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { + crate::v0::build_read_state(FUNGIBLES, state_query) +} + +mod constants { + /// 1. PSP-22 Interface: + pub(super) const TOTAL_SUPPLY: u8 = 0; + pub(super) const BALANCE_OF: u8 = 1; + pub(super) const ALLOWANCE: u8 = 2; + pub(super) const TRANSFER: u8 = 3; + pub(super) const TRANSFER_FROM: u8 = 4; + pub(super) const APPROVE: u8 = 5; + pub(super) const INCREASE_ALLOWANCE: u8 = 6; + pub(super) const DECREASE_ALLOWANCE: u8 = 7; + + /// 2. PSP-22 Metadata Interface: + pub(super) const TOKEN_NAME: u8 = 8; + pub(super) const TOKEN_SYMBOL: u8 = 9; + pub(super) const TOKEN_DECIMALS: u8 = 10; + + /// 3. Asset Management: + pub(super) const CREATE: u8 = 11; + pub(super) const START_DESTROY: u8 = 12; + pub(super) const SET_METADATA: u8 = 16; + pub(super) const CLEAR_METADATA: u8 = 17; + pub(super) const TOKEN_EXISTS: u8 = 18; + + /// 4. PSP-22 Mintable & Burnable interface: + pub(super) const MINT: u8 = 19; + pub(super) const BURN: u8 = 20; +} + +/// Returns the total token supply for a specified token. +/// +/// # Parameters +/// - `token` - The token. +#[inline] +pub fn total_supply(token: TokenId) -> Result { + build_read_state(TOTAL_SUPPLY) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) +} + +/// Returns the account balance for a specified `token` and `owner`. Returns `0` if +/// the account is non-existent. +/// +/// # Parameters +/// - `token` - The token. +/// - `owner` - The account whose balance is being queried. +#[inline] +pub fn balance_of(token: TokenId, owner: AccountId) -> Result { + build_read_state(BALANCE_OF) + .input::<(TokenId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(token, owner)) +} + +/// Returns the allowance for a `spender` approved by an `owner`, for a specified `token`. Returns +/// `0` if no allowance has been set. +/// +/// # Parameters +/// - `token` - The token. +/// - `owner` - The account that owns the tokens. +/// - `spender` - The account that is allowed to spend the tokens. +#[inline] +pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result { + build_read_state(ALLOWANCE) + .input::<(TokenId, AccountId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(token, owner, spender)) +} + +/// Transfers `value` amount of tokens from the caller's account to account `to`. +/// +/// # Parameters +/// - `token` - The token to transfer. +/// - `to` - The recipient account. +/// - `value` - The number of tokens to transfer. +#[inline] +pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { + build_dispatch(TRANSFER) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, to, value)) +} + +/// Transfers `value` amount tokens on behalf of `from` to account `to`. +/// +/// # Parameters +/// - `token` - The token to transfer. +/// - `from` - The account from which the token balance will be withdrawn. +/// - `to` - The recipient account. +/// - `value` - The number of tokens to transfer. +#[inline] +pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { + build_dispatch(TRANSFER_FROM) + .input::<(TokenId, AccountId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, from, to, value)) +} + +/// Approves `spender` to spend `value` amount of tokens on behalf of the caller. +/// +/// # Parameters +/// - `token` - The token to approve. +/// - `spender` - The account that is allowed to spend the tokens. +/// - `value` - The number of tokens to approve. +#[inline] +pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { + build_dispatch(APPROVE) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, spender, value)) +} + +/// Increases the allowance of `spender` by `value` amount of tokens. +/// +/// # Parameters +/// - `token` - The token to have an allowance increased. +/// - `spender` - The account that is allowed to spend the tokens. +/// - `value` - The number of tokens to increase the allowance by. +#[inline] +pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { + build_dispatch(INCREASE_ALLOWANCE) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, spender, value)) +} + +/// Decreases the allowance of `spender` by `value` amount of tokens. +/// +/// # Parameters +/// - `token` - The token to have an allowance decreased. +/// - `spender` - The account that is allowed to spend the tokens. +/// - `value` - The number of tokens to decrease the allowance by. +#[inline] +pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { + build_dispatch(DECREASE_ALLOWANCE) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, spender, value)) +} + +/// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. +/// +/// # Parameters +/// - `token` - The token to mint. +/// - `account` - The account to be credited with the created tokens. +/// - `value` - The number of tokens to mint. +#[inline] +pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { + build_dispatch(MINT) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, account, value)) +} + +/// Destroys `value` amount of tokens from `account`, reducing the total supply. +/// +/// # Parameters +/// - `token` - the token to burn. +/// - `account` - The account from which the tokens will be destroyed. +/// - `value` - The number of tokens to destroy. +#[inline] +pub fn burn(token: TokenId, account: AccountId, value: Balance) -> Result<()> { + build_dispatch(BURN) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, account, value)) +} + +/// The PSP-22 compliant interface for querying metadata. +pub mod metadata { + use super::*; + + /// Returns the name of the specified token. + /// + /// # Parameters + /// - `token` - The token. + #[inline] + pub fn token_name(token: TokenId) -> Result> { + build_read_state(TOKEN_NAME) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(token)) + } + + /// Returns the symbol for the specified token. + /// + /// # Parameters + /// - `token` - The token. + #[inline] + pub fn token_symbol(token: TokenId) -> Result> { + build_read_state(TOKEN_SYMBOL) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(token)) + } + + /// Returns the decimals for the specified token. + /// + /// # Parameters + /// - `token` - The token. + #[inline] + pub fn token_decimals(token: TokenId) -> Result { + build_read_state(TOKEN_DECIMALS) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) + } +} + +/// The interface for creating, managing and destroying fungible tokens. +pub mod management { + use super::*; + + /// Create a new token with a given identifier. + /// + /// # Parameters + /// - `id` - The identifier of the token. + /// - `admin` - The account that will administer the token. + /// - `min_balance` - The minimum balance required for accounts holding this token. + #[inline] + pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()> { + build_dispatch(CREATE) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, admin, min_balance)) + } + + /// Start the process of destroying a token. + /// + /// # Parameters + /// - `token` - The token to be destroyed. + #[inline] + pub fn start_destroy(token: TokenId) -> Result<()> { + build_dispatch(START_DESTROY) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) + } + + /// Set the metadata for a token. + /// + /// # Parameters + /// - `token`: The token to update. + /// - `name`: The user friendly name of this token. + /// - `symbol`: The exchange symbol for this token. + /// - `decimals`: The number of decimals this token uses to represent one unit. + #[inline] + pub fn set_metadata( + token: TokenId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()> { + build_dispatch(SET_METADATA) + .input::<(TokenId, Vec, Vec, u8)>() + .output::, true>() + .handle_error_code::() + .call(&(token, name, symbol, decimals)) + } + + /// Clear the metadata for a token. + /// + /// # Parameters + /// - `token` - The token to update + #[inline] + pub fn clear_metadata(token: TokenId) -> Result<()> { + build_dispatch(CLEAR_METADATA) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) + } + + /// Checks if a specified token exists. + /// + /// # Parameters + /// - `token` - The token. + #[inline] + pub fn token_exists(token: TokenId) -> Result { + build_read_state(TOKEN_EXISTS) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) + } +} diff --git a/pop-api/src/v0/fungibles/tests.rs b/pop-api/src/v0/fungibles/tests.rs new file mode 100644 index 00000000..128cf4cb --- /dev/null +++ b/pop-api/src/v0/fungibles/tests.rs @@ -0,0 +1,99 @@ +use super::FungiblesError; +use crate::{ + constants::{ASSETS, BALANCES}, + primitives::{ + ArithmeticError::*, + Error::{self, *}, + TokenError::*, + TransactionalError::*, + }, + StatusCode, +}; +use ink::scale::{Decode, Encode}; + +fn error_into_status_code(error: Error) -> StatusCode { + let mut encoded_error = error.encode(); + encoded_error.resize(4, 0); + let value = + u32::from_le_bytes(encoded_error.try_into().expect("qed, resized to 4 bytes line above")); + value.into() +} + +fn into_fungibles_error(error: Error) -> FungiblesError { + let status_code: StatusCode = error_into_status_code(error); + status_code.into() +} + +// If we ever want to change the conversion from bytes to `u32`. +#[test] +fn status_code_vs_encoded() { + assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 0, 0][..]).unwrap(), 13315u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 1, 0][..]).unwrap(), 78851u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 2, 0][..]).unwrap(), 144387u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 3, 0][..]).unwrap(), 209923u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 5, 0][..]).unwrap(), 340995u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 7, 0][..]).unwrap(), 472067u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 10, 0][..]).unwrap(), 668675u32); +} + +#[test] +fn converting_status_code_into_fungibles_error_works() { + let other_errors = vec![ + Other, + CannotLookup, + BadOrigin, + // `ModuleError` other than assets module. + Module { index: 2, error: [5, 0] }, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Token(OnlyProvider), + Arithmetic(Overflow), + Transactional(NoLayer), + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, + DecodingFailed, + ]; + for error in other_errors { + let status_code: StatusCode = error_into_status_code(error); + let fungibles_error: FungiblesError = status_code.into(); + assert_eq!(fungibles_error, FungiblesError::Other(status_code)) + } + + assert_eq!( + into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), + FungiblesError::NoBalance + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), + FungiblesError::NoAccount + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), + FungiblesError::NoPermission + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), + FungiblesError::Unknown + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), + FungiblesError::InUse + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), + FungiblesError::MinBalanceZero + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), + FungiblesError::InsufficientAllowance + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), + FungiblesError::NotLive + ); +} From 21c6826aa83261a7c1c2a5e6c16c1b9cdee168c2 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:45:48 +0800 Subject: [PATCH 072/161] refactor: fungible example --- pop-api/examples/fungibles/lib.rs | 129 ++++++++++++++++--------- pop-api/src/v0/fungibles/errors.rs | 30 ++++++ pop-api/src/v0/fungibles/interfaces.rs | 99 +++++-------------- 3 files changed, 142 insertions(+), 116 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 11eafe21..c46b302f 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -1,108 +1,151 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::prelude::vec::Vec; +use ink::prelude::{string::String, vec::Vec}; use pop_api::{ - fungibles::{self as api}, primitives::TokenId, + v0::fungibles::{self as api, events::Created, PSP22Error}, StatusCode, }; -pub type Result = core::result::Result; +#[cfg(test)] +mod tests; + +type PSP22Result = core::result::Result; #[ink::contract] mod fungibles { use super::*; #[ink(storage)] - #[derive(Default)] - pub struct Fungibles; + pub struct Fungibles { + id: TokenId, + } impl Fungibles { + /// Instantiate the contract and wrap around an existing token. + /// + /// # Parameters + /// * - `token` - The token. #[ink(constructor, payable)] - pub fn new() -> Self { - Default::default() + pub fn new_existing(id: TokenId) -> PSP22Result { + // Make sure token exists. + if !api::token_exists(id).unwrap_or_default() { + return Err(PSP22Error::Custom(String::from("Unknown"))); + } + let contract = Self { id }; + Ok(contract) } - #[ink(message)] - pub fn total_supply(&self, token: TokenId) -> Result { - api::total_supply(token) + /// Instantiate the contract and create a new token. The token identifier will be stored + /// in contract's storage. + /// + /// # Parameters + /// * - `id` - The identifier of the token. + /// * - `admin` - The account that will administer the token. + /// * - `min_balance` - The minimum balance required for accounts holding this token. + #[ink(constructor, payable)] + pub fn new(id: TokenId, admin: AccountId, min_balance: Balance) -> PSP22Result { + // TODO: should be nicer conversion possible. + api::create(id, admin, min_balance).map_err(|e| PSP22Error::from(e))?; + let contract = Self { id }; + contract + .env() + .emit_event(Created { id, creator: contract.env().account_id(), admin }); + Ok(contract) } #[ink(message)] - pub fn balance_of(&self, token: TokenId, owner: AccountId) -> Result { - api::balance_of(token, owner) + pub fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { + api::mint(self.id, account, amount).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn allowance( - &self, - token: TokenId, - owner: AccountId, - spender: AccountId, - ) -> Result { - api::allowance(token, owner, spender) + pub fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { + api::burn(self.id, account, amount).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> Result<()> { - api::transfer(token, to, value) + pub fn transfer(&mut self, to: AccountId, value: Balance) -> PSP22Result<()> { + api::transfer(self.id, to, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] pub fn transfer_from( &mut self, - token: TokenId, from: AccountId, to: AccountId, value: Balance, _data: Vec, - ) -> Result<()> { - api::transfer_from(token, from, to, value) + ) -> PSP22Result<()> { + api::transfer_from(self.id, from, to, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn approve( - &mut self, - token: TokenId, - spender: AccountId, - value: Balance, - ) -> Result<()> { - api::approve(token, spender, value) + pub fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { + api::approve(self.id, spender, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] pub fn increase_allowance( &mut self, - token: TokenId, spender: AccountId, value: Balance, - ) -> Result<()> { - api::increase_allowance(token, spender, value) + ) -> PSP22Result<()> { + api::increase_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] pub fn decrease_allowance( &mut self, - token: TokenId, spender: AccountId, value: Balance, - ) -> Result<()> { - api::decrease_allowance(token, spender, value) + ) -> PSP22Result<()> { + api::decrease_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) + } + + #[ink(message)] + pub fn set_metadata( + &self, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> PSP22Result<()> { + api::set_metadata(self.id, name, symbol, decimals).map_err(|e| PSP22Error::from(e)) + } + + #[ink(message)] + pub fn total_supply(&self) -> PSP22Result { + api::total_supply(self.id).map_err(|e| PSP22Error::from(e)) + } + + #[ink(message)] + pub fn balance_of(&self, owner: AccountId) -> PSP22Result { + api::balance_of(self.id, owner).map_err(|e| PSP22Error::from(e)) + } + + #[ink(message)] + pub fn allowance(&self, owner: AccountId, spender: AccountId) -> PSP22Result { + api::allowance(self.id, owner, spender).map_err(|e| PSP22Error::from(e)) + } + + #[ink(message)] + pub fn token_name(&self) -> PSP22Result> { + api::token_name(self.id).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn token_name(&self, token: TokenId) -> Result> { - api::token_name(token) + pub fn token_symbol(&self) -> PSP22Result> { + api::token_symbol(self.id).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn token_symbol(&self, token: TokenId) -> Result> { - api::token_symbol(token) + pub fn token_decimals(&self) -> PSP22Result { + api::token_decimals(self.id).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn token_decimals(&self, token: TokenId) -> Result { - api::token_decimals(token) + pub fn token_exists(&self) -> PSP22Result { + api::token_exists(self.id).map_err(|e| PSP22Error::from(e)) } } } diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index b29127e5..872e8d64 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -61,3 +61,33 @@ impl From for FungiblesError { } } } + +/// The PSP22 error. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum PSP22Error { + /// Custom error type for implementation-based errors. + Custom(String), + /// Returned when an account does not have enough tokens to complete the operation. + InsufficientBalance, + /// Returned if there is not enough allowance to complete the operation. + InsufficientAllowance, + /// Returned if recipient's address is zero. + ZeroRecipientAddress, + /// Returned if sender's address is zero. + ZeroSenderAddress, + /// Returned if a safe transfer check failed. + SafeTransferCheckFailed(String), +} + +impl From for PSP22Error { + /// Converts a `StatusCode` to a `PSP22Error`. + fn from(value: StatusCode) -> Self { + let encoded = value.0.to_le_bytes(); + match encoded { + [_, ASSETS, 3, _] => PSP22Error::Custom(String::from("Unknown")), + [_, ASSETS, 7, _] => PSP22Error::InsufficientAllowance, + _ => PSP22Error::Custom(String::from("Other")), + } + } +} diff --git a/pop-api/src/v0/fungibles/interfaces.rs b/pop-api/src/v0/fungibles/interfaces.rs index 6023ce37..5b52504a 100644 --- a/pop-api/src/v0/fungibles/interfaces.rs +++ b/pop-api/src/v0/fungibles/interfaces.rs @@ -12,8 +12,6 @@ pub trait Psp22 { /// /// # Parameters /// - `owner` - The account whose balance is being queried. - /// - /// Returns `0` if the account is non-existent. #[ink(message)] fn balance_of(&self, owner: AccountId) -> Balance; @@ -22,8 +20,6 @@ pub trait Psp22 { /// # Parameters /// - `owner` - The account that owns the tokens. /// - `spender` - The account that is allowed to spend the tokens. - /// - /// Returns `0` if no allowance has been set. #[ink(message)] fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; @@ -34,15 +30,6 @@ pub trait Psp22 { /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. /// - `data` - Additional data in unspecified format. - /// - /// # Events - /// On success a `Transfer` event is emitted. - /// - /// No-op if the caller and `to` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. #[ink(message)] fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; @@ -53,28 +40,6 @@ pub trait Psp22 { /// - `from` - The account from which the token balance will be withdrawn. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. - /// - /// If `from` and the caller are different addresses, the caller must be allowed - /// by `from` to spend at least `value` tokens. - /// - /// # Events - /// On success a `Transfer` event is emitted. - /// - /// No-op if `from` and `to` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// If `from` and the caller are different addresses, a successful transfer results - /// in decreased allowance by `from` to the caller and an `Approval` event with - /// the new allowance amount is emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account `from`. - /// - /// Reverts with `InsufficientAllowance` if `from` and the caller are different addresses and - /// the `value` exceeds the allowance granted by `from` to the caller. - /// - /// If conditions for both `InsufficientBalance` and `InsufficientAllowance` errors are met, - /// reverts with `InsufficientAllowance`. #[ink(message)] fn transfer_from( &mut self, @@ -91,11 +56,6 @@ pub trait Psp22 { /// # Parameters /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. - /// - /// # Events - /// An `Approval` event is emitted. - /// - /// No-op if the caller and `spender` is the same address, returns success and no events are emitted. #[ink(message)] fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; @@ -104,12 +64,6 @@ pub trait Psp22 { /// # Parameters /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. - /// - /// # Events - /// An `Approval` event with the new allowance amount is emitted. - /// - /// No-op if the caller and `spender` is the same address or `value` is zero, returns success - /// and no events are emitted. #[ink(message)] fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; @@ -118,16 +72,6 @@ pub trait Psp22 { /// # Parameters /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. - /// - /// # Events - /// An `Approval` event with the new allowance amount is emitted. - /// - /// No-op if the caller and `spender` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and - /// the `value` exceeds the allowance granted by the caller to `spender`. #[ink(message)] fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; } @@ -135,12 +79,30 @@ pub trait Psp22 { /// The PSP22 Metadata trait. #[ink::trait_definition] pub trait Psp22Managable { + /// Creates a new token with the specified `id`, assigns `admin` as the administrator, + /// and sets a minimum balance requirement. + /// + /// # Parameters + /// - `id`: The unique identifier for the token to be created. + /// - `admin`: The account that will have administrative privileges over the token. + /// - `min_balance`: The minimum balance required to hold the token. #[ink(message)] fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; + /// Initiates the process to destroy the specified `token`. + /// + /// # Parameters + /// - `token`: The identifier of the token to be destroyed. #[ink(message)] fn start_destroy(&mut self, token: TokenId) -> Result<()>; + /// Sets metadata for the specified `token`, including its name, symbol, and decimal places. + /// + /// # Parameters + /// - `token`: The identifier of the token to set metadata for. + /// - `name`: The name of the token. + /// - `symbol`: The symbol representing the token. + /// - `decimals`: The number of decimal places the token uses. #[ink(message)] fn set_metadata( &mut self, @@ -150,9 +112,17 @@ pub trait Psp22Managable { decimals: u8, ) -> Result<()>; + /// Clears the metadata for the specified `token`. + /// + /// # Parameters + /// - `token`: The identifier of the token to clear metadata for. #[ink(message)] fn clear_metadata(&mut self, token: TokenId) -> Result<()>; + /// Checks whether a token with the specified `token` identifier exists. + /// + /// # Parameters + /// - `token`: The identifier of the token to check for existence. #[ink(message)] fn token_exists(&self, token: TokenId) -> Result; } @@ -181,15 +151,6 @@ pub trait Psp22Mintable { /// # Parameters /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. - /// - /// # Events - /// On success a `Transfer` event is emitted with `None` sender. - /// - /// No-op if `value` is zero, returns success and no events are emitted. - /// - /// # Errors - /// Reverts with `Custom (max supply exceeded)` if the total supply increased by - /// `value` exceeds maximal value of `u128` type. #[ink(message)] fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; } @@ -202,14 +163,6 @@ pub trait Psp22Burnable { /// # Parameters /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. - /// - /// # Events - /// On success a `Transfer` event is emitted with `None` recipient. - /// - /// No-op if `value` is zero, returns success and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. #[ink(message)] fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; } From 894fcf90306a8a792d7df5b723ab7937d0ede4be Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:39:13 +0800 Subject: [PATCH 073/161] feat: refactor example contract to follow spec --- pop-api/examples/fungibles/lib.rs | 107 ++++++++++++++----------- pop-api/src/v0/fungibles/interfaces.rs | 28 +++---- pop-api/src/v0/fungibles/mod.rs | 81 ++++++++++--------- 3 files changed, 116 insertions(+), 100 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index c46b302f..0f6bcd63 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -3,15 +3,18 @@ use ink::prelude::{string::String, vec::Vec}; use pop_api::{ primitives::TokenId, - v0::fungibles::{self as api, events::Created, PSP22Error}, + v0::fungibles::{ + self as api, + events::Created, + interfaces::{Psp22, Psp22Burnable, Psp22Metadata, Psp22Mintable}, + PSP22Error, PSP22Result, + }, StatusCode, }; #[cfg(test)] mod tests; -type PSP22Result = core::result::Result; - #[ink::contract] mod fungibles { use super::*; @@ -55,97 +58,103 @@ mod fungibles { } #[ink(message)] - pub fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { - api::mint(self.id, account, amount).map_err(|e| PSP22Error::from(e)) + pub fn set_metadata( + &self, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> PSP22Result<()> { + api::set_metadata(self.id, name, symbol, decimals).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { - api::burn(self.id, account, amount).map_err(|e| PSP22Error::from(e)) + pub fn token_exists(&self) -> PSP22Result { + api::token_exists(self.id).map_err(|e| PSP22Error::from(e)) } + } + impl Psp22 for Fungibles { #[ink(message)] - pub fn transfer(&mut self, to: AccountId, value: Balance) -> PSP22Result<()> { - api::transfer(self.id, to, value).map_err(|e| PSP22Error::from(e)) + fn total_supply(&self) -> Balance { + api::total_supply(self.id).unwrap_or_default() } #[ink(message)] - pub fn transfer_from( - &mut self, - from: AccountId, - to: AccountId, - value: Balance, - _data: Vec, - ) -> PSP22Result<()> { - api::transfer_from(self.id, from, to, value).map_err(|e| PSP22Error::from(e)) + fn balance_of(&self, owner: AccountId) -> Balance { + api::balance_of(self.id, owner).unwrap_or_default() } #[ink(message)] - pub fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { - api::approve(self.id, spender, value).map_err(|e| PSP22Error::from(e)) + fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance { + api::allowance(self.id, owner, spender).unwrap_or_default() } #[ink(message)] - pub fn increase_allowance( - &mut self, - spender: AccountId, - value: Balance, - ) -> PSP22Result<()> { - api::increase_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) + fn transfer(&mut self, to: AccountId, value: Balance, _data: Vec) -> PSP22Result<()> { + api::transfer(self.id, to, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn decrease_allowance( + fn transfer_from( &mut self, - spender: AccountId, + from: AccountId, + to: AccountId, value: Balance, + _data: Vec, ) -> PSP22Result<()> { - api::decrease_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) + api::transfer_from(self.id, from, to, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn set_metadata( - &self, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> PSP22Result<()> { - api::set_metadata(self.id, name, symbol, decimals).map_err(|e| PSP22Error::from(e)) + fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { + api::approve(self.id, spender, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn total_supply(&self) -> PSP22Result { - api::total_supply(self.id).map_err(|e| PSP22Error::from(e)) + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { + api::increase_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn balance_of(&self, owner: AccountId) -> PSP22Result { - api::balance_of(self.id, owner).map_err(|e| PSP22Error::from(e)) + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { + api::decrease_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) } + } + impl Psp22Metadata for Fungibles { #[ink(message)] - pub fn allowance(&self, owner: AccountId, spender: AccountId) -> PSP22Result { - api::allowance(self.id, owner, spender).map_err(|e| PSP22Error::from(e)) + fn token_name(&self) -> Option> { + if let Ok(value) = api::token_name(self.id) { + return Some(value); + } + None } #[ink(message)] - pub fn token_name(&self) -> PSP22Result> { - api::token_name(self.id).map_err(|e| PSP22Error::from(e)) + fn token_symbol(&self) -> Option> { + if let Ok(value) = api::token_symbol(self.id) { + return Some(value); + } + None } #[ink(message)] - pub fn token_symbol(&self) -> PSP22Result> { - api::token_symbol(self.id).map_err(|e| PSP22Error::from(e)) + fn token_decimals(&self) -> u8 { + api::token_decimals(self.id).unwrap_or_default() } + } + impl Psp22Mintable for Fungibles { #[ink(message)] - pub fn token_decimals(&self) -> PSP22Result { - api::token_decimals(self.id).map_err(|e| PSP22Error::from(e)) + fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { + api::mint(self.id, account, amount).map_err(|e| PSP22Error::from(e)) } + } + impl Psp22Burnable for Fungibles { #[ink(message)] - pub fn token_exists(&self) -> PSP22Result { - api::token_exists(self.id).map_err(|e| PSP22Error::from(e)) + fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { + api::burn(self.id, account, amount).map_err(|e| PSP22Error::from(e)) } } } diff --git a/pop-api/src/v0/fungibles/interfaces.rs b/pop-api/src/v0/fungibles/interfaces.rs index 5b52504a..a4b48a4c 100644 --- a/pop-api/src/v0/fungibles/interfaces.rs +++ b/pop-api/src/v0/fungibles/interfaces.rs @@ -1,7 +1,5 @@ use super::*; -pub type Result = core::result::Result; - #[ink::trait_definition] pub trait Psp22 { /// Returns the total token supply. @@ -31,7 +29,7 @@ pub trait Psp22 { /// - `value` - The number of tokens to transfer. /// - `data` - Additional data in unspecified format. #[ink(message)] - fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; + fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> PSP22Result<()>; /// Transfers `value` tokens on behalf of `from` to the account `to` /// with additional `data` in unspecified format. @@ -47,7 +45,7 @@ pub trait Psp22 { to: AccountId, value: Balance, data: Vec, - ) -> Result<()>; + ) -> PSP22Result<()>; /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. /// @@ -57,7 +55,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[ink(message)] - fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; + fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; /// Increases the allowance of `spender` by `value` amount of tokens. /// @@ -65,7 +63,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[ink(message)] - fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; /// Decreases the allowance of `spender` by `value` amount of tokens. /// @@ -73,12 +71,12 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[ink(message)] - fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; } /// The PSP22 Metadata trait. #[ink::trait_definition] -pub trait Psp22Managable { +pub trait Management { /// Creates a new token with the specified `id`, assigns `admin` as the administrator, /// and sets a minimum balance requirement. /// @@ -87,14 +85,14 @@ pub trait Psp22Managable { /// - `admin`: The account that will have administrative privileges over the token. /// - `min_balance`: The minimum balance required to hold the token. #[ink(message)] - fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; + fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> PSP22Result<()>; /// Initiates the process to destroy the specified `token`. /// /// # Parameters /// - `token`: The identifier of the token to be destroyed. #[ink(message)] - fn start_destroy(&mut self, token: TokenId) -> Result<()>; + fn start_destroy(&mut self, token: TokenId) -> PSP22Result<()>; /// Sets metadata for the specified `token`, including its name, symbol, and decimal places. /// @@ -110,21 +108,21 @@ pub trait Psp22Managable { name: Vec, symbol: Vec, decimals: u8, - ) -> Result<()>; + ) -> PSP22Result<()>; /// Clears the metadata for the specified `token`. /// /// # Parameters /// - `token`: The identifier of the token to clear metadata for. #[ink(message)] - fn clear_metadata(&mut self, token: TokenId) -> Result<()>; + fn clear_metadata(&mut self, token: TokenId) -> PSP22Result<()>; /// Checks whether a token with the specified `token` identifier exists. /// /// # Parameters /// - `token`: The identifier of the token to check for existence. #[ink(message)] - fn token_exists(&self, token: TokenId) -> Result; + fn token_exists(&self, token: TokenId) -> PSP22Result; } /// The PSP22 Metadata trait. @@ -152,7 +150,7 @@ pub trait Psp22Mintable { /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[ink(message)] - fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; + fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()>; } /// The PSP22 Burnable trait. @@ -164,5 +162,5 @@ pub trait Psp22Burnable { /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[ink(message)] - fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; + fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()>; } diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index e8d4e81d..da731819 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -17,6 +17,7 @@ use crate::{ ChainExtensionMethodApi, StatusCode, }; use constants::*; +use core::result::Result; pub use errors::*; pub use events::*; use ink::prelude::vec::Vec; @@ -24,6 +25,9 @@ pub use interfaces::*; pub use management::*; pub use metadata::*; +pub type PSP22Result = Result; +pub type PopApiResult = Result; + // Helper method to build a dispatch call. // // Parameters: @@ -73,10 +77,10 @@ mod constants { /// # Parameters /// - `token` - The token. #[inline] -pub fn total_supply(token: TokenId) -> Result { +pub fn total_supply(token: TokenId) -> PopApiResult { build_read_state(TOTAL_SUPPLY) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -88,10 +92,10 @@ pub fn total_supply(token: TokenId) -> Result { /// - `token` - The token. /// - `owner` - The account whose balance is being queried. #[inline] -pub fn balance_of(token: TokenId, owner: AccountId) -> Result { +pub fn balance_of(token: TokenId, owner: AccountId) -> PopApiResult { build_read_state(BALANCE_OF) .input::<(TokenId, AccountId)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, owner)) } @@ -104,10 +108,10 @@ pub fn balance_of(token: TokenId, owner: AccountId) -> Result { /// - `owner` - The account that owns the tokens. /// - `spender` - The account that is allowed to spend the tokens. #[inline] -pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result { +pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> PopApiResult { build_read_state(ALLOWANCE) .input::<(TokenId, AccountId, AccountId)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, owner, spender)) } @@ -119,10 +123,10 @@ pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { +pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(TRANSFER) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, to, value)) } @@ -135,10 +139,15 @@ pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { +pub fn transfer_from( + token: TokenId, + from: AccountId, + to: AccountId, + value: Balance, +) -> PopApiResult<()> { build_dispatch(TRANSFER_FROM) .input::<(TokenId, AccountId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, from, to, value)) } @@ -150,10 +159,10 @@ pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Bala /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[inline] -pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { +pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(APPROVE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -165,10 +174,10 @@ pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[inline] -pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { +pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(INCREASE_ALLOWANCE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -180,10 +189,10 @@ pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[inline] -pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { +pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(DECREASE_ALLOWANCE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -195,10 +204,10 @@ pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[inline] -pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { +pub fn mint(token: TokenId, account: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(MINT) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, account, value)) } @@ -210,10 +219,10 @@ pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[inline] -pub fn burn(token: TokenId, account: AccountId, value: Balance) -> Result<()> { +pub fn burn(token: TokenId, account: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(BURN) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, account, value)) } @@ -227,10 +236,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_name(token: TokenId) -> Result> { + pub fn token_name(token: TokenId) -> PopApiResult> { build_read_state(TOKEN_NAME) .input::() - .output::>, true>() + .output::>, true>() .handle_error_code::() .call(&(token)) } @@ -240,10 +249,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_symbol(token: TokenId) -> Result> { + pub fn token_symbol(token: TokenId) -> PopApiResult> { build_read_state(TOKEN_SYMBOL) .input::() - .output::>, true>() + .output::>, true>() .handle_error_code::() .call(&(token)) } @@ -253,10 +262,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_decimals(token: TokenId) -> Result { + pub fn token_decimals(token: TokenId) -> PopApiResult { build_read_state(TOKEN_DECIMALS) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -273,10 +282,10 @@ pub mod management { /// - `admin` - The account that will administer the token. /// - `min_balance` - The minimum balance required for accounts holding this token. #[inline] - pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()> { + pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> PopApiResult<()> { build_dispatch(CREATE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(id, admin, min_balance)) } @@ -286,10 +295,10 @@ pub mod management { /// # Parameters /// - `token` - The token to be destroyed. #[inline] - pub fn start_destroy(token: TokenId) -> Result<()> { + pub fn start_destroy(token: TokenId) -> PopApiResult<()> { build_dispatch(START_DESTROY) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -307,10 +316,10 @@ pub mod management { name: Vec, symbol: Vec, decimals: u8, - ) -> Result<()> { + ) -> PopApiResult<()> { build_dispatch(SET_METADATA) .input::<(TokenId, Vec, Vec, u8)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, name, symbol, decimals)) } @@ -320,10 +329,10 @@ pub mod management { /// # Parameters /// - `token` - The token to update #[inline] - pub fn clear_metadata(token: TokenId) -> Result<()> { + pub fn clear_metadata(token: TokenId) -> PopApiResult<()> { build_dispatch(CLEAR_METADATA) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -333,10 +342,10 @@ pub mod management { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_exists(token: TokenId) -> Result { + pub fn token_exists(token: TokenId) -> PopApiResult { build_read_state(TOKEN_EXISTS) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } From 817a35155da041cbfc589549189a5c60fb0a8711 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:59:19 +0800 Subject: [PATCH 074/161] test: psp22error --- pop-api/src/v0/fungibles/tests.rs | 44 ++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/pop-api/src/v0/fungibles/tests.rs b/pop-api/src/v0/fungibles/tests.rs index 128cf4cb..55b832e4 100644 --- a/pop-api/src/v0/fungibles/tests.rs +++ b/pop-api/src/v0/fungibles/tests.rs @@ -1,4 +1,4 @@ -use super::FungiblesError; +use super::{FungiblesError, PSP22Error}; use crate::{ constants::{ASSETS, BALANCES}, primitives::{ @@ -24,6 +24,11 @@ fn into_fungibles_error(error: Error) -> FungiblesError { status_code.into() } +fn into_psp22_error(error: Error) -> PSP22Error { + let status_code: StatusCode = error_into_status_code(error); + status_code.into() +} + // If we ever want to change the conversion from bytes to `u32`. #[test] fn status_code_vs_encoded() { @@ -97,3 +102,40 @@ fn converting_status_code_into_fungibles_error_works() { FungiblesError::NotLive ); } + +#[test] +fn converting_status_code_into_psp22_error_works() { + let other_errors = vec![ + Other, + CannotLookup, + BadOrigin, + // `ModuleError` other than assets module. + Module { index: 2, error: [5, 0] }, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Token(OnlyProvider), + Arithmetic(Overflow), + Transactional(NoLayer), + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, + DecodingFailed, + ]; + for error in other_errors { + let status_code: StatusCode = error_into_status_code(error); + let fungibles_error: PSP22Error = status_code.into(); + assert_eq!(fungibles_error, PSP22Error::Custom(String::from("Other"))) + } + + assert_eq!( + into_psp22_error(Module { index: ASSETS, error: [3, 0] }), + PSP22Error::Custom(String::from("Unknown")) + ); + assert_eq!( + into_psp22_error(Module { index: ASSETS, error: [7, 0] }), + PSP22Error::InsufficientAllowance + ); +} From 6042f09370738a5e4ed24b04ccf5e6fbb39752fa Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:27:19 +0800 Subject: [PATCH 075/161] fix: missing String --- pop-api/src/v0/fungibles/errors.rs | 1 + pop-api/src/v0/fungibles/tests.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 872e8d64..486077c8 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,4 +1,5 @@ use super::*; +use ink::prelude::string::String; /// Represents various errors related to fungible tokens. /// diff --git a/pop-api/src/v0/fungibles/tests.rs b/pop-api/src/v0/fungibles/tests.rs index 55b832e4..bac16335 100644 --- a/pop-api/src/v0/fungibles/tests.rs +++ b/pop-api/src/v0/fungibles/tests.rs @@ -9,6 +9,7 @@ use crate::{ }, StatusCode, }; +use ink::prelude::string::String; use ink::scale::{Decode, Encode}; fn error_into_status_code(error: Error) -> StatusCode { From c8cc9d1112e2c1d6b10cb30a1dcecbd329e8af7a Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:24:29 +0800 Subject: [PATCH 076/161] chore: revert example --- pop-api/examples/fungibles/lib.rs | 107 ++++++++++++++---------------- 1 file changed, 49 insertions(+), 58 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 0f6bcd63..c46b302f 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -3,18 +3,15 @@ use ink::prelude::{string::String, vec::Vec}; use pop_api::{ primitives::TokenId, - v0::fungibles::{ - self as api, - events::Created, - interfaces::{Psp22, Psp22Burnable, Psp22Metadata, Psp22Mintable}, - PSP22Error, PSP22Result, - }, + v0::fungibles::{self as api, events::Created, PSP22Error}, StatusCode, }; #[cfg(test)] mod tests; +type PSP22Result = core::result::Result; + #[ink::contract] mod fungibles { use super::*; @@ -58,103 +55,97 @@ mod fungibles { } #[ink(message)] - pub fn set_metadata( - &self, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> PSP22Result<()> { - api::set_metadata(self.id, name, symbol, decimals).map_err(|e| PSP22Error::from(e)) + pub fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { + api::mint(self.id, account, amount).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - pub fn token_exists(&self) -> PSP22Result { - api::token_exists(self.id).map_err(|e| PSP22Error::from(e)) + pub fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { + api::burn(self.id, account, amount).map_err(|e| PSP22Error::from(e)) } - } - impl Psp22 for Fungibles { #[ink(message)] - fn total_supply(&self) -> Balance { - api::total_supply(self.id).unwrap_or_default() + pub fn transfer(&mut self, to: AccountId, value: Balance) -> PSP22Result<()> { + api::transfer(self.id, to, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - fn balance_of(&self, owner: AccountId) -> Balance { - api::balance_of(self.id, owner).unwrap_or_default() + pub fn transfer_from( + &mut self, + from: AccountId, + to: AccountId, + value: Balance, + _data: Vec, + ) -> PSP22Result<()> { + api::transfer_from(self.id, from, to, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance { - api::allowance(self.id, owner, spender).unwrap_or_default() + pub fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { + api::approve(self.id, spender, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - fn transfer(&mut self, to: AccountId, value: Balance, _data: Vec) -> PSP22Result<()> { - api::transfer(self.id, to, value).map_err(|e| PSP22Error::from(e)) + pub fn increase_allowance( + &mut self, + spender: AccountId, + value: Balance, + ) -> PSP22Result<()> { + api::increase_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - fn transfer_from( + pub fn decrease_allowance( &mut self, - from: AccountId, - to: AccountId, + spender: AccountId, value: Balance, - _data: Vec, ) -> PSP22Result<()> { - api::transfer_from(self.id, from, to, value).map_err(|e| PSP22Error::from(e)) + api::decrease_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { - api::approve(self.id, spender, value).map_err(|e| PSP22Error::from(e)) + pub fn set_metadata( + &self, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> PSP22Result<()> { + api::set_metadata(self.id, name, symbol, decimals).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { - api::increase_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) + pub fn total_supply(&self) -> PSP22Result { + api::total_supply(self.id).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { - api::decrease_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) + pub fn balance_of(&self, owner: AccountId) -> PSP22Result { + api::balance_of(self.id, owner).map_err(|e| PSP22Error::from(e)) } - } - impl Psp22Metadata for Fungibles { #[ink(message)] - fn token_name(&self) -> Option> { - if let Ok(value) = api::token_name(self.id) { - return Some(value); - } - None + pub fn allowance(&self, owner: AccountId, spender: AccountId) -> PSP22Result { + api::allowance(self.id, owner, spender).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - fn token_symbol(&self) -> Option> { - if let Ok(value) = api::token_symbol(self.id) { - return Some(value); - } - None + pub fn token_name(&self) -> PSP22Result> { + api::token_name(self.id).map_err(|e| PSP22Error::from(e)) } #[ink(message)] - fn token_decimals(&self) -> u8 { - api::token_decimals(self.id).unwrap_or_default() + pub fn token_symbol(&self) -> PSP22Result> { + api::token_symbol(self.id).map_err(|e| PSP22Error::from(e)) } - } - impl Psp22Mintable for Fungibles { #[ink(message)] - fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { - api::mint(self.id, account, amount).map_err(|e| PSP22Error::from(e)) + pub fn token_decimals(&self) -> PSP22Result { + api::token_decimals(self.id).map_err(|e| PSP22Error::from(e)) } - } - impl Psp22Burnable for Fungibles { #[ink(message)] - fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { - api::burn(self.id, account, amount).map_err(|e| PSP22Error::from(e)) + pub fn token_exists(&self) -> PSP22Result { + api::token_exists(self.id).map_err(|e| PSP22Error::from(e)) } } } From a8c063ca1de592785f2cd349462f67324905199a Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:41:13 +0800 Subject: [PATCH 077/161] fix: resolve comments --- pop-api/src/v0/fungibles/errors.rs | 149 ++++++++++++++++++ pop-api/src/v0/fungibles/events.rs | 20 +-- pop-api/src/v0/fungibles/mod.rs | 103 ++++++------ pop-api/src/v0/fungibles/tests.rs | 142 ----------------- .../v0/fungibles/{interfaces.rs => traits.rs} | 52 +----- 5 files changed, 211 insertions(+), 255 deletions(-) delete mode 100644 pop-api/src/v0/fungibles/tests.rs rename pop-api/src/v0/fungibles/{interfaces.rs => traits.rs} (68%) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 486077c8..c8dae082 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -11,6 +11,7 @@ use ink::prelude::string::String; /// operations. The `Other` variant serves as a catch-all for any unexpected errors. For more /// detailed debugging, the `Other` variant can be converted into the richer `Error` type defined in /// the primitives crate. +/// NOTE: The `FungiblesError` is WIP #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum FungiblesError { @@ -64,6 +65,7 @@ impl From for FungiblesError { } /// The PSP22 error. +/// TODO: Issue https://github.com/r0gue-io/pop-node/issues/298 #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum PSP22Error { @@ -92,3 +94,150 @@ impl From for PSP22Error { } } } + +#[cfg(test)] +mod tests { + use super::{FungiblesError, PSP22Error}; + use crate::{ + constants::{ASSETS, BALANCES}, + primitives::{ + ArithmeticError::*, + Error::{self, *}, + TokenError::*, + TransactionalError::*, + }, + StatusCode, + }; + use ink::prelude::string::String; + use ink::scale::{Decode, Encode}; + + fn error_into_status_code(error: Error) -> StatusCode { + let mut encoded_error = error.encode(); + encoded_error.resize(4, 0); + let value = u32::from_le_bytes( + encoded_error.try_into().expect("qed, resized to 4 bytes line above"), + ); + value.into() + } + + fn into_fungibles_error(error: Error) -> FungiblesError { + let status_code: StatusCode = error_into_status_code(error); + status_code.into() + } + + fn into_psp22_error(error: Error) -> PSP22Error { + let status_code: StatusCode = error_into_status_code(error); + status_code.into() + } + + // If we ever want to change the conversion from bytes to `u32`. + #[test] + fn status_code_vs_encoded() { + assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 0, 0][..]).unwrap(), 13315u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 1, 0][..]).unwrap(), 78851u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 2, 0][..]).unwrap(), 144387u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 3, 0][..]).unwrap(), 209923u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 5, 0][..]).unwrap(), 340995u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 7, 0][..]).unwrap(), 472067u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 10, 0][..]).unwrap(), 668675u32); + } + + #[test] + fn converting_status_code_into_fungibles_error_works() { + let other_errors = vec![ + Other, + CannotLookup, + BadOrigin, + // `ModuleError` other than assets module. + Module { index: 2, error: [5, 0] }, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Token(OnlyProvider), + Arithmetic(Overflow), + Transactional(NoLayer), + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, + DecodingFailed, + ]; + for error in other_errors { + let status_code: StatusCode = error_into_status_code(error); + let fungibles_error: FungiblesError = status_code.into(); + assert_eq!(fungibles_error, FungiblesError::Other(status_code)) + } + + assert_eq!( + into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), + FungiblesError::NoBalance + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), + FungiblesError::NoAccount + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), + FungiblesError::NoPermission + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), + FungiblesError::Unknown + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), + FungiblesError::InUse + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), + FungiblesError::MinBalanceZero + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), + FungiblesError::InsufficientAllowance + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), + FungiblesError::NotLive + ); + } + + #[test] + fn converting_status_code_into_psp22_error_works() { + let other_errors = vec![ + Other, + CannotLookup, + BadOrigin, + // `ModuleError` other than assets module. + Module { index: 2, error: [5, 0] }, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Token(OnlyProvider), + Arithmetic(Overflow), + Transactional(NoLayer), + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, + DecodingFailed, + ]; + for error in other_errors { + let status_code: StatusCode = error_into_status_code(error); + let fungibles_error: PSP22Error = status_code.into(); + assert_eq!(fungibles_error, PSP22Error::Custom(String::from("Other"))) + } + + assert_eq!( + into_psp22_error(Module { index: ASSETS, error: [3, 0] }), + PSP22Error::Custom(String::from("Unknown")) + ); + assert_eq!( + into_psp22_error(Module { index: ASSETS, error: [7, 0] }), + PSP22Error::InsufficientAllowance + ); + } +} diff --git a/pop-api/src/v0/fungibles/events.rs b/pop-api/src/v0/fungibles/events.rs index b0639e10..a018ac59 100644 --- a/pop-api/src/v0/fungibles/events.rs +++ b/pop-api/src/v0/fungibles/events.rs @@ -1,15 +1,16 @@ -/// A set of events for use in smart contracts interacting with the fungibles API. -/// -/// The `Transfer` and `Approval` events conform to the PSP-22 standard. The other events -/// (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. -/// -/// These events are not emitted by the API itself but can be used in your contracts to -/// track token operations. Be mindful of the costs associated with emitting events. -/// -/// For more details, refer to [ink! events](https://use.ink/basics/events). +//! A set of events for use in smart contracts interacting with the fungibles API. +//! +//! The `Transfer` and `Approval` events conform to the PSP-22 standard. The other events +//! (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. +//! +//! These events are not emitted by the API itself but can be used in your contracts to +//! track token operations. Be mindful of the costs associated with emitting events. +//! +//! For more details, refer to [ink! events](https://use.ink/basics/events). use super::*; /// Event emitted when allowance by `owner` to `spender` changes. +// Differing style: event name abides by the PSP22 standard. #[ink::event] pub struct Approval { /// The owner providing the allowance. @@ -23,6 +24,7 @@ pub struct Approval { } /// Event emitted when transfer of tokens occurs. +// Differing style: event name abides by the PSP22 standard. #[ink::event] pub struct Transfer { /// The source of the transfer. `None` when minting. diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index da731819..e864f690 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -1,15 +1,10 @@ //! The `fungibles` module provides an API for interacting and managing fungible tokens. //! -//! The API includes the following interfaces: +//! The API includes the following traits: //! 1. PSP-22 //! 2. PSP-22 Metadata //! 3. Management //! 4. PSP-22 Mintable & Burnable -pub mod errors; -pub mod events; -pub mod interfaces; -#[cfg(test)] -mod tests; use crate::{ constants::{ASSETS, BALANCES, FUNGIBLES}, @@ -17,60 +12,18 @@ use crate::{ ChainExtensionMethodApi, StatusCode, }; use constants::*; -use core::result::Result; pub use errors::*; pub use events::*; use ink::prelude::vec::Vec; -pub use interfaces::*; pub use management::*; pub use metadata::*; +pub use traits::*; -pub type PSP22Result = Result; -pub type PopApiResult = Result; - -// Helper method to build a dispatch call. -// -// Parameters: -// - 'dispatchable': The index of the dispatchable function within the module. -fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { - crate::v0::build_dispatch(FUNGIBLES, dispatchable) -} - -// Helper method to build a call to read state. -// -// Parameters: -// - 'state_query': The index of the runtime state query. -fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { - crate::v0::build_read_state(FUNGIBLES, state_query) -} - -mod constants { - /// 1. PSP-22 Interface: - pub(super) const TOTAL_SUPPLY: u8 = 0; - pub(super) const BALANCE_OF: u8 = 1; - pub(super) const ALLOWANCE: u8 = 2; - pub(super) const TRANSFER: u8 = 3; - pub(super) const TRANSFER_FROM: u8 = 4; - pub(super) const APPROVE: u8 = 5; - pub(super) const INCREASE_ALLOWANCE: u8 = 6; - pub(super) const DECREASE_ALLOWANCE: u8 = 7; - - /// 2. PSP-22 Metadata Interface: - pub(super) const TOKEN_NAME: u8 = 8; - pub(super) const TOKEN_SYMBOL: u8 = 9; - pub(super) const TOKEN_DECIMALS: u8 = 10; +pub mod errors; +pub mod events; +pub mod traits; - /// 3. Asset Management: - pub(super) const CREATE: u8 = 11; - pub(super) const START_DESTROY: u8 = 12; - pub(super) const SET_METADATA: u8 = 16; - pub(super) const CLEAR_METADATA: u8 = 17; - pub(super) const TOKEN_EXISTS: u8 = 18; - - /// 4. PSP-22 Mintable & Burnable interface: - pub(super) const MINT: u8 = 19; - pub(super) const BURN: u8 = 20; -} +pub type PSP22Result = core::result::Result; /// Returns the total token supply for a specified token. /// @@ -350,3 +303,47 @@ pub mod management { .call(&(token)) } } + +mod constants { + /// 1. PSP-22 Interface: + pub(super) const TOTAL_SUPPLY: u8 = 0; + pub(super) const BALANCE_OF: u8 = 1; + pub(super) const ALLOWANCE: u8 = 2; + pub(super) const TRANSFER: u8 = 3; + pub(super) const TRANSFER_FROM: u8 = 4; + pub(super) const APPROVE: u8 = 5; + pub(super) const INCREASE_ALLOWANCE: u8 = 6; + pub(super) const DECREASE_ALLOWANCE: u8 = 7; + + /// 2. PSP-22 Metadata Interface: + pub(super) const TOKEN_NAME: u8 = 8; + pub(super) const TOKEN_SYMBOL: u8 = 9; + pub(super) const TOKEN_DECIMALS: u8 = 10; + + /// 3. Asset Management: + pub(super) const CREATE: u8 = 11; + pub(super) const START_DESTROY: u8 = 12; + pub(super) const SET_METADATA: u8 = 16; + pub(super) const CLEAR_METADATA: u8 = 17; + pub(super) const TOKEN_EXISTS: u8 = 18; + + /// 4. PSP-22 Mintable & Burnable interface: + pub(super) const MINT: u8 = 19; + pub(super) const BURN: u8 = 20; +} + +// Helper method to build a dispatch call. +// +// Parameters: +// - 'dispatchable': The index of the dispatchable function within the module. +fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { + crate::v0::build_dispatch(FUNGIBLES, dispatchable) +} + +// Helper method to build a call to read state. +// +// Parameters: +// - 'state_query': The index of the runtime state query. +fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { + crate::v0::build_read_state(FUNGIBLES, state_query) +} diff --git a/pop-api/src/v0/fungibles/tests.rs b/pop-api/src/v0/fungibles/tests.rs deleted file mode 100644 index bac16335..00000000 --- a/pop-api/src/v0/fungibles/tests.rs +++ /dev/null @@ -1,142 +0,0 @@ -use super::{FungiblesError, PSP22Error}; -use crate::{ - constants::{ASSETS, BALANCES}, - primitives::{ - ArithmeticError::*, - Error::{self, *}, - TokenError::*, - TransactionalError::*, - }, - StatusCode, -}; -use ink::prelude::string::String; -use ink::scale::{Decode, Encode}; - -fn error_into_status_code(error: Error) -> StatusCode { - let mut encoded_error = error.encode(); - encoded_error.resize(4, 0); - let value = - u32::from_le_bytes(encoded_error.try_into().expect("qed, resized to 4 bytes line above")); - value.into() -} - -fn into_fungibles_error(error: Error) -> FungiblesError { - let status_code: StatusCode = error_into_status_code(error); - status_code.into() -} - -fn into_psp22_error(error: Error) -> PSP22Error { - let status_code: StatusCode = error_into_status_code(error); - status_code.into() -} - -// If we ever want to change the conversion from bytes to `u32`. -#[test] -fn status_code_vs_encoded() { - assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 0, 0][..]).unwrap(), 13315u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 1, 0][..]).unwrap(), 78851u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 2, 0][..]).unwrap(), 144387u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 3, 0][..]).unwrap(), 209923u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 5, 0][..]).unwrap(), 340995u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 7, 0][..]).unwrap(), 472067u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 10, 0][..]).unwrap(), 668675u32); -} - -#[test] -fn converting_status_code_into_fungibles_error_works() { - let other_errors = vec![ - Other, - CannotLookup, - BadOrigin, - // `ModuleError` other than assets module. - Module { index: 2, error: [5, 0] }, - ConsumerRemaining, - NoProviders, - TooManyConsumers, - Token(OnlyProvider), - Arithmetic(Overflow), - Transactional(NoLayer), - Exhausted, - Corruption, - Unavailable, - RootNotAllowed, - Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, - DecodingFailed, - ]; - for error in other_errors { - let status_code: StatusCode = error_into_status_code(error); - let fungibles_error: FungiblesError = status_code.into(); - assert_eq!(fungibles_error, FungiblesError::Other(status_code)) - } - - assert_eq!( - into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), - FungiblesError::NoBalance - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), - FungiblesError::NoAccount - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), - FungiblesError::NoPermission - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), - FungiblesError::Unknown - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), - FungiblesError::InUse - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), - FungiblesError::MinBalanceZero - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), - FungiblesError::InsufficientAllowance - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), - FungiblesError::NotLive - ); -} - -#[test] -fn converting_status_code_into_psp22_error_works() { - let other_errors = vec![ - Other, - CannotLookup, - BadOrigin, - // `ModuleError` other than assets module. - Module { index: 2, error: [5, 0] }, - ConsumerRemaining, - NoProviders, - TooManyConsumers, - Token(OnlyProvider), - Arithmetic(Overflow), - Transactional(NoLayer), - Exhausted, - Corruption, - Unavailable, - RootNotAllowed, - Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, - DecodingFailed, - ]; - for error in other_errors { - let status_code: StatusCode = error_into_status_code(error); - let fungibles_error: PSP22Error = status_code.into(); - assert_eq!(fungibles_error, PSP22Error::Custom(String::from("Other"))) - } - - assert_eq!( - into_psp22_error(Module { index: ASSETS, error: [3, 0] }), - PSP22Error::Custom(String::from("Unknown")) - ); - assert_eq!( - into_psp22_error(Module { index: ASSETS, error: [7, 0] }), - PSP22Error::InsufficientAllowance - ); -} diff --git a/pop-api/src/v0/fungibles/interfaces.rs b/pop-api/src/v0/fungibles/traits.rs similarity index 68% rename from pop-api/src/v0/fungibles/interfaces.rs rename to pop-api/src/v0/fungibles/traits.rs index a4b48a4c..74ef742a 100644 --- a/pop-api/src/v0/fungibles/interfaces.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -38,6 +38,7 @@ pub trait Psp22 { /// - `from` - The account from which the token balance will be withdrawn. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. + /// - `data` - Additional data with unspecified format. #[ink(message)] fn transfer_from( &mut self, @@ -74,57 +75,6 @@ pub trait Psp22 { fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; } -/// The PSP22 Metadata trait. -#[ink::trait_definition] -pub trait Management { - /// Creates a new token with the specified `id`, assigns `admin` as the administrator, - /// and sets a minimum balance requirement. - /// - /// # Parameters - /// - `id`: The unique identifier for the token to be created. - /// - `admin`: The account that will have administrative privileges over the token. - /// - `min_balance`: The minimum balance required to hold the token. - #[ink(message)] - fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> PSP22Result<()>; - - /// Initiates the process to destroy the specified `token`. - /// - /// # Parameters - /// - `token`: The identifier of the token to be destroyed. - #[ink(message)] - fn start_destroy(&mut self, token: TokenId) -> PSP22Result<()>; - - /// Sets metadata for the specified `token`, including its name, symbol, and decimal places. - /// - /// # Parameters - /// - `token`: The identifier of the token to set metadata for. - /// - `name`: The name of the token. - /// - `symbol`: The symbol representing the token. - /// - `decimals`: The number of decimal places the token uses. - #[ink(message)] - fn set_metadata( - &mut self, - token: TokenId, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> PSP22Result<()>; - - /// Clears the metadata for the specified `token`. - /// - /// # Parameters - /// - `token`: The identifier of the token to clear metadata for. - #[ink(message)] - fn clear_metadata(&mut self, token: TokenId) -> PSP22Result<()>; - - /// Checks whether a token with the specified `token` identifier exists. - /// - /// # Parameters - /// - `token`: The identifier of the token to check for existence. - #[ink(message)] - fn token_exists(&self, token: TokenId) -> PSP22Result; -} - /// The PSP22 Metadata trait. #[ink::trait_definition] pub trait Psp22Metadata { From 817647490967e06f023494782250883fdd9140a0 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:43:31 +0800 Subject: [PATCH 078/161] fix: revert example contract --- pop-api/examples/fungibles/lib.rs | 129 ++++++++++-------------------- 1 file changed, 43 insertions(+), 86 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index c46b302f..11eafe21 100755 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -1,151 +1,108 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::prelude::{string::String, vec::Vec}; +use ink::prelude::vec::Vec; use pop_api::{ + fungibles::{self as api}, primitives::TokenId, - v0::fungibles::{self as api, events::Created, PSP22Error}, StatusCode, }; -#[cfg(test)] -mod tests; - -type PSP22Result = core::result::Result; +pub type Result = core::result::Result; #[ink::contract] mod fungibles { use super::*; #[ink(storage)] - pub struct Fungibles { - id: TokenId, - } + #[derive(Default)] + pub struct Fungibles; impl Fungibles { - /// Instantiate the contract and wrap around an existing token. - /// - /// # Parameters - /// * - `token` - The token. #[ink(constructor, payable)] - pub fn new_existing(id: TokenId) -> PSP22Result { - // Make sure token exists. - if !api::token_exists(id).unwrap_or_default() { - return Err(PSP22Error::Custom(String::from("Unknown"))); - } - let contract = Self { id }; - Ok(contract) + pub fn new() -> Self { + Default::default() } - /// Instantiate the contract and create a new token. The token identifier will be stored - /// in contract's storage. - /// - /// # Parameters - /// * - `id` - The identifier of the token. - /// * - `admin` - The account that will administer the token. - /// * - `min_balance` - The minimum balance required for accounts holding this token. - #[ink(constructor, payable)] - pub fn new(id: TokenId, admin: AccountId, min_balance: Balance) -> PSP22Result { - // TODO: should be nicer conversion possible. - api::create(id, admin, min_balance).map_err(|e| PSP22Error::from(e))?; - let contract = Self { id }; - contract - .env() - .emit_event(Created { id, creator: contract.env().account_id(), admin }); - Ok(contract) + #[ink(message)] + pub fn total_supply(&self, token: TokenId) -> Result { + api::total_supply(token) } #[ink(message)] - pub fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { - api::mint(self.id, account, amount).map_err(|e| PSP22Error::from(e)) + pub fn balance_of(&self, token: TokenId, owner: AccountId) -> Result { + api::balance_of(token, owner) } #[ink(message)] - pub fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()> { - api::burn(self.id, account, amount).map_err(|e| PSP22Error::from(e)) + pub fn allowance( + &self, + token: TokenId, + owner: AccountId, + spender: AccountId, + ) -> Result { + api::allowance(token, owner, spender) } #[ink(message)] - pub fn transfer(&mut self, to: AccountId, value: Balance) -> PSP22Result<()> { - api::transfer(self.id, to, value).map_err(|e| PSP22Error::from(e)) + pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> Result<()> { + api::transfer(token, to, value) } #[ink(message)] pub fn transfer_from( &mut self, + token: TokenId, from: AccountId, to: AccountId, value: Balance, _data: Vec, - ) -> PSP22Result<()> { - api::transfer_from(self.id, from, to, value).map_err(|e| PSP22Error::from(e)) + ) -> Result<()> { + api::transfer_from(token, from, to, value) } #[ink(message)] - pub fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()> { - api::approve(self.id, spender, value).map_err(|e| PSP22Error::from(e)) + pub fn approve( + &mut self, + token: TokenId, + spender: AccountId, + value: Balance, + ) -> Result<()> { + api::approve(token, spender, value) } #[ink(message)] pub fn increase_allowance( &mut self, + token: TokenId, spender: AccountId, value: Balance, - ) -> PSP22Result<()> { - api::increase_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) + ) -> Result<()> { + api::increase_allowance(token, spender, value) } #[ink(message)] pub fn decrease_allowance( &mut self, + token: TokenId, spender: AccountId, value: Balance, - ) -> PSP22Result<()> { - api::decrease_allowance(self.id, spender, value).map_err(|e| PSP22Error::from(e)) - } - - #[ink(message)] - pub fn set_metadata( - &self, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> PSP22Result<()> { - api::set_metadata(self.id, name, symbol, decimals).map_err(|e| PSP22Error::from(e)) - } - - #[ink(message)] - pub fn total_supply(&self) -> PSP22Result { - api::total_supply(self.id).map_err(|e| PSP22Error::from(e)) - } - - #[ink(message)] - pub fn balance_of(&self, owner: AccountId) -> PSP22Result { - api::balance_of(self.id, owner).map_err(|e| PSP22Error::from(e)) - } - - #[ink(message)] - pub fn allowance(&self, owner: AccountId, spender: AccountId) -> PSP22Result { - api::allowance(self.id, owner, spender).map_err(|e| PSP22Error::from(e)) - } - - #[ink(message)] - pub fn token_name(&self) -> PSP22Result> { - api::token_name(self.id).map_err(|e| PSP22Error::from(e)) + ) -> Result<()> { + api::decrease_allowance(token, spender, value) } #[ink(message)] - pub fn token_symbol(&self) -> PSP22Result> { - api::token_symbol(self.id).map_err(|e| PSP22Error::from(e)) + pub fn token_name(&self, token: TokenId) -> Result> { + api::token_name(token) } #[ink(message)] - pub fn token_decimals(&self) -> PSP22Result { - api::token_decimals(self.id).map_err(|e| PSP22Error::from(e)) + pub fn token_symbol(&self, token: TokenId) -> Result> { + api::token_symbol(token) } #[ink(message)] - pub fn token_exists(&self) -> PSP22Result { - api::token_exists(self.id).map_err(|e| PSP22Error::from(e)) + pub fn token_decimals(&self, token: TokenId) -> Result { + api::token_decimals(token) } } } From 1945683237e7a6a018344f953b86cf06a3a33803 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:46:14 +0800 Subject: [PATCH 079/161] fix: add mod comment --- pop-api/src/v0/fungibles/errors.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index c8dae082..30d98285 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,3 +1,4 @@ +//! A set of errors for use in smart contracts to manage the returned errors. use super::*; use ink::prelude::string::String; From 6aede89bc5fc3b05cfb04b4ed5c394bb28e116f2 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 21:37:49 +0700 Subject: [PATCH 080/161] fix: result type --- pop-api/src/v0/fungibles/mod.rs | 79 +++++++++++++++------------------ 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index e864f690..fe6c685e 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -9,7 +9,7 @@ use crate::{ constants::{ASSETS, BALANCES, FUNGIBLES}, primitives::{AccountId, Balance, TokenId}, - ChainExtensionMethodApi, StatusCode, + ChainExtensionMethodApi, Result, StatusCode, }; use constants::*; pub use errors::*; @@ -30,10 +30,10 @@ pub type PSP22Result = core::result::Result; /// # Parameters /// - `token` - The token. #[inline] -pub fn total_supply(token: TokenId) -> PopApiResult { +pub fn total_supply(token: TokenId) -> Result { build_read_state(TOTAL_SUPPLY) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -45,10 +45,10 @@ pub fn total_supply(token: TokenId) -> PopApiResult { /// - `token` - The token. /// - `owner` - The account whose balance is being queried. #[inline] -pub fn balance_of(token: TokenId, owner: AccountId) -> PopApiResult { +pub fn balance_of(token: TokenId, owner: AccountId) -> Result { build_read_state(BALANCE_OF) .input::<(TokenId, AccountId)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, owner)) } @@ -61,10 +61,10 @@ pub fn balance_of(token: TokenId, owner: AccountId) -> PopApiResult { /// - `owner` - The account that owns the tokens. /// - `spender` - The account that is allowed to spend the tokens. #[inline] -pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> PopApiResult { +pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result { build_read_state(ALLOWANCE) .input::<(TokenId, AccountId, AccountId)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, owner, spender)) } @@ -76,10 +76,10 @@ pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> PopApi /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> PopApiResult<()> { +pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { build_dispatch(TRANSFER) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, to, value)) } @@ -92,15 +92,10 @@ pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> PopApiResult<( /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer_from( - token: TokenId, - from: AccountId, - to: AccountId, - value: Balance, -) -> PopApiResult<()> { +pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { build_dispatch(TRANSFER_FROM) .input::<(TokenId, AccountId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, from, to, value)) } @@ -112,10 +107,10 @@ pub fn transfer_from( /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[inline] -pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { +pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(APPROVE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -127,10 +122,10 @@ pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> PopApiResu /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[inline] -pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { +pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(INCREASE_ALLOWANCE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -142,10 +137,10 @@ pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[inline] -pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { +pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(DECREASE_ALLOWANCE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -157,10 +152,10 @@ pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[inline] -pub fn mint(token: TokenId, account: AccountId, value: Balance) -> PopApiResult<()> { +pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { build_dispatch(MINT) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, account, value)) } @@ -172,10 +167,10 @@ pub fn mint(token: TokenId, account: AccountId, value: Balance) -> PopApiResult< /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[inline] -pub fn burn(token: TokenId, account: AccountId, value: Balance) -> PopApiResult<()> { +pub fn burn(token: TokenId, account: AccountId, value: Balance) -> Result<()> { build_dispatch(BURN) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, account, value)) } @@ -189,10 +184,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_name(token: TokenId) -> PopApiResult> { + pub fn token_name(token: TokenId) -> Result> { build_read_state(TOKEN_NAME) .input::() - .output::>, true>() + .output::>, true>() .handle_error_code::() .call(&(token)) } @@ -202,10 +197,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_symbol(token: TokenId) -> PopApiResult> { + pub fn token_symbol(token: TokenId) -> Result> { build_read_state(TOKEN_SYMBOL) .input::() - .output::>, true>() + .output::>, true>() .handle_error_code::() .call(&(token)) } @@ -215,10 +210,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_decimals(token: TokenId) -> PopApiResult { + pub fn token_decimals(token: TokenId) -> Result { build_read_state(TOKEN_DECIMALS) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -235,10 +230,10 @@ pub mod management { /// - `admin` - The account that will administer the token. /// - `min_balance` - The minimum balance required for accounts holding this token. #[inline] - pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> PopApiResult<()> { + pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()> { build_dispatch(CREATE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(id, admin, min_balance)) } @@ -248,10 +243,10 @@ pub mod management { /// # Parameters /// - `token` - The token to be destroyed. #[inline] - pub fn start_destroy(token: TokenId) -> PopApiResult<()> { + pub fn start_destroy(token: TokenId) -> Result<()> { build_dispatch(START_DESTROY) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -269,10 +264,10 @@ pub mod management { name: Vec, symbol: Vec, decimals: u8, - ) -> PopApiResult<()> { + ) -> Result<()> { build_dispatch(SET_METADATA) .input::<(TokenId, Vec, Vec, u8)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, name, symbol, decimals)) } @@ -282,10 +277,10 @@ pub mod management { /// # Parameters /// - `token` - The token to update #[inline] - pub fn clear_metadata(token: TokenId) -> PopApiResult<()> { + pub fn clear_metadata(token: TokenId) -> Result<()> { build_dispatch(CLEAR_METADATA) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -295,10 +290,10 @@ pub mod management { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_exists(token: TokenId) -> PopApiResult { + pub fn token_exists(token: TokenId) -> Result { build_read_state(TOKEN_EXISTS) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } From b52ad332b87a8b6d63257763a98c86ad3cf70503 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 22:22:09 +0700 Subject: [PATCH 081/161] fix: update PSP22Metadata --- pop-api/src/v0/fungibles/traits.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 74ef742a..01f25710 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -80,11 +80,11 @@ pub trait Psp22 { pub trait Psp22Metadata { /// Returns the token name. #[ink(message)] - fn token_name(&self) -> Option>; + fn token_name(&self) -> Option; /// Returns the token symbol. #[ink(message)] - fn token_symbol(&self) -> Option>; + fn token_symbol(&self) -> Option; /// Returns the token decimals. #[ink(message)] From 6b2f17a556605e46dd3cf3adaa9b7f23a38c4ceb Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 22:25:06 +0700 Subject: [PATCH 082/161] fix: add comment for Psp22 trait --- pop-api/src/v0/fungibles/traits.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 01f25710..0d9d2d29 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,5 +1,6 @@ use super::*; +/// The PSP22 trait. #[ink::trait_definition] pub trait Psp22 { /// Returns the total token supply. From 4a1bf3b184979efff2af0b26032d7fed0196dcab Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:13:42 +0700 Subject: [PATCH 083/161] fix: resolve comments --- pop-api/src/v0/fungibles/errors.rs | 4 ++-- pop-api/src/v0/fungibles/events.rs | 1 + pop-api/src/v0/fungibles/mod.rs | 10 ++++------ pop-api/src/v0/fungibles/traits.rs | 15 ++++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 30d98285..e76c4bcc 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,4 +1,4 @@ -//! A set of errors for use in smart contracts to manage the returned errors. +//! A set of errors for use in smart contracts that interact with the fungibles api. This includes errors compliant to standards. use super::*; use ink::prelude::string::String; @@ -66,7 +66,7 @@ impl From for FungiblesError { } /// The PSP22 error. -/// TODO: Issue https://github.com/r0gue-io/pop-node/issues/298 +// TODO: Issue https://github.com/r0gue-io/pop-node/issues/298 #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum PSP22Error { diff --git a/pop-api/src/v0/fungibles/events.rs b/pop-api/src/v0/fungibles/events.rs index a018ac59..130ead65 100644 --- a/pop-api/src/v0/fungibles/events.rs +++ b/pop-api/src/v0/fungibles/events.rs @@ -7,6 +7,7 @@ //! track token operations. Be mindful of the costs associated with emitting events. //! //! For more details, refer to [ink! events](https://use.ink/basics/events). + use super::*; /// Event emitted when allowance by `owner` to `spender` changes. diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index fe6c685e..77f5f32c 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -23,8 +23,6 @@ pub mod errors; pub mod events; pub mod traits; -pub type PSP22Result = core::result::Result; - /// Returns the total token supply for a specified token. /// /// # Parameters @@ -300,7 +298,7 @@ pub mod management { } mod constants { - /// 1. PSP-22 Interface: + /// 1. PSP-22 pub(super) const TOTAL_SUPPLY: u8 = 0; pub(super) const BALANCE_OF: u8 = 1; pub(super) const ALLOWANCE: u8 = 2; @@ -310,19 +308,19 @@ mod constants { pub(super) const INCREASE_ALLOWANCE: u8 = 6; pub(super) const DECREASE_ALLOWANCE: u8 = 7; - /// 2. PSP-22 Metadata Interface: + /// 2. PSP-22 Metadata pub(super) const TOKEN_NAME: u8 = 8; pub(super) const TOKEN_SYMBOL: u8 = 9; pub(super) const TOKEN_DECIMALS: u8 = 10; - /// 3. Asset Management: + /// 3. Management pub(super) const CREATE: u8 = 11; pub(super) const START_DESTROY: u8 = 12; pub(super) const SET_METADATA: u8 = 16; pub(super) const CLEAR_METADATA: u8 = 17; pub(super) const TOKEN_EXISTS: u8 = 18; - /// 4. PSP-22 Mintable & Burnable interface: + /// 4. PSP-22 Mintable & Burnable pub(super) const MINT: u8 = 19; pub(super) const BURN: u8 = 20; } diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 0d9d2d29..0220d363 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,3 +1,4 @@ +/// A set of traits that implement the PSP22 token standard. use super::*; /// The PSP22 trait. @@ -30,7 +31,7 @@ pub trait Psp22 { /// - `value` - The number of tokens to transfer. /// - `data` - Additional data in unspecified format. #[ink(message)] - fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> PSP22Result<()>; + fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<(), PSP22Error>; /// Transfers `value` tokens on behalf of `from` to the account `to` /// with additional `data` in unspecified format. @@ -47,7 +48,7 @@ pub trait Psp22 { to: AccountId, value: Balance, data: Vec, - ) -> PSP22Result<()>; + ) -> Result<(), PSP22Error>; /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. /// @@ -57,7 +58,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[ink(message)] - fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; /// Increases the allowance of `spender` by `value` amount of tokens. /// @@ -65,7 +66,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[ink(message)] - fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; /// Decreases the allowance of `spender` by `value` amount of tokens. /// @@ -73,7 +74,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[ink(message)] - fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; } /// The PSP22 Metadata trait. @@ -101,7 +102,7 @@ pub trait Psp22Mintable { /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[ink(message)] - fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()>; + fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; } /// The PSP22 Burnable trait. @@ -113,5 +114,5 @@ pub trait Psp22Burnable { /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[ink(message)] - fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()>; + fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; } From 699275cdcc0932dadfbcd0cf805a32082c91afcf Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:18:36 +0700 Subject: [PATCH 084/161] fix: api integration tests --- pop-api/src/v0/fungibles/traits.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 0220d363..9bcf2e8d 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,5 +1,8 @@ -/// A set of traits that implement the PSP22 token standard. +//! A set of traits that implement the PSP22 token standard. + use super::*; +use ink::prelude::string::String; +use std::result::Result; /// The PSP22 trait. #[ink::trait_definition] From 94ee34ec9e4c4fc2eb8b4c0e066190bd91458707 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:49:26 +0700 Subject: [PATCH 085/161] fix: result type --- pop-api/src/v0/fungibles/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 9bcf2e8d..caa4c68d 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,8 +1,8 @@ //! A set of traits that implement the PSP22 token standard. use super::*; +use core::result::Result; use ink::prelude::string::String; -use std::result::Result; /// The PSP22 trait. #[ink::trait_definition] From 9bb3be84717e25359ed90afb1a98130a768adef6 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:53:54 +0700 Subject: [PATCH 086/161] fix: comment --- pop-api/src/v0/fungibles/errors.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index e76c4bcc..313107b4 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,4 +1,5 @@ //! A set of errors for use in smart contracts that interact with the fungibles api. This includes errors compliant to standards. + use super::*; use ink::prelude::string::String; From f03a5ae2a917503c79969b1701e9d368a43f4ea3 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 12:48:36 +0800 Subject: [PATCH 087/161] feat: add interfaces for psp22 --- pop-api/src/v0/fungibles.rs | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/pop-api/src/v0/fungibles.rs b/pop-api/src/v0/fungibles.rs index 99c1261a..9ab53957 100644 --- a/pop-api/src/v0/fungibles.rs +++ b/pop-api/src/v0/fungibles.rs @@ -420,6 +420,93 @@ pub mod management { } } +pub mod interfaces { + use super::*; + + pub type Result = core::result::Result; + + #[ink::trait_definition] + pub trait Psp22Impl { + #[ink(message)] + fn total_supply(&self) -> Balance; + + #[ink(message)] + fn balance_of(&self, owner: AccountId) -> Balance; + + #[ink(message)] + fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; + + #[ink(message)] + fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; + + #[ink(message)] + fn transfer_from( + &mut self, + from: AccountId, + to: AccountId, + value: Balance, + data: Vec, + ) -> Result<()>; + + #[ink(message)] + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; + + #[ink(message)] + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + + #[ink(message)] + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + } + + #[ink::trait_definition] + pub trait Psp2ManagableImpl { + #[ink(message)] + fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; + + #[ink(message)] + fn start_destroy(&mut self, token: TokenId) -> Result<()>; + + #[ink(message)] + fn set_metadata( + &mut self, + token: TokenId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()>; + + #[ink(message)] + fn clear_metadata(&mut self, token: TokenId) -> Result<()>; + + #[ink(message)] + fn token_exists(&self, token: TokenId) -> Result; + } + + #[ink::trait_definition] + pub trait Psp22MetadataImpl { + #[ink(message)] + fn token_name(&self) -> Option>; + + #[ink(message)] + fn token_symbol(&self) -> Option>; + + #[ink(message)] + fn token_decimals(&self, id: TokenId) -> u8; + } + + #[ink::trait_definition] + pub trait Psp22MintableImpl { + #[ink(message)] + fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; + } + + #[ink::trait_definition] + pub trait Psp22BurnableImpl { + #[ink(message)] + fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; + } +} + /// Represents various errors related to fungible tokens. /// /// The `FungiblesError` provides a detailed and specific set of error types that can occur when From 1bbc3ed4e182d45e97f5e6eb99c42b3b9db2ee31 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:03:39 +0800 Subject: [PATCH 088/161] chore: add comments --- pop-api/src/v0/fungibles.rs | 143 ++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 6 deletions(-) diff --git a/pop-api/src/v0/fungibles.rs b/pop-api/src/v0/fungibles.rs index 9ab53957..096017c6 100644 --- a/pop-api/src/v0/fungibles.rs +++ b/pop-api/src/v0/fungibles.rs @@ -426,19 +426,78 @@ pub mod interfaces { pub type Result = core::result::Result; #[ink::trait_definition] - pub trait Psp22Impl { + pub trait Psp22 { + /// Returns the total token supply. #[ink(message)] fn total_supply(&self) -> Balance; + /// Returns the account balance for the specified `owner`. + /// + /// # Parameters + /// - `owner` - The account whose balance is being queried. + /// + /// Returns `0` if the account is non-existent. #[ink(message)] fn balance_of(&self, owner: AccountId) -> Balance; + /// Returns the allowance for a `spender` approved by an `owner`. + /// + /// # Parameters + /// - `owner` - The account that owns the tokens. + /// - `spender` - The account that is allowed to spend the tokens. + /// + /// Returns `0` if no allowance has been set. #[ink(message)] fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; + /// Transfers `value` amount of tokens from the caller's account to account `to` + /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// - `data` - Additional data in unspecified format. + /// + /// # Events + /// On success a `Transfer` event is emitted. + /// + /// No-op if the caller and `to` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. #[ink(message)] fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; + /// Transfers `value` tokens on behalf of `from` to the account `to` + /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `from` - The account from which the token balance will be withdrawn. + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// + /// If `from` and the caller are different addresses, the caller must be allowed + /// by `from` to spend at least `value` tokens. + /// + /// # Events + /// On success a `Transfer` event is emitted. + /// + /// No-op if `from` and `to` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// If `from` and the caller are different addresses, a successful transfer results + /// in decreased allowance by `from` to the caller and an `Approval` event with + /// the new allowance amount is emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account `from`. + /// + /// Reverts with `InsufficientAllowance` if `from` and the caller are different addresses and + /// the `value` exceeds the allowance granted by `from` to the caller. + /// + /// If conditions for both `InsufficientBalance` and `InsufficientAllowance` errors are met, + /// reverts with `InsufficientAllowance`. #[ink(message)] fn transfer_from( &mut self, @@ -448,18 +507,57 @@ pub mod interfaces { data: Vec, ) -> Result<()>; + /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. + /// + /// Successive calls of this method overwrite previous values. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to approve. + /// + /// # Events + /// An `Approval` event is emitted. + /// + /// No-op if the caller and `spender` is the same address, returns success and no events are emitted. #[ink(message)] fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; + /// Increases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to increase the allowance by. + /// + /// # Events + /// An `Approval` event with the new allowance amount is emitted. + /// + /// No-op if the caller and `spender` is the same address or `value` is zero, returns success + /// and no events are emitted. #[ink(message)] fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + /// Decreases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to decrease the allowance by. + /// + /// # Events + /// An `Approval` event with the new allowance amount is emitted. + /// + /// No-op if the caller and `spender` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and + /// the `value` exceeds the allowance granted by the caller to `spender`. #[ink(message)] fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; } + /// The PSP22 Metadata trait. #[ink::trait_definition] - pub trait Psp2ManagableImpl { + pub trait Psp22Managable { #[ink(message)] fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; @@ -482,26 +580,59 @@ pub mod interfaces { fn token_exists(&self, token: TokenId) -> Result; } + /// The PSP22 Metadata trait. #[ink::trait_definition] - pub trait Psp22MetadataImpl { + pub trait Psp22Metadata { + /// Returns the token name. #[ink(message)] fn token_name(&self) -> Option>; + /// Returns the token symbol. #[ink(message)] fn token_symbol(&self) -> Option>; + /// Returns the token decimals. #[ink(message)] - fn token_decimals(&self, id: TokenId) -> u8; + fn token_decimals(&self) -> u8; } + /// The PSP22 Mintable trait. #[ink::trait_definition] - pub trait Psp22MintableImpl { + pub trait Psp22Mintable { + /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. + /// + /// # Parameters + /// - `account` - The account to be credited with the created tokens. + /// - `value` - The number of tokens to mint. + /// + /// # Events + /// On success a `Transfer` event is emitted with `None` sender. + /// + /// No-op if `value` is zero, returns success and no events are emitted. + /// + /// # Errors + /// Reverts with `Custom (max supply exceeded)` if the total supply increased by + /// `value` exceeds maximal value of `u128` type. #[ink(message)] fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; } + /// The PSP22 Burnable trait. #[ink::trait_definition] - pub trait Psp22BurnableImpl { + pub trait Psp22Burnable { + /// Destroys `value` amount of tokens from `account`, reducing the total supply. + /// + /// # Parameters + /// - `account` - The account from which the tokens will be destroyed. + /// - `value` - The number of tokens to destroy. + /// + /// # Events + /// On success a `Transfer` event is emitted with `None` recipient. + /// + /// No-op if `value` is zero, returns success and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. #[ink(message)] fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; } From e8d68a99e04a992f63e6831d885568bdd324375c Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:30:18 +0800 Subject: [PATCH 089/161] refactor: separate modules into files --- pop-api/src/v0/fungibles.rs | 806 ------------------------- pop-api/src/v0/fungibles/errors.rs | 63 ++ pop-api/src/v0/fungibles/events.rs | 82 +++ pop-api/src/v0/fungibles/interfaces.rs | 215 +++++++ pop-api/src/v0/fungibles/mod.rs | 343 +++++++++++ pop-api/src/v0/fungibles/tests.rs | 99 +++ 6 files changed, 802 insertions(+), 806 deletions(-) delete mode 100644 pop-api/src/v0/fungibles.rs create mode 100644 pop-api/src/v0/fungibles/errors.rs create mode 100644 pop-api/src/v0/fungibles/events.rs create mode 100644 pop-api/src/v0/fungibles/interfaces.rs create mode 100644 pop-api/src/v0/fungibles/mod.rs create mode 100644 pop-api/src/v0/fungibles/tests.rs diff --git a/pop-api/src/v0/fungibles.rs b/pop-api/src/v0/fungibles.rs deleted file mode 100644 index 096017c6..00000000 --- a/pop-api/src/v0/fungibles.rs +++ /dev/null @@ -1,806 +0,0 @@ -//! The `fungibles` module provides an API for interacting and managing fungible tokens. -//! -//! The API includes the following interfaces: -//! 1. PSP-22 -//! 2. PSP-22 Metadata -//! 3. Management -//! 4. PSP-22 Mintable & Burnable - -use constants::*; -use ink::prelude::vec::Vec; -pub use management::*; -pub use metadata::*; - -use crate::{ - constants::{ASSETS, BALANCES, FUNGIBLES}, - primitives::{AccountId, Balance, TokenId}, - ChainExtensionMethodApi, Result, StatusCode, -}; - -// Helper method to build a dispatch call. -// -// Parameters: -// - 'dispatchable': The index of the dispatchable function within the module. -fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { - crate::v0::build_dispatch(FUNGIBLES, dispatchable) -} - -// Helper method to build a call to read state. -// -// Parameters: -// - 'state_query': The index of the runtime state query. -fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { - crate::v0::build_read_state(FUNGIBLES, state_query) -} - -mod constants { - /// 1. PSP-22 Interface: - pub(super) const TOTAL_SUPPLY: u8 = 0; - pub(super) const BALANCE_OF: u8 = 1; - pub(super) const ALLOWANCE: u8 = 2; - pub(super) const TRANSFER: u8 = 3; - pub(super) const TRANSFER_FROM: u8 = 4; - pub(super) const APPROVE: u8 = 5; - pub(super) const INCREASE_ALLOWANCE: u8 = 6; - pub(super) const DECREASE_ALLOWANCE: u8 = 7; - - /// 2. PSP-22 Metadata Interface: - pub(super) const TOKEN_NAME: u8 = 8; - pub(super) const TOKEN_SYMBOL: u8 = 9; - pub(super) const TOKEN_DECIMALS: u8 = 10; - - /// 3. Asset Management: - pub(super) const CREATE: u8 = 11; - pub(super) const START_DESTROY: u8 = 12; - pub(super) const SET_METADATA: u8 = 16; - pub(super) const CLEAR_METADATA: u8 = 17; - pub(super) const TOKEN_EXISTS: u8 = 18; - - /// 4. PSP-22 Mintable & Burnable interface: - pub(super) const MINT: u8 = 19; - pub(super) const BURN: u8 = 20; -} - -/// A set of events for use in smart contracts interacting with the fungibles API. -/// -/// The `Transfer` and `Approval` events conform to the PSP-22 standard. The other events -/// (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. -/// -/// These events are not emitted by the API itself but can be used in your contracts to -/// track token operations. Be mindful of the costs associated with emitting events. -/// -/// For more details, refer to [ink! events](https://use.ink/basics/events). -pub mod events { - use super::*; - - /// Event emitted when allowance by `owner` to `spender` changes. - #[ink::event] - pub struct Approval { - /// The owner providing the allowance. - #[ink(topic)] - pub owner: AccountId, - /// The beneficiary of the allowance. - #[ink(topic)] - pub spender: AccountId, - /// The new allowance amount. - pub value: u128, - } - - /// Event emitted when transfer of tokens occurs. - #[ink::event] - pub struct Transfer { - /// The source of the transfer. `None` when minting. - #[ink(topic)] - pub from: Option, - /// The recipient of the transfer. `None` when burning. - #[ink(topic)] - pub to: Option, - /// The amount transferred (or minted/burned). - pub value: u128, - } - - /// Event emitted when a token is created. - #[ink::event] - pub struct Created { - /// The token identifier. - #[ink(topic)] - pub id: TokenId, - /// The creator of the token. - #[ink(topic)] - pub creator: AccountId, - /// The administrator of the token. - #[ink(topic)] - pub admin: AccountId, - } - - /// Event emitted when a token is in the process of being destroyed. - #[ink::event] - pub struct DestroyStarted { - /// The token. - #[ink(topic)] - pub token: TokenId, - } - - /// Event emitted when new metadata is set for a token. - #[ink::event] - pub struct MetadataSet { - /// The token. - #[ink(topic)] - pub token: TokenId, - /// The name of the token. - #[ink(topic)] - pub name: Vec, - /// The symbol of the token. - #[ink(topic)] - pub symbol: Vec, - /// The decimals of the token. - pub decimals: u8, - } - - /// Event emitted when metadata is cleared for a token. - #[ink::event] - pub struct MetadataCleared { - /// The token. - #[ink(topic)] - pub token: TokenId, - } -} - -/// Returns the total token supply for a specified token. -/// -/// # Parameters -/// - `token` - The token. -#[inline] -pub fn total_supply(token: TokenId) -> Result { - build_read_state(TOTAL_SUPPLY) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) -} - -/// Returns the account balance for a specified `token` and `owner`. Returns `0` if -/// the account is non-existent. -/// -/// # Parameters -/// - `token` - The token. -/// - `owner` - The account whose balance is being queried. -#[inline] -pub fn balance_of(token: TokenId, owner: AccountId) -> Result { - build_read_state(BALANCE_OF) - .input::<(TokenId, AccountId)>() - .output::, true>() - .handle_error_code::() - .call(&(token, owner)) -} - -/// Returns the allowance for a `spender` approved by an `owner`, for a specified `token`. Returns -/// `0` if no allowance has been set. -/// -/// # Parameters -/// - `token` - The token. -/// - `owner` - The account that owns the tokens. -/// - `spender` - The account that is allowed to spend the tokens. -#[inline] -pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result { - build_read_state(ALLOWANCE) - .input::<(TokenId, AccountId, AccountId)>() - .output::, true>() - .handle_error_code::() - .call(&(token, owner, spender)) -} - -/// Transfers `value` amount of tokens from the caller's account to account `to`. -/// -/// # Parameters -/// - `token` - The token to transfer. -/// - `to` - The recipient account. -/// - `value` - The number of tokens to transfer. -#[inline] -pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { - build_dispatch(TRANSFER) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, to, value)) -} - -/// Transfers `value` amount tokens on behalf of `from` to account `to`. -/// -/// # Parameters -/// - `token` - The token to transfer. -/// - `from` - The account from which the token balance will be withdrawn. -/// - `to` - The recipient account. -/// - `value` - The number of tokens to transfer. -#[inline] -pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { - build_dispatch(TRANSFER_FROM) - .input::<(TokenId, AccountId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, from, to, value)) -} - -/// Approves `spender` to spend `value` amount of tokens on behalf of the caller. -/// -/// # Parameters -/// - `token` - The token to approve. -/// - `spender` - The account that is allowed to spend the tokens. -/// - `value` - The number of tokens to approve. -#[inline] -pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { - build_dispatch(APPROVE) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, spender, value)) -} - -/// Increases the allowance of `spender` by `value` amount of tokens. -/// -/// # Parameters -/// - `token` - The token to have an allowance increased. -/// - `spender` - The account that is allowed to spend the tokens. -/// - `value` - The number of tokens to increase the allowance by. -#[inline] -pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { - build_dispatch(INCREASE_ALLOWANCE) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, spender, value)) -} - -/// Decreases the allowance of `spender` by `value` amount of tokens. -/// -/// # Parameters -/// - `token` - The token to have an allowance decreased. -/// - `spender` - The account that is allowed to spend the tokens. -/// - `value` - The number of tokens to decrease the allowance by. -#[inline] -pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { - build_dispatch(DECREASE_ALLOWANCE) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, spender, value)) -} - -/// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. -/// -/// # Parameters -/// - `token` - The token to mint. -/// - `account` - The account to be credited with the created tokens. -/// - `value` - The number of tokens to mint. -#[inline] -pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { - build_dispatch(MINT) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, account, value)) -} - -/// Destroys `value` amount of tokens from `account`, reducing the total supply. -/// -/// # Parameters -/// - `token` - the token to burn. -/// - `account` - The account from which the tokens will be destroyed. -/// - `value` - The number of tokens to destroy. -#[inline] -pub fn burn(token: TokenId, account: AccountId, value: Balance) -> Result<()> { - build_dispatch(BURN) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(token, account, value)) -} - -/// The PSP-22 compliant interface for querying metadata. -pub mod metadata { - use super::*; - - /// Returns the name of the specified token. - /// - /// # Parameters - /// - `token` - The token. - #[inline] - pub fn token_name(token: TokenId) -> Result> { - build_read_state(TOKEN_NAME) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(token)) - } - - /// Returns the symbol for the specified token. - /// - /// # Parameters - /// - `token` - The token. - #[inline] - pub fn token_symbol(token: TokenId) -> Result> { - build_read_state(TOKEN_SYMBOL) - .input::() - .output::>, true>() - .handle_error_code::() - .call(&(token)) - } - - /// Returns the decimals for the specified token. - /// - /// # Parameters - /// - `token` - The token. - #[inline] - pub fn token_decimals(token: TokenId) -> Result { - build_read_state(TOKEN_DECIMALS) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) - } -} - -/// The interface for creating, managing and destroying fungible tokens. -pub mod management { - use super::*; - - /// Create a new token with a given identifier. - /// - /// # Parameters - /// - `id` - The identifier of the token. - /// - `admin` - The account that will administer the token. - /// - `min_balance` - The minimum balance required for accounts holding this token. - #[inline] - pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()> { - build_dispatch(CREATE) - .input::<(TokenId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, admin, min_balance)) - } - - /// Start the process of destroying a token. - /// - /// # Parameters - /// - `token` - The token to be destroyed. - #[inline] - pub fn start_destroy(token: TokenId) -> Result<()> { - build_dispatch(START_DESTROY) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) - } - - /// Set the metadata for a token. - /// - /// # Parameters - /// - `token`: The token to update. - /// - `name`: The user friendly name of this token. - /// - `symbol`: The exchange symbol for this token. - /// - `decimals`: The number of decimals this token uses to represent one unit. - #[inline] - pub fn set_metadata( - token: TokenId, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> Result<()> { - build_dispatch(SET_METADATA) - .input::<(TokenId, Vec, Vec, u8)>() - .output::, true>() - .handle_error_code::() - .call(&(token, name, symbol, decimals)) - } - - /// Clear the metadata for a token. - /// - /// # Parameters - /// - `token` - The token to update - #[inline] - pub fn clear_metadata(token: TokenId) -> Result<()> { - build_dispatch(CLEAR_METADATA) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) - } - - /// Checks if a specified token exists. - /// - /// # Parameters - /// - `token` - The token. - #[inline] - pub fn token_exists(token: TokenId) -> Result { - build_read_state(TOKEN_EXISTS) - .input::() - .output::, true>() - .handle_error_code::() - .call(&(token)) - } -} - -pub mod interfaces { - use super::*; - - pub type Result = core::result::Result; - - #[ink::trait_definition] - pub trait Psp22 { - /// Returns the total token supply. - #[ink(message)] - fn total_supply(&self) -> Balance; - - /// Returns the account balance for the specified `owner`. - /// - /// # Parameters - /// - `owner` - The account whose balance is being queried. - /// - /// Returns `0` if the account is non-existent. - #[ink(message)] - fn balance_of(&self, owner: AccountId) -> Balance; - - /// Returns the allowance for a `spender` approved by an `owner`. - /// - /// # Parameters - /// - `owner` - The account that owns the tokens. - /// - `spender` - The account that is allowed to spend the tokens. - /// - /// Returns `0` if no allowance has been set. - #[ink(message)] - fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; - - /// Transfers `value` amount of tokens from the caller's account to account `to` - /// with additional `data` in unspecified format. - /// - /// # Parameters - /// - `to` - The recipient account. - /// - `value` - The number of tokens to transfer. - /// - `data` - Additional data in unspecified format. - /// - /// # Events - /// On success a `Transfer` event is emitted. - /// - /// No-op if the caller and `to` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. - #[ink(message)] - fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; - - /// Transfers `value` tokens on behalf of `from` to the account `to` - /// with additional `data` in unspecified format. - /// - /// # Parameters - /// - `from` - The account from which the token balance will be withdrawn. - /// - `to` - The recipient account. - /// - `value` - The number of tokens to transfer. - /// - /// If `from` and the caller are different addresses, the caller must be allowed - /// by `from` to spend at least `value` tokens. - /// - /// # Events - /// On success a `Transfer` event is emitted. - /// - /// No-op if `from` and `to` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// If `from` and the caller are different addresses, a successful transfer results - /// in decreased allowance by `from` to the caller and an `Approval` event with - /// the new allowance amount is emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account `from`. - /// - /// Reverts with `InsufficientAllowance` if `from` and the caller are different addresses and - /// the `value` exceeds the allowance granted by `from` to the caller. - /// - /// If conditions for both `InsufficientBalance` and `InsufficientAllowance` errors are met, - /// reverts with `InsufficientAllowance`. - #[ink(message)] - fn transfer_from( - &mut self, - from: AccountId, - to: AccountId, - value: Balance, - data: Vec, - ) -> Result<()>; - - /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. - /// - /// Successive calls of this method overwrite previous values. - /// - /// # Parameters - /// - `spender` - The account that is allowed to spend the tokens. - /// - `value` - The number of tokens to approve. - /// - /// # Events - /// An `Approval` event is emitted. - /// - /// No-op if the caller and `spender` is the same address, returns success and no events are emitted. - #[ink(message)] - fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; - - /// Increases the allowance of `spender` by `value` amount of tokens. - /// - /// # Parameters - /// - `spender` - The account that is allowed to spend the tokens. - /// - `value` - The number of tokens to increase the allowance by. - /// - /// # Events - /// An `Approval` event with the new allowance amount is emitted. - /// - /// No-op if the caller and `spender` is the same address or `value` is zero, returns success - /// and no events are emitted. - #[ink(message)] - fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; - - /// Decreases the allowance of `spender` by `value` amount of tokens. - /// - /// # Parameters - /// - `spender` - The account that is allowed to spend the tokens. - /// - `value` - The number of tokens to decrease the allowance by. - /// - /// # Events - /// An `Approval` event with the new allowance amount is emitted. - /// - /// No-op if the caller and `spender` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and - /// the `value` exceeds the allowance granted by the caller to `spender`. - #[ink(message)] - fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; - } - - /// The PSP22 Metadata trait. - #[ink::trait_definition] - pub trait Psp22Managable { - #[ink(message)] - fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; - - #[ink(message)] - fn start_destroy(&mut self, token: TokenId) -> Result<()>; - - #[ink(message)] - fn set_metadata( - &mut self, - token: TokenId, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> Result<()>; - - #[ink(message)] - fn clear_metadata(&mut self, token: TokenId) -> Result<()>; - - #[ink(message)] - fn token_exists(&self, token: TokenId) -> Result; - } - - /// The PSP22 Metadata trait. - #[ink::trait_definition] - pub trait Psp22Metadata { - /// Returns the token name. - #[ink(message)] - fn token_name(&self) -> Option>; - - /// Returns the token symbol. - #[ink(message)] - fn token_symbol(&self) -> Option>; - - /// Returns the token decimals. - #[ink(message)] - fn token_decimals(&self) -> u8; - } - - /// The PSP22 Mintable trait. - #[ink::trait_definition] - pub trait Psp22Mintable { - /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. - /// - /// # Parameters - /// - `account` - The account to be credited with the created tokens. - /// - `value` - The number of tokens to mint. - /// - /// # Events - /// On success a `Transfer` event is emitted with `None` sender. - /// - /// No-op if `value` is zero, returns success and no events are emitted. - /// - /// # Errors - /// Reverts with `Custom (max supply exceeded)` if the total supply increased by - /// `value` exceeds maximal value of `u128` type. - #[ink(message)] - fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; - } - - /// The PSP22 Burnable trait. - #[ink::trait_definition] - pub trait Psp22Burnable { - /// Destroys `value` amount of tokens from `account`, reducing the total supply. - /// - /// # Parameters - /// - `account` - The account from which the tokens will be destroyed. - /// - `value` - The number of tokens to destroy. - /// - /// # Events - /// On success a `Transfer` event is emitted with `None` recipient. - /// - /// No-op if `value` is zero, returns success and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. - #[ink(message)] - fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; - } -} - -/// Represents various errors related to fungible tokens. -/// -/// The `FungiblesError` provides a detailed and specific set of error types that can occur when -/// interacting with fungible tokens. Each variant signifies a particular error -/// condition, facilitating precise error handling and debugging. -/// -/// It is designed to be lightweight, including only the essential errors relevant to fungible token -/// operations. The `Other` variant serves as a catch-all for any unexpected errors. For more -/// detailed debugging, the `Other` variant can be converted into the richer `Error` type defined in -/// the primitives crate. -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub enum FungiblesError { - /// An unspecified or unknown error occurred. - Other(StatusCode), - /// The token is not live; either frozen or being destroyed. - NotLive, - /// Not enough allowance to fulfill a request is available. - InsufficientAllowance, - /// Not enough balance to fulfill a request is available. - InsufficientBalance, - /// The token ID is already taken. - InUse, - /// Minimum balance should be non-zero. - MinBalanceZero, - /// The account to alter does not exist. - NoAccount, - /// The signing account has no permission to do the operation. - NoPermission, - /// The given token ID is unknown. - Unknown, - /// No balance for creation of tokens or fees. - // TODO: Originally `pallet_balances::Error::InsufficientBalance` but collides with the - // `InsufficientBalance` error that is used for `pallet_assets::Error::BalanceLow` to adhere - // to the standard. This deserves a second look. - NoBalance, -} - -impl From for FungiblesError { - /// Converts a `StatusCode` to a `FungiblesError`. - /// - /// This conversion maps a `StatusCode`, returned by the runtime, to a more descriptive - /// `FungiblesError`. This provides better context and understanding of the error, allowing - /// developers to handle the most important errors effectively. - fn from(value: StatusCode) -> Self { - let encoded = value.0.to_le_bytes(); - match encoded { - // Balances. - [_, BALANCES, 2, _] => FungiblesError::NoBalance, - // Assets. - [_, ASSETS, 0, _] => FungiblesError::NoAccount, - [_, ASSETS, 1, _] => FungiblesError::NoPermission, - [_, ASSETS, 2, _] => FungiblesError::Unknown, - [_, ASSETS, 3, _] => FungiblesError::InUse, - [_, ASSETS, 5, _] => FungiblesError::MinBalanceZero, - [_, ASSETS, 7, _] => FungiblesError::InsufficientAllowance, - [_, ASSETS, 10, _] => FungiblesError::NotLive, - _ => FungiblesError::Other(value), - } - } -} - -#[cfg(test)] -mod tests { - use ink::scale::{Decode, Encode}; - - use super::FungiblesError; - use crate::{ - constants::{ASSETS, BALANCES}, - primitives::{ - ArithmeticError::*, - Error::{self, *}, - TokenError::*, - TransactionalError::*, - }, - StatusCode, - }; - - fn error_into_status_code(error: Error) -> StatusCode { - let mut encoded_error = error.encode(); - encoded_error.resize(4, 0); - let value = u32::from_le_bytes( - encoded_error.try_into().expect("qed, resized to 4 bytes line above"), - ); - value.into() - } - - fn into_fungibles_error(error: Error) -> FungiblesError { - let status_code: StatusCode = error_into_status_code(error); - status_code.into() - } - - // If we ever want to change the conversion from bytes to `u32`. - #[test] - fn status_code_vs_encoded() { - assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 0, 0][..]).unwrap(), 13315u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 1, 0][..]).unwrap(), 78851u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 2, 0][..]).unwrap(), 144387u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 3, 0][..]).unwrap(), 209923u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 5, 0][..]).unwrap(), 340995u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 7, 0][..]).unwrap(), 472067u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 10, 0][..]).unwrap(), 668675u32); - } - - #[test] - fn converting_status_code_into_fungibles_error_works() { - let other_errors = vec![ - Other, - CannotLookup, - BadOrigin, - // `ModuleError` other than assets module. - Module { index: 2, error: [5, 0] }, - ConsumerRemaining, - NoProviders, - TooManyConsumers, - Token(OnlyProvider), - Arithmetic(Overflow), - Transactional(NoLayer), - Exhausted, - Corruption, - Unavailable, - RootNotAllowed, - Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, - DecodingFailed, - ]; - for error in other_errors { - let status_code: StatusCode = error_into_status_code(error); - let fungibles_error: FungiblesError = status_code.into(); - assert_eq!(fungibles_error, FungiblesError::Other(status_code)) - } - - assert_eq!( - into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), - FungiblesError::NoBalance - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), - FungiblesError::NoAccount - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), - FungiblesError::NoPermission - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), - FungiblesError::Unknown - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), - FungiblesError::InUse - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), - FungiblesError::MinBalanceZero - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), - FungiblesError::InsufficientAllowance - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), - FungiblesError::NotLive - ); - } -} diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs new file mode 100644 index 00000000..b29127e5 --- /dev/null +++ b/pop-api/src/v0/fungibles/errors.rs @@ -0,0 +1,63 @@ +use super::*; + +/// Represents various errors related to fungible tokens. +/// +/// The `FungiblesError` provides a detailed and specific set of error types that can occur when +/// interacting with fungible tokens. Each variant signifies a particular error +/// condition, facilitating precise error handling and debugging. +/// +/// It is designed to be lightweight, including only the essential errors relevant to fungible token +/// operations. The `Other` variant serves as a catch-all for any unexpected errors. For more +/// detailed debugging, the `Other` variant can be converted into the richer `Error` type defined in +/// the primitives crate. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum FungiblesError { + /// An unspecified or unknown error occurred. + Other(StatusCode), + /// The token is not live; either frozen or being destroyed. + NotLive, + /// Not enough allowance to fulfill a request is available. + InsufficientAllowance, + /// Not enough balance to fulfill a request is available. + InsufficientBalance, + /// The token ID is already taken. + InUse, + /// Minimum balance should be non-zero. + MinBalanceZero, + /// The account to alter does not exist. + NoAccount, + /// The signing account has no permission to do the operation. + NoPermission, + /// The given token ID is unknown. + Unknown, + /// No balance for creation of tokens or fees. + // TODO: Originally `pallet_balances::Error::InsufficientBalance` but collides with the + // `InsufficientBalance` error that is used for `pallet_assets::Error::BalanceLow` to adhere + // to the standard. This deserves a second look. + NoBalance, +} + +impl From for FungiblesError { + /// Converts a `StatusCode` to a `FungiblesError`. + /// + /// This conversion maps a `StatusCode`, returned by the runtime, to a more descriptive + /// `FungiblesError`. This provides better context and understanding of the error, allowing + /// developers to handle the most important errors effectively. + fn from(value: StatusCode) -> Self { + let encoded = value.0.to_le_bytes(); + match encoded { + // Balances. + [_, BALANCES, 2, _] => FungiblesError::NoBalance, + // Assets. + [_, ASSETS, 0, _] => FungiblesError::NoAccount, + [_, ASSETS, 1, _] => FungiblesError::NoPermission, + [_, ASSETS, 2, _] => FungiblesError::Unknown, + [_, ASSETS, 3, _] => FungiblesError::InUse, + [_, ASSETS, 5, _] => FungiblesError::MinBalanceZero, + [_, ASSETS, 7, _] => FungiblesError::InsufficientAllowance, + [_, ASSETS, 10, _] => FungiblesError::NotLive, + _ => FungiblesError::Other(value), + } + } +} diff --git a/pop-api/src/v0/fungibles/events.rs b/pop-api/src/v0/fungibles/events.rs new file mode 100644 index 00000000..b0639e10 --- /dev/null +++ b/pop-api/src/v0/fungibles/events.rs @@ -0,0 +1,82 @@ +/// A set of events for use in smart contracts interacting with the fungibles API. +/// +/// The `Transfer` and `Approval` events conform to the PSP-22 standard. The other events +/// (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. +/// +/// These events are not emitted by the API itself but can be used in your contracts to +/// track token operations. Be mindful of the costs associated with emitting events. +/// +/// For more details, refer to [ink! events](https://use.ink/basics/events). +use super::*; + +/// Event emitted when allowance by `owner` to `spender` changes. +#[ink::event] +pub struct Approval { + /// The owner providing the allowance. + #[ink(topic)] + pub owner: AccountId, + /// The beneficiary of the allowance. + #[ink(topic)] + pub spender: AccountId, + /// The new allowance amount. + pub value: u128, +} + +/// Event emitted when transfer of tokens occurs. +#[ink::event] +pub struct Transfer { + /// The source of the transfer. `None` when minting. + #[ink(topic)] + pub from: Option, + /// The recipient of the transfer. `None` when burning. + #[ink(topic)] + pub to: Option, + /// The amount transferred (or minted/burned). + pub value: u128, +} + +/// Event emitted when a token is created. +#[ink::event] +pub struct Created { + /// The token identifier. + #[ink(topic)] + pub id: TokenId, + /// The creator of the token. + #[ink(topic)] + pub creator: AccountId, + /// The administrator of the token. + #[ink(topic)] + pub admin: AccountId, +} + +/// Event emitted when a token is in the process of being destroyed. +#[ink::event] +pub struct DestroyStarted { + /// The token. + #[ink(topic)] + pub token: TokenId, +} + +/// Event emitted when new metadata is set for a token. +#[ink::event] +pub struct MetadataSet { + /// The token. + #[ink(topic)] + pub token: TokenId, + /// The name of the token. + #[ink(topic)] + pub name: Vec, + /// The symbol of the token. + #[ink(topic)] + pub symbol: Vec, + /// The decimals of the token. + pub decimals: u8, +} + +/// Event emitted when metadata is cleared for a token. +#[ink::event] +pub struct MetadataCleared { + /// The token. + #[ink(topic)] + pub token: TokenId, +} diff --git a/pop-api/src/v0/fungibles/interfaces.rs b/pop-api/src/v0/fungibles/interfaces.rs new file mode 100644 index 00000000..6023ce37 --- /dev/null +++ b/pop-api/src/v0/fungibles/interfaces.rs @@ -0,0 +1,215 @@ +use super::*; + +pub type Result = core::result::Result; + +#[ink::trait_definition] +pub trait Psp22 { + /// Returns the total token supply. + #[ink(message)] + fn total_supply(&self) -> Balance; + + /// Returns the account balance for the specified `owner`. + /// + /// # Parameters + /// - `owner` - The account whose balance is being queried. + /// + /// Returns `0` if the account is non-existent. + #[ink(message)] + fn balance_of(&self, owner: AccountId) -> Balance; + + /// Returns the allowance for a `spender` approved by an `owner`. + /// + /// # Parameters + /// - `owner` - The account that owns the tokens. + /// - `spender` - The account that is allowed to spend the tokens. + /// + /// Returns `0` if no allowance has been set. + #[ink(message)] + fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; + + /// Transfers `value` amount of tokens from the caller's account to account `to` + /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// - `data` - Additional data in unspecified format. + /// + /// # Events + /// On success a `Transfer` event is emitted. + /// + /// No-op if the caller and `to` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. + #[ink(message)] + fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; + + /// Transfers `value` tokens on behalf of `from` to the account `to` + /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `from` - The account from which the token balance will be withdrawn. + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// + /// If `from` and the caller are different addresses, the caller must be allowed + /// by `from` to spend at least `value` tokens. + /// + /// # Events + /// On success a `Transfer` event is emitted. + /// + /// No-op if `from` and `to` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// If `from` and the caller are different addresses, a successful transfer results + /// in decreased allowance by `from` to the caller and an `Approval` event with + /// the new allowance amount is emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account `from`. + /// + /// Reverts with `InsufficientAllowance` if `from` and the caller are different addresses and + /// the `value` exceeds the allowance granted by `from` to the caller. + /// + /// If conditions for both `InsufficientBalance` and `InsufficientAllowance` errors are met, + /// reverts with `InsufficientAllowance`. + #[ink(message)] + fn transfer_from( + &mut self, + from: AccountId, + to: AccountId, + value: Balance, + data: Vec, + ) -> Result<()>; + + /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. + /// + /// Successive calls of this method overwrite previous values. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to approve. + /// + /// # Events + /// An `Approval` event is emitted. + /// + /// No-op if the caller and `spender` is the same address, returns success and no events are emitted. + #[ink(message)] + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; + + /// Increases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to increase the allowance by. + /// + /// # Events + /// An `Approval` event with the new allowance amount is emitted. + /// + /// No-op if the caller and `spender` is the same address or `value` is zero, returns success + /// and no events are emitted. + #[ink(message)] + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + + /// Decreases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to decrease the allowance by. + /// + /// # Events + /// An `Approval` event with the new allowance amount is emitted. + /// + /// No-op if the caller and `spender` is the same address or `value` is zero, returns success + /// and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and + /// the `value` exceeds the allowance granted by the caller to `spender`. + #[ink(message)] + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; +} + +/// The PSP22 Metadata trait. +#[ink::trait_definition] +pub trait Psp22Managable { + #[ink(message)] + fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; + + #[ink(message)] + fn start_destroy(&mut self, token: TokenId) -> Result<()>; + + #[ink(message)] + fn set_metadata( + &mut self, + token: TokenId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()>; + + #[ink(message)] + fn clear_metadata(&mut self, token: TokenId) -> Result<()>; + + #[ink(message)] + fn token_exists(&self, token: TokenId) -> Result; +} + +/// The PSP22 Metadata trait. +#[ink::trait_definition] +pub trait Psp22Metadata { + /// Returns the token name. + #[ink(message)] + fn token_name(&self) -> Option>; + + /// Returns the token symbol. + #[ink(message)] + fn token_symbol(&self) -> Option>; + + /// Returns the token decimals. + #[ink(message)] + fn token_decimals(&self) -> u8; +} + +/// The PSP22 Mintable trait. +#[ink::trait_definition] +pub trait Psp22Mintable { + /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. + /// + /// # Parameters + /// - `account` - The account to be credited with the created tokens. + /// - `value` - The number of tokens to mint. + /// + /// # Events + /// On success a `Transfer` event is emitted with `None` sender. + /// + /// No-op if `value` is zero, returns success and no events are emitted. + /// + /// # Errors + /// Reverts with `Custom (max supply exceeded)` if the total supply increased by + /// `value` exceeds maximal value of `u128` type. + #[ink(message)] + fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; +} + +/// The PSP22 Burnable trait. +#[ink::trait_definition] +pub trait Psp22Burnable { + /// Destroys `value` amount of tokens from `account`, reducing the total supply. + /// + /// # Parameters + /// - `account` - The account from which the tokens will be destroyed. + /// - `value` - The number of tokens to destroy. + /// + /// # Events + /// On success a `Transfer` event is emitted with `None` recipient. + /// + /// No-op if `value` is zero, returns success and no events are emitted. + /// + /// # Errors + /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. + #[ink(message)] + fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; +} diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs new file mode 100644 index 00000000..e8d4e81d --- /dev/null +++ b/pop-api/src/v0/fungibles/mod.rs @@ -0,0 +1,343 @@ +//! The `fungibles` module provides an API for interacting and managing fungible tokens. +//! +//! The API includes the following interfaces: +//! 1. PSP-22 +//! 2. PSP-22 Metadata +//! 3. Management +//! 4. PSP-22 Mintable & Burnable +pub mod errors; +pub mod events; +pub mod interfaces; +#[cfg(test)] +mod tests; + +use crate::{ + constants::{ASSETS, BALANCES, FUNGIBLES}, + primitives::{AccountId, Balance, TokenId}, + ChainExtensionMethodApi, StatusCode, +}; +use constants::*; +pub use errors::*; +pub use events::*; +use ink::prelude::vec::Vec; +pub use interfaces::*; +pub use management::*; +pub use metadata::*; + +// Helper method to build a dispatch call. +// +// Parameters: +// - 'dispatchable': The index of the dispatchable function within the module. +fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { + crate::v0::build_dispatch(FUNGIBLES, dispatchable) +} + +// Helper method to build a call to read state. +// +// Parameters: +// - 'state_query': The index of the runtime state query. +fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { + crate::v0::build_read_state(FUNGIBLES, state_query) +} + +mod constants { + /// 1. PSP-22 Interface: + pub(super) const TOTAL_SUPPLY: u8 = 0; + pub(super) const BALANCE_OF: u8 = 1; + pub(super) const ALLOWANCE: u8 = 2; + pub(super) const TRANSFER: u8 = 3; + pub(super) const TRANSFER_FROM: u8 = 4; + pub(super) const APPROVE: u8 = 5; + pub(super) const INCREASE_ALLOWANCE: u8 = 6; + pub(super) const DECREASE_ALLOWANCE: u8 = 7; + + /// 2. PSP-22 Metadata Interface: + pub(super) const TOKEN_NAME: u8 = 8; + pub(super) const TOKEN_SYMBOL: u8 = 9; + pub(super) const TOKEN_DECIMALS: u8 = 10; + + /// 3. Asset Management: + pub(super) const CREATE: u8 = 11; + pub(super) const START_DESTROY: u8 = 12; + pub(super) const SET_METADATA: u8 = 16; + pub(super) const CLEAR_METADATA: u8 = 17; + pub(super) const TOKEN_EXISTS: u8 = 18; + + /// 4. PSP-22 Mintable & Burnable interface: + pub(super) const MINT: u8 = 19; + pub(super) const BURN: u8 = 20; +} + +/// Returns the total token supply for a specified token. +/// +/// # Parameters +/// - `token` - The token. +#[inline] +pub fn total_supply(token: TokenId) -> Result { + build_read_state(TOTAL_SUPPLY) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) +} + +/// Returns the account balance for a specified `token` and `owner`. Returns `0` if +/// the account is non-existent. +/// +/// # Parameters +/// - `token` - The token. +/// - `owner` - The account whose balance is being queried. +#[inline] +pub fn balance_of(token: TokenId, owner: AccountId) -> Result { + build_read_state(BALANCE_OF) + .input::<(TokenId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(token, owner)) +} + +/// Returns the allowance for a `spender` approved by an `owner`, for a specified `token`. Returns +/// `0` if no allowance has been set. +/// +/// # Parameters +/// - `token` - The token. +/// - `owner` - The account that owns the tokens. +/// - `spender` - The account that is allowed to spend the tokens. +#[inline] +pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result { + build_read_state(ALLOWANCE) + .input::<(TokenId, AccountId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(token, owner, spender)) +} + +/// Transfers `value` amount of tokens from the caller's account to account `to`. +/// +/// # Parameters +/// - `token` - The token to transfer. +/// - `to` - The recipient account. +/// - `value` - The number of tokens to transfer. +#[inline] +pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { + build_dispatch(TRANSFER) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, to, value)) +} + +/// Transfers `value` amount tokens on behalf of `from` to account `to`. +/// +/// # Parameters +/// - `token` - The token to transfer. +/// - `from` - The account from which the token balance will be withdrawn. +/// - `to` - The recipient account. +/// - `value` - The number of tokens to transfer. +#[inline] +pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { + build_dispatch(TRANSFER_FROM) + .input::<(TokenId, AccountId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, from, to, value)) +} + +/// Approves `spender` to spend `value` amount of tokens on behalf of the caller. +/// +/// # Parameters +/// - `token` - The token to approve. +/// - `spender` - The account that is allowed to spend the tokens. +/// - `value` - The number of tokens to approve. +#[inline] +pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { + build_dispatch(APPROVE) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, spender, value)) +} + +/// Increases the allowance of `spender` by `value` amount of tokens. +/// +/// # Parameters +/// - `token` - The token to have an allowance increased. +/// - `spender` - The account that is allowed to spend the tokens. +/// - `value` - The number of tokens to increase the allowance by. +#[inline] +pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { + build_dispatch(INCREASE_ALLOWANCE) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, spender, value)) +} + +/// Decreases the allowance of `spender` by `value` amount of tokens. +/// +/// # Parameters +/// - `token` - The token to have an allowance decreased. +/// - `spender` - The account that is allowed to spend the tokens. +/// - `value` - The number of tokens to decrease the allowance by. +#[inline] +pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { + build_dispatch(DECREASE_ALLOWANCE) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, spender, value)) +} + +/// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. +/// +/// # Parameters +/// - `token` - The token to mint. +/// - `account` - The account to be credited with the created tokens. +/// - `value` - The number of tokens to mint. +#[inline] +pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { + build_dispatch(MINT) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, account, value)) +} + +/// Destroys `value` amount of tokens from `account`, reducing the total supply. +/// +/// # Parameters +/// - `token` - the token to burn. +/// - `account` - The account from which the tokens will be destroyed. +/// - `value` - The number of tokens to destroy. +#[inline] +pub fn burn(token: TokenId, account: AccountId, value: Balance) -> Result<()> { + build_dispatch(BURN) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(token, account, value)) +} + +/// The PSP-22 compliant interface for querying metadata. +pub mod metadata { + use super::*; + + /// Returns the name of the specified token. + /// + /// # Parameters + /// - `token` - The token. + #[inline] + pub fn token_name(token: TokenId) -> Result> { + build_read_state(TOKEN_NAME) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(token)) + } + + /// Returns the symbol for the specified token. + /// + /// # Parameters + /// - `token` - The token. + #[inline] + pub fn token_symbol(token: TokenId) -> Result> { + build_read_state(TOKEN_SYMBOL) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(token)) + } + + /// Returns the decimals for the specified token. + /// + /// # Parameters + /// - `token` - The token. + #[inline] + pub fn token_decimals(token: TokenId) -> Result { + build_read_state(TOKEN_DECIMALS) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) + } +} + +/// The interface for creating, managing and destroying fungible tokens. +pub mod management { + use super::*; + + /// Create a new token with a given identifier. + /// + /// # Parameters + /// - `id` - The identifier of the token. + /// - `admin` - The account that will administer the token. + /// - `min_balance` - The minimum balance required for accounts holding this token. + #[inline] + pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()> { + build_dispatch(CREATE) + .input::<(TokenId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, admin, min_balance)) + } + + /// Start the process of destroying a token. + /// + /// # Parameters + /// - `token` - The token to be destroyed. + #[inline] + pub fn start_destroy(token: TokenId) -> Result<()> { + build_dispatch(START_DESTROY) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) + } + + /// Set the metadata for a token. + /// + /// # Parameters + /// - `token`: The token to update. + /// - `name`: The user friendly name of this token. + /// - `symbol`: The exchange symbol for this token. + /// - `decimals`: The number of decimals this token uses to represent one unit. + #[inline] + pub fn set_metadata( + token: TokenId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()> { + build_dispatch(SET_METADATA) + .input::<(TokenId, Vec, Vec, u8)>() + .output::, true>() + .handle_error_code::() + .call(&(token, name, symbol, decimals)) + } + + /// Clear the metadata for a token. + /// + /// # Parameters + /// - `token` - The token to update + #[inline] + pub fn clear_metadata(token: TokenId) -> Result<()> { + build_dispatch(CLEAR_METADATA) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) + } + + /// Checks if a specified token exists. + /// + /// # Parameters + /// - `token` - The token. + #[inline] + pub fn token_exists(token: TokenId) -> Result { + build_read_state(TOKEN_EXISTS) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(token)) + } +} diff --git a/pop-api/src/v0/fungibles/tests.rs b/pop-api/src/v0/fungibles/tests.rs new file mode 100644 index 00000000..128cf4cb --- /dev/null +++ b/pop-api/src/v0/fungibles/tests.rs @@ -0,0 +1,99 @@ +use super::FungiblesError; +use crate::{ + constants::{ASSETS, BALANCES}, + primitives::{ + ArithmeticError::*, + Error::{self, *}, + TokenError::*, + TransactionalError::*, + }, + StatusCode, +}; +use ink::scale::{Decode, Encode}; + +fn error_into_status_code(error: Error) -> StatusCode { + let mut encoded_error = error.encode(); + encoded_error.resize(4, 0); + let value = + u32::from_le_bytes(encoded_error.try_into().expect("qed, resized to 4 bytes line above")); + value.into() +} + +fn into_fungibles_error(error: Error) -> FungiblesError { + let status_code: StatusCode = error_into_status_code(error); + status_code.into() +} + +// If we ever want to change the conversion from bytes to `u32`. +#[test] +fn status_code_vs_encoded() { + assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 0, 0][..]).unwrap(), 13315u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 1, 0][..]).unwrap(), 78851u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 2, 0][..]).unwrap(), 144387u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 3, 0][..]).unwrap(), 209923u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 5, 0][..]).unwrap(), 340995u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 7, 0][..]).unwrap(), 472067u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 10, 0][..]).unwrap(), 668675u32); +} + +#[test] +fn converting_status_code_into_fungibles_error_works() { + let other_errors = vec![ + Other, + CannotLookup, + BadOrigin, + // `ModuleError` other than assets module. + Module { index: 2, error: [5, 0] }, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Token(OnlyProvider), + Arithmetic(Overflow), + Transactional(NoLayer), + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, + DecodingFailed, + ]; + for error in other_errors { + let status_code: StatusCode = error_into_status_code(error); + let fungibles_error: FungiblesError = status_code.into(); + assert_eq!(fungibles_error, FungiblesError::Other(status_code)) + } + + assert_eq!( + into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), + FungiblesError::NoBalance + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), + FungiblesError::NoAccount + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), + FungiblesError::NoPermission + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), + FungiblesError::Unknown + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), + FungiblesError::InUse + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), + FungiblesError::MinBalanceZero + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), + FungiblesError::InsufficientAllowance + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), + FungiblesError::NotLive + ); +} From 4ead643455b4fbf90b0d3bbfef7279557e4e38e3 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:45:48 +0800 Subject: [PATCH 090/161] refactor: fungible example --- pop-api/examples/fungibles/lib.rs | 297 +++++++++++++++++-------- pop-api/src/v0/fungibles/errors.rs | 30 +++ pop-api/src/v0/fungibles/interfaces.rs | 99 +++------ 3 files changed, 262 insertions(+), 164 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 2148e967..0b660ee6 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -1,159 +1,274 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::prelude::vec::Vec; +use ink::prelude::{string::String, vec::Vec}; use pop_api::{ primitives::TokenId, - v0::fungibles::{self as api}, - StatusCode, + v0::fungibles::{ + self as api, + events::{Approval, Created, Transfer}, + traits::{Psp22, Psp22Burnable, Psp22Metadata, Psp22Mintable}, + PSP22Error, + }, }; -#[cfg(test)] -mod tests; - -type PopApiResult = core::result::Result; - #[ink::contract] mod fungibles { use super::*; #[ink(storage)] - #[derive(Default)] - pub struct Fungibles; + pub struct Fungibles { + id: TokenId, + } impl Fungibles { + fn emit_created_event(&mut self, id: u32, creator: AccountId, admin: AccountId) { + self.env().emit_event(Created { id, creator, admin }); + } + + fn emit_transfer_event( + &mut self, + from: Option, + to: Option, + value: Balance, + ) { + self.env().emit_event(Transfer { from, to, value }); + } + + fn emit_approval_event(&mut self, owner: AccountId, spender: AccountId, value: Balance) { + self.env().emit_event(Approval { owner, spender, value }); + } + + /// Instantiate the contract and wrap around an existing token. + /// + /// # Parameters + /// * - `token` - The token. + #[ink(constructor, payable)] + pub fn new_existing(id: TokenId) -> Result { + // Make sure token exists. + if !api::token_exists(id).unwrap_or_default() { + return Err(PSP22Error::Custom(String::from("Unknown"))); + } + let contract = Self { id }; + Ok(contract) + } + + /// Instantiate the contract and create a new token. The token identifier will be stored + /// in contract's storage. + /// + /// # Parameters + /// * - `id` - The identifier of the token. + /// * - `admin` - The account that will administer the token. + /// * - `min_balance` - The minimum balance required for accounts holding this token. #[ink(constructor, payable)] - pub fn new() -> Self { - Default::default() + pub fn new( + id: TokenId, + admin: AccountId, + min_balance: Balance, + ) -> Result { + api::create(id, admin, min_balance).map_err(PSP22Error::from)?; + let mut contract = Self { id }; + contract.emit_created_event(id, contract.env().account_id(), admin); + Ok(contract) } + } + impl Psp22 for Fungibles { + /// Returns the total token supply. #[ink(message)] - pub fn mint( - &mut self, - token: TokenId, - account: AccountId, - amount: Balance, - ) -> PopApiResult<()> { - api::mint(token, account, amount) + fn total_supply(&self) -> Balance { + api::total_supply(self.id).unwrap_or_default() } + /// Returns the account balance for the specified `owner` #[ink(message)] - pub fn burn( - &mut self, - token: TokenId, - account: AccountId, - amount: Balance, - ) -> PopApiResult<()> { - api::burn(token, account, amount) + fn balance_of(&self, owner: AccountId) -> Balance { + api::balance_of(self.id, owner).unwrap_or_default() } + /// Returns the amount which `spender` is still allowed to withdraw from `owner` #[ink(message)] - pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> PopApiResult<()> { - api::transfer(token, to, value) + fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance { + api::allowance(self.id, owner, spender).unwrap_or_default() } + /// Transfers `value` amount of tokens from the caller's account to account `to` + /// with additional `data` in unspecified format. #[ink(message)] - pub fn transfer_from( + fn transfer( &mut self, - token: TokenId, - from: AccountId, to: AccountId, value: Balance, _data: Vec, - ) -> PopApiResult<()> { - api::transfer_from(token, from, to, value) + ) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if the caller and `to` is the same address or `value` is zero, returns success + // and no events are emitted. + if caller == to || value == 0 { + return Ok(()); + } + + // Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. + if value > self.env().balance() { + return Err(PSP22Error::InsufficientBalance); + } + + api::transfer(self.id, to, value).map_err(PSP22Error::from)?; + self.emit_transfer_event(Some(caller), Some(to), value); + Ok(()) } + /// Transfers `value` tokens on the behalf of `from` to the account `to` + /// with additional `data` in unspecified format. #[ink(message)] - pub fn approve( + fn transfer_from( &mut self, - token: TokenId, - spender: AccountId, + from: AccountId, + to: AccountId, value: Balance, - ) -> PopApiResult<()> { - api::approve(token, spender, value) + _data: Vec, + ) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if `from` and `to` is the same address or `value` is zero, returns success and + // no events are emitted. + if from == to || value == 0 { + return Ok(()); + } + + // Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account + // `from`. + let allowance = self.allowance(from, caller); + if allowance < value { + return Err(PSP22Error::InsufficientAllowance); + } + + // Reverts with `InsufficientAllowance` if `from` and the caller are different addresses + // and the `value` exceeds the allowance granted by `from` to the caller. + let from_balance = self.balance_of(from); + if from_balance < value { + return Err(PSP22Error::InsufficientBalance); + } + + // If `from` and the caller are different addresses, a successful transfer results + // in decreased allowance by `from` to the caller and an `Approval` event with + // the new allowance amount is emitted. + api::transfer_from(self.id, from, to, value).map_err(PSP22Error::from)?; + // Emit events. + self.emit_transfer_event(Some(caller), Some(to), value); + let allowance = self.allowance(from, to).saturating_sub(value); + self.emit_approval_event(from, caller, allowance); + Ok(()) } + /// Allows `spender` to withdraw from the caller's account multiple times, up to + /// the total amount of `value`. #[ink(message)] - pub fn increase_allowance( - &mut self, - token: TokenId, - spender: AccountId, - value: Balance, - ) -> PopApiResult<()> { - api::increase_allowance(token, spender, value) + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if the caller and `spender` is the same address, returns success and no events + // are emitted. + if caller == spender { + return Ok(()); + } + + api::approve(self.id, spender, value).map_err(PSP22Error::from)?; + self.emit_approval_event(caller, spender, value); + Ok(()) } + /// Increases by `value` the allowance granted to `spender` by the caller. #[ink(message)] - pub fn decrease_allowance( + fn increase_allowance( &mut self, - token: TokenId, spender: AccountId, value: Balance, - ) -> PopApiResult<()> { - api::decrease_allowance(token, spender, value) - } + ) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if the caller and `spender` is the same address or `value` is zero, returns success + // and no events are emitted. + if caller == spender || value == 0 { + return Ok(()); + } - #[ink(message, payable)] - pub fn create( - &self, - id: TokenId, - admin: AccountId, - min_balance: Balance, - ) -> PopApiResult<()> { - api::create(id, admin, min_balance)?; - self.env().emit_event(api::events::Created { id, creator: admin, admin }); + api::increase_allowance(self.id, spender, value).map_err(PSP22Error::from)?; + let allowance = self.allowance(caller, spender).saturating_add(value); + self.emit_approval_event(caller, spender, allowance); Ok(()) } + /// Decreases by `value` the allowance granted to `spender` by the caller. #[ink(message)] - pub fn set_metadata( - &self, - token: TokenId, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> PopApiResult<()> { - api::set_metadata(token, name, symbol, decimals) - } - - #[ink(message)] - pub fn total_supply(&self, token: TokenId) -> PopApiResult { - api::total_supply(token) - } + fn decrease_allowance( + &mut self, + spender: AccountId, + value: Balance, + ) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if the caller and `spender` is the same address or `value` is zero, returns success + // and no events are emitted. + if caller == spender || value == 0 { + return Ok(()); + } + // Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and + // the `value` exceeds the allowance granted by the caller to `spender`. + let allowance = self.allowance(caller, spender); + if allowance < value { + return Err(PSP22Error::InsufficientAllowance); + } - #[ink(message)] - pub fn balance_of(&self, token: TokenId, owner: AccountId) -> PopApiResult { - api::balance_of(token, owner) + api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; + let allowance = allowance.saturating_sub(value); + self.emit_approval_event(caller, spender, allowance); + Ok(()) } + } + impl Psp22Metadata for Fungibles { + /// Returns the token name. #[ink(message)] - pub fn allowance( - &self, - token: TokenId, - owner: AccountId, - spender: AccountId, - ) -> PopApiResult { - api::allowance(token, owner, spender) + fn token_name(&self) -> Option { + api::token_name(self.id).ok().and_then(|v| String::from_utf8(v).ok()) } + /// Returns the token symbol. #[ink(message)] - pub fn token_name(&self, token: TokenId) -> PopApiResult> { - api::token_name(token) + fn token_symbol(&self) -> Option { + api::token_symbol(self.id).ok().and_then(|v| String::from_utf8(v).ok()) } + /// Returns the token decimals. #[ink(message)] - pub fn token_symbol(&self, token: TokenId) -> PopApiResult> { - api::token_symbol(token) + fn token_decimals(&self) -> u8 { + api::token_decimals(self.id).unwrap_or_default() } + } + impl Psp22Mintable for Fungibles { + /// Mints `value` tokens to the senders account. #[ink(message)] - pub fn token_decimals(&self, token: TokenId) -> PopApiResult { - api::token_decimals(token) + fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { + if value == 0 { + return Ok(()); + } + api::mint(self.id, account, value).map_err(PSP22Error::from)?; + self.emit_transfer_event(None, Some(account), value); + Ok(()) } + } + impl Psp22Burnable for Fungibles { + /// Burns `value` tokens from the senders account. #[ink(message)] - pub fn token_exists(&self, token: TokenId) -> PopApiResult { - api::token_exists(token) + fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { + if value == 0 { + return Ok(()); + } + let balance = self.balance_of(account); + if balance < value { + return Err(PSP22Error::InsufficientBalance); + } + api::burn(self.id, account, value).map_err(PSP22Error::from)?; + self.emit_transfer_event(Some(account), None, value); + Ok(()) } } } diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index b29127e5..872e8d64 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -61,3 +61,33 @@ impl From for FungiblesError { } } } + +/// The PSP22 error. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum PSP22Error { + /// Custom error type for implementation-based errors. + Custom(String), + /// Returned when an account does not have enough tokens to complete the operation. + InsufficientBalance, + /// Returned if there is not enough allowance to complete the operation. + InsufficientAllowance, + /// Returned if recipient's address is zero. + ZeroRecipientAddress, + /// Returned if sender's address is zero. + ZeroSenderAddress, + /// Returned if a safe transfer check failed. + SafeTransferCheckFailed(String), +} + +impl From for PSP22Error { + /// Converts a `StatusCode` to a `PSP22Error`. + fn from(value: StatusCode) -> Self { + let encoded = value.0.to_le_bytes(); + match encoded { + [_, ASSETS, 3, _] => PSP22Error::Custom(String::from("Unknown")), + [_, ASSETS, 7, _] => PSP22Error::InsufficientAllowance, + _ => PSP22Error::Custom(String::from("Other")), + } + } +} diff --git a/pop-api/src/v0/fungibles/interfaces.rs b/pop-api/src/v0/fungibles/interfaces.rs index 6023ce37..5b52504a 100644 --- a/pop-api/src/v0/fungibles/interfaces.rs +++ b/pop-api/src/v0/fungibles/interfaces.rs @@ -12,8 +12,6 @@ pub trait Psp22 { /// /// # Parameters /// - `owner` - The account whose balance is being queried. - /// - /// Returns `0` if the account is non-existent. #[ink(message)] fn balance_of(&self, owner: AccountId) -> Balance; @@ -22,8 +20,6 @@ pub trait Psp22 { /// # Parameters /// - `owner` - The account that owns the tokens. /// - `spender` - The account that is allowed to spend the tokens. - /// - /// Returns `0` if no allowance has been set. #[ink(message)] fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; @@ -34,15 +30,6 @@ pub trait Psp22 { /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. /// - `data` - Additional data in unspecified format. - /// - /// # Events - /// On success a `Transfer` event is emitted. - /// - /// No-op if the caller and `to` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. #[ink(message)] fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; @@ -53,28 +40,6 @@ pub trait Psp22 { /// - `from` - The account from which the token balance will be withdrawn. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. - /// - /// If `from` and the caller are different addresses, the caller must be allowed - /// by `from` to spend at least `value` tokens. - /// - /// # Events - /// On success a `Transfer` event is emitted. - /// - /// No-op if `from` and `to` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// If `from` and the caller are different addresses, a successful transfer results - /// in decreased allowance by `from` to the caller and an `Approval` event with - /// the new allowance amount is emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account `from`. - /// - /// Reverts with `InsufficientAllowance` if `from` and the caller are different addresses and - /// the `value` exceeds the allowance granted by `from` to the caller. - /// - /// If conditions for both `InsufficientBalance` and `InsufficientAllowance` errors are met, - /// reverts with `InsufficientAllowance`. #[ink(message)] fn transfer_from( &mut self, @@ -91,11 +56,6 @@ pub trait Psp22 { /// # Parameters /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. - /// - /// # Events - /// An `Approval` event is emitted. - /// - /// No-op if the caller and `spender` is the same address, returns success and no events are emitted. #[ink(message)] fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; @@ -104,12 +64,6 @@ pub trait Psp22 { /// # Parameters /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. - /// - /// # Events - /// An `Approval` event with the new allowance amount is emitted. - /// - /// No-op if the caller and `spender` is the same address or `value` is zero, returns success - /// and no events are emitted. #[ink(message)] fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; @@ -118,16 +72,6 @@ pub trait Psp22 { /// # Parameters /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. - /// - /// # Events - /// An `Approval` event with the new allowance amount is emitted. - /// - /// No-op if the caller and `spender` is the same address or `value` is zero, returns success - /// and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and - /// the `value` exceeds the allowance granted by the caller to `spender`. #[ink(message)] fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; } @@ -135,12 +79,30 @@ pub trait Psp22 { /// The PSP22 Metadata trait. #[ink::trait_definition] pub trait Psp22Managable { + /// Creates a new token with the specified `id`, assigns `admin` as the administrator, + /// and sets a minimum balance requirement. + /// + /// # Parameters + /// - `id`: The unique identifier for the token to be created. + /// - `admin`: The account that will have administrative privileges over the token. + /// - `min_balance`: The minimum balance required to hold the token. #[ink(message)] fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; + /// Initiates the process to destroy the specified `token`. + /// + /// # Parameters + /// - `token`: The identifier of the token to be destroyed. #[ink(message)] fn start_destroy(&mut self, token: TokenId) -> Result<()>; + /// Sets metadata for the specified `token`, including its name, symbol, and decimal places. + /// + /// # Parameters + /// - `token`: The identifier of the token to set metadata for. + /// - `name`: The name of the token. + /// - `symbol`: The symbol representing the token. + /// - `decimals`: The number of decimal places the token uses. #[ink(message)] fn set_metadata( &mut self, @@ -150,9 +112,17 @@ pub trait Psp22Managable { decimals: u8, ) -> Result<()>; + /// Clears the metadata for the specified `token`. + /// + /// # Parameters + /// - `token`: The identifier of the token to clear metadata for. #[ink(message)] fn clear_metadata(&mut self, token: TokenId) -> Result<()>; + /// Checks whether a token with the specified `token` identifier exists. + /// + /// # Parameters + /// - `token`: The identifier of the token to check for existence. #[ink(message)] fn token_exists(&self, token: TokenId) -> Result; } @@ -181,15 +151,6 @@ pub trait Psp22Mintable { /// # Parameters /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. - /// - /// # Events - /// On success a `Transfer` event is emitted with `None` sender. - /// - /// No-op if `value` is zero, returns success and no events are emitted. - /// - /// # Errors - /// Reverts with `Custom (max supply exceeded)` if the total supply increased by - /// `value` exceeds maximal value of `u128` type. #[ink(message)] fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; } @@ -202,14 +163,6 @@ pub trait Psp22Burnable { /// # Parameters /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. - /// - /// # Events - /// On success a `Transfer` event is emitted with `None` recipient. - /// - /// No-op if `value` is zero, returns success and no events are emitted. - /// - /// # Errors - /// Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. #[ink(message)] fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; } From 12d1af4376392dbba9981aa8f71cda845872df64 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:39:13 +0800 Subject: [PATCH 091/161] feat: refactor example contract to follow spec --- pop-api/src/v0/fungibles/interfaces.rs | 28 +++++---- pop-api/src/v0/fungibles/mod.rs | 81 ++++++++++++++------------ 2 files changed, 58 insertions(+), 51 deletions(-) diff --git a/pop-api/src/v0/fungibles/interfaces.rs b/pop-api/src/v0/fungibles/interfaces.rs index 5b52504a..a4b48a4c 100644 --- a/pop-api/src/v0/fungibles/interfaces.rs +++ b/pop-api/src/v0/fungibles/interfaces.rs @@ -1,7 +1,5 @@ use super::*; -pub type Result = core::result::Result; - #[ink::trait_definition] pub trait Psp22 { /// Returns the total token supply. @@ -31,7 +29,7 @@ pub trait Psp22 { /// - `value` - The number of tokens to transfer. /// - `data` - Additional data in unspecified format. #[ink(message)] - fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<()>; + fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> PSP22Result<()>; /// Transfers `value` tokens on behalf of `from` to the account `to` /// with additional `data` in unspecified format. @@ -47,7 +45,7 @@ pub trait Psp22 { to: AccountId, value: Balance, data: Vec, - ) -> Result<()>; + ) -> PSP22Result<()>; /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. /// @@ -57,7 +55,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[ink(message)] - fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()>; + fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; /// Increases the allowance of `spender` by `value` amount of tokens. /// @@ -65,7 +63,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[ink(message)] - fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; /// Decreases the allowance of `spender` by `value` amount of tokens. /// @@ -73,12 +71,12 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[ink(message)] - fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<()>; + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; } /// The PSP22 Metadata trait. #[ink::trait_definition] -pub trait Psp22Managable { +pub trait Management { /// Creates a new token with the specified `id`, assigns `admin` as the administrator, /// and sets a minimum balance requirement. /// @@ -87,14 +85,14 @@ pub trait Psp22Managable { /// - `admin`: The account that will have administrative privileges over the token. /// - `min_balance`: The minimum balance required to hold the token. #[ink(message)] - fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()>; + fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> PSP22Result<()>; /// Initiates the process to destroy the specified `token`. /// /// # Parameters /// - `token`: The identifier of the token to be destroyed. #[ink(message)] - fn start_destroy(&mut self, token: TokenId) -> Result<()>; + fn start_destroy(&mut self, token: TokenId) -> PSP22Result<()>; /// Sets metadata for the specified `token`, including its name, symbol, and decimal places. /// @@ -110,21 +108,21 @@ pub trait Psp22Managable { name: Vec, symbol: Vec, decimals: u8, - ) -> Result<()>; + ) -> PSP22Result<()>; /// Clears the metadata for the specified `token`. /// /// # Parameters /// - `token`: The identifier of the token to clear metadata for. #[ink(message)] - fn clear_metadata(&mut self, token: TokenId) -> Result<()>; + fn clear_metadata(&mut self, token: TokenId) -> PSP22Result<()>; /// Checks whether a token with the specified `token` identifier exists. /// /// # Parameters /// - `token`: The identifier of the token to check for existence. #[ink(message)] - fn token_exists(&self, token: TokenId) -> Result; + fn token_exists(&self, token: TokenId) -> PSP22Result; } /// The PSP22 Metadata trait. @@ -152,7 +150,7 @@ pub trait Psp22Mintable { /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[ink(message)] - fn mint(&mut self, account: AccountId, amount: Balance) -> Result<()>; + fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()>; } /// The PSP22 Burnable trait. @@ -164,5 +162,5 @@ pub trait Psp22Burnable { /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[ink(message)] - fn burn(&mut self, account: AccountId, amount: Balance) -> Result<()>; + fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()>; } diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index e8d4e81d..da731819 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -17,6 +17,7 @@ use crate::{ ChainExtensionMethodApi, StatusCode, }; use constants::*; +use core::result::Result; pub use errors::*; pub use events::*; use ink::prelude::vec::Vec; @@ -24,6 +25,9 @@ pub use interfaces::*; pub use management::*; pub use metadata::*; +pub type PSP22Result = Result; +pub type PopApiResult = Result; + // Helper method to build a dispatch call. // // Parameters: @@ -73,10 +77,10 @@ mod constants { /// # Parameters /// - `token` - The token. #[inline] -pub fn total_supply(token: TokenId) -> Result { +pub fn total_supply(token: TokenId) -> PopApiResult { build_read_state(TOTAL_SUPPLY) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -88,10 +92,10 @@ pub fn total_supply(token: TokenId) -> Result { /// - `token` - The token. /// - `owner` - The account whose balance is being queried. #[inline] -pub fn balance_of(token: TokenId, owner: AccountId) -> Result { +pub fn balance_of(token: TokenId, owner: AccountId) -> PopApiResult { build_read_state(BALANCE_OF) .input::<(TokenId, AccountId)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, owner)) } @@ -104,10 +108,10 @@ pub fn balance_of(token: TokenId, owner: AccountId) -> Result { /// - `owner` - The account that owns the tokens. /// - `spender` - The account that is allowed to spend the tokens. #[inline] -pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result { +pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> PopApiResult { build_read_state(ALLOWANCE) .input::<(TokenId, AccountId, AccountId)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, owner, spender)) } @@ -119,10 +123,10 @@ pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { +pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(TRANSFER) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, to, value)) } @@ -135,10 +139,15 @@ pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { +pub fn transfer_from( + token: TokenId, + from: AccountId, + to: AccountId, + value: Balance, +) -> PopApiResult<()> { build_dispatch(TRANSFER_FROM) .input::<(TokenId, AccountId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, from, to, value)) } @@ -150,10 +159,10 @@ pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Bala /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[inline] -pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { +pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(APPROVE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -165,10 +174,10 @@ pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[inline] -pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { +pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(INCREASE_ALLOWANCE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -180,10 +189,10 @@ pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[inline] -pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { +pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(DECREASE_ALLOWANCE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -195,10 +204,10 @@ pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[inline] -pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { +pub fn mint(token: TokenId, account: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(MINT) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, account, value)) } @@ -210,10 +219,10 @@ pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[inline] -pub fn burn(token: TokenId, account: AccountId, value: Balance) -> Result<()> { +pub fn burn(token: TokenId, account: AccountId, value: Balance) -> PopApiResult<()> { build_dispatch(BURN) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, account, value)) } @@ -227,10 +236,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_name(token: TokenId) -> Result> { + pub fn token_name(token: TokenId) -> PopApiResult> { build_read_state(TOKEN_NAME) .input::() - .output::>, true>() + .output::>, true>() .handle_error_code::() .call(&(token)) } @@ -240,10 +249,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_symbol(token: TokenId) -> Result> { + pub fn token_symbol(token: TokenId) -> PopApiResult> { build_read_state(TOKEN_SYMBOL) .input::() - .output::>, true>() + .output::>, true>() .handle_error_code::() .call(&(token)) } @@ -253,10 +262,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_decimals(token: TokenId) -> Result { + pub fn token_decimals(token: TokenId) -> PopApiResult { build_read_state(TOKEN_DECIMALS) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -273,10 +282,10 @@ pub mod management { /// - `admin` - The account that will administer the token. /// - `min_balance` - The minimum balance required for accounts holding this token. #[inline] - pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()> { + pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> PopApiResult<()> { build_dispatch(CREATE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(id, admin, min_balance)) } @@ -286,10 +295,10 @@ pub mod management { /// # Parameters /// - `token` - The token to be destroyed. #[inline] - pub fn start_destroy(token: TokenId) -> Result<()> { + pub fn start_destroy(token: TokenId) -> PopApiResult<()> { build_dispatch(START_DESTROY) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -307,10 +316,10 @@ pub mod management { name: Vec, symbol: Vec, decimals: u8, - ) -> Result<()> { + ) -> PopApiResult<()> { build_dispatch(SET_METADATA) .input::<(TokenId, Vec, Vec, u8)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, name, symbol, decimals)) } @@ -320,10 +329,10 @@ pub mod management { /// # Parameters /// - `token` - The token to update #[inline] - pub fn clear_metadata(token: TokenId) -> Result<()> { + pub fn clear_metadata(token: TokenId) -> PopApiResult<()> { build_dispatch(CLEAR_METADATA) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -333,10 +342,10 @@ pub mod management { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_exists(token: TokenId) -> Result { + pub fn token_exists(token: TokenId) -> PopApiResult { build_read_state(TOKEN_EXISTS) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } From 24afd1522dab8c34d97c395327ee72ba38f0f012 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:59:19 +0800 Subject: [PATCH 092/161] test: psp22error --- pop-api/src/v0/fungibles/tests.rs | 44 ++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/pop-api/src/v0/fungibles/tests.rs b/pop-api/src/v0/fungibles/tests.rs index 128cf4cb..55b832e4 100644 --- a/pop-api/src/v0/fungibles/tests.rs +++ b/pop-api/src/v0/fungibles/tests.rs @@ -1,4 +1,4 @@ -use super::FungiblesError; +use super::{FungiblesError, PSP22Error}; use crate::{ constants::{ASSETS, BALANCES}, primitives::{ @@ -24,6 +24,11 @@ fn into_fungibles_error(error: Error) -> FungiblesError { status_code.into() } +fn into_psp22_error(error: Error) -> PSP22Error { + let status_code: StatusCode = error_into_status_code(error); + status_code.into() +} + // If we ever want to change the conversion from bytes to `u32`. #[test] fn status_code_vs_encoded() { @@ -97,3 +102,40 @@ fn converting_status_code_into_fungibles_error_works() { FungiblesError::NotLive ); } + +#[test] +fn converting_status_code_into_psp22_error_works() { + let other_errors = vec![ + Other, + CannotLookup, + BadOrigin, + // `ModuleError` other than assets module. + Module { index: 2, error: [5, 0] }, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Token(OnlyProvider), + Arithmetic(Overflow), + Transactional(NoLayer), + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, + DecodingFailed, + ]; + for error in other_errors { + let status_code: StatusCode = error_into_status_code(error); + let fungibles_error: PSP22Error = status_code.into(); + assert_eq!(fungibles_error, PSP22Error::Custom(String::from("Other"))) + } + + assert_eq!( + into_psp22_error(Module { index: ASSETS, error: [3, 0] }), + PSP22Error::Custom(String::from("Unknown")) + ); + assert_eq!( + into_psp22_error(Module { index: ASSETS, error: [7, 0] }), + PSP22Error::InsufficientAllowance + ); +} From 8ecf6d955ce88eae329268099be803be85dd2859 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:27:19 +0800 Subject: [PATCH 093/161] fix: missing String --- pop-api/src/v0/fungibles/errors.rs | 1 + pop-api/src/v0/fungibles/tests.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 872e8d64..486077c8 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,4 +1,5 @@ use super::*; +use ink::prelude::string::String; /// Represents various errors related to fungible tokens. /// diff --git a/pop-api/src/v0/fungibles/tests.rs b/pop-api/src/v0/fungibles/tests.rs index 55b832e4..bac16335 100644 --- a/pop-api/src/v0/fungibles/tests.rs +++ b/pop-api/src/v0/fungibles/tests.rs @@ -9,6 +9,7 @@ use crate::{ }, StatusCode, }; +use ink::prelude::string::String; use ink::scale::{Decode, Encode}; fn error_into_status_code(error: Error) -> StatusCode { From 6f521f4f14ce4512f1fd778ebdbaea8344df945d Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:41:13 +0800 Subject: [PATCH 094/161] fix: resolve comments --- pop-api/src/v0/fungibles/errors.rs | 149 ++++++++++++++++++ pop-api/src/v0/fungibles/events.rs | 20 +-- pop-api/src/v0/fungibles/mod.rs | 103 ++++++------ pop-api/src/v0/fungibles/tests.rs | 142 ----------------- .../v0/fungibles/{interfaces.rs => traits.rs} | 52 +----- 5 files changed, 211 insertions(+), 255 deletions(-) delete mode 100644 pop-api/src/v0/fungibles/tests.rs rename pop-api/src/v0/fungibles/{interfaces.rs => traits.rs} (68%) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 486077c8..c8dae082 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -11,6 +11,7 @@ use ink::prelude::string::String; /// operations. The `Other` variant serves as a catch-all for any unexpected errors. For more /// detailed debugging, the `Other` variant can be converted into the richer `Error` type defined in /// the primitives crate. +/// NOTE: The `FungiblesError` is WIP #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum FungiblesError { @@ -64,6 +65,7 @@ impl From for FungiblesError { } /// The PSP22 error. +/// TODO: Issue https://github.com/r0gue-io/pop-node/issues/298 #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum PSP22Error { @@ -92,3 +94,150 @@ impl From for PSP22Error { } } } + +#[cfg(test)] +mod tests { + use super::{FungiblesError, PSP22Error}; + use crate::{ + constants::{ASSETS, BALANCES}, + primitives::{ + ArithmeticError::*, + Error::{self, *}, + TokenError::*, + TransactionalError::*, + }, + StatusCode, + }; + use ink::prelude::string::String; + use ink::scale::{Decode, Encode}; + + fn error_into_status_code(error: Error) -> StatusCode { + let mut encoded_error = error.encode(); + encoded_error.resize(4, 0); + let value = u32::from_le_bytes( + encoded_error.try_into().expect("qed, resized to 4 bytes line above"), + ); + value.into() + } + + fn into_fungibles_error(error: Error) -> FungiblesError { + let status_code: StatusCode = error_into_status_code(error); + status_code.into() + } + + fn into_psp22_error(error: Error) -> PSP22Error { + let status_code: StatusCode = error_into_status_code(error); + status_code.into() + } + + // If we ever want to change the conversion from bytes to `u32`. + #[test] + fn status_code_vs_encoded() { + assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 0, 0][..]).unwrap(), 13315u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 1, 0][..]).unwrap(), 78851u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 2, 0][..]).unwrap(), 144387u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 3, 0][..]).unwrap(), 209923u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 5, 0][..]).unwrap(), 340995u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 7, 0][..]).unwrap(), 472067u32); + assert_eq!(u32::decode(&mut &[3u8, 52, 10, 0][..]).unwrap(), 668675u32); + } + + #[test] + fn converting_status_code_into_fungibles_error_works() { + let other_errors = vec![ + Other, + CannotLookup, + BadOrigin, + // `ModuleError` other than assets module. + Module { index: 2, error: [5, 0] }, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Token(OnlyProvider), + Arithmetic(Overflow), + Transactional(NoLayer), + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, + DecodingFailed, + ]; + for error in other_errors { + let status_code: StatusCode = error_into_status_code(error); + let fungibles_error: FungiblesError = status_code.into(); + assert_eq!(fungibles_error, FungiblesError::Other(status_code)) + } + + assert_eq!( + into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), + FungiblesError::NoBalance + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), + FungiblesError::NoAccount + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), + FungiblesError::NoPermission + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), + FungiblesError::Unknown + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), + FungiblesError::InUse + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), + FungiblesError::MinBalanceZero + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), + FungiblesError::InsufficientAllowance + ); + assert_eq!( + into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), + FungiblesError::NotLive + ); + } + + #[test] + fn converting_status_code_into_psp22_error_works() { + let other_errors = vec![ + Other, + CannotLookup, + BadOrigin, + // `ModuleError` other than assets module. + Module { index: 2, error: [5, 0] }, + ConsumerRemaining, + NoProviders, + TooManyConsumers, + Token(OnlyProvider), + Arithmetic(Overflow), + Transactional(NoLayer), + Exhausted, + Corruption, + Unavailable, + RootNotAllowed, + Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, + DecodingFailed, + ]; + for error in other_errors { + let status_code: StatusCode = error_into_status_code(error); + let fungibles_error: PSP22Error = status_code.into(); + assert_eq!(fungibles_error, PSP22Error::Custom(String::from("Other"))) + } + + assert_eq!( + into_psp22_error(Module { index: ASSETS, error: [3, 0] }), + PSP22Error::Custom(String::from("Unknown")) + ); + assert_eq!( + into_psp22_error(Module { index: ASSETS, error: [7, 0] }), + PSP22Error::InsufficientAllowance + ); + } +} diff --git a/pop-api/src/v0/fungibles/events.rs b/pop-api/src/v0/fungibles/events.rs index b0639e10..a018ac59 100644 --- a/pop-api/src/v0/fungibles/events.rs +++ b/pop-api/src/v0/fungibles/events.rs @@ -1,15 +1,16 @@ -/// A set of events for use in smart contracts interacting with the fungibles API. -/// -/// The `Transfer` and `Approval` events conform to the PSP-22 standard. The other events -/// (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. -/// -/// These events are not emitted by the API itself but can be used in your contracts to -/// track token operations. Be mindful of the costs associated with emitting events. -/// -/// For more details, refer to [ink! events](https://use.ink/basics/events). +//! A set of events for use in smart contracts interacting with the fungibles API. +//! +//! The `Transfer` and `Approval` events conform to the PSP-22 standard. The other events +//! (`Create`, `StartDestroy`, `SetMetadata`, `ClearMetadata`) are provided for convenience. +//! +//! These events are not emitted by the API itself but can be used in your contracts to +//! track token operations. Be mindful of the costs associated with emitting events. +//! +//! For more details, refer to [ink! events](https://use.ink/basics/events). use super::*; /// Event emitted when allowance by `owner` to `spender` changes. +// Differing style: event name abides by the PSP22 standard. #[ink::event] pub struct Approval { /// The owner providing the allowance. @@ -23,6 +24,7 @@ pub struct Approval { } /// Event emitted when transfer of tokens occurs. +// Differing style: event name abides by the PSP22 standard. #[ink::event] pub struct Transfer { /// The source of the transfer. `None` when minting. diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index da731819..e864f690 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -1,15 +1,10 @@ //! The `fungibles` module provides an API for interacting and managing fungible tokens. //! -//! The API includes the following interfaces: +//! The API includes the following traits: //! 1. PSP-22 //! 2. PSP-22 Metadata //! 3. Management //! 4. PSP-22 Mintable & Burnable -pub mod errors; -pub mod events; -pub mod interfaces; -#[cfg(test)] -mod tests; use crate::{ constants::{ASSETS, BALANCES, FUNGIBLES}, @@ -17,60 +12,18 @@ use crate::{ ChainExtensionMethodApi, StatusCode, }; use constants::*; -use core::result::Result; pub use errors::*; pub use events::*; use ink::prelude::vec::Vec; -pub use interfaces::*; pub use management::*; pub use metadata::*; +pub use traits::*; -pub type PSP22Result = Result; -pub type PopApiResult = Result; - -// Helper method to build a dispatch call. -// -// Parameters: -// - 'dispatchable': The index of the dispatchable function within the module. -fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { - crate::v0::build_dispatch(FUNGIBLES, dispatchable) -} - -// Helper method to build a call to read state. -// -// Parameters: -// - 'state_query': The index of the runtime state query. -fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { - crate::v0::build_read_state(FUNGIBLES, state_query) -} - -mod constants { - /// 1. PSP-22 Interface: - pub(super) const TOTAL_SUPPLY: u8 = 0; - pub(super) const BALANCE_OF: u8 = 1; - pub(super) const ALLOWANCE: u8 = 2; - pub(super) const TRANSFER: u8 = 3; - pub(super) const TRANSFER_FROM: u8 = 4; - pub(super) const APPROVE: u8 = 5; - pub(super) const INCREASE_ALLOWANCE: u8 = 6; - pub(super) const DECREASE_ALLOWANCE: u8 = 7; - - /// 2. PSP-22 Metadata Interface: - pub(super) const TOKEN_NAME: u8 = 8; - pub(super) const TOKEN_SYMBOL: u8 = 9; - pub(super) const TOKEN_DECIMALS: u8 = 10; +pub mod errors; +pub mod events; +pub mod traits; - /// 3. Asset Management: - pub(super) const CREATE: u8 = 11; - pub(super) const START_DESTROY: u8 = 12; - pub(super) const SET_METADATA: u8 = 16; - pub(super) const CLEAR_METADATA: u8 = 17; - pub(super) const TOKEN_EXISTS: u8 = 18; - - /// 4. PSP-22 Mintable & Burnable interface: - pub(super) const MINT: u8 = 19; - pub(super) const BURN: u8 = 20; -} +pub type PSP22Result = core::result::Result; /// Returns the total token supply for a specified token. /// @@ -350,3 +303,47 @@ pub mod management { .call(&(token)) } } + +mod constants { + /// 1. PSP-22 Interface: + pub(super) const TOTAL_SUPPLY: u8 = 0; + pub(super) const BALANCE_OF: u8 = 1; + pub(super) const ALLOWANCE: u8 = 2; + pub(super) const TRANSFER: u8 = 3; + pub(super) const TRANSFER_FROM: u8 = 4; + pub(super) const APPROVE: u8 = 5; + pub(super) const INCREASE_ALLOWANCE: u8 = 6; + pub(super) const DECREASE_ALLOWANCE: u8 = 7; + + /// 2. PSP-22 Metadata Interface: + pub(super) const TOKEN_NAME: u8 = 8; + pub(super) const TOKEN_SYMBOL: u8 = 9; + pub(super) const TOKEN_DECIMALS: u8 = 10; + + /// 3. Asset Management: + pub(super) const CREATE: u8 = 11; + pub(super) const START_DESTROY: u8 = 12; + pub(super) const SET_METADATA: u8 = 16; + pub(super) const CLEAR_METADATA: u8 = 17; + pub(super) const TOKEN_EXISTS: u8 = 18; + + /// 4. PSP-22 Mintable & Burnable interface: + pub(super) const MINT: u8 = 19; + pub(super) const BURN: u8 = 20; +} + +// Helper method to build a dispatch call. +// +// Parameters: +// - 'dispatchable': The index of the dispatchable function within the module. +fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { + crate::v0::build_dispatch(FUNGIBLES, dispatchable) +} + +// Helper method to build a call to read state. +// +// Parameters: +// - 'state_query': The index of the runtime state query. +fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { + crate::v0::build_read_state(FUNGIBLES, state_query) +} diff --git a/pop-api/src/v0/fungibles/tests.rs b/pop-api/src/v0/fungibles/tests.rs deleted file mode 100644 index bac16335..00000000 --- a/pop-api/src/v0/fungibles/tests.rs +++ /dev/null @@ -1,142 +0,0 @@ -use super::{FungiblesError, PSP22Error}; -use crate::{ - constants::{ASSETS, BALANCES}, - primitives::{ - ArithmeticError::*, - Error::{self, *}, - TokenError::*, - TransactionalError::*, - }, - StatusCode, -}; -use ink::prelude::string::String; -use ink::scale::{Decode, Encode}; - -fn error_into_status_code(error: Error) -> StatusCode { - let mut encoded_error = error.encode(); - encoded_error.resize(4, 0); - let value = - u32::from_le_bytes(encoded_error.try_into().expect("qed, resized to 4 bytes line above")); - value.into() -} - -fn into_fungibles_error(error: Error) -> FungiblesError { - let status_code: StatusCode = error_into_status_code(error); - status_code.into() -} - -fn into_psp22_error(error: Error) -> PSP22Error { - let status_code: StatusCode = error_into_status_code(error); - status_code.into() -} - -// If we ever want to change the conversion from bytes to `u32`. -#[test] -fn status_code_vs_encoded() { - assert_eq!(u32::decode(&mut &[3u8, 10, 2, 0][..]).unwrap(), 133635u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 0, 0][..]).unwrap(), 13315u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 1, 0][..]).unwrap(), 78851u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 2, 0][..]).unwrap(), 144387u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 3, 0][..]).unwrap(), 209923u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 5, 0][..]).unwrap(), 340995u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 7, 0][..]).unwrap(), 472067u32); - assert_eq!(u32::decode(&mut &[3u8, 52, 10, 0][..]).unwrap(), 668675u32); -} - -#[test] -fn converting_status_code_into_fungibles_error_works() { - let other_errors = vec![ - Other, - CannotLookup, - BadOrigin, - // `ModuleError` other than assets module. - Module { index: 2, error: [5, 0] }, - ConsumerRemaining, - NoProviders, - TooManyConsumers, - Token(OnlyProvider), - Arithmetic(Overflow), - Transactional(NoLayer), - Exhausted, - Corruption, - Unavailable, - RootNotAllowed, - Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, - DecodingFailed, - ]; - for error in other_errors { - let status_code: StatusCode = error_into_status_code(error); - let fungibles_error: FungiblesError = status_code.into(); - assert_eq!(fungibles_error, FungiblesError::Other(status_code)) - } - - assert_eq!( - into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), - FungiblesError::NoBalance - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), - FungiblesError::NoAccount - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), - FungiblesError::NoPermission - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), - FungiblesError::Unknown - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), - FungiblesError::InUse - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), - FungiblesError::MinBalanceZero - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), - FungiblesError::InsufficientAllowance - ); - assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), - FungiblesError::NotLive - ); -} - -#[test] -fn converting_status_code_into_psp22_error_works() { - let other_errors = vec![ - Other, - CannotLookup, - BadOrigin, - // `ModuleError` other than assets module. - Module { index: 2, error: [5, 0] }, - ConsumerRemaining, - NoProviders, - TooManyConsumers, - Token(OnlyProvider), - Arithmetic(Overflow), - Transactional(NoLayer), - Exhausted, - Corruption, - Unavailable, - RootNotAllowed, - Unknown { dispatch_error_index: 5, error_index: 5, error: 1 }, - DecodingFailed, - ]; - for error in other_errors { - let status_code: StatusCode = error_into_status_code(error); - let fungibles_error: PSP22Error = status_code.into(); - assert_eq!(fungibles_error, PSP22Error::Custom(String::from("Other"))) - } - - assert_eq!( - into_psp22_error(Module { index: ASSETS, error: [3, 0] }), - PSP22Error::Custom(String::from("Unknown")) - ); - assert_eq!( - into_psp22_error(Module { index: ASSETS, error: [7, 0] }), - PSP22Error::InsufficientAllowance - ); -} diff --git a/pop-api/src/v0/fungibles/interfaces.rs b/pop-api/src/v0/fungibles/traits.rs similarity index 68% rename from pop-api/src/v0/fungibles/interfaces.rs rename to pop-api/src/v0/fungibles/traits.rs index a4b48a4c..74ef742a 100644 --- a/pop-api/src/v0/fungibles/interfaces.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -38,6 +38,7 @@ pub trait Psp22 { /// - `from` - The account from which the token balance will be withdrawn. /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. + /// - `data` - Additional data with unspecified format. #[ink(message)] fn transfer_from( &mut self, @@ -74,57 +75,6 @@ pub trait Psp22 { fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; } -/// The PSP22 Metadata trait. -#[ink::trait_definition] -pub trait Management { - /// Creates a new token with the specified `id`, assigns `admin` as the administrator, - /// and sets a minimum balance requirement. - /// - /// # Parameters - /// - `id`: The unique identifier for the token to be created. - /// - `admin`: The account that will have administrative privileges over the token. - /// - `min_balance`: The minimum balance required to hold the token. - #[ink(message)] - fn create(&mut self, id: TokenId, admin: AccountId, min_balance: Balance) -> PSP22Result<()>; - - /// Initiates the process to destroy the specified `token`. - /// - /// # Parameters - /// - `token`: The identifier of the token to be destroyed. - #[ink(message)] - fn start_destroy(&mut self, token: TokenId) -> PSP22Result<()>; - - /// Sets metadata for the specified `token`, including its name, symbol, and decimal places. - /// - /// # Parameters - /// - `token`: The identifier of the token to set metadata for. - /// - `name`: The name of the token. - /// - `symbol`: The symbol representing the token. - /// - `decimals`: The number of decimal places the token uses. - #[ink(message)] - fn set_metadata( - &mut self, - token: TokenId, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> PSP22Result<()>; - - /// Clears the metadata for the specified `token`. - /// - /// # Parameters - /// - `token`: The identifier of the token to clear metadata for. - #[ink(message)] - fn clear_metadata(&mut self, token: TokenId) -> PSP22Result<()>; - - /// Checks whether a token with the specified `token` identifier exists. - /// - /// # Parameters - /// - `token`: The identifier of the token to check for existence. - #[ink(message)] - fn token_exists(&self, token: TokenId) -> PSP22Result; -} - /// The PSP22 Metadata trait. #[ink::trait_definition] pub trait Psp22Metadata { From 7ce5d52e29f031949cce67e41db4be77ef552068 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:46:14 +0800 Subject: [PATCH 095/161] fix: add mod comment --- pop-api/src/v0/fungibles/errors.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index c8dae082..30d98285 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,3 +1,4 @@ +//! A set of errors for use in smart contracts to manage the returned errors. use super::*; use ink::prelude::string::String; From b29cf17b10d731b5081811cf6d08de93bf7f53e0 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 21:37:49 +0700 Subject: [PATCH 096/161] fix: result type --- pop-api/src/v0/fungibles/mod.rs | 79 +++++++++++++++------------------ 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index e864f690..fe6c685e 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -9,7 +9,7 @@ use crate::{ constants::{ASSETS, BALANCES, FUNGIBLES}, primitives::{AccountId, Balance, TokenId}, - ChainExtensionMethodApi, StatusCode, + ChainExtensionMethodApi, Result, StatusCode, }; use constants::*; pub use errors::*; @@ -30,10 +30,10 @@ pub type PSP22Result = core::result::Result; /// # Parameters /// - `token` - The token. #[inline] -pub fn total_supply(token: TokenId) -> PopApiResult { +pub fn total_supply(token: TokenId) -> Result { build_read_state(TOTAL_SUPPLY) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -45,10 +45,10 @@ pub fn total_supply(token: TokenId) -> PopApiResult { /// - `token` - The token. /// - `owner` - The account whose balance is being queried. #[inline] -pub fn balance_of(token: TokenId, owner: AccountId) -> PopApiResult { +pub fn balance_of(token: TokenId, owner: AccountId) -> Result { build_read_state(BALANCE_OF) .input::<(TokenId, AccountId)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, owner)) } @@ -61,10 +61,10 @@ pub fn balance_of(token: TokenId, owner: AccountId) -> PopApiResult { /// - `owner` - The account that owns the tokens. /// - `spender` - The account that is allowed to spend the tokens. #[inline] -pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> PopApiResult { +pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> Result { build_read_state(ALLOWANCE) .input::<(TokenId, AccountId, AccountId)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, owner, spender)) } @@ -76,10 +76,10 @@ pub fn allowance(token: TokenId, owner: AccountId, spender: AccountId) -> PopApi /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> PopApiResult<()> { +pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> Result<()> { build_dispatch(TRANSFER) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, to, value)) } @@ -92,15 +92,10 @@ pub fn transfer(token: TokenId, to: AccountId, value: Balance) -> PopApiResult<( /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[inline] -pub fn transfer_from( - token: TokenId, - from: AccountId, - to: AccountId, - value: Balance, -) -> PopApiResult<()> { +pub fn transfer_from(token: TokenId, from: AccountId, to: AccountId, value: Balance) -> Result<()> { build_dispatch(TRANSFER_FROM) .input::<(TokenId, AccountId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, from, to, value)) } @@ -112,10 +107,10 @@ pub fn transfer_from( /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[inline] -pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { +pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(APPROVE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -127,10 +122,10 @@ pub fn approve(token: TokenId, spender: AccountId, value: Balance) -> PopApiResu /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[inline] -pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { +pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(INCREASE_ALLOWANCE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -142,10 +137,10 @@ pub fn increase_allowance(token: TokenId, spender: AccountId, value: Balance) -> /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[inline] -pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> PopApiResult<()> { +pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> Result<()> { build_dispatch(DECREASE_ALLOWANCE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, spender, value)) } @@ -157,10 +152,10 @@ pub fn decrease_allowance(token: TokenId, spender: AccountId, value: Balance) -> /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[inline] -pub fn mint(token: TokenId, account: AccountId, value: Balance) -> PopApiResult<()> { +pub fn mint(token: TokenId, account: AccountId, value: Balance) -> Result<()> { build_dispatch(MINT) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, account, value)) } @@ -172,10 +167,10 @@ pub fn mint(token: TokenId, account: AccountId, value: Balance) -> PopApiResult< /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[inline] -pub fn burn(token: TokenId, account: AccountId, value: Balance) -> PopApiResult<()> { +pub fn burn(token: TokenId, account: AccountId, value: Balance) -> Result<()> { build_dispatch(BURN) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, account, value)) } @@ -189,10 +184,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_name(token: TokenId) -> PopApiResult> { + pub fn token_name(token: TokenId) -> Result> { build_read_state(TOKEN_NAME) .input::() - .output::>, true>() + .output::>, true>() .handle_error_code::() .call(&(token)) } @@ -202,10 +197,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_symbol(token: TokenId) -> PopApiResult> { + pub fn token_symbol(token: TokenId) -> Result> { build_read_state(TOKEN_SYMBOL) .input::() - .output::>, true>() + .output::>, true>() .handle_error_code::() .call(&(token)) } @@ -215,10 +210,10 @@ pub mod metadata { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_decimals(token: TokenId) -> PopApiResult { + pub fn token_decimals(token: TokenId) -> Result { build_read_state(TOKEN_DECIMALS) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -235,10 +230,10 @@ pub mod management { /// - `admin` - The account that will administer the token. /// - `min_balance` - The minimum balance required for accounts holding this token. #[inline] - pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> PopApiResult<()> { + pub fn create(id: TokenId, admin: AccountId, min_balance: Balance) -> Result<()> { build_dispatch(CREATE) .input::<(TokenId, AccountId, Balance)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(id, admin, min_balance)) } @@ -248,10 +243,10 @@ pub mod management { /// # Parameters /// - `token` - The token to be destroyed. #[inline] - pub fn start_destroy(token: TokenId) -> PopApiResult<()> { + pub fn start_destroy(token: TokenId) -> Result<()> { build_dispatch(START_DESTROY) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -269,10 +264,10 @@ pub mod management { name: Vec, symbol: Vec, decimals: u8, - ) -> PopApiResult<()> { + ) -> Result<()> { build_dispatch(SET_METADATA) .input::<(TokenId, Vec, Vec, u8)>() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token, name, symbol, decimals)) } @@ -282,10 +277,10 @@ pub mod management { /// # Parameters /// - `token` - The token to update #[inline] - pub fn clear_metadata(token: TokenId) -> PopApiResult<()> { + pub fn clear_metadata(token: TokenId) -> Result<()> { build_dispatch(CLEAR_METADATA) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } @@ -295,10 +290,10 @@ pub mod management { /// # Parameters /// - `token` - The token. #[inline] - pub fn token_exists(token: TokenId) -> PopApiResult { + pub fn token_exists(token: TokenId) -> Result { build_read_state(TOKEN_EXISTS) .input::() - .output::, true>() + .output::, true>() .handle_error_code::() .call(&(token)) } From 933c62e80491f291b07812993e11fcd7c346eb56 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 22:22:09 +0700 Subject: [PATCH 097/161] fix: update PSP22Metadata --- pop-api/src/v0/fungibles/traits.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 74ef742a..01f25710 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -80,11 +80,11 @@ pub trait Psp22 { pub trait Psp22Metadata { /// Returns the token name. #[ink(message)] - fn token_name(&self) -> Option>; + fn token_name(&self) -> Option; /// Returns the token symbol. #[ink(message)] - fn token_symbol(&self) -> Option>; + fn token_symbol(&self) -> Option; /// Returns the token decimals. #[ink(message)] From de809068c982ae0a256999306832acd44f3c388d Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 22:25:06 +0700 Subject: [PATCH 098/161] fix: add comment for Psp22 trait --- pop-api/src/v0/fungibles/traits.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 01f25710..0d9d2d29 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,5 +1,6 @@ use super::*; +/// The PSP22 trait. #[ink::trait_definition] pub trait Psp22 { /// Returns the total token supply. From 8717adb1fb7376888e566d0aedaa58563f7daac6 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:13:42 +0700 Subject: [PATCH 099/161] fix: resolve comments --- pop-api/src/v0/fungibles/errors.rs | 4 ++-- pop-api/src/v0/fungibles/events.rs | 1 + pop-api/src/v0/fungibles/mod.rs | 10 ++++------ pop-api/src/v0/fungibles/traits.rs | 15 ++++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 30d98285..e76c4bcc 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,4 +1,4 @@ -//! A set of errors for use in smart contracts to manage the returned errors. +//! A set of errors for use in smart contracts that interact with the fungibles api. This includes errors compliant to standards. use super::*; use ink::prelude::string::String; @@ -66,7 +66,7 @@ impl From for FungiblesError { } /// The PSP22 error. -/// TODO: Issue https://github.com/r0gue-io/pop-node/issues/298 +// TODO: Issue https://github.com/r0gue-io/pop-node/issues/298 #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum PSP22Error { diff --git a/pop-api/src/v0/fungibles/events.rs b/pop-api/src/v0/fungibles/events.rs index a018ac59..130ead65 100644 --- a/pop-api/src/v0/fungibles/events.rs +++ b/pop-api/src/v0/fungibles/events.rs @@ -7,6 +7,7 @@ //! track token operations. Be mindful of the costs associated with emitting events. //! //! For more details, refer to [ink! events](https://use.ink/basics/events). + use super::*; /// Event emitted when allowance by `owner` to `spender` changes. diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index fe6c685e..77f5f32c 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -23,8 +23,6 @@ pub mod errors; pub mod events; pub mod traits; -pub type PSP22Result = core::result::Result; - /// Returns the total token supply for a specified token. /// /// # Parameters @@ -300,7 +298,7 @@ pub mod management { } mod constants { - /// 1. PSP-22 Interface: + /// 1. PSP-22 pub(super) const TOTAL_SUPPLY: u8 = 0; pub(super) const BALANCE_OF: u8 = 1; pub(super) const ALLOWANCE: u8 = 2; @@ -310,19 +308,19 @@ mod constants { pub(super) const INCREASE_ALLOWANCE: u8 = 6; pub(super) const DECREASE_ALLOWANCE: u8 = 7; - /// 2. PSP-22 Metadata Interface: + /// 2. PSP-22 Metadata pub(super) const TOKEN_NAME: u8 = 8; pub(super) const TOKEN_SYMBOL: u8 = 9; pub(super) const TOKEN_DECIMALS: u8 = 10; - /// 3. Asset Management: + /// 3. Management pub(super) const CREATE: u8 = 11; pub(super) const START_DESTROY: u8 = 12; pub(super) const SET_METADATA: u8 = 16; pub(super) const CLEAR_METADATA: u8 = 17; pub(super) const TOKEN_EXISTS: u8 = 18; - /// 4. PSP-22 Mintable & Burnable interface: + /// 4. PSP-22 Mintable & Burnable pub(super) const MINT: u8 = 19; pub(super) const BURN: u8 = 20; } diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 0d9d2d29..0220d363 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,3 +1,4 @@ +/// A set of traits that implement the PSP22 token standard. use super::*; /// The PSP22 trait. @@ -30,7 +31,7 @@ pub trait Psp22 { /// - `value` - The number of tokens to transfer. /// - `data` - Additional data in unspecified format. #[ink(message)] - fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> PSP22Result<()>; + fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<(), PSP22Error>; /// Transfers `value` tokens on behalf of `from` to the account `to` /// with additional `data` in unspecified format. @@ -47,7 +48,7 @@ pub trait Psp22 { to: AccountId, value: Balance, data: Vec, - ) -> PSP22Result<()>; + ) -> Result<(), PSP22Error>; /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. /// @@ -57,7 +58,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[ink(message)] - fn approve(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; /// Increases the allowance of `spender` by `value` amount of tokens. /// @@ -65,7 +66,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[ink(message)] - fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; /// Decreases the allowance of `spender` by `value` amount of tokens. /// @@ -73,7 +74,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[ink(message)] - fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> PSP22Result<()>; + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; } /// The PSP22 Metadata trait. @@ -101,7 +102,7 @@ pub trait Psp22Mintable { /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[ink(message)] - fn mint(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()>; + fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; } /// The PSP22 Burnable trait. @@ -113,5 +114,5 @@ pub trait Psp22Burnable { /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[ink(message)] - fn burn(&mut self, account: AccountId, amount: Balance) -> PSP22Result<()>; + fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; } From 8ae2c0000da19032a8cfd7b131702e03e247b041 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:18:36 +0700 Subject: [PATCH 100/161] fix: api integration tests --- pop-api/src/v0/fungibles/traits.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 0220d363..9bcf2e8d 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,5 +1,8 @@ -/// A set of traits that implement the PSP22 token standard. +//! A set of traits that implement the PSP22 token standard. + use super::*; +use ink::prelude::string::String; +use std::result::Result; /// The PSP22 trait. #[ink::trait_definition] From 97417e3431459d8141d8b6271190250f655b3d8c Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:49:26 +0700 Subject: [PATCH 101/161] fix: result type --- pop-api/src/v0/fungibles/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 9bcf2e8d..caa4c68d 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,8 +1,8 @@ //! A set of traits that implement the PSP22 token standard. use super::*; +use core::result::Result; use ink::prelude::string::String; -use std::result::Result; /// The PSP22 trait. #[ink::trait_definition] From 204ee060ae44fee7359020e0c513716b4b205ef9 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:13:42 +0700 Subject: [PATCH 102/161] fix: resolve comments --- pop-api/src/v0/fungibles/traits.rs | 383 ++++++++++++++++++++--------- 1 file changed, 268 insertions(+), 115 deletions(-) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index caa4c68d..0b660ee6 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,121 +1,274 @@ -//! A set of traits that implement the PSP22 token standard. - -use super::*; -use core::result::Result; -use ink::prelude::string::String; - -/// The PSP22 trait. -#[ink::trait_definition] -pub trait Psp22 { - /// Returns the total token supply. - #[ink(message)] - fn total_supply(&self) -> Balance; - - /// Returns the account balance for the specified `owner`. - /// - /// # Parameters - /// - `owner` - The account whose balance is being queried. - #[ink(message)] - fn balance_of(&self, owner: AccountId) -> Balance; - - /// Returns the allowance for a `spender` approved by an `owner`. - /// - /// # Parameters - /// - `owner` - The account that owns the tokens. - /// - `spender` - The account that is allowed to spend the tokens. - #[ink(message)] - fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; - - /// Transfers `value` amount of tokens from the caller's account to account `to` - /// with additional `data` in unspecified format. - /// - /// # Parameters - /// - `to` - The recipient account. - /// - `value` - The number of tokens to transfer. - /// - `data` - Additional data in unspecified format. - #[ink(message)] - fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<(), PSP22Error>; - - /// Transfers `value` tokens on behalf of `from` to the account `to` - /// with additional `data` in unspecified format. - /// - /// # Parameters - /// - `from` - The account from which the token balance will be withdrawn. - /// - `to` - The recipient account. - /// - `value` - The number of tokens to transfer. - /// - `data` - Additional data with unspecified format. - #[ink(message)] - fn transfer_from( - &mut self, - from: AccountId, - to: AccountId, - value: Balance, - data: Vec, - ) -> Result<(), PSP22Error>; - - /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. - /// - /// Successive calls of this method overwrite previous values. - /// - /// # Parameters - /// - `spender` - The account that is allowed to spend the tokens. - /// - `value` - The number of tokens to approve. - #[ink(message)] - fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; - - /// Increases the allowance of `spender` by `value` amount of tokens. - /// - /// # Parameters - /// - `spender` - The account that is allowed to spend the tokens. - /// - `value` - The number of tokens to increase the allowance by. - #[ink(message)] - fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; - - /// Decreases the allowance of `spender` by `value` amount of tokens. - /// - /// # Parameters - /// - `spender` - The account that is allowed to spend the tokens. - /// - `value` - The number of tokens to decrease the allowance by. - #[ink(message)] - fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; -} +#![cfg_attr(not(feature = "std"), no_std, no_main)] -/// The PSP22 Metadata trait. -#[ink::trait_definition] -pub trait Psp22Metadata { - /// Returns the token name. - #[ink(message)] - fn token_name(&self) -> Option; +use ink::prelude::{string::String, vec::Vec}; +use pop_api::{ + primitives::TokenId, + v0::fungibles::{ + self as api, + events::{Approval, Created, Transfer}, + traits::{Psp22, Psp22Burnable, Psp22Metadata, Psp22Mintable}, + PSP22Error, + }, +}; - /// Returns the token symbol. - #[ink(message)] - fn token_symbol(&self) -> Option; +#[ink::contract] +mod fungibles { + use super::*; - /// Returns the token decimals. - #[ink(message)] - fn token_decimals(&self) -> u8; -} + #[ink(storage)] + pub struct Fungibles { + id: TokenId, + } -/// The PSP22 Mintable trait. -#[ink::trait_definition] -pub trait Psp22Mintable { - /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. - /// - /// # Parameters - /// - `account` - The account to be credited with the created tokens. - /// - `value` - The number of tokens to mint. - #[ink(message)] - fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; -} + impl Fungibles { + fn emit_created_event(&mut self, id: u32, creator: AccountId, admin: AccountId) { + self.env().emit_event(Created { id, creator, admin }); + } + + fn emit_transfer_event( + &mut self, + from: Option, + to: Option, + value: Balance, + ) { + self.env().emit_event(Transfer { from, to, value }); + } + + fn emit_approval_event(&mut self, owner: AccountId, spender: AccountId, value: Balance) { + self.env().emit_event(Approval { owner, spender, value }); + } + + /// Instantiate the contract and wrap around an existing token. + /// + /// # Parameters + /// * - `token` - The token. + #[ink(constructor, payable)] + pub fn new_existing(id: TokenId) -> Result { + // Make sure token exists. + if !api::token_exists(id).unwrap_or_default() { + return Err(PSP22Error::Custom(String::from("Unknown"))); + } + let contract = Self { id }; + Ok(contract) + } + + /// Instantiate the contract and create a new token. The token identifier will be stored + /// in contract's storage. + /// + /// # Parameters + /// * - `id` - The identifier of the token. + /// * - `admin` - The account that will administer the token. + /// * - `min_balance` - The minimum balance required for accounts holding this token. + #[ink(constructor, payable)] + pub fn new( + id: TokenId, + admin: AccountId, + min_balance: Balance, + ) -> Result { + api::create(id, admin, min_balance).map_err(PSP22Error::from)?; + let mut contract = Self { id }; + contract.emit_created_event(id, contract.env().account_id(), admin); + Ok(contract) + } + } + + impl Psp22 for Fungibles { + /// Returns the total token supply. + #[ink(message)] + fn total_supply(&self) -> Balance { + api::total_supply(self.id).unwrap_or_default() + } + + /// Returns the account balance for the specified `owner` + #[ink(message)] + fn balance_of(&self, owner: AccountId) -> Balance { + api::balance_of(self.id, owner).unwrap_or_default() + } + + /// Returns the amount which `spender` is still allowed to withdraw from `owner` + #[ink(message)] + fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance { + api::allowance(self.id, owner, spender).unwrap_or_default() + } + + /// Transfers `value` amount of tokens from the caller's account to account `to` + /// with additional `data` in unspecified format. + #[ink(message)] + fn transfer( + &mut self, + to: AccountId, + value: Balance, + _data: Vec, + ) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if the caller and `to` is the same address or `value` is zero, returns success + // and no events are emitted. + if caller == to || value == 0 { + return Ok(()); + } + + // Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. + if value > self.env().balance() { + return Err(PSP22Error::InsufficientBalance); + } + + api::transfer(self.id, to, value).map_err(PSP22Error::from)?; + self.emit_transfer_event(Some(caller), Some(to), value); + Ok(()) + } + + /// Transfers `value` tokens on the behalf of `from` to the account `to` + /// with additional `data` in unspecified format. + #[ink(message)] + fn transfer_from( + &mut self, + from: AccountId, + to: AccountId, + value: Balance, + _data: Vec, + ) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if `from` and `to` is the same address or `value` is zero, returns success and + // no events are emitted. + if from == to || value == 0 { + return Ok(()); + } + + // Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account + // `from`. + let allowance = self.allowance(from, caller); + if allowance < value { + return Err(PSP22Error::InsufficientAllowance); + } + + // Reverts with `InsufficientAllowance` if `from` and the caller are different addresses + // and the `value` exceeds the allowance granted by `from` to the caller. + let from_balance = self.balance_of(from); + if from_balance < value { + return Err(PSP22Error::InsufficientBalance); + } + + // If `from` and the caller are different addresses, a successful transfer results + // in decreased allowance by `from` to the caller and an `Approval` event with + // the new allowance amount is emitted. + api::transfer_from(self.id, from, to, value).map_err(PSP22Error::from)?; + // Emit events. + self.emit_transfer_event(Some(caller), Some(to), value); + let allowance = self.allowance(from, to).saturating_sub(value); + self.emit_approval_event(from, caller, allowance); + Ok(()) + } + + /// Allows `spender` to withdraw from the caller's account multiple times, up to + /// the total amount of `value`. + #[ink(message)] + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if the caller and `spender` is the same address, returns success and no events + // are emitted. + if caller == spender { + return Ok(()); + } + + api::approve(self.id, spender, value).map_err(PSP22Error::from)?; + self.emit_approval_event(caller, spender, value); + Ok(()) + } + + /// Increases by `value` the allowance granted to `spender` by the caller. + #[ink(message)] + fn increase_allowance( + &mut self, + spender: AccountId, + value: Balance, + ) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if the caller and `spender` is the same address or `value` is zero, returns success + // and no events are emitted. + if caller == spender || value == 0 { + return Ok(()); + } + + api::increase_allowance(self.id, spender, value).map_err(PSP22Error::from)?; + let allowance = self.allowance(caller, spender).saturating_add(value); + self.emit_approval_event(caller, spender, allowance); + Ok(()) + } + + /// Decreases by `value` the allowance granted to `spender` by the caller. + #[ink(message)] + fn decrease_allowance( + &mut self, + spender: AccountId, + value: Balance, + ) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + // No-op if the caller and `spender` is the same address or `value` is zero, returns success + // and no events are emitted. + if caller == spender || value == 0 { + return Ok(()); + } + // Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and + // the `value` exceeds the allowance granted by the caller to `spender`. + let allowance = self.allowance(caller, spender); + if allowance < value { + return Err(PSP22Error::InsufficientAllowance); + } + + api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; + let allowance = allowance.saturating_sub(value); + self.emit_approval_event(caller, spender, allowance); + Ok(()) + } + } + + impl Psp22Metadata for Fungibles { + /// Returns the token name. + #[ink(message)] + fn token_name(&self) -> Option { + api::token_name(self.id).ok().and_then(|v| String::from_utf8(v).ok()) + } + + /// Returns the token symbol. + #[ink(message)] + fn token_symbol(&self) -> Option { + api::token_symbol(self.id).ok().and_then(|v| String::from_utf8(v).ok()) + } + + /// Returns the token decimals. + #[ink(message)] + fn token_decimals(&self) -> u8 { + api::token_decimals(self.id).unwrap_or_default() + } + } + + impl Psp22Mintable for Fungibles { + /// Mints `value` tokens to the senders account. + #[ink(message)] + fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { + if value == 0 { + return Ok(()); + } + api::mint(self.id, account, value).map_err(PSP22Error::from)?; + self.emit_transfer_event(None, Some(account), value); + Ok(()) + } + } -/// The PSP22 Burnable trait. -#[ink::trait_definition] -pub trait Psp22Burnable { - /// Destroys `value` amount of tokens from `account`, reducing the total supply. - /// - /// # Parameters - /// - `account` - The account from which the tokens will be destroyed. - /// - `value` - The number of tokens to destroy. - #[ink(message)] - fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; + impl Psp22Burnable for Fungibles { + /// Burns `value` tokens from the senders account. + #[ink(message)] + fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { + if value == 0 { + return Ok(()); + } + let balance = self.balance_of(account); + if balance < value { + return Err(PSP22Error::InsufficientBalance); + } + api::burn(self.id, account, value).map_err(PSP22Error::from)?; + self.emit_transfer_event(Some(account), None, value); + Ok(()) + } + } } From 867cc283f1561c6bd73f011c1a38edd43f95701b Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 20 Sep 2024 18:03:11 +0700 Subject: [PATCH 103/161] feat: drink test for example contract --- pop-api/examples/fungibles/Cargo.toml | 1 + pop-api/examples/fungibles/lib.rs | 24 +-- pop-api/examples/fungibles/tests.rs | 209 +++++++++++--------------- pop-api/src/v0/fungibles/errors.rs | 13 +- pop-api/src/v0/fungibles/mod.rs | 11 +- pop-api/src/v0/fungibles/traits.rs | 4 +- 6 files changed, 122 insertions(+), 140 deletions(-) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 075ea943..c06bc0f5 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -20,6 +20,7 @@ scale-info = { version = "2.6", default-features = false, features = [ drink = { path = "../../../../pop-drink/drink" } env_logger = { version = "0.11.3" } pop-sandbox = { path = "../../../pop-sandbox", default-features = false } +serde_json = "1.0.114" [lib] path = "lib.rs" diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 0b660ee6..e3457e18 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -11,6 +11,9 @@ use pop_api::{ }, }; +#[cfg(test)] +mod tests; + #[ink::contract] mod fungibles { use super::*; @@ -62,12 +65,14 @@ mod fungibles { #[ink(constructor, payable)] pub fn new( id: TokenId, - admin: AccountId, + // TODO: If admin is different than the contract address, `NoPermission` thrown for mint, burn + // _admin: AccountId, min_balance: Balance, ) -> Result { - api::create(id, admin, min_balance).map_err(PSP22Error::from)?; let mut contract = Self { id }; - contract.emit_created_event(id, contract.env().account_id(), admin); + let contract_id = contract.env().account_id(); + api::create(id, contract_id, min_balance).map_err(PSP22Error::from)?; + contract.emit_created_event(id, contract_id, contract_id); Ok(contract) } } @@ -183,8 +188,8 @@ mod fungibles { value: Balance, ) -> Result<(), PSP22Error> { let caller = self.env().caller(); - // No-op if the caller and `spender` is the same address or `value` is zero, returns success - // and no events are emitted. + // No-op if the caller and `spender` is the same address or `value` is zero, returns + // success and no events are emitted. if caller == spender || value == 0 { return Ok(()); } @@ -203,13 +208,14 @@ mod fungibles { value: Balance, ) -> Result<(), PSP22Error> { let caller = self.env().caller(); - // No-op if the caller and `spender` is the same address or `value` is zero, returns success - // and no events are emitted. + // No-op if the caller and `spender` is the same address or `value` is zero, returns + // success and no events are emitted. if caller == spender || value == 0 { return Ok(()); } - // Reverts with `InsufficientAllowance` if `spender` and the caller are different addresses and - // the `value` exceeds the allowance granted by the caller to `spender`. + // Reverts with `InsufficientAllowance` if `spender` and the caller are different + // addresses and the `value` exceeds the allowance granted by the caller to + // `spender`. let allowance = self.allowance(caller, spender); if allowance < value { return Err(PSP22Error::InsufficientAllowance); diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 216b9de3..89d4298e 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -1,15 +1,14 @@ -use drink::session::{Session, NO_ARGS, NO_SALT}; +use drink::session::{error::SessionError, Session, NO_ARGS, NO_SALT}; use pop_api::{ - primitives::TokenId, - v0::fungibles::{self as api}, + primitives::{AccountId, TokenId}, + v0::fungibles::{self as api, PSP22Error}, }; use pop_sandbox::{AccountId32, Balance, Sandbox, ALICE, BOB, INIT_VALUE}; use scale::{Decode, Encode}; use super::*; -const TOKEN_A: TokenId = 1; -const TOKEN_B: TokenId = 2; +const TOKEN_ID: TokenId = 1; #[drink::contract_bundle_provider] enum BundleProvider {} @@ -20,8 +19,8 @@ mod test_methods { use super::*; // Decode slice of bytes to `pop-api` AccountId. - pub(super) fn account_id_from_slice(s: &[u8; 32]) -> pop_api::primitives::AccountId { - pop_api::primitives::AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") + pub(super) fn account_id_from_slice(s: &[u8; 32]) -> AccountId { + AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") } // Call a contract method and decode the returned data. @@ -42,175 +41,143 @@ mod test_methods { assert_eq!(last_event, event.as_slice()); } - pub(super) fn mint( + // Test methods for deployment with constructor function. + + pub(super) fn deploy_with_new_constructor( session: &mut Session, - token: TokenId, - account: AccountId32, - amount: Balance, - ) -> Result<(), Box> { - Ok(session.call( - "mint", - &vec![token.to_string(), account.to_string(), amount.to_string()], - None, - )??) + id: TokenId, + min_balance: Balance, + ) -> Result { + session.deploy_bundle( + BundleProvider::local()?, + "new", + &[id.to_string(), min_balance.to_string()], + NO_SALT, + Some(INIT_VALUE), + ) } - pub(super) fn burn( + // Test methods for `PSP22`.` + + pub(super) fn total_supply( session: &mut Session, - token: TokenId, - account: AccountId32, - amount: Balance, - ) -> Result<(), Box> { - Ok(session.call( - "burn", - &vec![token.to_string(), account.to_string(), amount.to_string()], - None, - )??) + ) -> Result> { + Ok(decoded_call::(session, "Psp22::total_supply", vec![], None)?) + } + + pub(super) fn balance_of( + session: &mut Session, + owner: AccountId32, + ) -> Result> { + Ok(decoded_call::(session, "Psp22::balance_of", vec![owner.to_string()], None)?) } pub(super) fn transfer( session: &mut Session, - token: TokenId, to: AccountId32, amount: Balance, ) -> Result<(), Box> { + let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); Ok(session.call( - "transfer", - &vec![token.to_string(), to.to_string(), amount.to_string()], + "Psp22::transfer", + &vec![to.to_string(), amount.to_string(), data], None, )??) } - pub(super) fn create( + // Test methods for `PSP22Metadata``. + + pub(super) fn token_name( session: &mut Session, - id: TokenId, - admin: AccountId32, - min_balance: Balance, - ) -> Result<(), Box> { - Ok(session.call( - "create", - &vec![id.to_string(), admin.to_string(), min_balance.to_string()], - None, - )??) + ) -> Result> { + Ok(decoded_call::(session, "Psp22Metadata::token_name", vec![], None)?) } - pub(super) fn token_exist( + pub(super) fn token_symbol( session: &mut Session, - token: TokenId, - ) -> Result, Box> { - Ok(decoded_call::>(session, "token_exists", vec![token.to_string()], None)?) + ) -> Result> { + Ok(decoded_call::(session, "Psp22Metadata::token_symbol", vec![], None)?) } - pub(super) fn total_supply( + pub(super) fn token_decimals( session: &mut Session, - token: TokenId, - ) -> Result, Box> { - Ok(decoded_call::>( - session, - "total_supply", - vec![token.to_string()], - None, - )?) + ) -> Result> { + Ok(decoded_call::(session, "Psp22Metadata::token_decimals", vec![], None)?) } - pub(super) fn balance_of( + // Test methods for `PSP22Mintable``. + + pub(super) fn mint( session: &mut Session, - token: TokenId, - owner: AccountId32, - ) -> Result, Box> { - Ok(decoded_call::>( - session, - "balance_of", - vec![token.to_string(), owner.to_string()], + account: AccountId32, + amount: Balance, + ) -> Result<(), Box> { + Ok(session.call( + "Psp22Mintable::mint", + &vec![account.to_string(), amount.to_string()], None, - )?) + )??) } -} -#[drink::test(sandbox = Sandbox)] -fn test_create_multiple_token_works( - mut session: Session, -) -> Result<(), Box> { - let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - // Deploy a contract. - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - // Create new tokens. - create(&mut session, TOKEN_A, ALICE, 1_000)?; - - assert_event( - &mut session, - api::events::Created { - id: TOKEN_A, - admin: account_id_from_slice(ALICE.as_ref()), - creator: account_id_from_slice(ALICE.as_ref()), - } - .encode(), - ); - - create(&mut session, TOKEN_B, ALICE, 2_000)?; - // Check that the token is created successfully. - assert_eq!(token_exist(&mut session, TOKEN_A)?, Ok(true)); - assert_eq!(token_exist(&mut session, TOKEN_B)?, Ok(true)); - Ok(()) + // Test methods for `PSP22MPsp22Burnablentable``. + + pub(super) fn burn( + session: &mut Session, + account: AccountId32, + amount: Balance, + ) -> Result<(), Box> { + Ok(session.call( + "Psp22Burnable::burn", + &vec![account.to_string(), amount.to_string()], + None, + )??) + } } #[drink::test(sandbox = Sandbox)] fn test_mint_token_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - // Deploy a contract. - let contract_address = - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - // Create a new token. - create(&mut session, TOKEN_A, contract_address, 10_000)?; + // Deploy a new contract. + let contract_address = deploy_with_new_constructor(&mut session, 1, 10_000)?; // Mint tokens. const AMOUNT: Balance = 12_000; - mint(&mut session, TOKEN_A, ALICE, AMOUNT)?; - mint(&mut session, TOKEN_A, BOB, AMOUNT)?; + mint(&mut session, ALICE, AMOUNT)?; + mint(&mut session, BOB, AMOUNT)?; // Check if the tokens were minted with the right amount. - assert_eq!(total_supply(&mut session, TOKEN_A)?, Ok(AMOUNT * 2)); - assert_eq!(balance_of(&mut session, TOKEN_A, ALICE)?, Ok(AMOUNT)); - assert_eq!(balance_of(&mut session, TOKEN_A, BOB)?, Ok(AMOUNT)); + assert_eq!(total_supply(&mut session)?, AMOUNT * 2); + assert_eq!(balance_of(&mut session, ALICE)?, AMOUNT); + assert_eq!(balance_of(&mut session, BOB)?, AMOUNT); Ok(()) } #[drink::test(sandbox = Sandbox)] fn test_burn_token_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - // Deploy a contract. - let contract_address = - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - // Create a new token. - create(&mut session, TOKEN_A, contract_address, 10_000)?; + // Deploy a new contract. + let contract_address = deploy_with_new_constructor(&mut session, TOKEN_ID, 10_000)?; // Mint tokens. const AMOUNT: Balance = 12_000; - mint(&mut session, TOKEN_A, ALICE, AMOUNT)?; + mint(&mut session, ALICE, AMOUNT)?; // Burn tokens. - burn(&mut session, TOKEN_A, ALICE, 1)?; - assert_eq!(total_supply(&mut session, TOKEN_A)?, Ok(AMOUNT - 1)); - assert_eq!(balance_of(&mut session, TOKEN_A, ALICE)?, Ok(AMOUNT - 1)); + burn(&mut session, ALICE, 1)?; + assert_eq!(total_supply(&mut session)?, AMOUNT - 1); + assert_eq!(balance_of(&mut session, ALICE)?, AMOUNT - 1); Ok(()) } #[drink::test(sandbox = Sandbox)] fn test_transfer_token_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - // Deploy a contract. - let contract_address = - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - // Create a new token. - create(&mut session, TOKEN_A, contract_address.clone(), 10_000)?; + // Deploy a new contract. + let contract_address = deploy_with_new_constructor(&mut session, TOKEN_ID, 10_000)?; // Mint tokens. const AMOUNT: Balance = 12_000; const TRANSFERED: Balance = 500; - mint(&mut session, TOKEN_A, contract_address.clone(), AMOUNT)?; - mint(&mut session, TOKEN_A, BOB, AMOUNT)?; + mint(&mut session, contract_address.clone(), AMOUNT)?; + mint(&mut session, BOB, AMOUNT)?; // Transfer tokens. - transfer(&mut session, TOKEN_A, BOB, TRANSFERED)?; - assert_eq!(balance_of(&mut session, TOKEN_A, contract_address)?, Ok(AMOUNT - TRANSFERED)); - assert_eq!(balance_of(&mut session, TOKEN_A, BOB)?, Ok(AMOUNT + TRANSFERED)); + transfer(&mut session, BOB, TRANSFERED)?; + assert_eq!(balance_of(&mut session, contract_address)?, AMOUNT - TRANSFERED); + assert_eq!(balance_of(&mut session, BOB)?, AMOUNT + TRANSFERED); Ok(()) } diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 313107b4..a6df4348 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,8 +1,10 @@ -//! A set of errors for use in smart contracts that interact with the fungibles api. This includes errors compliant to standards. +//! A set of errors for use in smart contracts that interact with the fungibles api. This includes +//! errors compliant to standards. -use super::*; use ink::prelude::string::String; +use super::*; + /// Represents various errors related to fungible tokens. /// /// The `FungiblesError` provides a detailed and specific set of error types that can occur when @@ -99,6 +101,11 @@ impl From for PSP22Error { #[cfg(test)] mod tests { + use ink::{ + prelude::string::String, + scale::{Decode, Encode}, + }; + use super::{FungiblesError, PSP22Error}; use crate::{ constants::{ASSETS, BALANCES}, @@ -110,8 +117,6 @@ mod tests { }, StatusCode, }; - use ink::prelude::string::String; - use ink::scale::{Decode, Encode}; fn error_into_status_code(error: Error) -> StatusCode { let mut encoded_error = error.encode(); diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index 77f5f32c..7d1594c0 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -6,11 +6,6 @@ //! 3. Management //! 4. PSP-22 Mintable & Burnable -use crate::{ - constants::{ASSETS, BALANCES, FUNGIBLES}, - primitives::{AccountId, Balance, TokenId}, - ChainExtensionMethodApi, Result, StatusCode, -}; use constants::*; pub use errors::*; pub use events::*; @@ -19,6 +14,12 @@ pub use management::*; pub use metadata::*; pub use traits::*; +use crate::{ + constants::{ASSETS, BALANCES, FUNGIBLES}, + primitives::{AccountId, Balance, TokenId}, + ChainExtensionMethodApi, Result, StatusCode, +}; + pub mod errors; pub mod events; pub mod traits; diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index caa4c68d..6d7bda79 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,9 +1,11 @@ //! A set of traits that implement the PSP22 token standard. -use super::*; use core::result::Result; + use ink::prelude::string::String; +use super::*; + /// The PSP22 trait. #[ink::trait_definition] pub trait Psp22 { From 7dc60472c409f4834353271d8bf801c4de3baa8b Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 20 Sep 2024 19:14:41 +0700 Subject: [PATCH 104/161] refactor: add helpers module --- pop-api/examples/fungibles/helpers.rs | 128 ++++++++++++++++++ pop-api/examples/fungibles/lib.rs | 2 + pop-api/examples/fungibles/tests.rs | 182 ++++++++------------------ 3 files changed, 182 insertions(+), 130 deletions(-) create mode 100644 pop-api/examples/fungibles/helpers.rs diff --git a/pop-api/examples/fungibles/helpers.rs b/pop-api/examples/fungibles/helpers.rs new file mode 100644 index 00000000..5cf1d616 --- /dev/null +++ b/pop-api/examples/fungibles/helpers.rs @@ -0,0 +1,128 @@ +// A set of helper methods to test the contract calls. + +use drink::session::{bundle::ContractBundle, error::SessionError, Session, NO_SALT}; +use pop_api::primitives::{AccountId, TokenId}; +use pop_sandbox::{AccountId32, Balance, Sandbox, INIT_VALUE}; +use scale::{Decode, Encode}; + +use super::*; + +// Decode slice of bytes to `pop-api` AccountId. +pub(super) fn account_id_from_slice(s: &[u8; 32]) -> AccountId { + AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") +} + +// Call a contract method and decode the returned data. +pub(super) fn decoded_call( + session: &mut Session, + func_name: &str, + input: Vec, + endowment: Option, +) -> Result> { + session.call(func_name, &input, endowment)??; + Ok(session.record().last_call_return_decoded::()??) +} + +// Check if the event emitted correctly. +pub(super) fn assert_event(session: &mut Session, event: Vec) { + let contract_events = session.record().last_event_batch().contract_events(); + let last_event = contract_events.last().unwrap().to_vec(); + assert_eq!(last_event, event.as_slice()); +} + +// Test methods for deployment with constructor function. + +pub(super) fn deploy_with_new_constructor( + session: &mut Session, + bundle: ContractBundle, + id: TokenId, + min_balance: Balance, +) -> Result { + session.deploy_bundle( + bundle, + "new", + &[id.to_string(), min_balance.to_string()], + NO_SALT, + Some(INIT_VALUE), + ) +} + +pub(super) fn deploy_with_new_existing_constructor( + session: &mut Session, + bundle: ContractBundle, + id: TokenId, +) -> Result { + session.deploy_bundle(bundle, "new_existing", &[id.to_string()], NO_SALT, Some(INIT_VALUE)) +} + +// Test methods for `PSP22`.` + +pub(super) fn total_supply( + session: &mut Session, +) -> Result> { + Ok(decoded_call::(session, "Psp22::total_supply", vec![], None)?) +} + +pub(super) fn balance_of( + session: &mut Session, + owner: AccountId32, +) -> Result> { + Ok(decoded_call::(session, "Psp22::balance_of", vec![owner.to_string()], None)?) +} + +pub(super) fn transfer( + session: &mut Session, + to: AccountId32, + amount: Balance, +) -> Result<(), Box> { + let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); + Ok(session.call("Psp22::transfer", &vec![to.to_string(), amount.to_string(), data], None)??) +} + +// Test methods for `PSP22Metadata``. + +pub(super) fn token_name( + session: &mut Session, +) -> Result> { + Ok(decoded_call::(session, "Psp22Metadata::token_name", vec![], None)?) +} + +pub(super) fn token_symbol( + session: &mut Session, +) -> Result> { + Ok(decoded_call::(session, "Psp22Metadata::token_symbol", vec![], None)?) +} + +pub(super) fn token_decimals( + session: &mut Session, +) -> Result> { + Ok(decoded_call::(session, "Psp22Metadata::token_decimals", vec![], None)?) +} + +// Test methods for `PSP22Mintable``. + +pub(super) fn mint( + session: &mut Session, + account: AccountId32, + amount: Balance, +) -> Result<(), Box> { + Ok(session.call( + "Psp22Mintable::mint", + &vec![account.to_string(), amount.to_string()], + None, + )??) +} + +// Test methods for `PSP22MPsp22Burnablentable``. + +pub(super) fn burn( + session: &mut Session, + account: AccountId32, + amount: Balance, +) -> Result<(), Box> { + Ok(session.call( + "Psp22Burnable::burn", + &vec![account.to_string(), amount.to_string()], + None, + )??) +} diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index e3457e18..b13542bb 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -11,6 +11,8 @@ use pop_api::{ }, }; +#[cfg(test)] +mod helpers; #[cfg(test)] mod tests; diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 89d4298e..28093336 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -1,144 +1,56 @@ -use drink::session::{error::SessionError, Session, NO_ARGS, NO_SALT}; -use pop_api::{ - primitives::{AccountId, TokenId}, - v0::fungibles::{self as api, PSP22Error}, -}; -use pop_sandbox::{AccountId32, Balance, Sandbox, ALICE, BOB, INIT_VALUE}; -use scale::{Decode, Encode}; +use drink::{sandbox_api::assets_api::AssetsAPI, session::Session}; +use helpers::*; +use pop_api::primitives::TokenId; +use pop_sandbox::{Balance, Sandbox, ALICE, BOB}; use super::*; const TOKEN_ID: TokenId = 1; +const TOKEN_MIN_BALANCE: Balance = 10_000; #[drink::contract_bundle_provider] enum BundleProvider {} -use test_methods::*; -// Utility methods to test the contract calls. -mod test_methods { - use super::*; - - // Decode slice of bytes to `pop-api` AccountId. - pub(super) fn account_id_from_slice(s: &[u8; 32]) -> AccountId { - AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") - } - - // Call a contract method and decode the returned data. - pub(super) fn decoded_call( - session: &mut Session, - func_name: &str, - input: Vec, - endowment: Option, - ) -> Result> { - session.call(func_name, &input, endowment)??; - Ok(session.record().last_call_return_decoded::()??) - } - - // Check if the event emitted correctly. - pub(super) fn assert_event(session: &mut Session, event: Vec) { - let contract_events = session.record().last_event_batch().contract_events(); - let last_event = contract_events.last().unwrap().to_vec(); - assert_eq!(last_event, event.as_slice()); - } - - // Test methods for deployment with constructor function. - - pub(super) fn deploy_with_new_constructor( - session: &mut Session, - id: TokenId, - min_balance: Balance, - ) -> Result { - session.deploy_bundle( - BundleProvider::local()?, - "new", - &[id.to_string(), min_balance.to_string()], - NO_SALT, - Some(INIT_VALUE), - ) - } - - // Test methods for `PSP22`.` - - pub(super) fn total_supply( - session: &mut Session, - ) -> Result> { - Ok(decoded_call::(session, "Psp22::total_supply", vec![], None)?) - } - - pub(super) fn balance_of( - session: &mut Session, - owner: AccountId32, - ) -> Result> { - Ok(decoded_call::(session, "Psp22::balance_of", vec![owner.to_string()], None)?) - } - - pub(super) fn transfer( - session: &mut Session, - to: AccountId32, - amount: Balance, - ) -> Result<(), Box> { - let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); - Ok(session.call( - "Psp22::transfer", - &vec![to.to_string(), amount.to_string(), data], - None, - )??) - } - - // Test methods for `PSP22Metadata``. - - pub(super) fn token_name( - session: &mut Session, - ) -> Result> { - Ok(decoded_call::(session, "Psp22Metadata::token_name", vec![], None)?) - } - - pub(super) fn token_symbol( - session: &mut Session, - ) -> Result> { - Ok(decoded_call::(session, "Psp22Metadata::token_symbol", vec![], None)?) - } - - pub(super) fn token_decimals( - session: &mut Session, - ) -> Result> { - Ok(decoded_call::(session, "Psp22Metadata::token_decimals", vec![], None)?) - } - - // Test methods for `PSP22Mintable``. - - pub(super) fn mint( - session: &mut Session, - account: AccountId32, - amount: Balance, - ) -> Result<(), Box> { - Ok(session.call( - "Psp22Mintable::mint", - &vec![account.to_string(), amount.to_string()], - None, - )??) - } +#[drink::test(sandbox = Sandbox)] +fn new_constructor_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + // Check if token exists after the deployment. + assert!(session.sandbox().asset_exists(&TOKEN_ID)); + // Check if `Created` event is emitted. + Ok(()) +} - // Test methods for `PSP22MPsp22Burnablentable``. +#[drink::test(sandbox = Sandbox)] +fn new_existing_constructor_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); - pub(super) fn burn( - session: &mut Session, - account: AccountId32, - amount: Balance, - ) -> Result<(), Box> { - Ok(session.call( - "Psp22Burnable::burn", - &vec![account.to_string(), amount.to_string()], - None, - )??) - } + // Create token. + let actor = session.get_actor(); + session.sandbox().create(&TOKEN_ID, &actor, TOKEN_MIN_BALANCE).unwrap(); + // Deploy a new contract. + deploy_with_new_existing_constructor(&mut session, BundleProvider::local()?, TOKEN_ID)?; + // Check if token is created successfully. + assert!(session.sandbox().asset_exists(&TOKEN_ID)); + Ok(()) } #[drink::test(sandbox = Sandbox)] -fn test_mint_token_works(mut session: Session) -> Result<(), Box> { +fn mint_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. - let contract_address = deploy_with_new_constructor(&mut session, 1, 10_000)?; + let contract_address = deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; // Mint tokens. const AMOUNT: Balance = 12_000; mint(&mut session, ALICE, AMOUNT)?; @@ -151,10 +63,15 @@ fn test_mint_token_works(mut session: Session) -> Result<(), Box Result<(), Box> { +fn burn_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. - let contract_address = deploy_with_new_constructor(&mut session, TOKEN_ID, 10_000)?; + let contract_address = deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; // Mint tokens. const AMOUNT: Balance = 12_000; mint(&mut session, ALICE, AMOUNT)?; @@ -166,10 +83,15 @@ fn test_burn_token_works(mut session: Session) -> Result<(), Box Result<(), Box> { +fn transfer_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. - let contract_address = deploy_with_new_constructor(&mut session, TOKEN_ID, 10_000)?; + let contract_address = deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; // Mint tokens. const AMOUNT: Balance = 12_000; const TRANSFERED: Balance = 500; From b433c6783ba08ed28f309426f9c73712712aba99 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 20 Sep 2024 20:19:47 +0700 Subject: [PATCH 105/161] feat: add event assertions --- pop-api/examples/fungibles/helpers.rs | 8 +++- pop-api/examples/fungibles/lib.rs | 2 +- pop-api/examples/fungibles/tests.rs | 57 ++++++++++++++++++++------- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/pop-api/examples/fungibles/helpers.rs b/pop-api/examples/fungibles/helpers.rs index 5cf1d616..027528df 100644 --- a/pop-api/examples/fungibles/helpers.rs +++ b/pop-api/examples/fungibles/helpers.rs @@ -7,11 +7,17 @@ use scale::{Decode, Encode}; use super::*; -// Decode slice of bytes to `pop-api` AccountId. +/// This is used to resolve type mismatches between the `AccountId` in the quasi testing environment and the +/// contract environment. pub(super) fn account_id_from_slice(s: &[u8; 32]) -> AccountId { AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") } +/// Get the last event from pallet contracts. +pub(super) fn last_contract_event(session: &Session) -> Option> { + session.record().last_event_batch().contract_events().last().cloned() +} + // Call a contract method and decode the returned data. pub(super) fn decoded_call( session: &mut Session, diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index b13542bb..d7dc7d95 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -115,7 +115,7 @@ mod fungibles { } // Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. - if value > self.env().balance() { + if value > self.balance_of(caller) { return Err(PSP22Error::InsufficientBalance); } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 28093336..027f02c6 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -1,7 +1,11 @@ use drink::{sandbox_api::assets_api::AssetsAPI, session::Session}; use helpers::*; -use pop_api::primitives::TokenId; +use pop_api::{ + primitives::TokenId, + v0::fungibles::events::{Approval, Created, Transfer}, +}; use pop_sandbox::{Balance, Sandbox, ALICE, BOB}; +use scale::Encode; use super::*; @@ -15,15 +19,18 @@ enum BundleProvider {} fn new_constructor_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. - deploy_with_new_constructor( + let contract = deploy_with_new_constructor( &mut session, BundleProvider::local()?, TOKEN_ID, TOKEN_MIN_BALANCE, )?; - // Check if token exists after the deployment. + // Token exists after the deployment. assert!(session.sandbox().asset_exists(&TOKEN_ID)); - // Check if `Created` event is emitted. + let contract = account_id_from_slice(contract.as_ref()); + // Successfully emit event. + let expected = Created { id: TOKEN_ID, creator: contract, admin: contract }.encode(); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); Ok(()) } @@ -36,8 +43,10 @@ fn new_existing_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. - let contract_address = deploy_with_new_constructor( + deploy_with_new_constructor( &mut session, BundleProvider::local()?, TOKEN_ID, @@ -54,11 +63,14 @@ fn mint_works(mut session: Session) -> Result<(), Box> { // Mint tokens. const AMOUNT: Balance = 12_000; mint(&mut session, ALICE, AMOUNT)?; - mint(&mut session, BOB, AMOUNT)?; - // Check if the tokens were minted with the right amount. - assert_eq!(total_supply(&mut session)?, AMOUNT * 2); + // Successfully emit event. + let expected = + Transfer { from: None, to: Some(account_id_from_slice(ALICE.as_ref())), value: AMOUNT } + .encode(); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + // Tokens were minted with the right amount. + assert_eq!(total_supply(&mut session)?, AMOUNT); assert_eq!(balance_of(&mut session, ALICE)?, AMOUNT); - assert_eq!(balance_of(&mut session, BOB)?, AMOUNT); Ok(()) } @@ -66,7 +78,7 @@ fn mint_works(mut session: Session) -> Result<(), Box> { fn burn_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. - let contract_address = deploy_with_new_constructor( + deploy_with_new_constructor( &mut session, BundleProvider::local()?, TOKEN_ID, @@ -77,6 +89,11 @@ fn burn_works(mut session: Session) -> Result<(), Box> { mint(&mut session, ALICE, AMOUNT)?; // Burn tokens. burn(&mut session, ALICE, 1)?; + // Successfully emit event. + let expected = + Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value: 1 }.encode(); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + assert_eq!(total_supply(&mut session)?, AMOUNT - 1); assert_eq!(balance_of(&mut session, ALICE)?, AMOUNT - 1); Ok(()) @@ -86,7 +103,7 @@ fn burn_works(mut session: Session) -> Result<(), Box> { fn transfer_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. - let contract_address = deploy_with_new_constructor( + let contract = deploy_with_new_constructor( &mut session, BundleProvider::local()?, TOKEN_ID, @@ -95,11 +112,21 @@ fn transfer_works(mut session: Session) -> Result<(), Box // Mint tokens. const AMOUNT: Balance = 12_000; const TRANSFERED: Balance = 500; - mint(&mut session, contract_address.clone(), AMOUNT)?; + mint(&mut session, contract.clone(), AMOUNT)?; mint(&mut session, BOB, AMOUNT)?; - // Transfer tokens. + // Transfer tokens from `contract` to `account`. + session.set_actor(contract.clone()); transfer(&mut session, BOB, TRANSFERED)?; - assert_eq!(balance_of(&mut session, contract_address)?, AMOUNT - TRANSFERED); + // Successfully emit event. + let expected = Transfer { + from: Some(account_id_from_slice(contract.clone().as_ref())), + to: Some(account_id_from_slice(BOB.as_ref())), + value: TRANSFERED, + } + .encode(); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + + assert_eq!(balance_of(&mut session, contract)?, AMOUNT - TRANSFERED); assert_eq!(balance_of(&mut session, BOB)?, AMOUNT + TRANSFERED); Ok(()) } From e018e34777e0359a63e525b243ac3e75aeb97c6d Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 20 Sep 2024 22:37:49 +0700 Subject: [PATCH 106/161] test: event assertion --- pop-api/examples/fungibles/Cargo.toml | 9 ++- pop-api/examples/fungibles/helpers.rs | 41 +++++----- pop-api/examples/fungibles/tests.rs | 110 +++++++++++++++++++++++--- 3 files changed, 123 insertions(+), 37 deletions(-) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index c06bc0f5..a2960895 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -17,11 +17,16 @@ scale-info = { version = "2.6", default-features = false, features = [ ], optional = true } [dev-dependencies] -drink = { path = "../../../../pop-drink/drink" } env_logger = { version = "0.11.3" } -pop-sandbox = { path = "../../../pop-sandbox", default-features = false } serde_json = "1.0.114" +# Local +drink = { path = "../../../../pop-drink/drink" } +pop-sandbox = { path = "../../../pop-sandbox", default-features = false } + +# Substrate +frame-support = { version = "36.0.0", default-features = false } + [lib] path = "lib.rs" diff --git a/pop-api/examples/fungibles/helpers.rs b/pop-api/examples/fungibles/helpers.rs index 027528df..506904b5 100644 --- a/pop-api/examples/fungibles/helpers.rs +++ b/pop-api/examples/fungibles/helpers.rs @@ -1,6 +1,9 @@ // A set of helper methods to test the contract calls. -use drink::session::{bundle::ContractBundle, error::SessionError, Session, NO_SALT}; +use drink::{ + session::{bundle::ContractBundle, error::SessionError, Session, NO_SALT}, + DispatchError, +}; use pop_api::primitives::{AccountId, TokenId}; use pop_sandbox::{AccountId32, Balance, Sandbox, INIT_VALUE}; use scale::{Decode, Encode}; @@ -18,6 +21,11 @@ pub(super) fn last_contract_event(session: &Session) -> Option> session.record().last_event_batch().contract_events().last().cloned() } +/// Get the last contract execution result. +pub(super) fn last_contract_error(session: &Session) -> Option { + session.record().last_call_result().result.clone().err() +} + // Call a contract method and decode the returned data. pub(super) fn decoded_call( session: &mut Session, @@ -63,17 +71,12 @@ pub(super) fn deploy_with_new_existing_constructor( // Test methods for `PSP22`.` -pub(super) fn total_supply( - session: &mut Session, -) -> Result> { - Ok(decoded_call::(session, "Psp22::total_supply", vec![], None)?) +pub(super) fn total_supply(session: &mut Session) -> Balance { + decoded_call::(session, "Psp22::total_supply", vec![], None).unwrap() } -pub(super) fn balance_of( - session: &mut Session, - owner: AccountId32, -) -> Result> { - Ok(decoded_call::(session, "Psp22::balance_of", vec![owner.to_string()], None)?) +pub(super) fn balance_of(session: &mut Session, owner: AccountId32) -> Balance { + decoded_call::(session, "Psp22::balance_of", vec![owner.to_string()], None).unwrap() } pub(super) fn transfer( @@ -87,22 +90,16 @@ pub(super) fn transfer( // Test methods for `PSP22Metadata``. -pub(super) fn token_name( - session: &mut Session, -) -> Result> { - Ok(decoded_call::(session, "Psp22Metadata::token_name", vec![], None)?) +pub(super) fn token_name(session: &mut Session) -> String { + decoded_call::(session, "Psp22Metadata::token_name", vec![], None).unwrap() } -pub(super) fn token_symbol( - session: &mut Session, -) -> Result> { - Ok(decoded_call::(session, "Psp22Metadata::token_symbol", vec![], None)?) +pub(super) fn token_symbol(session: &mut Session) -> String { + decoded_call::(session, "Psp22Metadata::token_symbol", vec![], None).unwrap() } -pub(super) fn token_decimals( - session: &mut Session, -) -> Result> { - Ok(decoded_call::(session, "Psp22Metadata::token_decimals", vec![], None)?) +pub(super) fn token_decimals(session: &mut Session) -> u8 { + decoded_call::(session, "Psp22Metadata::token_decimals", vec![], None).unwrap() } // Test methods for `PSP22Mintable``. diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 027f02c6..af3144d0 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -1,4 +1,8 @@ -use drink::{sandbox_api::assets_api::AssetsAPI, session::Session}; +use drink::{ + sandbox_api::assets_api::AssetsAPI, + session::{error::SessionError, Session}, +}; +use frame_support::assert_ok; use helpers::*; use pop_api::{ primitives::TokenId, @@ -50,6 +54,18 @@ fn new_existing_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box> { + let _ = env_logger::try_init(); + + let result = + deploy_with_new_existing_constructor(&mut session, BundleProvider::local()?, TOKEN_ID); + assert!(result.is_err()); + Ok(()) +} + #[drink::test(sandbox = Sandbox)] fn mint_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); @@ -62,15 +78,35 @@ fn mint_works(mut session: Session) -> Result<(), Box> { )?; // Mint tokens. const AMOUNT: Balance = 12_000; - mint(&mut session, ALICE, AMOUNT)?; + assert_ok!(mint(&mut session, ALICE, AMOUNT)); // Successfully emit event. let expected = Transfer { from: None, to: Some(account_id_from_slice(ALICE.as_ref())), value: AMOUNT } .encode(); assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Tokens were minted with the right amount. - assert_eq!(total_supply(&mut session)?, AMOUNT); - assert_eq!(balance_of(&mut session, ALICE)?, AMOUNT); + assert_eq!(total_supply(&mut session), AMOUNT); + assert_eq!(balance_of(&mut session, ALICE), AMOUNT); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn mint_zero_value_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + // Mint tokens. + assert_ok!(mint(&mut session, ALICE, 0)); + // No event emitted. + assert_eq!(last_contract_event(&session), None); + // Tokens were minted with the right amount. + assert_eq!(total_supply(&mut session), 0); + assert_eq!(balance_of(&mut session, ALICE), 0); Ok(()) } @@ -86,16 +122,64 @@ fn burn_works(mut session: Session) -> Result<(), Box> { )?; // Mint tokens. const AMOUNT: Balance = 12_000; - mint(&mut session, ALICE, AMOUNT)?; + assert_ok!(mint(&mut session, ALICE, AMOUNT)); // Burn tokens. - burn(&mut session, ALICE, 1)?; + assert_ok!(burn(&mut session, ALICE, 1)); // Successfully emit event. let expected = Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value: 1 }.encode(); assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - assert_eq!(total_supply(&mut session)?, AMOUNT - 1); - assert_eq!(balance_of(&mut session, ALICE)?, AMOUNT - 1); + assert_eq!(total_supply(&mut session), AMOUNT - 1); + assert_eq!(balance_of(&mut session, ALICE), AMOUNT - 1); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn burn_zero_value_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + // Burn tokens. + assert_ok!(burn(&mut session, ALICE, 0)); + // No event emitted. + assert_eq!(last_contract_event(&session), None); + // Tokens were minted with the right amount. + assert_eq!(total_supply(&mut session), 0); + assert_eq!(balance_of(&mut session, ALICE), 0); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn burn_fails_with_insufficient_amount( + mut session: Session, +) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + // Mint tokens. + const AMOUNT: Balance = 12_000; + assert_ok!(mint(&mut session, ALICE, AMOUNT)); + + // Burn tokens reverted with `InsufficientBalance`. + let function: &str = "Psp22Burnable::burn"; + let params: Vec = vec![ALICE.to_string(), (AMOUNT + 1).to_string()]; + let call = session.call::(function, ¶ms, None); + + // TODO: Failed assertion [0, 1, 1] and [1]. + if let Err(SessionError::CallReverted(error)) = call { + assert_eq!(error, PSP22Error::InsufficientBalance.encode()); + } Ok(()) } @@ -112,11 +196,11 @@ fn transfer_works(mut session: Session) -> Result<(), Box // Mint tokens. const AMOUNT: Balance = 12_000; const TRANSFERED: Balance = 500; - mint(&mut session, contract.clone(), AMOUNT)?; - mint(&mut session, BOB, AMOUNT)?; + assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); + assert_ok!(mint(&mut session, BOB, AMOUNT)); // Transfer tokens from `contract` to `account`. session.set_actor(contract.clone()); - transfer(&mut session, BOB, TRANSFERED)?; + assert_ok!(transfer(&mut session, BOB, TRANSFERED)); // Successfully emit event. let expected = Transfer { from: Some(account_id_from_slice(contract.clone().as_ref())), @@ -126,7 +210,7 @@ fn transfer_works(mut session: Session) -> Result<(), Box .encode(); assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - assert_eq!(balance_of(&mut session, contract)?, AMOUNT - TRANSFERED); - assert_eq!(balance_of(&mut session, BOB)?, AMOUNT + TRANSFERED); + assert_eq!(balance_of(&mut session, contract), AMOUNT - TRANSFERED); + assert_eq!(balance_of(&mut session, BOB), AMOUNT + TRANSFERED); Ok(()) } From baab872ce12afae46a01edb7114afe7c6f445021 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 20 Sep 2024 22:53:39 +0700 Subject: [PATCH 107/161] refactor: call expect error methods & function constant --- pop-api/examples/fungibles/lib.rs | 4 +- pop-api/examples/fungibles/tests.rs | 17 +++---- .../fungibles/{helpers.rs => utils.rs} | 51 ++++++++++++------- 3 files changed, 41 insertions(+), 31 deletions(-) rename pop-api/examples/fungibles/{helpers.rs => utils.rs} (66%) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index d7dc7d95..b84bec4e 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -11,10 +11,10 @@ use pop_api::{ }, }; -#[cfg(test)] -mod helpers; #[cfg(test)] mod tests; +#[cfg(test)] +mod utils; #[ink::contract] mod fungibles { diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index af3144d0..99b97cfd 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -3,13 +3,13 @@ use drink::{ session::{error::SessionError, Session}, }; use frame_support::assert_ok; -use helpers::*; use pop_api::{ primitives::TokenId, v0::fungibles::events::{Approval, Created, Transfer}, }; use pop_sandbox::{Balance, Sandbox, ALICE, BOB}; use scale::Encode; +use utils::*; use super::*; @@ -170,16 +170,13 @@ fn burn_fails_with_insufficient_amount( // Mint tokens. const AMOUNT: Balance = 12_000; assert_ok!(mint(&mut session, ALICE, AMOUNT)); - // Burn tokens reverted with `InsufficientBalance`. - let function: &str = "Psp22Burnable::burn"; - let params: Vec = vec![ALICE.to_string(), (AMOUNT + 1).to_string()]; - let call = session.call::(function, ¶ms, None); - - // TODO: Failed assertion [0, 1, 1] and [1]. - if let Err(SessionError::CallReverted(error)) = call { - assert_eq!(error, PSP22Error::InsufficientBalance.encode()); - } + expect_call_reverted( + &mut session, + BURN, + vec![ALICE.to_string(), (AMOUNT + 1).to_string()], + PSP22Error::InsufficientBalance, + ); Ok(()) } diff --git a/pop-api/examples/fungibles/helpers.rs b/pop-api/examples/fungibles/utils.rs similarity index 66% rename from pop-api/examples/fungibles/helpers.rs rename to pop-api/examples/fungibles/utils.rs index 506904b5..baff68e5 100644 --- a/pop-api/examples/fungibles/helpers.rs +++ b/pop-api/examples/fungibles/utils.rs @@ -10,6 +10,19 @@ use scale::{Decode, Encode}; use super::*; +// PSP22 functions. +pub const BALANCE_OF: &str = "Psp22::balance_of"; +pub const TOTAL_SUPPLY: &str = "Psp22::total_supply"; +pub const TRANSFER: &str = "Psp22::transfer"; +// PSP22Metadata functions. +pub const TOKEN_NAME: &str = "Psp22Metadata::token_name"; +pub const TOKEN_SYMBOL: &str = "Psp22Metadata::token_symbol"; +pub const TOKEN_DECIMALS: &str = "Psp22Metadata::token_decimals"; +// PSP22Mintable functions. +pub const MINT: &str = "Psp22Mintable::mint"; +// PSP22Burnable functions. +pub const BURN: &str = "Psp22Burnable::burn"; + /// This is used to resolve type mismatches between the `AccountId` in the quasi testing environment and the /// contract environment. pub(super) fn account_id_from_slice(s: &[u8; 32]) -> AccountId { @@ -21,9 +34,17 @@ pub(super) fn last_contract_event(session: &Session) -> Option> session.record().last_event_batch().contract_events().last().cloned() } -/// Get the last contract execution result. -pub(super) fn last_contract_error(session: &Session) -> Option { - session.record().last_call_result().result.clone().err() +/// Execute a contract method and exepct CallReverted error to be returned. +pub(super) fn expect_call_reverted( + session: &mut Session, + function: &str, + params: Vec, + err: PSP22Error, +) { + let call = session.call::(function, ¶ms, None); + if let Err(SessionError::CallReverted(error)) = call { + assert_eq!(error[1..], Err::<(), PSP22Error>(err).encode()); + } } // Call a contract method and decode the returned data. @@ -72,11 +93,11 @@ pub(super) fn deploy_with_new_existing_constructor( // Test methods for `PSP22`.` pub(super) fn total_supply(session: &mut Session) -> Balance { - decoded_call::(session, "Psp22::total_supply", vec![], None).unwrap() + decoded_call::(session, TOTAL_SUPPLY, vec![], None).unwrap() } pub(super) fn balance_of(session: &mut Session, owner: AccountId32) -> Balance { - decoded_call::(session, "Psp22::balance_of", vec![owner.to_string()], None).unwrap() + decoded_call::(session, BALANCE_OF, vec![owner.to_string()], None).unwrap() } pub(super) fn transfer( @@ -85,21 +106,21 @@ pub(super) fn transfer( amount: Balance, ) -> Result<(), Box> { let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); - Ok(session.call("Psp22::transfer", &vec![to.to_string(), amount.to_string(), data], None)??) + Ok(session.call(TRANSFER, &vec![to.to_string(), amount.to_string(), data], None)??) } // Test methods for `PSP22Metadata``. pub(super) fn token_name(session: &mut Session) -> String { - decoded_call::(session, "Psp22Metadata::token_name", vec![], None).unwrap() + decoded_call::(session, TOKEN_NAME, vec![], None).unwrap() } pub(super) fn token_symbol(session: &mut Session) -> String { - decoded_call::(session, "Psp22Metadata::token_symbol", vec![], None).unwrap() + decoded_call::(session, TOKEN_SYMBOL, vec![], None).unwrap() } pub(super) fn token_decimals(session: &mut Session) -> u8 { - decoded_call::(session, "Psp22Metadata::token_decimals", vec![], None).unwrap() + decoded_call::(session, TOKEN_DECIMALS, vec![], None).unwrap() } // Test methods for `PSP22Mintable``. @@ -109,11 +130,7 @@ pub(super) fn mint( account: AccountId32, amount: Balance, ) -> Result<(), Box> { - Ok(session.call( - "Psp22Mintable::mint", - &vec![account.to_string(), amount.to_string()], - None, - )??) + Ok(session.call(MINT, &vec![account.to_string(), amount.to_string()], None)??) } // Test methods for `PSP22MPsp22Burnablentable``. @@ -123,9 +140,5 @@ pub(super) fn burn( account: AccountId32, amount: Balance, ) -> Result<(), Box> { - Ok(session.call( - "Psp22Burnable::burn", - &vec![account.to_string(), amount.to_string()], - None, - )??) + Ok(session.call(BURN, &vec![account.to_string(), amount.to_string()], None)??) } From cb48a4de6f767fd4176a6ac7da6e0ab93e621115 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:31:43 +0700 Subject: [PATCH 108/161] test: add more test cases --- pop-api/examples/fungibles/lib.rs | 7 +- pop-api/examples/fungibles/tests.rs | 198 +++++++++++++++++++++++++++- pop-api/examples/fungibles/utils.rs | 54 +++++++- 3 files changed, 247 insertions(+), 12 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index b84bec4e..69d22247 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -196,9 +196,9 @@ mod fungibles { return Ok(()); } + let allowance = self.allowance(caller, spender); api::increase_allowance(self.id, spender, value).map_err(PSP22Error::from)?; - let allowance = self.allowance(caller, spender).saturating_add(value); - self.emit_approval_event(caller, spender, allowance); + self.emit_approval_event(caller, spender, allowance.saturating_add(value)); Ok(()) } @@ -224,8 +224,7 @@ mod fungibles { } api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; - let allowance = allowance.saturating_sub(value); - self.emit_approval_event(caller, spender, allowance); + self.emit_approval_event(caller, spender, allowance.saturating_sub(value)); Ok(()) } } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 99b97cfd..7046d83f 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -66,6 +66,25 @@ fn new_existing_constructor_deployment_fails( Ok(()) } +#[drink::test(sandbox = Sandbox)] +fn balance_of_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + // Mint tokens. + const AMOUNT: Balance = 12_000; + assert_ok!(mint(&mut session, ALICE, AMOUNT)); + // Tokens were minted with the right amount. + assert_eq!(balance_of(&mut session, ALICE), AMOUNT); + assert_eq!(balance_of(&mut session, ALICE), session.sandbox().balance_of(&TOKEN_ID, &ALICE)); + Ok(()) +} + #[drink::test(sandbox = Sandbox)] fn mint_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); @@ -156,7 +175,7 @@ fn burn_zero_value_works(mut session: Session) -> Result<(), Box Result<(), Box> { let _ = env_logger::try_init(); @@ -170,7 +189,7 @@ fn burn_fails_with_insufficient_amount( // Mint tokens. const AMOUNT: Balance = 12_000; assert_ok!(mint(&mut session, ALICE, AMOUNT)); - // Burn tokens reverted with `InsufficientBalance`. + // Failed with `InsufficientBalance`. expect_call_reverted( &mut session, BURN, @@ -192,22 +211,187 @@ fn transfer_works(mut session: Session) -> Result<(), Box )?; // Mint tokens. const AMOUNT: Balance = 12_000; - const TRANSFERED: Balance = 500; + const TRANSFERRED: Balance = 500; assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); assert_ok!(mint(&mut session, BOB, AMOUNT)); // Transfer tokens from `contract` to `account`. session.set_actor(contract.clone()); - assert_ok!(transfer(&mut session, BOB, TRANSFERED)); + assert_ok!(transfer(&mut session, BOB, TRANSFERRED)); // Successfully emit event. let expected = Transfer { from: Some(account_id_from_slice(contract.clone().as_ref())), to: Some(account_id_from_slice(BOB.as_ref())), - value: TRANSFERED, + value: TRANSFERRED, + } + .encode(); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + + assert_eq!(balance_of(&mut session, contract), AMOUNT - TRANSFERRED); + assert_eq!(balance_of(&mut session, BOB), AMOUNT + TRANSFERRED); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn transfer_zero_value_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + assert_ok!(transfer(&mut session, ALICE, 0)); + // No event emitted. + assert_eq!(last_contract_event(&session), None); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn transfer_fails_with_insufficient_balance( + mut session: Session, +) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + // Mint tokens. + const AMOUNT: Balance = 12_000; + assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); + assert_ok!(mint(&mut session, BOB, AMOUNT)); + + session.set_actor(contract.clone()); + // Failed with `InsufficientBalance`. + expect_call_reverted( + &mut session, + TRANSFER, + vec![BOB.to_string(), (AMOUNT + 1).to_string()], + PSP22Error::InsufficientBalance, + ); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn approve_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + + const AMOUNT: Balance = 12_000; + // Mint tokens. + assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); + // Successfully apporve. + session.set_actor(contract.clone()); + assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); + // Successfully emit event. + let expected = Approval { + owner: account_id_from_slice(contract.clone().as_ref()), + spender: account_id_from_slice(ALICE.as_ref()), + value: AMOUNT / 2, + } + .encode(); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn increase_allowance_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + + const AMOUNT: Balance = 12_000; + // Mint tokens. + assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); + // Successfully apporve. + session.set_actor(contract.clone()); + assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); + assert_ok!(increase_allowance(&mut session, ALICE, AMOUNT / 2)); + // Successfully emit event. + let expected = Approval { + owner: account_id_from_slice(contract.clone().as_ref()), + spender: account_id_from_slice(ALICE.as_ref()), + value: AMOUNT, } .encode(); assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT); + Ok(()) +} - assert_eq!(balance_of(&mut session, contract), AMOUNT - TRANSFERED); - assert_eq!(balance_of(&mut session, BOB), AMOUNT + TRANSFERED); +#[drink::test(sandbox = Sandbox)] +fn decrease_allowance_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + + const AMOUNT: Balance = 12_000; + // Mint tokens. + assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); + // Successfully apporve. + session.set_actor(contract.clone()); + assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); + assert_ok!(decrease_allowance(&mut session, ALICE, 1)); + // Successfully emit event. + let expected = Approval { + owner: account_id_from_slice(contract.clone().as_ref()), + spender: account_id_from_slice(ALICE.as_ref()), + value: AMOUNT / 2 - 1, + } + .encode(); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2 - 1); + Ok(()) +} + +#[drink::test(sandbox = Sandbox)] +fn transfer_from_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + + const AMOUNT: Balance = 12_000; + // Mint tokens. + assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); + // Successfully transfer from `owner`. + session.set_actor(contract.clone()); + assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); + assert_eq!(allowance(&mut session, contract.clone(), ALICE), AMOUNT / 2); + + session.set_actor(ALICE); + assert_ok!(transfer_from(&mut session, contract, BOB, AMOUNT / 2)); + // Successfully emit event. + let expected = Transfer { + from: Some(account_id_from_slice(ALICE.as_ref())), + to: Some(account_id_from_slice(BOB.as_ref())), + value: AMOUNT / 4, + } + .encode(); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); Ok(()) } diff --git a/pop-api/examples/fungibles/utils.rs b/pop-api/examples/fungibles/utils.rs index baff68e5..38968afd 100644 --- a/pop-api/examples/fungibles/utils.rs +++ b/pop-api/examples/fungibles/utils.rs @@ -11,9 +11,14 @@ use scale::{Decode, Encode}; use super::*; // PSP22 functions. +pub const ALLOWANCE: &str = "Psp22::allowance"; pub const BALANCE_OF: &str = "Psp22::balance_of"; pub const TOTAL_SUPPLY: &str = "Psp22::total_supply"; pub const TRANSFER: &str = "Psp22::transfer"; +pub const TRANSFER_FROM: &str = "Psp22::transfer_from"; +pub const APPROVE: &str = "Psp22::approve"; +pub const INCREASE_ALLOWANCE: &str = "Psp22::increase_allowance"; +pub const DECREASE_ALLOWANCE: &str = "Psp22::decrease_allowance"; // PSP22Metadata functions. pub const TOKEN_NAME: &str = "Psp22Metadata::token_name"; pub const TOKEN_SYMBOL: &str = "Psp22Metadata::token_symbol"; @@ -90,7 +95,7 @@ pub(super) fn deploy_with_new_existing_constructor( session.deploy_bundle(bundle, "new_existing", &[id.to_string()], NO_SALT, Some(INIT_VALUE)) } -// Test methods for `PSP22`.` +// Test methods for `PSP22`. pub(super) fn total_supply(session: &mut Session) -> Balance { decoded_call::(session, TOTAL_SUPPLY, vec![], None).unwrap() @@ -100,6 +105,15 @@ pub(super) fn balance_of(session: &mut Session, owner: AccountId32) -> decoded_call::(session, BALANCE_OF, vec![owner.to_string()], None).unwrap() } +pub(super) fn allowance( + session: &mut Session, + owner: AccountId32, + spender: AccountId32, +) -> Balance { + decoded_call::(session, ALLOWANCE, vec![owner.to_string(), spender.to_string()], None) + .unwrap() +} + pub(super) fn transfer( session: &mut Session, to: AccountId32, @@ -109,6 +123,44 @@ pub(super) fn transfer( Ok(session.call(TRANSFER, &vec![to.to_string(), amount.to_string(), data], None)??) } +pub(super) fn transfer_from( + session: &mut Session, + from: AccountId32, + to: AccountId32, + amount: Balance, +) -> Result<(), Box> { + let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); + Ok(session.call( + TRANSFER_FROM, + &vec![from.to_string(), to.to_string(), amount.to_string(), data], + None, + )??) +} + +pub(super) fn approve( + session: &mut Session, + spender: AccountId32, + value: Balance, +) -> Result<(), Box> { + Ok(session.call(APPROVE, &vec![spender.to_string(), value.to_string()], None)??) +} + +pub(super) fn increase_allowance( + session: &mut Session, + spender: AccountId32, + value: Balance, +) -> Result<(), Box> { + Ok(session.call(INCREASE_ALLOWANCE, &vec![spender.to_string(), value.to_string()], None)??) +} + +pub(super) fn decrease_allowance( + session: &mut Session, + spender: AccountId32, + value: Balance, +) -> Result<(), Box> { + Ok(session.call(DECREASE_ALLOWANCE, &vec![spender.to_string(), value.to_string()], None)??) +} + // Test methods for `PSP22Metadata``. pub(super) fn token_name(session: &mut Session) -> String { From 763742065fee44d1a448c08884a8ceed89d73042 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:23:13 +0700 Subject: [PATCH 109/161] fix: comment --- pop-api/src/v0/fungibles/mod.rs | 2 +- pop-api/src/v0/fungibles/traits.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index 77f5f32c..032af4d1 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -1,6 +1,6 @@ //! The `fungibles` module provides an API for interacting and managing fungible tokens. //! -//! The API includes the following traits: +//! The API includes the following interfaces: //! 1. PSP-22 //! 2. PSP-22 Metadata //! 3. Management diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index caa4c68d..92ad55e3 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,4 +1,4 @@ -//! A set of traits that implement the PSP22 token standard. +//! Traits that can be used by contracts. Including standard compliant traits. use super::*; use core::result::Result; From cbcf66a1425ec0e8cac6f1f2f954b27d7fd3bb87 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:29:40 +0700 Subject: [PATCH 110/161] chore: revert example contract changes --- pop-api/examples/balance-transfer/Cargo.toml | 28 +++ pop-api/examples/balance-transfer/lib.rs | 135 +++++++++++ pop-api/examples/fungibles/Cargo.toml | 22 +- pop-api/examples/fungibles/lib.rs | 97 ++------ pop-api/examples/fungibles/tests.rs | 216 ------------------ pop-api/examples/nfts/Cargo.toml | 25 ++ pop-api/examples/nfts/lib.rs | 117 ++++++++++ pop-api/examples/place-spot-order/Cargo.toml | 25 ++ pop-api/examples/place-spot-order/lib.rs | 43 ++++ .../examples/read-runtime-state/Cargo.toml | 25 ++ pop-api/examples/read-runtime-state/lib.rs | 36 +++ 11 files changed, 460 insertions(+), 309 deletions(-) create mode 100644 pop-api/examples/balance-transfer/Cargo.toml create mode 100644 pop-api/examples/balance-transfer/lib.rs delete mode 100644 pop-api/examples/fungibles/tests.rs create mode 100644 pop-api/examples/nfts/Cargo.toml create mode 100644 pop-api/examples/nfts/lib.rs create mode 100644 pop-api/examples/place-spot-order/Cargo.toml create mode 100644 pop-api/examples/place-spot-order/lib.rs create mode 100644 pop-api/examples/read-runtime-state/Cargo.toml create mode 100644 pop-api/examples/read-runtime-state/lib.rs diff --git a/pop-api/examples/balance-transfer/Cargo.toml b/pop-api/examples/balance-transfer/Cargo.toml new file mode 100644 index 00000000..2a12e532 --- /dev/null +++ b/pop-api/examples/balance-transfer/Cargo.toml @@ -0,0 +1,28 @@ +[package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" +name = "balance_transfer" +version = "0.1.0" + +[dependencies] +ink = { version = "5.0.0", default-features = false } +pop-api = { path = "../../../pop-api", default-features = false } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } + +[dev-dependencies] +ink_e2e = "5.0.0" + +[lib] +path = "lib.rs" + +[features] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] +std = [ + "ink/std", + "pop-api/std", + "scale-info/std", + "scale/std", +] diff --git a/pop-api/examples/balance-transfer/lib.rs b/pop-api/examples/balance-transfer/lib.rs new file mode 100644 index 00000000..e75c15b9 --- /dev/null +++ b/pop-api/examples/balance-transfer/lib.rs @@ -0,0 +1,135 @@ +// DEPRECATED +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +use pop_api::balances::*; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum ContractError { + BalancesError(Error), +} + +impl From for ContractError { + fn from(value: Error) -> Self { + ContractError::BalancesError(value) + } +} + +#[ink::contract] +mod balance_transfer { + use super::*; + + #[ink(storage)] + #[derive(Default)] + pub struct BalanceTransfer; + + impl BalanceTransfer { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("BalanceTransfer::new"); + Default::default() + } + + #[ink(message)] + pub fn transfer( + &mut self, + receiver: AccountId, + value: Balance, + ) -> Result<(), ContractError> { + ink::env::debug_println!( + "BalanceTransfer::transfer: \nreceiver: {:?}, \nvalue: {:?}", + receiver, + value + ); + + transfer_keep_alive(receiver, value)?; + + ink::env::debug_println!("BalanceTransfer::transfer end"); + Ok(()) + } + } + + #[cfg(all(test, feature = "e2e-tests"))] + mod e2e_tests { + use super::*; + use ink_e2e::{ChainBackend, ContractsBackend}; + + use ink::{ + env::{test::default_accounts, DefaultEnvironment}, + primitives::AccountId, + }; + + type E2EResult = Result>; + + /// The base number of indivisible units for balances on the + /// `substrate-contracts-node`. + const UNIT: Balance = 1_000_000_000_000; + + /// The contract will be given 1000 tokens during instantiation. + const CONTRACT_BALANCE: Balance = 1_000 * UNIT; + + /// The receiver will get enough funds to have the required existential deposit. + /// + /// If your chain has this threshold higher, increase the transfer value. + const TRANSFER_VALUE: Balance = 1 / 10 * UNIT; + + /// An amount that is below the existential deposit, so that a transfer to an + /// empty account fails. + /// + /// Must not be zero, because such an operation would be a successful no-op. + const INSUFFICIENT_TRANSFER_VALUE: Balance = 1; + + /// Positive case scenario: + /// - the call is valid + /// - the call execution succeeds + #[ink_e2e::test] + async fn transfer_with_call_runtime_works( + mut client: Client, + ) -> E2EResult<()> { + // given + let mut constructor = RuntimeCallerRef::new(); + let contract = client + .instantiate("call-runtime", &ink_e2e::alice(), &mut constructor) + .value(CONTRACT_BALANCE) + .submit() + .await + .expect("instantiate failed"); + let mut call_builder = contract.call_builder::(); + + let accounts = default_accounts::(); + + let receiver: AccountId = accounts.bob; + + let sender_balance_before = client + .free_balance(accounts.alice) + .await + .expect("Failed to get account balance"); + let receiver_balance_before = + client.free_balance(receiver).await.expect("Failed to get account balance"); + + // when + let transfer_message = call_builder.transfer(receiver, TRANSFER_VALUE); + + let call_res = client + .call(&ink_e2e::alice(), &transfer_message) + .submit() + .await + .expect("call failed"); + + assert!(call_res.return_value().is_ok()); + + // then + let sender_balance_after = client + .free_balance(accounts.alice) + .await + .expect("Failed to get account balance"); + let receiver_balance_after = + client.free_balance(receiver).await.expect("Failed to get account balance"); + + assert_eq!(contract_balance_before, contract_balance_after + TRANSFER_VALUE); + assert_eq!(receiver_balance_before, receiver_balance_after - TRANSFER_VALUE); + + Ok(()) + } + } +} diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 075ea943..0b79e1b2 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -1,25 +1,12 @@ [package] authors = [ "[your_name] <[your_email]>" ] edition = "2021" -name = "api_example_fungibles" +name = "fungibles" version = "0.1.0" [dependencies] -ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } -pop-api = { path = "../../../pop-api", default-features = false, features = [ - "fungibles", -] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", -] } -scale-info = { version = "2.6", default-features = false, features = [ - "derive", -], optional = true } - -[dev-dependencies] -drink = { path = "../../../../pop-drink/drink" } -env_logger = { version = "0.11.3" } -pop-sandbox = { path = "../../../pop-sandbox", default-features = false } +ink = { version = "5.0.0", default-features = false } +pop-api = { path = "../../../pop-api", default-features = false, features = [ "fungibles" ] } [lib] path = "lib.rs" @@ -31,7 +18,4 @@ ink-as-dependency = [ ] std = [ "ink/std", "pop-api/std", - "pop-sandbox/std", - "scale-info/std", - "scale/std", ] diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 2148e967..11eafe21 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -2,15 +2,12 @@ use ink::prelude::vec::Vec; use pop_api::{ + fungibles::{self as api}, primitives::TokenId, - v0::fungibles::{self as api}, StatusCode, }; -#[cfg(test)] -mod tests; - -type PopApiResult = core::result::Result; +pub type Result = core::result::Result; #[ink::contract] mod fungibles { @@ -27,27 +24,27 @@ mod fungibles { } #[ink(message)] - pub fn mint( - &mut self, - token: TokenId, - account: AccountId, - amount: Balance, - ) -> PopApiResult<()> { - api::mint(token, account, amount) + pub fn total_supply(&self, token: TokenId) -> Result { + api::total_supply(token) } #[ink(message)] - pub fn burn( - &mut self, + pub fn balance_of(&self, token: TokenId, owner: AccountId) -> Result { + api::balance_of(token, owner) + } + + #[ink(message)] + pub fn allowance( + &self, token: TokenId, - account: AccountId, - amount: Balance, - ) -> PopApiResult<()> { - api::burn(token, account, amount) + owner: AccountId, + spender: AccountId, + ) -> Result { + api::allowance(token, owner, spender) } #[ink(message)] - pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> PopApiResult<()> { + pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> Result<()> { api::transfer(token, to, value) } @@ -59,7 +56,7 @@ mod fungibles { to: AccountId, value: Balance, _data: Vec, - ) -> PopApiResult<()> { + ) -> Result<()> { api::transfer_from(token, from, to, value) } @@ -69,7 +66,7 @@ mod fungibles { token: TokenId, spender: AccountId, value: Balance, - ) -> PopApiResult<()> { + ) -> Result<()> { api::approve(token, spender, value) } @@ -79,7 +76,7 @@ mod fungibles { token: TokenId, spender: AccountId, value: Balance, - ) -> PopApiResult<()> { + ) -> Result<()> { api::increase_allowance(token, spender, value) } @@ -89,71 +86,23 @@ mod fungibles { token: TokenId, spender: AccountId, value: Balance, - ) -> PopApiResult<()> { + ) -> Result<()> { api::decrease_allowance(token, spender, value) } - #[ink(message, payable)] - pub fn create( - &self, - id: TokenId, - admin: AccountId, - min_balance: Balance, - ) -> PopApiResult<()> { - api::create(id, admin, min_balance)?; - self.env().emit_event(api::events::Created { id, creator: admin, admin }); - Ok(()) - } - - #[ink(message)] - pub fn set_metadata( - &self, - token: TokenId, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> PopApiResult<()> { - api::set_metadata(token, name, symbol, decimals) - } - - #[ink(message)] - pub fn total_supply(&self, token: TokenId) -> PopApiResult { - api::total_supply(token) - } - #[ink(message)] - pub fn balance_of(&self, token: TokenId, owner: AccountId) -> PopApiResult { - api::balance_of(token, owner) - } - - #[ink(message)] - pub fn allowance( - &self, - token: TokenId, - owner: AccountId, - spender: AccountId, - ) -> PopApiResult { - api::allowance(token, owner, spender) - } - - #[ink(message)] - pub fn token_name(&self, token: TokenId) -> PopApiResult> { + pub fn token_name(&self, token: TokenId) -> Result> { api::token_name(token) } #[ink(message)] - pub fn token_symbol(&self, token: TokenId) -> PopApiResult> { + pub fn token_symbol(&self, token: TokenId) -> Result> { api::token_symbol(token) } #[ink(message)] - pub fn token_decimals(&self, token: TokenId) -> PopApiResult { + pub fn token_decimals(&self, token: TokenId) -> Result { api::token_decimals(token) } - - #[ink(message)] - pub fn token_exists(&self, token: TokenId) -> PopApiResult { - api::token_exists(token) - } } } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs deleted file mode 100644 index 216b9de3..00000000 --- a/pop-api/examples/fungibles/tests.rs +++ /dev/null @@ -1,216 +0,0 @@ -use drink::session::{Session, NO_ARGS, NO_SALT}; -use pop_api::{ - primitives::TokenId, - v0::fungibles::{self as api}, -}; -use pop_sandbox::{AccountId32, Balance, Sandbox, ALICE, BOB, INIT_VALUE}; -use scale::{Decode, Encode}; - -use super::*; - -const TOKEN_A: TokenId = 1; -const TOKEN_B: TokenId = 2; - -#[drink::contract_bundle_provider] -enum BundleProvider {} - -use test_methods::*; -// Utility methods to test the contract calls. -mod test_methods { - use super::*; - - // Decode slice of bytes to `pop-api` AccountId. - pub(super) fn account_id_from_slice(s: &[u8; 32]) -> pop_api::primitives::AccountId { - pop_api::primitives::AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") - } - - // Call a contract method and decode the returned data. - pub(super) fn decoded_call( - session: &mut Session, - func_name: &str, - input: Vec, - endowment: Option, - ) -> Result> { - session.call(func_name, &input, endowment)??; - Ok(session.record().last_call_return_decoded::()??) - } - - // Check if the event emitted correctly. - pub(super) fn assert_event(session: &mut Session, event: Vec) { - let contract_events = session.record().last_event_batch().contract_events(); - let last_event = contract_events.last().unwrap().to_vec(); - assert_eq!(last_event, event.as_slice()); - } - - pub(super) fn mint( - session: &mut Session, - token: TokenId, - account: AccountId32, - amount: Balance, - ) -> Result<(), Box> { - Ok(session.call( - "mint", - &vec![token.to_string(), account.to_string(), amount.to_string()], - None, - )??) - } - - pub(super) fn burn( - session: &mut Session, - token: TokenId, - account: AccountId32, - amount: Balance, - ) -> Result<(), Box> { - Ok(session.call( - "burn", - &vec![token.to_string(), account.to_string(), amount.to_string()], - None, - )??) - } - - pub(super) fn transfer( - session: &mut Session, - token: TokenId, - to: AccountId32, - amount: Balance, - ) -> Result<(), Box> { - Ok(session.call( - "transfer", - &vec![token.to_string(), to.to_string(), amount.to_string()], - None, - )??) - } - - pub(super) fn create( - session: &mut Session, - id: TokenId, - admin: AccountId32, - min_balance: Balance, - ) -> Result<(), Box> { - Ok(session.call( - "create", - &vec![id.to_string(), admin.to_string(), min_balance.to_string()], - None, - )??) - } - - pub(super) fn token_exist( - session: &mut Session, - token: TokenId, - ) -> Result, Box> { - Ok(decoded_call::>(session, "token_exists", vec![token.to_string()], None)?) - } - - pub(super) fn total_supply( - session: &mut Session, - token: TokenId, - ) -> Result, Box> { - Ok(decoded_call::>( - session, - "total_supply", - vec![token.to_string()], - None, - )?) - } - - pub(super) fn balance_of( - session: &mut Session, - token: TokenId, - owner: AccountId32, - ) -> Result, Box> { - Ok(decoded_call::>( - session, - "balance_of", - vec![token.to_string(), owner.to_string()], - None, - )?) - } -} - -#[drink::test(sandbox = Sandbox)] -fn test_create_multiple_token_works( - mut session: Session, -) -> Result<(), Box> { - let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - // Deploy a contract. - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - // Create new tokens. - create(&mut session, TOKEN_A, ALICE, 1_000)?; - - assert_event( - &mut session, - api::events::Created { - id: TOKEN_A, - admin: account_id_from_slice(ALICE.as_ref()), - creator: account_id_from_slice(ALICE.as_ref()), - } - .encode(), - ); - - create(&mut session, TOKEN_B, ALICE, 2_000)?; - // Check that the token is created successfully. - assert_eq!(token_exist(&mut session, TOKEN_A)?, Ok(true)); - assert_eq!(token_exist(&mut session, TOKEN_B)?, Ok(true)); - Ok(()) -} - -#[drink::test(sandbox = Sandbox)] -fn test_mint_token_works(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - // Deploy a contract. - let contract_address = - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - // Create a new token. - create(&mut session, TOKEN_A, contract_address, 10_000)?; - // Mint tokens. - const AMOUNT: Balance = 12_000; - mint(&mut session, TOKEN_A, ALICE, AMOUNT)?; - mint(&mut session, TOKEN_A, BOB, AMOUNT)?; - // Check if the tokens were minted with the right amount. - assert_eq!(total_supply(&mut session, TOKEN_A)?, Ok(AMOUNT * 2)); - assert_eq!(balance_of(&mut session, TOKEN_A, ALICE)?, Ok(AMOUNT)); - assert_eq!(balance_of(&mut session, TOKEN_A, BOB)?, Ok(AMOUNT)); - Ok(()) -} - -#[drink::test(sandbox = Sandbox)] -fn test_burn_token_works(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - // Deploy a contract. - let contract_address = - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - // Create a new token. - create(&mut session, TOKEN_A, contract_address, 10_000)?; - // Mint tokens. - const AMOUNT: Balance = 12_000; - mint(&mut session, TOKEN_A, ALICE, AMOUNT)?; - // Burn tokens. - burn(&mut session, TOKEN_A, ALICE, 1)?; - assert_eq!(total_supply(&mut session, TOKEN_A)?, Ok(AMOUNT - 1)); - assert_eq!(balance_of(&mut session, TOKEN_A, ALICE)?, Ok(AMOUNT - 1)); - Ok(()) -} - -#[drink::test(sandbox = Sandbox)] -fn test_transfer_token_works(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - let contract_bundle = BundleProvider::local()?; - // Deploy a contract. - let contract_address = - session.deploy_bundle(contract_bundle, "new", NO_ARGS, NO_SALT, Some(INIT_VALUE))?; - // Create a new token. - create(&mut session, TOKEN_A, contract_address.clone(), 10_000)?; - // Mint tokens. - const AMOUNT: Balance = 12_000; - const TRANSFERED: Balance = 500; - mint(&mut session, TOKEN_A, contract_address.clone(), AMOUNT)?; - mint(&mut session, TOKEN_A, BOB, AMOUNT)?; - // Transfer tokens. - transfer(&mut session, TOKEN_A, BOB, TRANSFERED)?; - assert_eq!(balance_of(&mut session, TOKEN_A, contract_address)?, Ok(AMOUNT - TRANSFERED)); - assert_eq!(balance_of(&mut session, TOKEN_A, BOB)?, Ok(AMOUNT + TRANSFERED)); - Ok(()) -} diff --git a/pop-api/examples/nfts/Cargo.toml b/pop-api/examples/nfts/Cargo.toml new file mode 100644 index 00000000..ef50b7ec --- /dev/null +++ b/pop-api/examples/nfts/Cargo.toml @@ -0,0 +1,25 @@ +[package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" +name = "nfts" +version = "0.1.0" + +[dependencies] +ink = { version = "5.0.0", default-features = false } +pop-api = { path = "../../../pop-api", default-features = false } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } + +[lib] +path = "lib.rs" + +[features] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] +std = [ + "ink/std", + "pop-api/std", + "scale-info/std", + "scale/std", +] diff --git a/pop-api/examples/nfts/lib.rs b/pop-api/examples/nfts/lib.rs new file mode 100644 index 00000000..0cd0f313 --- /dev/null +++ b/pop-api/examples/nfts/lib.rs @@ -0,0 +1,117 @@ +// DEPRECATED +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +use pop_api::nfts::*; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum ContractError { + InvalidCollection, + ItemAlreadyExists, + NftsError(Error), + NotOwner, +} + +impl From for ContractError { + fn from(value: Error) -> Self { + ContractError::NftsError(value) + } +} + +#[ink::contract] +mod nfts { + use super::*; + + #[ink(storage)] + #[derive(Default)] + pub struct Nfts; + + impl Nfts { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("Nfts::new"); + Default::default() + } + + #[ink(message)] + pub fn create_nft_collection(&self) -> Result<(), ContractError> { + ink::env::debug_println!("Nfts::create_nft_collection: collection creation started."); + let admin = Self::env().caller(); + let item_settings = ItemSettings(BitFlags::from(ItemSetting::Transferable)); + + let mint_settings = MintSettings { + mint_type: MintType::Issuer, + price: Some(0), + start_block: Some(0), + end_block: Some(0), + default_item_settings: item_settings, + }; + + let config = CollectionConfig { + settings: CollectionSettings(BitFlags::from(CollectionSetting::TransferableItems)), + max_supply: None, + mint_settings, + }; + pop_api::nfts::create(admin, config)?; + ink::env::debug_println!( + "Nfts::create_nft_collection: collection created successfully." + ); + Ok(()) + } + + #[ink(message)] + pub fn mint_nft( + &mut self, + collection_id: u32, + item_id: u32, + receiver: AccountId, + ) -> Result<(), ContractError> { + ink::env::debug_println!( + "Nfts::mint: collection_id: {:?} item_id {:?} receiver: {:?}", + collection_id, + item_id, + receiver + ); + + // Check if item already exists (demo purposes only, unnecessary as would expect check in mint call) + if item(collection_id, item_id)?.is_some() { + return Err(ContractError::ItemAlreadyExists); + } + + // mint api + mint(collection_id, item_id, receiver)?; + ink::env::debug_println!("Nfts::mint: item minted successfully"); + + // check owner + match owner(collection_id, item_id)? { + Some(owner) if owner == receiver => { + ink::env::debug_println!("Nfts::mint success: minted item belongs to receiver"); + }, + _ => { + return Err(ContractError::NotOwner); + }, + } + + ink::env::debug_println!("Nfts::mint end"); + Ok(()) + } + + #[ink(message)] + pub fn read_collection(&self, collection_id: u32) -> Result<(), ContractError> { + ink::env::debug_println!("Nfts::read_collection: collection_id: {:?}", collection_id); + let collection = pop_api::nfts::collection(collection_id)?; + ink::env::debug_println!("Nfts::read_collection: collection: {:?}", collection); + Ok(()) + } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[ink::test] + fn default_works() { + Nfts::new(); + } + } +} diff --git a/pop-api/examples/place-spot-order/Cargo.toml b/pop-api/examples/place-spot-order/Cargo.toml new file mode 100644 index 00000000..f523bea7 --- /dev/null +++ b/pop-api/examples/place-spot-order/Cargo.toml @@ -0,0 +1,25 @@ +[package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" +name = "spot_order" +version = "0.1.0" + +[dependencies] +ink = { version = "5.0.0", default-features = false } +pop-api = { path = "../../../pop-api", default-features = false } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } + +[lib] +path = "lib.rs" + +[features] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] +std = [ + "ink/std", + "pop-api/std", + "scale-info/std", + "scale/std", +] diff --git a/pop-api/examples/place-spot-order/lib.rs b/pop-api/examples/place-spot-order/lib.rs new file mode 100644 index 00000000..965917d1 --- /dev/null +++ b/pop-api/examples/place-spot-order/lib.rs @@ -0,0 +1,43 @@ +// DEPRECATED +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +#[ink::contract] +mod spot_order { + + #[ink(storage)] + #[derive(Default)] + pub struct SpotOrder; + + impl SpotOrder { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("SpotOrder::new"); + Default::default() + } + + #[ink(message)] + pub fn place_spot_order(&mut self, max_amount: Balance, para_id: u32) { + ink::env::debug_println!( + "SpotOrder::place_spot_order: max_amount {:?} para_id: {:?} ", + max_amount, + para_id, + ); + + #[allow(unused_variables)] + let res = pop_api::cross_chain::coretime::place_spot_order(max_amount, para_id); + ink::env::debug_println!("SpotOrder::place_spot_order: res {:?} ", res,); + + ink::env::debug_println!("SpotOrder::place_spot_order end"); + } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[ink::test] + fn default_works() { + SpotOrder::new(); + } + } +} diff --git a/pop-api/examples/read-runtime-state/Cargo.toml b/pop-api/examples/read-runtime-state/Cargo.toml new file mode 100644 index 00000000..f5464730 --- /dev/null +++ b/pop-api/examples/read-runtime-state/Cargo.toml @@ -0,0 +1,25 @@ +[package] +authors = [ "[your_name] <[your_email]>" ] +edition = "2021" +name = "read_relay_blocknumber" +version = "0.1.0" + +[dependencies] +ink = { version = "5.0.0", default-features = false } +pop-api = { path = "../../../pop-api", default-features = false } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } + +[lib] +path = "lib.rs" + +[features] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] +std = [ + "ink/std", + "pop-api/std", + "scale-info/std", + "scale/std", +] diff --git a/pop-api/examples/read-runtime-state/lib.rs b/pop-api/examples/read-runtime-state/lib.rs new file mode 100644 index 00000000..092e9f2f --- /dev/null +++ b/pop-api/examples/read-runtime-state/lib.rs @@ -0,0 +1,36 @@ +// DEPRECATED +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +#[ink::contract] +mod read_relay_blocknumber { + use pop_api::primitives::storage_keys::{ + ParachainSystemKeys::LastRelayChainBlockNumber, RuntimeStateKeys::ParachainSystem, + }; + + #[ink(event)] + pub struct RelayBlockNumberRead { + value: BlockNumber, + } + + #[ink(storage)] + #[derive(Default)] + pub struct ReadRelayBlockNumber; + + impl ReadRelayBlockNumber { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("ReadRelayBlockNumber::new"); + Default::default() + } + + #[ink(message)] + pub fn read_relay_block_number(&self) { + let result = + pop_api::state::read::(ParachainSystem(LastRelayChainBlockNumber)); + ink::env::debug_println!("Last relay block number read by contract: {:?}", result); + self.env().emit_event(RelayBlockNumberRead { + value: result.expect("Failed to read relay block number."), + }); + } + } +} From 12c368bc542b73b0b12e240439b93e30f26c6307 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:29:16 +0700 Subject: [PATCH 111/161] chore: resolve comments --- pop-sandbox/README.md | 30 +++++++++++++++++++++-------- pop-sandbox/examples/flipper/lib.rs | 6 +++--- pop-sandbox/src/lib.rs | 21 ++++++++++---------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/pop-sandbox/README.md b/pop-sandbox/README.md index b911cd17..cacfdc22 100644 --- a/pop-sandbox/README.md +++ b/pop-sandbox/README.md @@ -1,6 +1,8 @@ # Pop Sandbox -Implementation of the `pop_drink::Sandbox` struct for the Pop Network runtimes required for the quasi testing with `drink`. +Implementation of the [`pop_drink::Sandbox`](https://github.com/r0gue-io/pop-drink) struct for the Pop Network runtimes (located in `pop-node/runtime`) required for the quasi testing with `drink`. + +In the context of quasi-testing with pop-drink, a sandbox refers to an isolated runtime environment that simulates the behavior of a full node, without requiring an actual node. It can emulate key processes (where runtime `pallets` are involved) such as block initialization, execution, and block finalization. ## Getting Started @@ -12,28 +14,36 @@ pop_drink = { version = "1.0.0", package = "pop-drink" } ### Import Sandbox for the specific runtime -For mainnet +- For `devnet` runtime + +Implementation of the sandbox runtime environment for `devnet` runtime located in `pop-node/runtime/devnet` ```rs -use pop_sandbox::MainnetSandbox; +use pop_sandbox::DevnetSandbox; ``` -For devnet +- For `testnet` runtime + +Implementation of the sandbox runtime environment for `testnet` runtime located in `pop-node/runtime/testnet` ```rs -use pop_sandbox::DevnetSandbox; +use pop_sandbox::TestnetSandbox; ``` -For testnet +- For `mainnet` runtime + +Implementation of the sandbox runtime environment for `mainnet` runtime located in `pop-node/runtime/mainnet` ```rs -use pop_sandbox::TestnetSandbox; +use pop_sandbox::MainnetSandbox; ``` ### Setup test environment for your contract +Below is an example for the contract testing with `pop_drink` and `pop_sandbox` for `devnet` environment using `DevnetSandbox`. + ```rs -use drink::session::Session; +use pop_drink::session::Session; use pop_sandbox::DevnetSandbox as Sandbox; #[drink::contract_bundle_provider] @@ -44,3 +54,7 @@ fn test(mut session: Session) { // Your test case } ``` + +## Examples + +Please find more examples of `pop_drink` tests in the [`pop_drink/examples`](https://github.com/r0gue-io/pop-drink/tree/main/examples). diff --git a/pop-sandbox/examples/flipper/lib.rs b/pop-sandbox/examples/flipper/lib.rs index cf0352a9..c26c6ead 100644 --- a/pop-sandbox/examples/flipper/lib.rs +++ b/pop-sandbox/examples/flipper/lib.rs @@ -74,7 +74,7 @@ mod tests { /// runtime and it exposes a broad API for interacting with it. Session is generic over the /// runtime type, but usually and by default, we use `MinimalSandbox`, which is a minimalistic /// runtime that allows using smart contracts. - #[drink::test(sandbox = pop_sandbox::PopSandbox)] + #[drink::test(sandbox = pop_sandbox::DevnetSandbox)] fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Now we get the contract bundle from the `BundleProvider` enum. Since the current crate @@ -119,7 +119,7 @@ mod tests { } /// In this testcase we will see how to get and read debug logs from the contract. - #[drink::test(sandbox = pop_sandbox::PopSandbox)] + #[drink::test(sandbox = pop_sandbox::DevnetSandbox)] fn get_debug_logs(mut session: Session) -> Result<(), Box> { session.deploy_bundle(BundleProvider::local()?, "new", &["true"], NO_SALT, None)?; @@ -139,7 +139,7 @@ mod tests { } /// In this testcase we will see how to work with multiple contracts. - #[drink::test(sandbox = pop_sandbox::PopSandbox)] + #[drink::test(sandbox = pop_sandbox::DevnetSandbox)] fn work_with_multiple_contracts( mut session: Session, ) -> Result<(), Box> { diff --git a/pop-sandbox/src/lib.rs b/pop-sandbox/src/lib.rs index dbdb9a06..ad15cf90 100644 --- a/pop-sandbox/src/lib.rs +++ b/pop-sandbox/src/lib.rs @@ -1,13 +1,11 @@ +pub use frame_support::sp_runtime::AccountId32; use frame_support::{ - sp_runtime::{ - traits::{Header, One}, - }, + sp_runtime::traits::{Header, One}, traits::Hooks, }; use frame_system::pallet_prelude::BlockNumberFor; -use pop_runtime_devnet::{BuildStorage, Runtime}; pub use pop_runtime_devnet::Balance; -pub use frame_support::sp_runtime::AccountId32; +use pop_runtime_devnet::{BuildStorage, Runtime}; /// Alias for the account ID type. pub type AccountIdFor = ::AccountId; @@ -49,7 +47,7 @@ impl< frame_system::Pallet::::reset_events(); frame_system::Pallet::::initialize(&height, &parent_hash, &Default::default()); pallet_balances::Pallet::::on_initialize(height); - // TODO: Resolve an issue with pallet-aura to simulate the time. + // TODO: Resolve an issue with pallet-aura to simulate the time: Timestamp slot must match `CurrentSlot` // pallet_timestamp::Pallet::::set_timestamp( // SystemTime::now() // .duration_since(SystemTime::UNIX_EPOCH) @@ -72,16 +70,19 @@ impl< } } -pub struct Sandbox { +/// Sandbox runtime environment for `devnet` runtime. +pub struct DevnetSandbox { ext: sp_io::TestExternalities, } -impl Default for Sandbox { +impl Default for DevnetSandbox { fn default() -> Self { - let balances: Vec<(AccountId32, u128)> = vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)]; + let balances: Vec<(AccountId32, u128)> = + vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)]; let ext = BlockBuilder::::new_ext(balances); Self { ext } } } -drink::impl_sandbox!(Sandbox, Runtime, BlockBuilder, ALICE); +/// Implement core functionalities of the `DevnetSandbox`. +drink::impl_sandbox!(DevnetSandbox, Runtime, BlockBuilder, ALICE); From e76a5248a872d0b578be03d96afad3129fff38d1 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:31:21 +0700 Subject: [PATCH 112/161] chore: remove deprecated example contracts --- pop-api/examples/balance-transfer/Cargo.toml | 28 ---- pop-api/examples/balance-transfer/lib.rs | 135 ------------------ pop-api/examples/nfts/Cargo.toml | 25 ---- pop-api/examples/nfts/lib.rs | 117 --------------- pop-api/examples/place-spot-order/Cargo.toml | 25 ---- pop-api/examples/place-spot-order/lib.rs | 43 ------ .../examples/read-runtime-state/Cargo.toml | 25 ---- pop-api/examples/read-runtime-state/lib.rs | 36 ----- 8 files changed, 434 deletions(-) delete mode 100644 pop-api/examples/balance-transfer/Cargo.toml delete mode 100644 pop-api/examples/balance-transfer/lib.rs delete mode 100644 pop-api/examples/nfts/Cargo.toml delete mode 100644 pop-api/examples/nfts/lib.rs delete mode 100644 pop-api/examples/place-spot-order/Cargo.toml delete mode 100644 pop-api/examples/place-spot-order/lib.rs delete mode 100644 pop-api/examples/read-runtime-state/Cargo.toml delete mode 100644 pop-api/examples/read-runtime-state/lib.rs diff --git a/pop-api/examples/balance-transfer/Cargo.toml b/pop-api/examples/balance-transfer/Cargo.toml deleted file mode 100644 index 2a12e532..00000000 --- a/pop-api/examples/balance-transfer/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "balance_transfer" -version = "0.1.0" - -[dependencies] -ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } - -[dev-dependencies] -ink_e2e = "5.0.0" - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "ink/std", - "pop-api/std", - "scale-info/std", - "scale/std", -] diff --git a/pop-api/examples/balance-transfer/lib.rs b/pop-api/examples/balance-transfer/lib.rs deleted file mode 100644 index e75c15b9..00000000 --- a/pop-api/examples/balance-transfer/lib.rs +++ /dev/null @@ -1,135 +0,0 @@ -// DEPRECATED -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -use pop_api::balances::*; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum ContractError { - BalancesError(Error), -} - -impl From for ContractError { - fn from(value: Error) -> Self { - ContractError::BalancesError(value) - } -} - -#[ink::contract] -mod balance_transfer { - use super::*; - - #[ink(storage)] - #[derive(Default)] - pub struct BalanceTransfer; - - impl BalanceTransfer { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("BalanceTransfer::new"); - Default::default() - } - - #[ink(message)] - pub fn transfer( - &mut self, - receiver: AccountId, - value: Balance, - ) -> Result<(), ContractError> { - ink::env::debug_println!( - "BalanceTransfer::transfer: \nreceiver: {:?}, \nvalue: {:?}", - receiver, - value - ); - - transfer_keep_alive(receiver, value)?; - - ink::env::debug_println!("BalanceTransfer::transfer end"); - Ok(()) - } - } - - #[cfg(all(test, feature = "e2e-tests"))] - mod e2e_tests { - use super::*; - use ink_e2e::{ChainBackend, ContractsBackend}; - - use ink::{ - env::{test::default_accounts, DefaultEnvironment}, - primitives::AccountId, - }; - - type E2EResult = Result>; - - /// The base number of indivisible units for balances on the - /// `substrate-contracts-node`. - const UNIT: Balance = 1_000_000_000_000; - - /// The contract will be given 1000 tokens during instantiation. - const CONTRACT_BALANCE: Balance = 1_000 * UNIT; - - /// The receiver will get enough funds to have the required existential deposit. - /// - /// If your chain has this threshold higher, increase the transfer value. - const TRANSFER_VALUE: Balance = 1 / 10 * UNIT; - - /// An amount that is below the existential deposit, so that a transfer to an - /// empty account fails. - /// - /// Must not be zero, because such an operation would be a successful no-op. - const INSUFFICIENT_TRANSFER_VALUE: Balance = 1; - - /// Positive case scenario: - /// - the call is valid - /// - the call execution succeeds - #[ink_e2e::test] - async fn transfer_with_call_runtime_works( - mut client: Client, - ) -> E2EResult<()> { - // given - let mut constructor = RuntimeCallerRef::new(); - let contract = client - .instantiate("call-runtime", &ink_e2e::alice(), &mut constructor) - .value(CONTRACT_BALANCE) - .submit() - .await - .expect("instantiate failed"); - let mut call_builder = contract.call_builder::(); - - let accounts = default_accounts::(); - - let receiver: AccountId = accounts.bob; - - let sender_balance_before = client - .free_balance(accounts.alice) - .await - .expect("Failed to get account balance"); - let receiver_balance_before = - client.free_balance(receiver).await.expect("Failed to get account balance"); - - // when - let transfer_message = call_builder.transfer(receiver, TRANSFER_VALUE); - - let call_res = client - .call(&ink_e2e::alice(), &transfer_message) - .submit() - .await - .expect("call failed"); - - assert!(call_res.return_value().is_ok()); - - // then - let sender_balance_after = client - .free_balance(accounts.alice) - .await - .expect("Failed to get account balance"); - let receiver_balance_after = - client.free_balance(receiver).await.expect("Failed to get account balance"); - - assert_eq!(contract_balance_before, contract_balance_after + TRANSFER_VALUE); - assert_eq!(receiver_balance_before, receiver_balance_after - TRANSFER_VALUE); - - Ok(()) - } - } -} diff --git a/pop-api/examples/nfts/Cargo.toml b/pop-api/examples/nfts/Cargo.toml deleted file mode 100644 index ef50b7ec..00000000 --- a/pop-api/examples/nfts/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "nfts" -version = "0.1.0" - -[dependencies] -ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "ink/std", - "pop-api/std", - "scale-info/std", - "scale/std", -] diff --git a/pop-api/examples/nfts/lib.rs b/pop-api/examples/nfts/lib.rs deleted file mode 100644 index 0cd0f313..00000000 --- a/pop-api/examples/nfts/lib.rs +++ /dev/null @@ -1,117 +0,0 @@ -// DEPRECATED -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -use pop_api::nfts::*; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] -#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub enum ContractError { - InvalidCollection, - ItemAlreadyExists, - NftsError(Error), - NotOwner, -} - -impl From for ContractError { - fn from(value: Error) -> Self { - ContractError::NftsError(value) - } -} - -#[ink::contract] -mod nfts { - use super::*; - - #[ink(storage)] - #[derive(Default)] - pub struct Nfts; - - impl Nfts { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("Nfts::new"); - Default::default() - } - - #[ink(message)] - pub fn create_nft_collection(&self) -> Result<(), ContractError> { - ink::env::debug_println!("Nfts::create_nft_collection: collection creation started."); - let admin = Self::env().caller(); - let item_settings = ItemSettings(BitFlags::from(ItemSetting::Transferable)); - - let mint_settings = MintSettings { - mint_type: MintType::Issuer, - price: Some(0), - start_block: Some(0), - end_block: Some(0), - default_item_settings: item_settings, - }; - - let config = CollectionConfig { - settings: CollectionSettings(BitFlags::from(CollectionSetting::TransferableItems)), - max_supply: None, - mint_settings, - }; - pop_api::nfts::create(admin, config)?; - ink::env::debug_println!( - "Nfts::create_nft_collection: collection created successfully." - ); - Ok(()) - } - - #[ink(message)] - pub fn mint_nft( - &mut self, - collection_id: u32, - item_id: u32, - receiver: AccountId, - ) -> Result<(), ContractError> { - ink::env::debug_println!( - "Nfts::mint: collection_id: {:?} item_id {:?} receiver: {:?}", - collection_id, - item_id, - receiver - ); - - // Check if item already exists (demo purposes only, unnecessary as would expect check in mint call) - if item(collection_id, item_id)?.is_some() { - return Err(ContractError::ItemAlreadyExists); - } - - // mint api - mint(collection_id, item_id, receiver)?; - ink::env::debug_println!("Nfts::mint: item minted successfully"); - - // check owner - match owner(collection_id, item_id)? { - Some(owner) if owner == receiver => { - ink::env::debug_println!("Nfts::mint success: minted item belongs to receiver"); - }, - _ => { - return Err(ContractError::NotOwner); - }, - } - - ink::env::debug_println!("Nfts::mint end"); - Ok(()) - } - - #[ink(message)] - pub fn read_collection(&self, collection_id: u32) -> Result<(), ContractError> { - ink::env::debug_println!("Nfts::read_collection: collection_id: {:?}", collection_id); - let collection = pop_api::nfts::collection(collection_id)?; - ink::env::debug_println!("Nfts::read_collection: collection: {:?}", collection); - Ok(()) - } - } - - #[cfg(test)] - mod tests { - use super::*; - - #[ink::test] - fn default_works() { - Nfts::new(); - } - } -} diff --git a/pop-api/examples/place-spot-order/Cargo.toml b/pop-api/examples/place-spot-order/Cargo.toml deleted file mode 100644 index f523bea7..00000000 --- a/pop-api/examples/place-spot-order/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "spot_order" -version = "0.1.0" - -[dependencies] -ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "ink/std", - "pop-api/std", - "scale-info/std", - "scale/std", -] diff --git a/pop-api/examples/place-spot-order/lib.rs b/pop-api/examples/place-spot-order/lib.rs deleted file mode 100644 index 965917d1..00000000 --- a/pop-api/examples/place-spot-order/lib.rs +++ /dev/null @@ -1,43 +0,0 @@ -// DEPRECATED -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -#[ink::contract] -mod spot_order { - - #[ink(storage)] - #[derive(Default)] - pub struct SpotOrder; - - impl SpotOrder { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("SpotOrder::new"); - Default::default() - } - - #[ink(message)] - pub fn place_spot_order(&mut self, max_amount: Balance, para_id: u32) { - ink::env::debug_println!( - "SpotOrder::place_spot_order: max_amount {:?} para_id: {:?} ", - max_amount, - para_id, - ); - - #[allow(unused_variables)] - let res = pop_api::cross_chain::coretime::place_spot_order(max_amount, para_id); - ink::env::debug_println!("SpotOrder::place_spot_order: res {:?} ", res,); - - ink::env::debug_println!("SpotOrder::place_spot_order end"); - } - } - - #[cfg(test)] - mod tests { - use super::*; - - #[ink::test] - fn default_works() { - SpotOrder::new(); - } - } -} diff --git a/pop-api/examples/read-runtime-state/Cargo.toml b/pop-api/examples/read-runtime-state/Cargo.toml deleted file mode 100644 index f5464730..00000000 --- a/pop-api/examples/read-runtime-state/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -edition = "2021" -name = "read_relay_blocknumber" -version = "0.1.0" - -[dependencies] -ink = { version = "5.0.0", default-features = false } -pop-api = { path = "../../../pop-api", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.6", default-features = false, features = [ "derive" ], optional = true } - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -e2e-tests = [ ] -ink-as-dependency = [ ] -std = [ - "ink/std", - "pop-api/std", - "scale-info/std", - "scale/std", -] diff --git a/pop-api/examples/read-runtime-state/lib.rs b/pop-api/examples/read-runtime-state/lib.rs deleted file mode 100644 index 092e9f2f..00000000 --- a/pop-api/examples/read-runtime-state/lib.rs +++ /dev/null @@ -1,36 +0,0 @@ -// DEPRECATED -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -#[ink::contract] -mod read_relay_blocknumber { - use pop_api::primitives::storage_keys::{ - ParachainSystemKeys::LastRelayChainBlockNumber, RuntimeStateKeys::ParachainSystem, - }; - - #[ink(event)] - pub struct RelayBlockNumberRead { - value: BlockNumber, - } - - #[ink(storage)] - #[derive(Default)] - pub struct ReadRelayBlockNumber; - - impl ReadRelayBlockNumber { - #[ink(constructor, payable)] - pub fn new() -> Self { - ink::env::debug_println!("ReadRelayBlockNumber::new"); - Default::default() - } - - #[ink(message)] - pub fn read_relay_block_number(&self) { - let result = - pop_api::state::read::(ParachainSystem(LastRelayChainBlockNumber)); - ink::env::debug_println!("Last relay block number read by contract: {:?}", result); - self.env().emit_event(RelayBlockNumberRead { - value: result.expect("Failed to read relay block number."), - }); - } - } -} From a39b1a4e875e5ab7b6272ddad2ade7e915c069de Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:59:57 +0700 Subject: [PATCH 113/161] chore: rebase --- pop-api/examples/fungibles/Cargo.toml | 3 ++ pop-api/examples/fungibles/lib.rs | 45 +++++++++++++-------------- pop-api/examples/fungibles/tests.rs | 11 +++---- pop-api/examples/fungibles/utils.rs | 8 ++--- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 088f71cb..4caf80a1 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -37,4 +37,7 @@ ink-as-dependency = [ ] std = [ "ink/std", "pop-api/std", + "pop-sandbox/std", + "scale-info/std", + "scale/std", ] diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 4e0eb66e..3a8e71da 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -2,7 +2,6 @@ use ink::prelude::{string::String, vec::Vec}; use pop_api::{ - fungibles::{self as api}, primitives::TokenId, v0::fungibles::{ self as api, @@ -27,19 +26,6 @@ mod fungibles { } impl Fungibles { - fn emit_created_event(&mut self, id: u32, creator: AccountId, admin: AccountId) { - self.env().emit_event(Created { id, creator, admin }); - } - - fn emit_transfer_event( - &mut self, - from: Option, - to: Option, - value: Balance, - ) { - self.env().emit_event(Transfer { from, to, value }); - } - fn emit_approval_event(&mut self, owner: AccountId, spender: AccountId, value: Balance) { self.env().emit_event(Approval { owner, spender, value }); } @@ -49,7 +35,7 @@ mod fungibles { /// # Parameters /// * - `token` - The token. #[ink(constructor, payable)] - pub fn new_existing(id: TokenId) -> Result { + pub fn existing(id: TokenId) -> Result { // Make sure token exists. if !api::token_exists(id).unwrap_or_default() { return Err(PSP22Error::Custom(String::from("Unknown"))); @@ -75,7 +61,9 @@ mod fungibles { let mut contract = Self { id }; let contract_id = contract.env().account_id(); api::create(id, contract_id, min_balance).map_err(PSP22Error::from)?; - contract.emit_created_event(id, contract_id, contract_id); + contract + .env() + .emit_event(Created { id, creator: contract_id, admin: contract_id }); Ok(contract) } } @@ -121,7 +109,7 @@ mod fungibles { } api::transfer(self.id, to, value).map_err(PSP22Error::from)?; - self.emit_transfer_event(Some(caller), Some(to), value); + self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); Ok(()) } @@ -161,9 +149,10 @@ mod fungibles { // the new allowance amount is emitted. api::transfer_from(self.id, from, to, value).map_err(PSP22Error::from)?; // Emit events. - self.emit_transfer_event(Some(caller), Some(to), value); + self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); let allowance = self.allowance(from, to).saturating_sub(value); - self.emit_approval_event(from, caller, allowance); + self.env() + .emit_event(Approval { owner: from, spender: caller, value: allowance }); Ok(()) } @@ -179,7 +168,7 @@ mod fungibles { } api::approve(self.id, spender, value).map_err(PSP22Error::from)?; - self.emit_approval_event(caller, spender, value); + self.env().emit_event(Approval { owner: caller, spender, value }); Ok(()) } @@ -199,7 +188,11 @@ mod fungibles { let allowance = self.allowance(caller, spender); api::increase_allowance(self.id, spender, value).map_err(PSP22Error::from)?; - self.emit_approval_event(caller, spender, allowance.saturating_add(value)); + self.env().emit_event(Approval { + owner: caller, + spender, + value: allowance.saturating_add(value), + }); Ok(()) } @@ -225,7 +218,11 @@ mod fungibles { } api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; - self.emit_approval_event(caller, spender, allowance.saturating_sub(value)); + self.env().emit_event(Approval { + owner: caller, + spender, + value: allowance.saturating_sub(value), + }); Ok(()) } } @@ -258,7 +255,7 @@ mod fungibles { return Ok(()); } api::mint(self.id, account, value).map_err(PSP22Error::from)?; - self.emit_transfer_event(None, Some(account), value); + self.env().emit_event(Transfer { from: None, to: Some(account), value }); Ok(()) } } @@ -275,7 +272,7 @@ mod fungibles { return Err(PSP22Error::InsufficientBalance); } api::burn(self.id, account, value).map_err(PSP22Error::from)?; - self.emit_transfer_event(Some(account), None, value); + self.env().emit_event(Transfer { from: Some(account), to: None, value }); Ok(()) } } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 7046d83f..eb32801c 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -7,7 +7,7 @@ use pop_api::{ primitives::TokenId, v0::fungibles::events::{Approval, Created, Transfer}, }; -use pop_sandbox::{Balance, Sandbox, ALICE, BOB}; +use pop_sandbox::{Balance, DevnetSandbox as Sandbox, ALICE, BOB}; use scale::Encode; use utils::*; @@ -39,14 +39,14 @@ fn new_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box> { +fn existing_constructor_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Create token. let actor = session.get_actor(); session.sandbox().create(&TOKEN_ID, &actor, TOKEN_MIN_BALANCE).unwrap(); // Deploy a new contract. - deploy_with_new_existing_constructor(&mut session, BundleProvider::local()?, TOKEN_ID)?; + deploy_with_existing_constructor(&mut session, BundleProvider::local()?, TOKEN_ID)?; // Token is created successfully. assert!(session.sandbox().asset_exists(&TOKEN_ID)); // No event emitted. @@ -55,13 +55,12 @@ fn new_existing_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box> { let _ = env_logger::try_init(); - let result = - deploy_with_new_existing_constructor(&mut session, BundleProvider::local()?, TOKEN_ID); + let result = deploy_with_existing_constructor(&mut session, BundleProvider::local()?, TOKEN_ID); assert!(result.is_err()); Ok(()) } diff --git a/pop-api/examples/fungibles/utils.rs b/pop-api/examples/fungibles/utils.rs index 38968afd..8e8a7ef7 100644 --- a/pop-api/examples/fungibles/utils.rs +++ b/pop-api/examples/fungibles/utils.rs @@ -5,7 +5,7 @@ use drink::{ DispatchError, }; use pop_api::primitives::{AccountId, TokenId}; -use pop_sandbox::{AccountId32, Balance, Sandbox, INIT_VALUE}; +use pop_sandbox::{AccountId32, Balance, DevnetSandbox as Sandbox, INIT_VALUE}; use scale::{Decode, Encode}; use super::*; @@ -87,12 +87,12 @@ pub(super) fn deploy_with_new_constructor( ) } -pub(super) fn deploy_with_new_existing_constructor( +pub(super) fn deploy_with_existing_constructor( session: &mut Session, bundle: ContractBundle, id: TokenId, ) -> Result { - session.deploy_bundle(bundle, "new_existing", &[id.to_string()], NO_SALT, Some(INIT_VALUE)) + session.deploy_bundle(bundle, "existing", &[id.to_string()], NO_SALT, Some(INIT_VALUE)) } // Test methods for `PSP22`. @@ -192,5 +192,5 @@ pub(super) fn burn( account: AccountId32, amount: Balance, ) -> Result<(), Box> { - Ok(session.call(BURN, &vec![account.to_string(), amount.to_string()], None)??) + Ok(session.call(, &vec![account.to_string(), amount.to_string()], None)??) } From 517ddd37a4d80d209781e5e62ea304976bad8c16 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 23 Sep 2024 20:26:58 +0700 Subject: [PATCH 114/161] fix: resolve comments & fix transfer_from() --- pop-api/examples/fungibles/lib.rs | 27 +++---- pop-api/examples/fungibles/tests.rs | 113 ++++++++++++++++------------ pop-api/examples/fungibles/utils.rs | 2 +- 3 files changed, 76 insertions(+), 66 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 3a8e71da..1de56772 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -26,10 +26,6 @@ mod fungibles { } impl Fungibles { - fn emit_approval_event(&mut self, owner: AccountId, spender: AccountId, value: Balance) { - self.env().emit_event(Approval { owner, spender, value }); - } - /// Instantiate the contract and wrap around an existing token. /// /// # Parameters @@ -150,9 +146,11 @@ mod fungibles { api::transfer_from(self.id, from, to, value).map_err(PSP22Error::from)?; // Emit events. self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); - let allowance = self.allowance(from, to).saturating_sub(value); - self.env() - .emit_event(Approval { owner: from, spender: caller, value: allowance }); + self.env().emit_event(Approval { + owner: from, + spender: caller, + value: self.allowance(from, caller), + }); Ok(()) } @@ -186,13 +184,9 @@ mod fungibles { return Ok(()); } - let allowance = self.allowance(caller, spender); api::increase_allowance(self.id, spender, value).map_err(PSP22Error::from)?; - self.env().emit_event(Approval { - owner: caller, - spender, - value: allowance.saturating_add(value), - }); + let allowance = self.allowance(caller, spender); + self.env().emit_event(Approval { owner: caller, spender, value: allowance }); Ok(()) } @@ -218,11 +212,8 @@ mod fungibles { } api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; - self.env().emit_event(Approval { - owner: caller, - spender, - value: allowance.saturating_sub(value), - }); + let allowance = self.allowance(caller, spender); + self.env().emit_event(Approval { owner: caller, spender, value: allowance }); Ok(()) } } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index eb32801c..33ee18bd 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -31,9 +31,13 @@ fn new_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box Result<(), Box> { TOKEN_MIN_BALANCE, )?; // Mint tokens. - const AMOUNT: Balance = 12_000; + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; assert_ok!(mint(&mut session, ALICE, AMOUNT)); // Successfully emit event. let expected = @@ -103,8 +107,8 @@ fn mint_works(mut session: Session) -> Result<(), Box> { .encode(); assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Tokens were minted with the right amount. - assert_eq!(total_supply(&mut session), AMOUNT); - assert_eq!(balance_of(&mut session, ALICE), AMOUNT); + assert_eq!(session.sandbox().total_supply(&TOKEN_ID), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); Ok(()) } @@ -123,8 +127,8 @@ fn mint_zero_value_works(mut session: Session) -> Result<(), Box Result<(), Box> { TOKEN_MIN_BALANCE, )?; // Mint tokens. - const AMOUNT: Balance = 12_000; - assert_ok!(mint(&mut session, ALICE, AMOUNT)); + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &ALICE, AMOUNT)); // Burn tokens. assert_ok!(burn(&mut session, ALICE, 1)); // Successfully emit event. @@ -148,8 +152,8 @@ fn burn_works(mut session: Session) -> Result<(), Box> { Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value: 1 }.encode(); assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - assert_eq!(total_supply(&mut session), AMOUNT - 1); - assert_eq!(balance_of(&mut session, ALICE), AMOUNT - 1); + assert_eq!(session.sandbox().total_supply(&TOKEN_ID), AMOUNT - 1); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT - 1); Ok(()) } @@ -186,8 +190,8 @@ fn burn_fails_with_insufficient_balance( TOKEN_MIN_BALANCE, )?; // Mint tokens. - const AMOUNT: Balance = 12_000; - assert_ok!(mint(&mut session, ALICE, AMOUNT)); + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &ALICE, AMOUNT)); // Failed with `InsufficientBalance`. expect_call_reverted( &mut session, @@ -209,10 +213,13 @@ fn transfer_works(mut session: Session) -> Result<(), Box TOKEN_MIN_BALANCE, )?; // Mint tokens. - const AMOUNT: Balance = 12_000; - const TRANSFERRED: Balance = 500; - assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); - assert_ok!(mint(&mut session, BOB, AMOUNT)); + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + const TRANSFERRED: Balance = TOKEN_MIN_BALANCE; + assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); + assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &BOB, AMOUNT)); + // Check balance of accounts. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract.clone()), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT); // Transfer tokens from `contract` to `account`. session.set_actor(contract.clone()); assert_ok!(transfer(&mut session, BOB, TRANSFERRED)); @@ -224,9 +231,8 @@ fn transfer_works(mut session: Session) -> Result<(), Box } .encode(); assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - - assert_eq!(balance_of(&mut session, contract), AMOUNT - TRANSFERRED); - assert_eq!(balance_of(&mut session, BOB), AMOUNT + TRANSFERRED); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), AMOUNT - TRANSFERRED); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT + TRANSFERRED); Ok(()) } @@ -259,9 +265,9 @@ fn transfer_fails_with_insufficient_balance( TOKEN_MIN_BALANCE, )?; // Mint tokens. - const AMOUNT: Balance = 12_000; - assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); - assert_ok!(mint(&mut session, BOB, AMOUNT)); + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); + assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &BOB, AMOUNT)); session.set_actor(contract.clone()); // Failed with `InsufficientBalance`. @@ -274,6 +280,11 @@ fn transfer_fails_with_insufficient_balance( Ok(()) } +#[drink::test(sandbox = Sandbox)] +fn allowance_works(mut session: Session) -> Result<(), Box> { + Ok(()) +} + #[drink::test(sandbox = Sandbox)] fn approve_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); @@ -285,9 +296,9 @@ fn approve_works(mut session: Session) -> Result<(), Box> TOKEN_MIN_BALANCE, )?; - const AMOUNT: Balance = 12_000; + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; // Mint tokens. - assert_ok!(mint(&mut session, contract.clone(), AMOUNT)); + assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); // Successfully apporve. session.set_actor(contract.clone()); assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); @@ -299,7 +310,7 @@ fn approve_works(mut session: Session) -> Result<(), Box> } .encode(); assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2); + assert_eq!(session.sandbox().allowance(&TOKEN_ID, &contract, &ALICE), AMOUNT / 2); Ok(()) } @@ -314,12 +325,12 @@ fn increase_allowance_works(mut session: Session) -> Result<(), Box Result<(), Box Result<(), Box Result<(), Box Result<(), Box Result<(), Box> { - Ok(session.call(, &vec![account.to_string(), amount.to_string()], None)??) + Ok(session.call(BURN, &vec![account.to_string(), amount.to_string()], None)??) } From 86e7d85b02bd5749243b955c2d06621decf26b59 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 24 Sep 2024 12:01:10 +0700 Subject: [PATCH 115/161] fix: expect return error method --- pop-api/examples/fungibles/tests.rs | 6 +++++- pop-api/examples/fungibles/utils.rs | 9 ++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 33ee18bd..57e93005 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -268,15 +268,19 @@ fn transfer_fails_with_insufficient_balance( const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &BOB, AMOUNT)); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract.clone()), AMOUNT); session.set_actor(contract.clone()); // Failed with `InsufficientBalance`. + let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); expect_call_reverted( &mut session, TRANSFER, - vec![BOB.to_string(), (AMOUNT + 1).to_string()], + vec![BOB.to_string(), (AMOUNT + 1).to_string(), data], PSP22Error::InsufficientBalance, ); + // Check that balance of account is not changed. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), AMOUNT); Ok(()) } diff --git a/pop-api/examples/fungibles/utils.rs b/pop-api/examples/fungibles/utils.rs index 44755f8b..fb6a1e3f 100644 --- a/pop-api/examples/fungibles/utils.rs +++ b/pop-api/examples/fungibles/utils.rs @@ -39,7 +39,7 @@ pub(super) fn last_contract_event(session: &Session) -> Option> session.record().last_event_batch().contract_events().last().cloned() } -/// Execute a contract method and exepct CallReverted error to be returned. +/// Execute a contract method and expect CallReverted error to be returned. pub(super) fn expect_call_reverted( session: &mut Session, function: &str, @@ -47,8 +47,11 @@ pub(super) fn expect_call_reverted( err: PSP22Error, ) { let call = session.call::(function, ¶ms, None); - if let Err(SessionError::CallReverted(error)) = call { - assert_eq!(error[1..], Err::<(), PSP22Error>(err).encode()); + match call { + Err(SessionError::CallReverted(error)) => { + assert_eq!(error[1..], Err::<(), PSP22Error>(err).encode()) + }, + _ => panic!("Expect call reverted"), } } From f8fc1b5bafc78f6b775de5fe26bc98a76c80c9ff Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 24 Sep 2024 12:54:18 +0700 Subject: [PATCH 116/161] fix: add missing conversions in PSP22Error --- pop-api/src/lib.rs | 6 ++++ pop-api/src/v0/fungibles/errors.rs | 46 ++++++++++++++++-------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 546106e5..875da576 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -39,6 +39,12 @@ impl From for StatusCode { } } +impl ToString for StatusCode { + fn to_string(&self) -> String { + self.0.to_string() + } +} + impl FromStatusCode for StatusCode { /// Converts a `u32` status code to a `Result`. /// diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 313107b4..0ed98bc1 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -90,9 +90,13 @@ impl From for PSP22Error { fn from(value: StatusCode) -> Self { let encoded = value.0.to_le_bytes(); match encoded { + // BalanceLow. + [_, ASSETS, 0, _] => PSP22Error::InsufficientBalance, + // Unapproved. + [_, ASSETS, 10, _] => PSP22Error::InsufficientAllowance, + // Unknown. [_, ASSETS, 3, _] => PSP22Error::Custom(String::from("Unknown")), - [_, ASSETS, 7, _] => PSP22Error::InsufficientAllowance, - _ => PSP22Error::Custom(String::from("Other")), + _ => PSP22Error::Custom(value.to_string()), } } } @@ -122,14 +126,8 @@ mod tests { value.into() } - fn into_fungibles_error(error: Error) -> FungiblesError { - let status_code: StatusCode = error_into_status_code(error); - status_code.into() - } - - fn into_psp22_error(error: Error) -> PSP22Error { - let status_code: StatusCode = error_into_status_code(error); - status_code.into() + fn into_error>(error: Error) -> T { + error_into_status_code(error).into() } // If we ever want to change the conversion from bytes to `u32`. @@ -173,35 +171,35 @@ mod tests { } assert_eq!( - into_fungibles_error(Module { index: BALANCES, error: [2, 0] }), + into_error::(Module { index: BALANCES, error: [2, 0] }), FungiblesError::NoBalance ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [0, 0] }), + into_error::(Module { index: ASSETS, error: [0, 0] }), FungiblesError::NoAccount ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [1, 0] }), + into_error::(Module { index: ASSETS, error: [1, 0] }), FungiblesError::NoPermission ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [2, 0] }), + into_error::(Module { index: ASSETS, error: [2, 0] }), FungiblesError::Unknown ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [3, 0] }), + into_error::(Module { index: ASSETS, error: [3, 0] }), FungiblesError::InUse ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [5, 0] }), + into_error::(Module { index: ASSETS, error: [5, 0] }), FungiblesError::MinBalanceZero ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [7, 0] }), + into_error::(Module { index: ASSETS, error: [7, 0] }), FungiblesError::InsufficientAllowance ); assert_eq!( - into_fungibles_error(Module { index: ASSETS, error: [10, 0] }), + into_error::(Module { index: ASSETS, error: [10, 0] }), FungiblesError::NotLive ); } @@ -230,16 +228,20 @@ mod tests { for error in other_errors { let status_code: StatusCode = error_into_status_code(error); let fungibles_error: PSP22Error = status_code.into(); - assert_eq!(fungibles_error, PSP22Error::Custom(String::from("Other"))) + assert_eq!(fungibles_error, PSP22Error::Custom(String::from(status_code.to_string()))) } assert_eq!( - into_psp22_error(Module { index: ASSETS, error: [3, 0] }), - PSP22Error::Custom(String::from("Unknown")) + into_error::(Module { index: ASSETS, error: [0, 0] }), + PSP22Error::InsufficientBalance ); assert_eq!( - into_psp22_error(Module { index: ASSETS, error: [7, 0] }), + into_error::(Module { index: ASSETS, error: [10, 0] }), PSP22Error::InsufficientAllowance ); + assert_eq!( + into_error::(Module { index: ASSETS, error: [3, 0] }), + PSP22Error::Custom(String::from("Unknown")) + ); } } From 4a2077fbe967dbdc63d63e27a44367a46567d811 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 24 Sep 2024 13:07:57 +0700 Subject: [PATCH 117/161] fix: remove ToString --- pop-api/src/lib.rs | 6 ------ pop-api/src/v0/fungibles/errors.rs | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 875da576..546106e5 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -39,12 +39,6 @@ impl From for StatusCode { } } -impl ToString for StatusCode { - fn to_string(&self) -> String { - self.0.to_string() - } -} - impl FromStatusCode for StatusCode { /// Converts a `u32` status code to a `Result`. /// diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 0ed98bc1..ea13da14 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -96,7 +96,7 @@ impl From for PSP22Error { [_, ASSETS, 10, _] => PSP22Error::InsufficientAllowance, // Unknown. [_, ASSETS, 3, _] => PSP22Error::Custom(String::from("Unknown")), - _ => PSP22Error::Custom(value.to_string()), + _ => PSP22Error::Custom(value.0.to_string()), } } } @@ -228,7 +228,7 @@ mod tests { for error in other_errors { let status_code: StatusCode = error_into_status_code(error); let fungibles_error: PSP22Error = status_code.into(); - assert_eq!(fungibles_error, PSP22Error::Custom(String::from(status_code.to_string()))) + assert_eq!(fungibles_error, PSP22Error::Custom(String::from(status_code.0.to_string()))) } assert_eq!( From 8fc8d07cfa36fe1df8cdb1533be2d1c171411d18 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 24 Sep 2024 13:16:24 +0700 Subject: [PATCH 118/161] fix: ToString --- pop-api/src/v0/fungibles/errors.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index ea13da14..a5c548a6 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,7 +1,7 @@ //! A set of errors for use in smart contracts that interact with the fungibles api. This includes errors compliant to standards. use super::*; -use ink::prelude::string::String; +use ink::prelude::string::{String, ToString}; /// Represents various errors related to fungible tokens. /// @@ -228,7 +228,7 @@ mod tests { for error in other_errors { let status_code: StatusCode = error_into_status_code(error); let fungibles_error: PSP22Error = status_code.into(); - assert_eq!(fungibles_error, PSP22Error::Custom(String::from(status_code.0.to_string()))) + assert_eq!(fungibles_error, PSP22Error::Custom(status_code.0.to_string())) } assert_eq!( From 52ec10dd0322e92c62aee0e410d28ce1c8898c3e Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 24 Sep 2024 14:17:42 +0700 Subject: [PATCH 119/161] refactor: tests --- pop-api/examples/fungibles/lib.rs | 32 +--- pop-api/examples/fungibles/tests.rs | 249 +++++++++++++--------------- pop-api/examples/fungibles/utils.rs | 5 +- 3 files changed, 127 insertions(+), 159 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 1de56772..87aebdb4 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -1,3 +1,9 @@ +// TODO: If `admin` in `create` is different than the contract address, `NoPermission` thrown for +// mint, burn +// TODO: `Fungibles::decrease_allowance()` saturating_sub the value, it should +// `checked_sub` and throw an error instead. Hence, we don't have to handle `InsufficientAllowance` +// on the contract side. + #![cfg_attr(not(feature = "std"), no_std, no_main)] use ink::prelude::{string::String, vec::Vec}; @@ -48,12 +54,7 @@ mod fungibles { /// * - `admin` - The account that will administer the token. /// * - `min_balance` - The minimum balance required for accounts holding this token. #[ink(constructor, payable)] - pub fn new( - id: TokenId, - // TODO: If admin is different than the contract address, `NoPermission` thrown for mint, burn - // _admin: AccountId, - min_balance: Balance, - ) -> Result { + pub fn new(id: TokenId, min_balance: Balance) -> Result { let mut contract = Self { id }; let contract_id = contract.env().account_id(); api::create(id, contract_id, min_balance).map_err(PSP22Error::from)?; @@ -99,11 +100,6 @@ mod fungibles { return Ok(()); } - // Reverts with `InsufficientBalance` if the `value` exceeds the caller's balance. - if value > self.balance_of(caller) { - return Err(PSP22Error::InsufficientBalance); - } - api::transfer(self.id, to, value).map_err(PSP22Error::from)?; self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); Ok(()) @@ -126,20 +122,6 @@ mod fungibles { return Ok(()); } - // Reverts with `InsufficientBalance` if the `value` exceeds the balance of the account - // `from`. - let allowance = self.allowance(from, caller); - if allowance < value { - return Err(PSP22Error::InsufficientAllowance); - } - - // Reverts with `InsufficientAllowance` if `from` and the caller are different addresses - // and the `value` exceeds the allowance granted by `from` to the caller. - let from_balance = self.balance_of(from); - if from_balance < value { - return Err(PSP22Error::InsufficientBalance); - } - // If `from` and the caller are different addresses, a successful transfer results // in decreased allowance by `from` to the caller and an `Approval` event with // the new allowance amount is emitted. diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 57e93005..32b1989c 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -31,14 +31,13 @@ fn new_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box Result<(), Box Result<(), Box> { TOKEN_ID, TOKEN_MIN_BALANCE, )?; - // Mint tokens. + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + + // Successfully mint tokens. + assert_ok!(mint(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().total_supply(&TOKEN_ID), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), 0); + + // Mint tokens. assert_ok!(mint(&mut session, ALICE, AMOUNT)); - // Successfully emit event. let expected = Transfer { from: None, to: Some(account_id_from_slice(ALICE.as_ref())), value: AMOUNT } .encode(); - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - // Tokens were minted with the right amount. + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Successfully emit event. + assert_eq!(session.sandbox().total_supply(&TOKEN_ID), AMOUNT); assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); Ok(()) } -#[drink::test(sandbox = Sandbox)] -fn mint_zero_value_works(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - // Deploy a new contract. - deploy_with_new_constructor( - &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - // Mint tokens. - assert_ok!(mint(&mut session, ALICE, 0)); - // No event emitted. - assert_eq!(last_contract_event(&session), None); - // Tokens were minted with the right amount. - assert_eq!(session.sandbox().total_supply(&TOKEN_ID), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), 0); - Ok(()) -} - #[drink::test(sandbox = Sandbox)] fn burn_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); @@ -142,56 +131,15 @@ fn burn_works(mut session: Session) -> Result<(), Box> { TOKEN_ID, TOKEN_MIN_BALANCE, )?; - // Mint tokens. + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &ALICE, AMOUNT)); - // Burn tokens. - assert_ok!(burn(&mut session, ALICE, 1)); - // Successfully emit event. - let expected = - Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value: 1 }.encode(); - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - - assert_eq!(session.sandbox().total_supply(&TOKEN_ID), AMOUNT - 1); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT - 1); - Ok(()) -} -#[drink::test(sandbox = Sandbox)] -fn burn_zero_value_works(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - // Deploy a new contract. - deploy_with_new_constructor( - &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - // Burn tokens. + // No-op. assert_ok!(burn(&mut session, ALICE, 0)); - // No event emitted. - assert_eq!(last_contract_event(&session), None); - // Tokens were minted with the right amount. - assert_eq!(total_supply(&mut session), 0); - assert_eq!(balance_of(&mut session, ALICE), 0); - Ok(()) -} + assert_eq!(last_contract_event(&session), None); // No event emitted. -#[drink::test(sandbox = Sandbox)] -fn burn_fails_with_insufficient_balance( - mut session: Session, -) -> Result<(), Box> { - let _ = env_logger::try_init(); - // Deploy a new contract. - deploy_with_new_constructor( - &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - // Mint tokens. - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &ALICE, AMOUNT)); // Failed with `InsufficientBalance`. expect_call_reverted( &mut session, @@ -199,6 +147,15 @@ fn burn_fails_with_insufficient_balance( vec![ALICE.to_string(), (AMOUNT + 1).to_string()], PSP22Error::InsufficientBalance, ); + + // Successfully burn tokens. + assert_ok!(burn(&mut session, ALICE, 1)); + let expected = + Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value: 1 }.encode(); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Successfully emit event. + + assert_eq!(session.sandbox().total_supply(&TOKEN_ID), AMOUNT - 1); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT - 1); Ok(()) } @@ -212,50 +169,49 @@ fn transfer_works(mut session: Session) -> Result<(), Box TOKEN_ID, TOKEN_MIN_BALANCE, )?; - // Mint tokens. + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; const TRANSFERRED: Balance = TOKEN_MIN_BALANCE; + // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &BOB, AMOUNT)); // Check balance of accounts. assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract.clone()), AMOUNT); assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT); - // Transfer tokens from `contract` to `account`. + + // No-op. + assert_ok!(transfer(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + + // Failed with `InsufficientBalance`. + let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); + expect_call_reverted( + &mut session, + TRANSFER, + vec![BOB.to_string(), (AMOUNT + 1).to_string(), data], + PSP22Error::InsufficientBalance, + ); + // Make sure balance is not changed. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), AMOUNT); + + // Successfully transfer tokens from `contract` to `account`. session.set_actor(contract.clone()); assert_ok!(transfer(&mut session, BOB, TRANSFERRED)); - // Successfully emit event. let expected = Transfer { from: Some(account_id_from_slice(contract.clone().as_ref())), to: Some(account_id_from_slice(BOB.as_ref())), value: TRANSFERRED, } .encode(); - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Successfully emit event. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), AMOUNT - TRANSFERRED); assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT + TRANSFERRED); Ok(()) } #[drink::test(sandbox = Sandbox)] -fn transfer_zero_value_works(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - // Deploy a new contract. - deploy_with_new_constructor( - &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - assert_ok!(transfer(&mut session, ALICE, 0)); - // No event emitted. - assert_eq!(last_contract_event(&session), None); - Ok(()) -} - -#[drink::test(sandbox = Sandbox)] -fn transfer_fails_with_insufficient_balance( - mut session: Session, -) -> Result<(), Box> { +fn allowance_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. let contract = deploy_with_new_constructor( @@ -264,28 +220,14 @@ fn transfer_fails_with_insufficient_balance( TOKEN_ID, TOKEN_MIN_BALANCE, )?; - // Mint tokens. + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &BOB, AMOUNT)); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract.clone()), AMOUNT); - - session.set_actor(contract.clone()); - // Failed with `InsufficientBalance`. - let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); - expect_call_reverted( - &mut session, - TRANSFER, - vec![BOB.to_string(), (AMOUNT + 1).to_string(), data], - PSP22Error::InsufficientBalance, - ); - // Check that balance of account is not changed. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), AMOUNT); - Ok(()) -} + assert_ok!(session.sandbox().approve(&TOKEN_ID, &contract.clone(), &ALICE, AMOUNT / 2)); -#[drink::test(sandbox = Sandbox)] -fn allowance_works(mut session: Session) -> Result<(), Box> { + // Successfully return a correct allowance. + assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2); Ok(()) } @@ -303,17 +245,17 @@ fn approve_works(mut session: Session) -> Result<(), Box> const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); - // Successfully apporve. + + // Successfully approve. session.set_actor(contract.clone()); assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); - // Successfully emit event. let expected = Approval { owner: account_id_from_slice(contract.clone().as_ref()), spender: account_id_from_slice(ALICE.as_ref()), value: AMOUNT / 2, } .encode(); - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Successfully emit event. assert_eq!(session.sandbox().allowance(&TOKEN_ID, &contract, &ALICE), AMOUNT / 2); Ok(()) } @@ -330,20 +272,20 @@ fn increase_allowance_works(mut session: Session) -> Result<(), Box Result<(), Box Result<(), Box(&[]).unwrap(); + expect_call_reverted( + &mut session, + TRANSFER_FROM, + vec![ALICE.to_string(), contract.clone().to_string(), (AMOUNT * 2 + 1).to_string(), data], + PSP22Error::InsufficientAllowance, + ); + // Make sure balances are unchaged. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); + + // Failed with `InsufficientBalance`. + session.set_actor(contract.clone()); + let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); + expect_call_reverted( + &mut session, + TRANSFER_FROM, + vec![ALICE.to_string(), contract.clone().to_string(), (AMOUNT + 1).to_string(), data], + PSP22Error::InsufficientBalance, + ); + // Make sure balances are unchaged. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); + // Successfully transfer from `owner`. session.set_actor(contract.clone()); assert_ok!(transfer_from(&mut session, ALICE, BOB, AMOUNT / 2)); @@ -406,11 +388,14 @@ fn transfer_from_works(mut session: Session) -> Result<(), Box AccountId { AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") } @@ -47,6 +47,7 @@ pub(super) fn expect_call_reverted( err: PSP22Error, ) { let call = session.call::(function, ¶ms, None); + println!("call: {:?}", call); match call { Err(SessionError::CallReverted(error)) => { assert_eq!(error[1..], Err::<(), PSP22Error>(err).encode()) From f9e76ec074586523489cd7ea519fe9fb4fcc8d8a Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 24 Sep 2024 18:16:57 +0700 Subject: [PATCH 120/161] feat: check deployment error --- pop-api/examples/fungibles/lib.rs | 2 + pop-api/examples/fungibles/tests.rs | 223 ++++++++++++++++------------ pop-api/examples/fungibles/utils.rs | 8 +- 3 files changed, 135 insertions(+), 98 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 87aebdb4..24a647e4 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -3,6 +3,8 @@ // TODO: `Fungibles::decrease_allowance()` saturating_sub the value, it should // `checked_sub` and throw an error instead. Hence, we don't have to handle `InsufficientAllowance` // on the contract side. +// TODO: `InsufficientBalance` case is not returned in the `burn` pallet api if the `value` exceeds +// the minted value. In `decrease_balance` method of `pallet-assets`, it is also `saturating_sub`. #![cfg_attr(not(feature = "std"), no_std, no_main)] diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 32b1989c..16d1907f 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -29,6 +29,7 @@ fn new_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box Result<(), Box> { let _ = env_logger::try_init(); - // Create token. + // Fails to deploy contract with a non-existing token ID. + assert!( + deploy_with_existing_constructor(&mut session, BundleProvider::local()?, TOKEN_ID).is_err() + ); + expect_deployment_reverted(&session, PSP22Error::Custom(String::from("Unknown"))); + + // Successfully deploy contract with an existing token ID. let actor = session.get_actor(); session.sandbox().create(&TOKEN_ID, &actor, TOKEN_MIN_BALANCE).unwrap(); - // Deploy a new contract. deploy_with_existing_constructor(&mut session, BundleProvider::local()?, TOKEN_ID)?; - // Successfully create a token. assert!(session.sandbox().asset_exists(&TOKEN_ID)); assert_eq!(last_contract_event(&session), None); // No event emitted. assert_eq!(session.sandbox().total_supply(&TOKEN_ID), 0); Ok(()) } -#[drink::test(sandbox = Sandbox)] -fn existing_constructor_deployment_fails( - mut session: Session, -) -> Result<(), Box> { - let _ = env_logger::try_init(); - - let result = deploy_with_existing_constructor(&mut session, BundleProvider::local()?, TOKEN_ID); - assert!(result.is_err()); - Ok(()) -} - #[drink::test(sandbox = Sandbox)] fn balance_of_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); @@ -94,7 +88,7 @@ fn balance_of_works(mut session: Session) -> Result<(), Box Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. - deploy_with_new_constructor( + let contract = deploy_with_new_constructor( &mut session, BundleProvider::local()?, TOKEN_ID, @@ -109,12 +103,14 @@ fn mint_works(mut session: Session) -> Result<(), Box> { assert_eq!(session.sandbox().total_supply(&TOKEN_ID), 0); assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), 0); + session.set_actor(contract.clone()); // Mint tokens. assert_ok!(mint(&mut session, ALICE, AMOUNT)); let expected = Transfer { from: None, to: Some(account_id_from_slice(ALICE.as_ref())), value: AMOUNT } .encode(); - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Successfully emit event. + // A `Transfer` event is emitted. + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); assert_eq!(session.sandbox().total_supply(&TOKEN_ID), AMOUNT); assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); @@ -144,7 +140,7 @@ fn burn_works(mut session: Session) -> Result<(), Box> { expect_call_reverted( &mut session, BURN, - vec![ALICE.to_string(), (AMOUNT + 1).to_string()], + vec![ALICE.to_string(), (AMOUNT * 2).to_string()], PSP22Error::InsufficientBalance, ); @@ -152,7 +148,8 @@ fn burn_works(mut session: Session) -> Result<(), Box> { assert_ok!(burn(&mut session, ALICE, 1)); let expected = Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value: 1 }.encode(); - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Successfully emit event. + // A `Transfer` event is emitted. + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); assert_eq!(session.sandbox().total_supply(&TOKEN_ID), AMOUNT - 1); assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT - 1); @@ -179,10 +176,15 @@ fn transfer_works(mut session: Session) -> Result<(), Box assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract.clone()), AMOUNT); assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT); - // No-op. + session.set_actor(contract.clone()); + // No-op if `value` is zero. assert_ok!(transfer(&mut session, ALICE, 0)); assert_eq!(last_contract_event(&session), None); // No event emitted. + // No-op if the caller and `to` is the same address, returns success and no events are emitted. + assert_ok!(transfer(&mut session, contract.clone(), TRANSFERRED)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + // Failed with `InsufficientBalance`. let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); expect_call_reverted( @@ -195,7 +197,6 @@ fn transfer_works(mut session: Session) -> Result<(), Box assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), AMOUNT); // Successfully transfer tokens from `contract` to `account`. - session.set_actor(contract.clone()); assert_ok!(transfer(&mut session, BOB, TRANSFERRED)); let expected = Transfer { from: Some(account_id_from_slice(contract.clone().as_ref())), @@ -203,13 +204,95 @@ fn transfer_works(mut session: Session) -> Result<(), Box value: TRANSFERRED, } .encode(); - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Successfully emit event. + // A `Transfer` event is emitted. + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), AMOUNT - TRANSFERRED); assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT + TRANSFERRED); Ok(()) } +#[drink::test(sandbox = Sandbox)] +fn transfer_from_works(mut session: Session) -> Result<(), Box> { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = deploy_with_new_constructor( + &mut session, + BundleProvider::local()?, + TOKEN_ID, + TOKEN_MIN_BALANCE, + )?; + + const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + // Mint tokens. + assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &ALICE, AMOUNT)); + // Approve `contract` to spend `ALICE` tokens. + assert_ok!(session.sandbox().approve(&TOKEN_ID, &ALICE, &contract.clone(), AMOUNT * 2)); + assert_eq!(session.sandbox().allowance(&TOKEN_ID, &ALICE, &contract.clone()), AMOUNT * 2); + // Check balance of accounts. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); + + session.set_actor(contract.clone()); + // Failed with `InsufficientAllowance`. + let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); + expect_call_reverted( + &mut session, + TRANSFER_FROM, + vec![ALICE.to_string(), contract.clone().to_string(), (AMOUNT * 2 + 1).to_string(), data], + PSP22Error::InsufficientAllowance, + ); + // Make sure balances are unchaged. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); + + session.set_actor(contract.clone()); + // No-op if `value` is zero. + assert_ok!(transfer_from(&mut session, ALICE, BOB, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + + // No-op if the `from` and `to` is the same address, returns success and no events are emitted. + assert_ok!(transfer_from(&mut session, ALICE, ALICE, AMOUNT / 2)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + + // Failed with `InsufficientBalance`. + let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); + expect_call_reverted( + &mut session, + TRANSFER_FROM, + vec![ALICE.to_string(), contract.clone().to_string(), (AMOUNT + 1).to_string(), data], + PSP22Error::InsufficientBalance, + ); + // Make sure balances are unchaged. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); + + session.set_actor(contract.clone()); + // Successfully transfer from `owner`. + assert_ok!(transfer_from(&mut session, ALICE, BOB, AMOUNT / 2)); + // Successfully emit event. + let expected = Approval { + owner: account_id_from_slice(ALICE.as_ref()), + spender: account_id_from_slice(contract.clone().as_ref()), + value: AMOUNT + AMOUNT / 2, + } + .encode(); + // An `Approval` event is emitted. + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + assert_eq!( + session.sandbox().allowance(&TOKEN_ID, &ALICE, &contract.clone()), + AMOUNT + AMOUNT / 2 + ); + // Check balance of accounts. + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT / 2); + assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT / 2); + Ok(()) +} + #[drink::test(sandbox = Sandbox)] fn allowance_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); @@ -246,8 +329,13 @@ fn approve_works(mut session: Session) -> Result<(), Box> // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); - // Successfully approve. session.set_actor(contract.clone()); + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. + assert_ok!(approve(&mut session, contract.clone(), AMOUNT / 2)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + + // Successfully approve. assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); let expected = Approval { owner: account_id_from_slice(contract.clone().as_ref()), @@ -255,7 +343,8 @@ fn approve_works(mut session: Session) -> Result<(), Box> value: AMOUNT / 2, } .encode(); - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); // Successfully emit event. + // An `Approval` event is emitted. + assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); assert_eq!(session.sandbox().allowance(&TOKEN_ID, &contract, &ALICE), AMOUNT / 2); Ok(()) } @@ -276,8 +365,13 @@ fn increase_allowance_works(mut session: Session) -> Result<(), Box Result<(), Box Result<(), Box Result<(), Box Result<(), Box> { - let _ = env_logger::try_init(); - // Deploy a new contract. - let contract = deploy_with_new_constructor( - &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; - // Mint tokens. - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &ALICE, AMOUNT)); - // Approve `contract` to spend `ALICE` tokens. - assert_ok!(session.sandbox().approve(&TOKEN_ID, &ALICE, &contract.clone(), AMOUNT * 2)); - assert_eq!(session.sandbox().allowance(&TOKEN_ID, &ALICE, &contract.clone()), AMOUNT * 2); - // Check balance of accounts. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); - - // Failed with `InsufficientAllowance`. - session.set_actor(contract.clone()); - let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); - expect_call_reverted( - &mut session, - TRANSFER_FROM, - vec![ALICE.to_string(), contract.clone().to_string(), (AMOUNT * 2 + 1).to_string(), data], - PSP22Error::InsufficientAllowance, - ); - // Make sure balances are unchaged. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); - - // Failed with `InsufficientBalance`. - session.set_actor(contract.clone()); - let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); - expect_call_reverted( - &mut session, - TRANSFER_FROM, - vec![ALICE.to_string(), contract.clone().to_string(), (AMOUNT + 1).to_string(), data], - PSP22Error::InsufficientBalance, - ); - // Make sure balances are unchaged. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); - - // Successfully transfer from `owner`. - session.set_actor(contract.clone()); - assert_ok!(transfer_from(&mut session, ALICE, BOB, AMOUNT / 2)); - // Successfully emit event. - let expected = Approval { - owner: account_id_from_slice(ALICE.as_ref()), - spender: account_id_from_slice(contract.clone().as_ref()), - value: AMOUNT + AMOUNT / 2, - } - .encode(); - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - assert_eq!( - session.sandbox().allowance(&TOKEN_ID, &ALICE, &contract.clone()), - AMOUNT + AMOUNT / 2 - ); - // Check balance of accounts. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT / 2); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT / 2); - Ok(()) -} diff --git a/pop-api/examples/fungibles/utils.rs b/pop-api/examples/fungibles/utils.rs index 06208084..5e06d42e 100644 --- a/pop-api/examples/fungibles/utils.rs +++ b/pop-api/examples/fungibles/utils.rs @@ -47,7 +47,6 @@ pub(super) fn expect_call_reverted( err: PSP22Error, ) { let call = session.call::(function, ¶ms, None); - println!("call: {:?}", call); match call { Err(SessionError::CallReverted(error)) => { assert_eq!(error[1..], Err::<(), PSP22Error>(err).encode()) @@ -56,6 +55,13 @@ pub(super) fn expect_call_reverted( } } +/// Return the last deployment result data. +pub(super) fn expect_deployment_reverted(session: &Session, err: PSP22Error) { + let result = session.record().last_deploy_result().result.clone(); + let error = result.unwrap().result.data; + assert_eq!(error[1..], Err::<(), PSP22Error>(err).encode()) +} + // Call a contract method and decode the returned data. pub(super) fn decoded_call( session: &mut Session, From e151ef1051ed4f986cb29967ca3776d350c3ea84 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 24 Sep 2024 18:17:24 +0700 Subject: [PATCH 121/161] refactor: update constant visibility --- pop-api/examples/fungibles/utils.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pop-api/examples/fungibles/utils.rs b/pop-api/examples/fungibles/utils.rs index 5e06d42e..e3ee1281 100644 --- a/pop-api/examples/fungibles/utils.rs +++ b/pop-api/examples/fungibles/utils.rs @@ -11,22 +11,22 @@ use scale::{Decode, Encode}; use super::*; // PSP22 functions. -pub const ALLOWANCE: &str = "Psp22::allowance"; -pub const BALANCE_OF: &str = "Psp22::balance_of"; -pub const TOTAL_SUPPLY: &str = "Psp22::total_supply"; -pub const TRANSFER: &str = "Psp22::transfer"; -pub const TRANSFER_FROM: &str = "Psp22::transfer_from"; -pub const APPROVE: &str = "Psp22::approve"; -pub const INCREASE_ALLOWANCE: &str = "Psp22::increase_allowance"; -pub const DECREASE_ALLOWANCE: &str = "Psp22::decrease_allowance"; +pub(super) const ALLOWANCE: &str = "Psp22::allowance"; +pub(super) const BALANCE_OF: &str = "Psp22::balance_of"; +pub(super) const TOTAL_SUPPLY: &str = "Psp22::total_supply"; +pub(super) const TRANSFER: &str = "Psp22::transfer"; +pub(super) const TRANSFER_FROM: &str = "Psp22::transfer_from"; +pub(super) const APPROVE: &str = "Psp22::approve"; +pub(super) const INCREASE_ALLOWANCE: &str = "Psp22::increase_allowance"; +pub(super) const DECREASE_ALLOWANCE: &str = "Psp22::decrease_allowance"; // PSP22Metadata functions. -pub const TOKEN_NAME: &str = "Psp22Metadata::token_name"; -pub const TOKEN_SYMBOL: &str = "Psp22Metadata::token_symbol"; -pub const TOKEN_DECIMALS: &str = "Psp22Metadata::token_decimals"; +pub(super) const TOKEN_NAME: &str = "Psp22Metadata::token_name"; +pub(super) const TOKEN_SYMBOL: &str = "Psp22Metadata::token_symbol"; +pub(super) const TOKEN_DECIMALS: &str = "Psp22Metadata::token_decimals"; // PSP22Mintable functions. -pub const MINT: &str = "Psp22Mintable::mint"; +pub(super) const MINT: &str = "Psp22Mintable::mint"; // PSP22Burnable functions. -pub const BURN: &str = "Psp22Burnable::burn"; +pub(super) const BURN: &str = "Psp22Burnable::burn"; /// This is used to resolve type mismatches between the `AccountId` in the quasi testing environment /// and the contract environment. From e370777e6cbba15faeb346010132474210caac95 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:03:32 +0700 Subject: [PATCH 122/161] fix: resolve review comments --- pop-api/examples/fungibles/lib.rs | 14 +- pop-api/examples/fungibles/tests.rs | 910 +++++++++++++++++++--------- pop-api/examples/fungibles/utils.rs | 206 ------- 3 files changed, 637 insertions(+), 493 deletions(-) delete mode 100644 pop-api/examples/fungibles/utils.rs diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 24a647e4..e916f0c8 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -21,8 +21,6 @@ use pop_api::{ #[cfg(test)] mod tests; -#[cfg(test)] -mod utils; #[ink::contract] mod fungibles { @@ -57,7 +55,7 @@ mod fungibles { /// * - `min_balance` - The minimum balance required for accounts holding this token. #[ink(constructor, payable)] pub fn new(id: TokenId, min_balance: Balance) -> Result { - let mut contract = Self { id }; + let contract = Self { id }; let contract_id = contract.env().account_id(); api::create(id, contract_id, min_balance).map_err(PSP22Error::from)?; contract @@ -206,13 +204,19 @@ mod fungibles { /// Returns the token name. #[ink(message)] fn token_name(&self) -> Option { - api::token_name(self.id).ok().and_then(|v| String::from_utf8(v).ok()) + api::token_name(self.id) + .ok() + .filter(|v| !v.is_empty()) + .and_then(|v| String::from_utf8(v).ok()) } /// Returns the token symbol. #[ink(message)] fn token_symbol(&self) -> Option { - api::token_symbol(self.id).ok().and_then(|v| String::from_utf8(v).ok()) + api::token_symbol(self.id) + .ok() + .filter(|v| !v.is_empty()) + .and_then(|v| String::from_utf8(v).ok()) } /// Returns the token decimals. diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 16d1907f..80e9b1dc 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -1,10 +1,12 @@ +use std::sync::LazyLock; + use drink::{ sandbox_api::assets_api::AssetsAPI, - session::{error::SessionError, Session}, + session::{ContractBundle, Session}, }; use frame_support::assert_ok; use pop_api::{ - primitives::TokenId, + primitives::{Error::Module, TokenId}, v0::fungibles::events::{Approval, Created, Transfer}, }; use pop_sandbox::{Balance, DevnetSandbox as Sandbox, ALICE, BOB}; @@ -13,27 +15,34 @@ use utils::*; use super::*; -const TOKEN_ID: TokenId = 1; -const TOKEN_MIN_BALANCE: Balance = 10_000; - #[drink::contract_bundle_provider] enum BundleProvider {} +const AMOUNT: Balance = MIN_BALANCE * 4; +const MIN_BALANCE: Balance = 10_000; +const TOKEN: TokenId = 1; + +static CONTRACT: LazyLock = LazyLock::new(|| BundleProvider::local().unwrap()); + +/// Deployment and constructor method tests. + #[drink::test(sandbox = Sandbox)] fn new_constructor_works(mut session: Session) -> Result<(), Box> { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy_with_new_constructor( + let contract = deploy( &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); // Token exists after the deployment. - assert!(session.sandbox().asset_exists(&TOKEN_ID)); + assert!(session.sandbox().asset_exists(&TOKEN)); + // Successfully emit event. let expected = Created { - id: TOKEN_ID, + id: TOKEN, creator: account_id_from_slice(contract.as_ref()), admin: account_id_from_slice(contract.as_ref()), } @@ -47,208 +56,163 @@ fn existing_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box> { +fn total_supply_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - deploy_with_new_constructor( - &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; - // Mint tokens. - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &ALICE, AMOUNT)); - - // Successfully return a correct balance. - assert_eq!(balance_of(&mut session, ALICE), AMOUNT); - assert_eq!(balance_of(&mut session, ALICE), session.sandbox().balance_of(&TOKEN_ID, &ALICE)); - Ok(()) + deploy(&mut session, CONTRACT.clone(), "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]) + .unwrap(); + + // No tokens in circulation. + assert_eq!(total_supply(&mut session), 0); + assert_eq!(total_supply(&mut session), session.sandbox().total_supply(&TOKEN)); + + // Tokens in circulation. + assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); + assert_ok!(session.sandbox().mint_into(&TOKEN, &BOB, AMOUNT * 2)); + assert_eq!(total_supply(&mut session), AMOUNT * 3); + assert_eq!(total_supply(&mut session), session.sandbox().total_supply(&TOKEN)); } #[drink::test(sandbox = Sandbox)] -fn mint_works(mut session: Session) -> Result<(), Box> { +fn balance_of_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy_with_new_constructor( - &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; - - // Successfully mint tokens. - assert_ok!(mint(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().total_supply(&TOKEN_ID), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), 0); + deploy(&mut session, CONTRACT.clone(), "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]) + .unwrap(); - session.set_actor(contract.clone()); - // Mint tokens. - assert_ok!(mint(&mut session, ALICE, AMOUNT)); - let expected = - Transfer { from: None, to: Some(account_id_from_slice(ALICE.as_ref())), value: AMOUNT } - .encode(); - // A `Transfer` event is emitted. - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + // No tokens in circulation. + assert_eq!(balance_of(&mut session, ALICE), 0); + assert_eq!(balance_of(&mut session, ALICE), session.sandbox().balance_of(&TOKEN, &ALICE)); - assert_eq!(session.sandbox().total_supply(&TOKEN_ID), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); - Ok(()) + // Tokens in circulation. + assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); + assert_eq!(balance_of(&mut session, ALICE), AMOUNT); + assert_eq!(balance_of(&mut session, ALICE), session.sandbox().balance_of(&TOKEN, &ALICE)); } #[drink::test(sandbox = Sandbox)] -fn burn_works(mut session: Session) -> Result<(), Box> { +fn allowance_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - deploy_with_new_constructor( + let contract = deploy( &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; - // Mint tokens. - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &ALICE, AMOUNT)); - - // No-op. - assert_ok!(burn(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - - // Failed with `InsufficientBalance`. - expect_call_reverted( - &mut session, - BURN, - vec![ALICE.to_string(), (AMOUNT * 2).to_string()], - PSP22Error::InsufficientBalance, - ); - - // Successfully burn tokens. - assert_ok!(burn(&mut session, ALICE, 1)); - let expected = - Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value: 1 }.encode(); - // A `Transfer` event is emitted. - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - - assert_eq!(session.sandbox().total_supply(&TOKEN_ID), AMOUNT - 1); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT - 1); - Ok(()) + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); + + // No tokens in circulation. + assert_eq!(allowance(&mut session, contract.clone(), ALICE), 0); + + // Tokens in circulation. + assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); + assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT / 2)); + assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2); } #[drink::test(sandbox = Sandbox)] -fn transfer_works(mut session: Session) -> Result<(), Box> { +fn transfer_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy_with_new_constructor( + let contract = deploy( &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); + session.set_actor(contract.clone()); + // `pallet-assets` returns `NoAccount` error. + let error = Module { index: 52, error: [1, 0] }.encode(); + assert_eq!( + transfer(&mut session, ALICE, AMOUNT / 4), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; - const TRANSFERRED: Balance = TOKEN_MIN_BALANCE; // Mint tokens. - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &BOB, AMOUNT)); - // Check balance of accounts. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract.clone()), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT); + assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); + assert_ok!(session.sandbox().mint_into(&TOKEN, &BOB, AMOUNT)); - session.set_actor(contract.clone()); // No-op if `value` is zero. assert_ok!(transfer(&mut session, ALICE, 0)); assert_eq!(last_contract_event(&session), None); // No event emitted. // No-op if the caller and `to` is the same address, returns success and no events are emitted. - assert_ok!(transfer(&mut session, contract.clone(), TRANSFERRED)); + assert_ok!(transfer(&mut session, contract.clone(), AMOUNT / 4)); assert_eq!(last_contract_event(&session), None); // No event emitted. // Failed with `InsufficientBalance`. - let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); - expect_call_reverted( - &mut session, - TRANSFER, - vec![BOB.to_string(), (AMOUNT + 1).to_string(), data], - PSP22Error::InsufficientBalance, - ); - // Make sure balance is not changed. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), AMOUNT); + assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); // Successfully transfer tokens from `contract` to `account`. - assert_ok!(transfer(&mut session, BOB, TRANSFERRED)); - let expected = Transfer { - from: Some(account_id_from_slice(contract.clone().as_ref())), - to: Some(account_id_from_slice(BOB.as_ref())), - value: TRANSFERRED, - } - .encode(); - // A `Transfer` event is emitted. - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); + assert_ok!(transfer(&mut session, BOB, AMOUNT / 4)); + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); + assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), AMOUNT + AMOUNT / 4); + // Successfully emit event. + assert_eq!( + last_contract_event(&session).unwrap(), + Transfer { + from: Some(account_id_from_slice(contract.as_ref())), + to: Some(account_id_from_slice(BOB.as_ref())), + value: AMOUNT / 4, + } + .encode() + .as_slice() + ); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), AMOUNT - TRANSFERRED); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT + TRANSFERRED); - Ok(()) + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `AssetNotLive` error. + let error = Module { index: 52, error: [16, 0] }.encode(); + assert_eq!( + transfer(&mut session, BOB, AMOUNT / 4), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); } #[drink::test(sandbox = Sandbox)] -fn transfer_from_works(mut session: Session) -> Result<(), Box> { +fn transfer_from_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy_with_new_constructor( + let contract = deploy( &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; - // Mint tokens. - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &ALICE, AMOUNT)); - // Approve `contract` to spend `ALICE` tokens. - assert_ok!(session.sandbox().approve(&TOKEN_ID, &ALICE, &contract.clone(), AMOUNT * 2)); - assert_eq!(session.sandbox().allowance(&TOKEN_ID, &ALICE, &contract.clone()), AMOUNT * 2); - // Check balance of accounts. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); - + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); session.set_actor(contract.clone()); - // Failed with `InsufficientAllowance`. - let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); - expect_call_reverted( - &mut session, - TRANSFER_FROM, - vec![ALICE.to_string(), contract.clone().to_string(), (AMOUNT * 2 + 1).to_string(), data], - PSP22Error::InsufficientAllowance, + // Unapproved transfer. Failed with `InsufficientAllowance`. + assert_eq!( + transfer_from(&mut session, ALICE, contract.clone(), AMOUNT * 2 + 1), + Err(PSP22Error::InsufficientAllowance) ); - // Make sure balances are unchaged. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); - session.set_actor(contract.clone()); // No-op if `value` is zero. assert_ok!(transfer_from(&mut session, ALICE, BOB, 0)); assert_eq!(last_contract_event(&session), None); // No event emitted. @@ -257,177 +221,559 @@ fn transfer_from_works(mut session: Session) -> Result<(), Box(&[]).unwrap(); - expect_call_reverted( - &mut session, - TRANSFER_FROM, - vec![ALICE.to_string(), contract.clone().to_string(), (AMOUNT + 1).to_string(), data], - PSP22Error::InsufficientBalance, + // Not enough balance. Failed with `InsufficientBalance`. + assert_eq!( + transfer_from(&mut session, ALICE, contract.clone(), AMOUNT + 1), + Err(PSP22Error::InsufficientBalance) ); - // Make sure balances are unchaged. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), 0); - session.set_actor(contract.clone()); - // Successfully transfer from `owner`. + // Successful transfer. assert_ok!(transfer_from(&mut session, ALICE, BOB, AMOUNT / 2)); + assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT + AMOUNT / 2); + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT / 2); + assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), AMOUNT / 2); // Successfully emit event. - let expected = Approval { - owner: account_id_from_slice(ALICE.as_ref()), - spender: account_id_from_slice(contract.clone().as_ref()), - value: AMOUNT + AMOUNT / 2, - } - .encode(); - // An `Approval` event is emitted. - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); assert_eq!( - session.sandbox().allowance(&TOKEN_ID, &ALICE, &contract.clone()), - AMOUNT + AMOUNT / 2 + last_contract_event(&session).unwrap(), + Approval { + owner: account_id_from_slice(ALICE.as_ref()), + spender: account_id_from_slice(contract.as_ref()), + value: AMOUNT + AMOUNT / 2, + } + .encode() + .as_slice() ); - // Check balance of accounts. - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &ALICE), AMOUNT / 2); - assert_eq!(session.sandbox().balance_of(&TOKEN_ID, &BOB), AMOUNT / 2); - Ok(()) -} - -#[drink::test(sandbox = Sandbox)] -fn allowance_works(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - // Deploy a new contract. - let contract = deploy_with_new_constructor( - &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; - // Mint tokens and approve. - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); - assert_ok!(session.sandbox().approve(&TOKEN_ID, &contract.clone(), &ALICE, AMOUNT / 2)); - // Successfully return a correct allowance. - assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2); - Ok(()) + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `AssetNotLive` error. + let error = Module { index: 52, error: [16, 0] }.encode(); + assert_eq!( + transfer_from(&mut session, ALICE, BOB, AMOUNT / 2), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); } #[drink::test(sandbox = Sandbox)] -fn approve_works(mut session: Session) -> Result<(), Box> { +fn approve_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy_with_new_constructor( + let contract = deploy( &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); + session.set_actor(contract.clone()); // Mint tokens. - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); + assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); - session.set_actor(contract.clone()); // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(approve(&mut session, contract.clone(), AMOUNT / 2)); assert_eq!(last_contract_event(&session), None); // No event emitted. - // Successfully approve. + // Successfully approvals. assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); - let expected = Approval { - owner: account_id_from_slice(contract.clone().as_ref()), - spender: account_id_from_slice(ALICE.as_ref()), - value: AMOUNT / 2, - } - .encode(); - // An `Approval` event is emitted. - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - assert_eq!(session.sandbox().allowance(&TOKEN_ID, &contract, &ALICE), AMOUNT / 2); - Ok(()) + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2); + // Successfully emit event. + assert_eq!( + last_contract_event(&session).unwrap(), + Approval { + owner: account_id_from_slice(contract.clone().as_ref()), + spender: account_id_from_slice(ALICE.as_ref()), + value: AMOUNT / 2, + } + .encode() + .as_slice() + ); + + // Non-additive, sets new value. + assert_ok!(approve(&mut session, ALICE, AMOUNT / 2 - 1)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); + // Successfully emit event. + assert_eq!( + last_contract_event(&session).unwrap(), + Approval { + owner: account_id_from_slice(contract.as_ref()), + spender: account_id_from_slice(ALICE.as_ref()), + value: AMOUNT / 2 - 1, + } + .encode() + .as_slice() + ); + + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `AssetNotLive` error. + let error = Module { index: 52, error: [16, 0] }.encode(); + assert_eq!( + approve(&mut session, ALICE, AMOUNT / 2), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); } #[drink::test(sandbox = Sandbox)] -fn increase_allowance_works(mut session: Session) -> Result<(), Box> { +fn increase_allowance_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy_with_new_constructor( + let contract = deploy( &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); + session.set_actor(contract.clone()); // Mint tokens and approve. - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); - assert_ok!(session.sandbox().approve(&TOKEN_ID, &contract.clone(), &ALICE, AMOUNT / 2)); + assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); + assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT / 2)); - session.set_actor(contract.clone()); // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(increase_allowance(&mut session, contract.clone(), AMOUNT / 2)); assert_eq!(last_contract_event(&session), None); // No event emitted. - // Successfully increase allowance. + // Successfully approvals. assert_ok!(increase_allowance(&mut session, ALICE, AMOUNT / 2)); - let expected = Approval { - owner: account_id_from_slice(contract.clone().as_ref()), - spender: account_id_from_slice(ALICE.as_ref()), - value: AMOUNT, - } - .encode(); - // An `Approval` event is emitted. - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - assert_eq!(session.sandbox().allowance(&TOKEN_ID, &contract, &ALICE), AMOUNT); - Ok(()) + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); + // Successfully emit event. + assert_eq!( + last_contract_event(&session).unwrap(), + Approval { + owner: account_id_from_slice(contract.as_ref()), + spender: account_id_from_slice(ALICE.as_ref()), + value: AMOUNT, + } + .encode() + .as_slice() + ); + + // Additive. + assert_ok!(increase_allowance(&mut session, ALICE, AMOUNT / 2)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT + AMOUNT / 2); + + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `AssetNotLive` error. + let error = Module { index: 52, error: [16, 0] }.encode(); + assert_eq!( + increase_allowance(&mut session, ALICE, AMOUNT / 2), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); } #[drink::test(sandbox = Sandbox)] -fn decrease_allowance_works(mut session: Session) -> Result<(), Box> { +fn decrease_allowance_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy_with_new_constructor( + let contract = deploy( &mut session, - BundleProvider::local()?, - TOKEN_ID, - TOKEN_MIN_BALANCE, - )?; - - const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4; - // Mint tokens. - assert_ok!(session.sandbox().mint_into(&TOKEN_ID, &contract.clone(), AMOUNT)); - assert_ok!(session.sandbox().approve(&TOKEN_ID, &contract.clone(), &ALICE, AMOUNT / 2)); - + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); session.set_actor(contract.clone()); + // Mint tokens and approve. + assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); + assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT / 2)); + // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(decrease_allowance(&mut session, contract.clone(), AMOUNT / 2)); assert_eq!(last_contract_event(&session), None); // No event emitted. // Failed with `InsufficientAllowance`. - expect_call_reverted( - &mut session, - DECREASE_ALLOWANCE, - vec![ALICE.to_string(), AMOUNT.to_string()], - PSP22Error::InsufficientAllowance, + assert_eq!( + decrease_allowance(&mut session, ALICE, AMOUNT), + Err(PSP22Error::InsufficientAllowance) ); - // Make sure allowance is unchaged. - assert_eq!(session.sandbox().allowance(&TOKEN_ID, &contract, &ALICE), AMOUNT / 2); - // Successfully decrease allowance. + // Successfully approvals. assert_ok!(decrease_allowance(&mut session, ALICE, 1)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); // Successfully emit event. - let expected = Approval { - owner: account_id_from_slice(contract.clone().as_ref()), - spender: account_id_from_slice(ALICE.as_ref()), - value: AMOUNT / 2 - 1, + assert_eq!( + last_contract_event(&session).unwrap(), + Approval { + owner: account_id_from_slice(contract.as_ref()), + spender: account_id_from_slice(ALICE.as_ref()), + value: AMOUNT / 2 - 1, + } + .encode() + .as_slice() + ); + + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `AssetNotLive` error. + let error = Module { index: 52, error: [16, 0] }.encode(); + assert_eq!( + decrease_allowance(&mut session, ALICE, 1), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); +} + +/// 2. PSP-22 Metadata Interface: +/// - token_name +/// - token_symbol +/// - token_decimals + +#[drink::test(sandbox = Sandbox)] +fn token_metadata(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = deploy( + &mut session, + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); + let name: String = String::from("Paseo Token"); + let symbol: String = String::from("PAS"); + let decimals: u8 = 69; + + session.set_actor(contract.clone()); + // Token does not exist. + assert_eq!(token_name(&mut session), None); + assert_eq!(token_symbol(&mut session), None); + assert_eq!(token_decimals(&mut session), 0); + // Create Token. + let actor = session.get_actor(); + assert_ok!(session.sandbox().set_metadata( + Some(actor), + &TOKEN, + name.clone().into(), + symbol.clone().into(), + decimals + )); + assert_eq!(token_name(&mut session), Some(name)); + assert_eq!(token_symbol(&mut session), Some(symbol)); + assert_eq!(token_decimals(&mut session), decimals); +} + +/// 3. PSP-22 Mintable Interface: +/// - mint + +#[drink::test(sandbox = Sandbox)] +fn mint_works(mut session: Session) { + let _ = env_logger::try_init(); + // No permission to mint. + assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); // Create a new token owned by `BOB`. + deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()]).unwrap(); + // `pallet-assets` returns `NoPermission` error. + let error = Module { index: 52, error: [2, 0] }.encode(); + assert_eq!( + mint(&mut session, BOB, AMOUNT), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); + + // Deploy a new contract. + let contract = deploy( + &mut session, + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); + session.set_actor(contract.clone()); + + // No-op if minted value is zero. + assert_ok!(mint(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), 0); + + // Successfully mint tokens. + assert_ok!(mint(&mut session, ALICE, AMOUNT)); + assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + // Successfully emit event. + assert_eq!( + last_contract_event(&session).unwrap(), + Transfer { from: None, to: Some(account_id_from_slice(ALICE.as_ref())), value: AMOUNT } + .encode() + .as_slice() + ); + + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `AssetNotLive` error. + let error = Module { index: 52, error: [16, 0] }.encode(); + assert_eq!( + mint(&mut session, ALICE, AMOUNT), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); +} + +/// 4. PSP-22 Burnable Interface: +/// - burn + +#[drink::test(sandbox = Sandbox)] +fn burn_works(mut session: Session) { + let _ = env_logger::try_init(); + // No permission to burn. + assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); // Create a new token owned by `BOB`. + assert_ok!(session.sandbox().mint_into(&(TOKEN + 1), &BOB, AMOUNT)); + deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()]).unwrap(); + // `pallet-assets` returns `NoPermission` error. + let error = Module { index: 52, error: [2, 0] }.encode(); + assert_eq!( + burn(&mut session, BOB, AMOUNT), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); + + // Deploy a new contract. + let contract = deploy( + &mut session, + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()], + ) + .unwrap(); + session.set_actor(contract.clone()); + // Mint tokens. + assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); + + // No-op. + assert_ok!(burn(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + + // Failed with `InsufficientBalance`. + assert_eq!(burn(&mut session, ALICE, AMOUNT * 2), Err(PSP22Error::InsufficientBalance)); + + // Successfully burn tokens. + assert_ok!(burn(&mut session, ALICE, 1)); + assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT - 1); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT - 1); + // Successfully emit event. + assert_eq!( + last_contract_event(&session).unwrap(), + Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value: 1 } + .encode() + .as_slice() + ); + + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `IncorrectStatus` error. + let error = Module { index: 52, error: [17, 0] }.encode(); + assert_eq!( + burn(&mut session, ALICE, 1), + Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + ); +} + +// A set of helper methods to test the contract calls. +mod utils { + use drink::session::{error::SessionError, NO_SALT}; + use pop_api::primitives::AccountId; + use pop_sandbox::{AccountId32, Balance, INIT_VALUE}; + use scale::Decode; + + use super::*; + + // Test methods for deployment with constructor function. + + pub(super) fn deploy( + session: &mut Session, + bundle: ContractBundle, + method: &str, + inputs: Vec, + ) -> Result { + let result = session.deploy_bundle(bundle, method, &inputs, NO_SALT, Some(INIT_VALUE)); + if result.is_err() { + let deployment_result = session.record().last_deploy_result().result.clone(); + let error = deployment_result.unwrap().result.data; + return Err(PSP22Error::decode(&mut &error[2..]).unwrap()); + } + Ok(result.unwrap()) + } + + // Test methods for `PSP22`. + + pub(super) fn total_supply(session: &mut Session) -> Balance { + call::(session, "Psp22::total_supply", vec![], None).unwrap() + } + + pub(super) fn balance_of(session: &mut Session, owner: AccountId32) -> Balance { + call::(session, "Psp22::balance_of", vec![owner.to_string()], None).unwrap() + } + + pub(super) fn allowance( + session: &mut Session, + owner: AccountId32, + spender: AccountId32, + ) -> Balance { + call::( + session, + "Psp22::allowance", + vec![owner.to_string(), spender.to_string()], + None, + ) + .unwrap() + } + + pub(super) fn transfer( + session: &mut Session, + to: AccountId32, + amount: Balance, + ) -> Result<(), PSP22Error> { + call::<()>( + session, + "Psp22::transfer", + vec![ + to.to_string(), + amount.to_string(), + serde_json::to_string::<[u8; 0]>(&[]).unwrap(), + ], + None, + ) + } + + pub(super) fn transfer_from( + session: &mut Session, + from: AccountId32, + to: AccountId32, + amount: Balance, + ) -> Result<(), PSP22Error> { + call::<()>( + session, + "Psp22::transfer_from", + vec![ + from.to_string(), + to.to_string(), + amount.to_string(), + serde_json::to_string::<[u8; 0]>(&[]).unwrap(), + ], + None, + ) + } + + pub(super) fn approve( + session: &mut Session, + spender: AccountId32, + value: Balance, + ) -> Result<(), PSP22Error> { + call::<()>(session, "Psp22::approve", vec![spender.to_string(), value.to_string()], None) + } + + pub(super) fn increase_allowance( + session: &mut Session, + spender: AccountId32, + value: Balance, + ) -> Result<(), PSP22Error> { + call::<()>( + session, + "Psp22::increase_allowance", + vec![spender.to_string(), value.to_string()], + None, + ) + } + + pub(super) fn decrease_allowance( + session: &mut Session, + spender: AccountId32, + value: Balance, + ) -> Result<(), PSP22Error> { + call::<()>( + session, + "Psp22::decrease_allowance", + vec![spender.to_string(), value.to_string()], + None, + ) + } + + // Test methods for `PSP22Metadata``. + + pub(super) fn token_name(session: &mut Session) -> Option { + call::>(session, "Psp22Metadata::token_name", vec![], None).unwrap() + } + + pub(super) fn token_symbol(session: &mut Session) -> Option { + call::>(session, "Psp22Metadata::token_symbol", vec![], None).unwrap() + } + + pub(super) fn token_decimals(session: &mut Session) -> u8 { + call::(session, "Psp22Metadata::token_decimals", vec![], None).unwrap() + } + + // Test methods for `PSP22Mintable``. + + pub(super) fn mint( + session: &mut Session, + account: AccountId32, + amount: Balance, + ) -> Result<(), PSP22Error> { + call::<()>( + session, + "Psp22Mintable::mint", + vec![account.to_string(), amount.to_string()], + None, + ) + } + + // Test methods for `PSP22MPsp22Burnablentable``. + + pub(super) fn burn( + session: &mut Session, + account: AccountId32, + amount: Balance, + ) -> Result<(), PSP22Error> { + call::<()>( + session, + "Psp22Burnable::burn", + vec![account.to_string(), amount.to_string()], + None, + ) + } + + /// Call a contract method and decode the returned data. + pub(super) fn call( + session: &mut Session, + func_name: &str, + input: Vec, + endowment: Option, + ) -> Result { + match session.call::(func_name, &input, endowment) { + // If the call is reverted, decode the error into `PSP22Error`. + Err(SessionError::CallReverted(error)) => { + Err(PSP22Error::decode(&mut &error[2..]) + .unwrap_or_else(|_| panic!("Decoding failed"))) + }, + // If the call is successful, decode the last returned value. + Ok(_) => Ok(session + .record() + .last_call_return_decoded::() + .unwrap_or_else(|_| panic!("Expected a return value")) + .unwrap_or_else(|_| panic!("Decoding failed"))), + // Catch-all for unexpected results. + _ => panic!("Expected call to revert or return a value"), + } + } + + /// This is used to resolve type mismatches between the `AccountId` in the quasi testing + /// environment and the contract environment. + pub(super) fn account_id_from_slice(s: &[u8; 32]) -> AccountId { + AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") + } + + /// Get the last event from pallet contracts. + pub(super) fn last_contract_event(session: &Session) -> Option> { + session.record().last_event_batch().contract_events().last().cloned() + } + + /// convert bytes array to u32. + pub(super) fn vec_u8_to_u32(vec: Vec) -> Result { + if vec.len() == 4 { + // Try to convert the Vec to an array of 4 bytes and then convert to u32. + let array: [u8; 4] = vec.try_into().map_err(|_| "Invalid length")?; + Ok(u32::from_le_bytes(array)) + } else { + Err("Vector must be exactly 4 bytes long") + } } - .encode(); - // An `Approval` event is emitted. - assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice()); - assert_eq!(session.sandbox().allowance(&TOKEN_ID, &contract, &ALICE), AMOUNT / 2 - 1); - Ok(()) } diff --git a/pop-api/examples/fungibles/utils.rs b/pop-api/examples/fungibles/utils.rs deleted file mode 100644 index e3ee1281..00000000 --- a/pop-api/examples/fungibles/utils.rs +++ /dev/null @@ -1,206 +0,0 @@ -// A set of helper methods to test the contract calls. - -use drink::{ - session::{bundle::ContractBundle, error::SessionError, Session, NO_SALT}, - DispatchError, -}; -use pop_api::primitives::{AccountId, TokenId}; -use pop_sandbox::{AccountId32, Balance, DevnetSandbox as Sandbox, INIT_VALUE}; -use scale::{Decode, Encode}; - -use super::*; - -// PSP22 functions. -pub(super) const ALLOWANCE: &str = "Psp22::allowance"; -pub(super) const BALANCE_OF: &str = "Psp22::balance_of"; -pub(super) const TOTAL_SUPPLY: &str = "Psp22::total_supply"; -pub(super) const TRANSFER: &str = "Psp22::transfer"; -pub(super) const TRANSFER_FROM: &str = "Psp22::transfer_from"; -pub(super) const APPROVE: &str = "Psp22::approve"; -pub(super) const INCREASE_ALLOWANCE: &str = "Psp22::increase_allowance"; -pub(super) const DECREASE_ALLOWANCE: &str = "Psp22::decrease_allowance"; -// PSP22Metadata functions. -pub(super) const TOKEN_NAME: &str = "Psp22Metadata::token_name"; -pub(super) const TOKEN_SYMBOL: &str = "Psp22Metadata::token_symbol"; -pub(super) const TOKEN_DECIMALS: &str = "Psp22Metadata::token_decimals"; -// PSP22Mintable functions. -pub(super) const MINT: &str = "Psp22Mintable::mint"; -// PSP22Burnable functions. -pub(super) const BURN: &str = "Psp22Burnable::burn"; - -/// This is used to resolve type mismatches between the `AccountId` in the quasi testing environment -/// and the contract environment. -pub(super) fn account_id_from_slice(s: &[u8; 32]) -> AccountId { - AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") -} - -/// Get the last event from pallet contracts. -pub(super) fn last_contract_event(session: &Session) -> Option> { - session.record().last_event_batch().contract_events().last().cloned() -} - -/// Execute a contract method and expect CallReverted error to be returned. -pub(super) fn expect_call_reverted( - session: &mut Session, - function: &str, - params: Vec, - err: PSP22Error, -) { - let call = session.call::(function, ¶ms, None); - match call { - Err(SessionError::CallReverted(error)) => { - assert_eq!(error[1..], Err::<(), PSP22Error>(err).encode()) - }, - _ => panic!("Expect call reverted"), - } -} - -/// Return the last deployment result data. -pub(super) fn expect_deployment_reverted(session: &Session, err: PSP22Error) { - let result = session.record().last_deploy_result().result.clone(); - let error = result.unwrap().result.data; - assert_eq!(error[1..], Err::<(), PSP22Error>(err).encode()) -} - -// Call a contract method and decode the returned data. -pub(super) fn decoded_call( - session: &mut Session, - func_name: &str, - input: Vec, - endowment: Option, -) -> Result> { - session.call(func_name, &input, endowment)??; - Ok(session.record().last_call_return_decoded::()??) -} - -// Check if the event emitted correctly. -pub(super) fn assert_event(session: &mut Session, event: Vec) { - let contract_events = session.record().last_event_batch().contract_events(); - let last_event = contract_events.last().unwrap().to_vec(); - assert_eq!(last_event, event.as_slice()); -} - -// Test methods for deployment with constructor function. - -pub(super) fn deploy_with_new_constructor( - session: &mut Session, - bundle: ContractBundle, - id: TokenId, - min_balance: Balance, -) -> Result { - session.deploy_bundle( - bundle, - "new", - &[id.to_string(), min_balance.to_string()], - NO_SALT, - Some(INIT_VALUE), - ) -} - -pub(super) fn deploy_with_existing_constructor( - session: &mut Session, - bundle: ContractBundle, - id: TokenId, -) -> Result { - session.deploy_bundle(bundle, "existing", &[id.to_string()], NO_SALT, Some(INIT_VALUE)) -} - -// Test methods for `PSP22`. - -pub(super) fn total_supply(session: &mut Session) -> Balance { - decoded_call::(session, TOTAL_SUPPLY, vec![], None).unwrap() -} - -pub(super) fn balance_of(session: &mut Session, owner: AccountId32) -> Balance { - decoded_call::(session, BALANCE_OF, vec![owner.to_string()], None).unwrap() -} - -pub(super) fn allowance( - session: &mut Session, - owner: AccountId32, - spender: AccountId32, -) -> Balance { - decoded_call::(session, ALLOWANCE, vec![owner.to_string(), spender.to_string()], None) - .unwrap() -} - -pub(super) fn transfer( - session: &mut Session, - to: AccountId32, - amount: Balance, -) -> Result<(), Box> { - let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); - Ok(session.call(TRANSFER, &vec![to.to_string(), amount.to_string(), data], None)??) -} - -pub(super) fn transfer_from( - session: &mut Session, - from: AccountId32, - to: AccountId32, - amount: Balance, -) -> Result<(), Box> { - let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); - Ok(session.call( - TRANSFER_FROM, - &vec![from.to_string(), to.to_string(), amount.to_string(), data], - None, - )??) -} - -pub(super) fn approve( - session: &mut Session, - spender: AccountId32, - value: Balance, -) -> Result<(), Box> { - Ok(session.call(APPROVE, &vec![spender.to_string(), value.to_string()], None)??) -} - -pub(super) fn increase_allowance( - session: &mut Session, - spender: AccountId32, - value: Balance, -) -> Result<(), Box> { - Ok(session.call(INCREASE_ALLOWANCE, &vec![spender.to_string(), value.to_string()], None)??) -} - -pub(super) fn decrease_allowance( - session: &mut Session, - spender: AccountId32, - value: Balance, -) -> Result<(), Box> { - Ok(session.call(DECREASE_ALLOWANCE, &vec![spender.to_string(), value.to_string()], None)??) -} - -// Test methods for `PSP22Metadata``. - -pub(super) fn token_name(session: &mut Session) -> String { - decoded_call::(session, TOKEN_NAME, vec![], None).unwrap() -} - -pub(super) fn token_symbol(session: &mut Session) -> String { - decoded_call::(session, TOKEN_SYMBOL, vec![], None).unwrap() -} - -pub(super) fn token_decimals(session: &mut Session) -> u8 { - decoded_call::(session, TOKEN_DECIMALS, vec![], None).unwrap() -} - -// Test methods for `PSP22Mintable``. - -pub(super) fn mint( - session: &mut Session, - account: AccountId32, - amount: Balance, -) -> Result<(), Box> { - Ok(session.call(MINT, &vec![account.to_string(), amount.to_string()], None)??) -} - -// Test methods for `PSP22MPsp22Burnablentable``. - -pub(super) fn burn( - session: &mut Session, - account: AccountId32, - amount: Balance, -) -> Result<(), Box> { - Ok(session.call(BURN, &vec![account.to_string(), amount.to_string()], None)??) -} From 7b2ce9017bf1923e4d787000a2b87b4497eb51df Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:08:42 +0700 Subject: [PATCH 123/161] fix: comment --- pop-api/examples/fungibles/tests.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 80e9b1dc..040e6104 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -37,7 +37,6 @@ fn new_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box Result<(), Box> { let _ = env_logger::try_init(); - // Fails to deploy contract with a non-existing token ID. assert_eq!( deploy(&mut session, CONTRACT.clone(), "existing", vec![TOKEN.to_string()]), Err(PSP22Error::Custom(String::from("Unknown"))) ); - // Successfully deploy contract with an existing token ID. let actor = session.get_actor(); session.sandbox().create(&TOKEN, &actor, MIN_BALANCE).unwrap(); @@ -169,7 +166,7 @@ fn transfer_works(mut session: Session) { // Failed with `InsufficientBalance`. assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); - // Successfully transfer tokens from `contract` to `account`. + // Successfully transfer. assert_ok!(transfer(&mut session, BOB, AMOUNT / 4)); assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), AMOUNT + AMOUNT / 4); From 17d12a026c309800bf3e56f825f88a428113a713 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:12:33 +0700 Subject: [PATCH 124/161] fix: transfer_from test --- pop-api/examples/fungibles/tests.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 040e6104..6cfde314 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -40,13 +40,16 @@ fn new_constructor_works(mut session: Session) -> Result<(), Box Date: Thu, 26 Sep 2024 09:03:24 +0700 Subject: [PATCH 125/161] fix: decrease_allowance --- pop-api/examples/fungibles/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index e916f0c8..282f3959 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -194,8 +194,11 @@ mod fungibles { } api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; - let allowance = self.allowance(caller, spender); - self.env().emit_event(Approval { owner: caller, spender, value: allowance }); + self.env().emit_event(Approval { + owner: caller, + spender, + value: allowance.saturating_sub(value), + }); Ok(()) } } From 30fb60a604adb037d6db1ecb8e845a0cd43fd938 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:06:26 +0700 Subject: [PATCH 126/161] fix: constructor test --- pop-api/examples/fungibles/tests.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 6cfde314..410fe685 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -27,7 +27,7 @@ static CONTRACT: LazyLock = LazyLock::new(|| BundleProvider::loc /// Deployment and constructor method tests. #[drink::test(sandbox = Sandbox)] -fn new_constructor_works(mut session: Session) -> Result<(), Box> { +fn new_constructor_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. let contract = deploy( @@ -50,23 +50,22 @@ fn new_constructor_works(mut session: Session) -> Result<(), Box Result<(), Box> { +fn existing_constructor_works(mut session: Session) { let _ = env_logger::try_init(); // Fails to deploy contract with a non-existing token ID. assert_eq!( deploy(&mut session, CONTRACT.clone(), "existing", vec![TOKEN.to_string()]), Err(PSP22Error::Custom(String::from("Unknown"))) ); + // Successfully deploy contract with an existing token ID. let actor = session.get_actor(); session.sandbox().create(&TOKEN, &actor, MIN_BALANCE).unwrap(); deploy(&mut session, CONTRACT.clone(), "existing", vec![TOKEN.to_string()]).unwrap(); assert!(session.sandbox().asset_exists(&TOKEN)); - Ok(()) } /// 1. PSP-22 Interface: From 17fa0d20b8ef066eab6aba79a939abc00adef06b Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:11:17 +0700 Subject: [PATCH 127/161] fix: comment --- pop-api/examples/fungibles/tests.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 410fe685..49c7b924 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -445,7 +445,8 @@ fn token_metadata(mut session: Session) { assert_eq!(token_name(&mut session), None); assert_eq!(token_symbol(&mut session), None); assert_eq!(token_decimals(&mut session), 0); - // Create Token. + + // Set token metadata. let actor = session.get_actor(); assert_ok!(session.sandbox().set_metadata( Some(actor), From 462c327339f6a6d90bcd2aface3a70d27c30cb8a Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:16:42 +0700 Subject: [PATCH 128/161] fix: comment --- pop-api/examples/fungibles/tests.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 49c7b924..0ce2f08b 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -571,7 +571,7 @@ fn burn_works(mut session: Session) { ); } -// A set of helper methods to test the contract calls. +/// A set of helper methods to test the contract calls. mod utils { use drink::session::{error::SessionError, NO_SALT}; use pop_api::primitives::AccountId; @@ -580,7 +580,7 @@ mod utils { use super::*; - // Test methods for deployment with constructor function. + /// Deploy test utilities. pub(super) fn deploy( session: &mut Session, @@ -597,7 +597,7 @@ mod utils { Ok(result.unwrap()) } - // Test methods for `PSP22`. + /// PSP22 test utilities. pub(super) fn total_supply(session: &mut Session) -> Balance { call::(session, "Psp22::total_supply", vec![], None).unwrap() @@ -691,7 +691,7 @@ mod utils { ) } - // Test methods for `PSP22Metadata``. + /// PSP22Metadata test utilities. pub(super) fn token_name(session: &mut Session) -> Option { call::>(session, "Psp22Metadata::token_name", vec![], None).unwrap() @@ -705,7 +705,7 @@ mod utils { call::(session, "Psp22Metadata::token_decimals", vec![], None).unwrap() } - // Test methods for `PSP22Mintable``. + /// PSP22Mintable test utilities. pub(super) fn mint( session: &mut Session, @@ -720,7 +720,7 @@ mod utils { ) } - // Test methods for `PSP22MPsp22Burnablentable``. + /// PSP22Burnable test utilities. pub(super) fn burn( session: &mut Session, @@ -770,10 +770,9 @@ mod utils { session.record().last_event_batch().contract_events().last().cloned() } - /// convert bytes array to u32. + /// Convert the Vec to u32. pub(super) fn vec_u8_to_u32(vec: Vec) -> Result { if vec.len() == 4 { - // Try to convert the Vec to an array of 4 bytes and then convert to u32. let array: [u8; 4] = vec.try_into().map_err(|_| "Invalid length")?; Ok(u32::from_le_bytes(array)) } else { From 7babeddde8910eea62407c02d01319dbe6221a70 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:36:54 +0700 Subject: [PATCH 129/161] refactor: dependecy order --- pop-api/examples/fungibles/tests.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 0ce2f08b..46320370 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -1,5 +1,4 @@ -use std::sync::LazyLock; - +use super::*; use drink::{ sandbox_api::assets_api::AssetsAPI, session::{ContractBundle, Session}, @@ -11,10 +10,9 @@ use pop_api::{ }; use pop_sandbox::{Balance, DevnetSandbox as Sandbox, ALICE, BOB}; use scale::Encode; +use std::sync::LazyLock; use utils::*; -use super::*; - #[drink::contract_bundle_provider] enum BundleProvider {} From b47fc516a97b18967ca939fe987840ff57bd421d Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:27:23 +0700 Subject: [PATCH 130/161] fix: refactor and add more tests --- pop-api/examples/fungibles/tests.rs | 202 +++++++++++++++++----------- 1 file changed, 125 insertions(+), 77 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 46320370..3c5b875a 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -5,7 +5,11 @@ use drink::{ }; use frame_support::assert_ok; use pop_api::{ - primitives::{Error::Module, TokenId}, + primitives::{ + ArithmeticError::Overflow, + Error::{Arithmetic, Module}, + TokenId, + }, v0::fungibles::events::{Approval, Created, Transfer}, }; use pop_sandbox::{Balance, DevnetSandbox as Sandbox, ALICE, BOB}; @@ -145,27 +149,17 @@ fn transfer_works(mut session: Session) { .unwrap(); session.set_actor(contract.clone()); // `pallet-assets` returns `NoAccount` error. - let error = Module { index: 52, error: [1, 0] }.encode(); assert_eq!( transfer(&mut session, ALICE, AMOUNT / 4), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [1, 0] }.encode()).unwrap().to_string() + )) ); // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); assert_ok!(session.sandbox().mint_into(&TOKEN, &BOB, AMOUNT)); - // No-op if `value` is zero. - assert_ok!(transfer(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - - // No-op if the caller and `to` is the same address, returns success and no events are emitted. - assert_ok!(transfer(&mut session, contract.clone(), AMOUNT / 4)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - - // Failed with `InsufficientBalance`. - assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); - // Successfully transfer. assert_ok!(transfer(&mut session, BOB, AMOUNT / 4)); assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); @@ -182,13 +176,30 @@ fn transfer_works(mut session: Session) { .as_slice() ); + // No-op if `value` is zero. + assert_ok!(transfer(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); + + // No-op if the caller and `to` is the same address, returns success and no events are emitted. + assert_ok!(transfer(&mut session, contract.clone(), AMOUNT / 4)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); + + // Failed with `InsufficientBalance`. + assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); + // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - let error = Module { index: 52, error: [16, 0] }.encode(); assert_eq!( transfer(&mut session, BOB, AMOUNT / 4), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) + .unwrap() + .to_string() + )) ); } @@ -208,12 +219,6 @@ fn transfer_from_works(mut session: Session) { assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &ALICE, &contract.clone(), AMOUNT * 2)); - // Unapproved transfer. Failed with `InsufficientAllowance`. - assert_eq!( - transfer_from(&mut session, ALICE, contract.clone(), AMOUNT * 2 + 1), - Err(PSP22Error::InsufficientAllowance) - ); - // No-op if `value` is zero. assert_ok!(transfer_from(&mut session, ALICE, BOB, 0)); assert_eq!(last_contract_event(&session), None); // No event emitted. @@ -228,6 +233,12 @@ fn transfer_from_works(mut session: Session) { Err(PSP22Error::InsufficientBalance) ); + // Unapproved transfer. Failed with `InsufficientAllowance`. + assert_eq!( + transfer_from(&mut session, ALICE, contract.clone(), AMOUNT * 2 + 1), + Err(PSP22Error::InsufficientAllowance) + ); + // Successful transfer. assert_ok!(transfer_from(&mut session, ALICE, BOB, AMOUNT / 2)); assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT + AMOUNT / 2); @@ -249,10 +260,13 @@ fn transfer_from_works(mut session: Session) { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - let error = Module { index: 52, error: [16, 0] }.encode(); assert_eq!( transfer_from(&mut session, ALICE, BOB, AMOUNT / 2), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) + .unwrap() + .to_string() + )) ); } @@ -271,11 +285,6 @@ fn approve_works(mut session: Session) { // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); - // No-op if the caller and `spender` is the same address, returns success and no events are - // emitted. - assert_ok!(approve(&mut session, contract.clone(), AMOUNT / 2)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - // Successfully approvals. assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2); @@ -291,6 +300,12 @@ fn approve_works(mut session: Session) { .as_slice() ); + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. + assert_ok!(approve(&mut session, contract.clone(), AMOUNT / 2)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2); + // Non-additive, sets new value. assert_ok!(approve(&mut session, ALICE, AMOUNT / 2 - 1)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); @@ -309,10 +324,13 @@ fn approve_works(mut session: Session) { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - let error = Module { index: 52, error: [16, 0] }.encode(); assert_eq!( approve(&mut session, ALICE, AMOUNT / 2), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) + .unwrap() + .to_string() + )) ); } @@ -332,11 +350,6 @@ fn increase_allowance_works(mut session: Session) { assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT / 2)); - // No-op if the caller and `spender` is the same address, returns success and no events are - // emitted. - assert_ok!(increase_allowance(&mut session, contract.clone(), AMOUNT / 2)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - // Successfully approvals. assert_ok!(increase_allowance(&mut session, ALICE, AMOUNT / 2)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); @@ -352,6 +365,17 @@ fn increase_allowance_works(mut session: Session) { .as_slice() ); + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. + assert_ok!(increase_allowance(&mut session, contract.clone(), AMOUNT / 2)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); + + // No-op if the `value` is zero. + assert_ok!(increase_allowance(&mut session, contract.clone(), 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); + // Additive. assert_ok!(increase_allowance(&mut session, ALICE, AMOUNT / 2)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT + AMOUNT / 2); @@ -359,10 +383,13 @@ fn increase_allowance_works(mut session: Session) { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - let error = Module { index: 52, error: [16, 0] }.encode(); assert_eq!( increase_allowance(&mut session, ALICE, AMOUNT / 2), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) + .unwrap() + .to_string() + )) ); } @@ -382,17 +409,6 @@ fn decrease_allowance_works(mut session: Session) { assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT / 2)); - // No-op if the caller and `spender` is the same address, returns success and no events are - // emitted. - assert_ok!(decrease_allowance(&mut session, contract.clone(), AMOUNT / 2)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - - // Failed with `InsufficientAllowance`. - assert_eq!( - decrease_allowance(&mut session, ALICE, AMOUNT), - Err(PSP22Error::InsufficientAllowance) - ); - // Successfully approvals. assert_ok!(decrease_allowance(&mut session, ALICE, 1)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); @@ -408,13 +424,29 @@ fn decrease_allowance_works(mut session: Session) { .as_slice() ); + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. + assert_ok!(decrease_allowance(&mut session, contract.clone(), 1)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); + + // Failed with `InsufficientAllowance`. + assert_eq!( + decrease_allowance(&mut session, ALICE, AMOUNT), + Err(PSP22Error::InsufficientAllowance) + ); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); + // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - let error = Module { index: 52, error: [16, 0] }.encode(); assert_eq!( decrease_allowance(&mut session, ALICE, 1), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) + .unwrap() + .to_string() + )) ); } @@ -468,10 +500,11 @@ fn mint_works(mut session: Session) { assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); // Create a new token owned by `BOB`. deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()]).unwrap(); // `pallet-assets` returns `NoPermission` error. - let error = Module { index: 52, error: [2, 0] }.encode(); assert_eq!( mint(&mut session, BOB, AMOUNT), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [2, 0] }.encode()).unwrap().to_string() + )) ); // Deploy a new contract. @@ -484,11 +517,6 @@ fn mint_works(mut session: Session) { .unwrap(); session.set_actor(contract.clone()); - // No-op if minted value is zero. - assert_ok!(mint(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), 0); - // Successfully mint tokens. assert_ok!(mint(&mut session, ALICE, AMOUNT)); assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT); @@ -501,13 +529,28 @@ fn mint_works(mut session: Session) { .as_slice() ); + // No-op if minted value is zero. + assert_ok!(mint(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + + // Total supply increased by `value` exceeds maximal value of `u128` type. + assert_eq!( + mint(&mut session, ALICE, u128::MAX), + Err(PSP22Error::Custom(vec_u8_to_u32(Arithmetic(Overflow).encode()).unwrap().to_string())) + ); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - let error = Module { index: 52, error: [16, 0] }.encode(); assert_eq!( mint(&mut session, ALICE, AMOUNT), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) + .unwrap() + .to_string() + )) ); } @@ -522,10 +565,11 @@ fn burn_works(mut session: Session) { assert_ok!(session.sandbox().mint_into(&(TOKEN + 1), &BOB, AMOUNT)); deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()]).unwrap(); // `pallet-assets` returns `NoPermission` error. - let error = Module { index: 52, error: [2, 0] }.encode(); assert_eq!( burn(&mut session, BOB, AMOUNT), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [2, 0] }.encode()).unwrap().to_string() + )) ); // Deploy a new contract. @@ -540,13 +584,6 @@ fn burn_works(mut session: Session) { // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); - // No-op. - assert_ok!(burn(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - - // Failed with `InsufficientBalance`. - assert_eq!(burn(&mut session, ALICE, AMOUNT * 2), Err(PSP22Error::InsufficientBalance)); - // Successfully burn tokens. assert_ok!(burn(&mut session, ALICE, 1)); assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT - 1); @@ -559,13 +596,25 @@ fn burn_works(mut session: Session) { .as_slice() ); + // No-op. + assert_ok!(burn(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT - 1); + + // Failed with `InsufficientBalance`. + assert_eq!(burn(&mut session, ALICE, AMOUNT * 2), Err(PSP22Error::InsufficientBalance)); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT - 1); + // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `IncorrectStatus` error. - let error = Module { index: 52, error: [17, 0] }.encode(); assert_eq!( burn(&mut session, ALICE, 1), - Err(PSP22Error::Custom(vec_u8_to_u32(error).unwrap().to_string())) + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [17, 0] }.encode()) + .unwrap() + .to_string() + )) ); } @@ -770,11 +819,10 @@ mod utils { /// Convert the Vec to u32. pub(super) fn vec_u8_to_u32(vec: Vec) -> Result { - if vec.len() == 4 { - let array: [u8; 4] = vec.try_into().map_err(|_| "Invalid length")?; - Ok(u32::from_le_bytes(array)) - } else { - Err("Vector must be exactly 4 bytes long") - } + let mut padded_vec = vec.to_vec(); + padded_vec.resize(4, 0); + + let array: [u8; 4] = padded_vec.try_into().map_err(|_| "Invalid length")?; + Ok(u32::from_le_bytes(array)) } } From 6a3166fd67329c68cf8209897a54bd741a19709e Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:19:50 +0700 Subject: [PATCH 131/161] fix: resolve review comments --- pop-api/examples/fungibles/tests.rs | 292 +++++++++++++++++----------- 1 file changed, 180 insertions(+), 112 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 3c5b875a..333beefa 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -31,6 +31,22 @@ static CONTRACT: LazyLock = LazyLock::new(|| BundleProvider::loc #[drink::test(sandbox = Sandbox)] fn new_constructor_works(mut session: Session) { let _ = env_logger::try_init(); + // Fails to deploy contract with a used token ID. + let token = TOKEN + 1; + assert_ok!(session.sandbox().create(&token, &ALICE, MIN_BALANCE)); + // `pallet-assets` returns `InUse` error. + assert_eq!( + deploy( + &mut session, + CONTRACT.clone(), + "new", + vec![token.to_string(), MIN_BALANCE.to_string()] + ), + Err(PSP22Error::Custom( + vec_u8_to_u32(Module { index: 52, error: [5, 0] }.encode()).unwrap().to_string() + )) + ); + // Deploy a new contract. let contract = deploy( &mut session, @@ -65,8 +81,8 @@ fn existing_constructor_works(mut session: Session) { // Successfully deploy contract with an existing token ID. let actor = session.get_actor(); - session.sandbox().create(&TOKEN, &actor, MIN_BALANCE).unwrap(); - deploy(&mut session, CONTRACT.clone(), "existing", vec![TOKEN.to_string()]).unwrap(); + assert_ok!(session.sandbox().create(&TOKEN, &actor, MIN_BALANCE)); + assert_ok!(deploy(&mut session, CONTRACT.clone(), "existing", vec![TOKEN.to_string()])); assert!(session.sandbox().asset_exists(&TOKEN)); } @@ -84,8 +100,12 @@ fn existing_constructor_works(mut session: Session) { fn total_supply_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - deploy(&mut session, CONTRACT.clone(), "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]) - .unwrap(); + assert_ok!(deploy( + &mut session, + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()] + )); // No tokens in circulation. assert_eq!(total_supply(&mut session), 0); @@ -93,8 +113,7 @@ fn total_supply_works(mut session: Session) { // Tokens in circulation. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); - assert_ok!(session.sandbox().mint_into(&TOKEN, &BOB, AMOUNT * 2)); - assert_eq!(total_supply(&mut session), AMOUNT * 3); + assert_eq!(total_supply(&mut session), AMOUNT); assert_eq!(total_supply(&mut session), session.sandbox().total_supply(&TOKEN)); } @@ -102,8 +121,12 @@ fn total_supply_works(mut session: Session) { fn balance_of_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - deploy(&mut session, CONTRACT.clone(), "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]) - .unwrap(); + assert_ok!(deploy( + &mut session, + CONTRACT.clone(), + "new", + vec![TOKEN.to_string(), MIN_BALANCE.to_string()] + )); // No tokens in circulation. assert_eq!(balance_of(&mut session, ALICE), 0); @@ -147,10 +170,11 @@ fn transfer_works(mut session: Session) { vec![TOKEN.to_string(), MIN_BALANCE.to_string()], ) .unwrap(); + let value = AMOUNT / 4; session.set_actor(contract.clone()); // `pallet-assets` returns `NoAccount` error. assert_eq!( - transfer(&mut session, ALICE, AMOUNT / 4), + transfer(&mut session, ALICE, value), Err(PSP22Error::Custom( vec_u8_to_u32(Module { index: 52, error: [1, 0] }.encode()).unwrap().to_string() )) @@ -158,43 +182,42 @@ fn transfer_works(mut session: Session) { // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); - assert_ok!(session.sandbox().mint_into(&TOKEN, &BOB, AMOUNT)); + + // No-op if `value` is zero. + assert_ok!(transfer(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT); + + // No-op if the caller and `to` is the same address, returns success and no events are emitted. + assert_ok!(transfer(&mut session, contract.clone(), value)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT); + + // Failed with `InsufficientBalance`. + assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT); // Successfully transfer. - assert_ok!(transfer(&mut session, BOB, AMOUNT / 4)); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); - assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), AMOUNT + AMOUNT / 4); + assert_ok!(transfer(&mut session, BOB, value)); + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - value); + assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), value); // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), Transfer { from: Some(account_id_from_slice(contract.as_ref())), to: Some(account_id_from_slice(BOB.as_ref())), - value: AMOUNT / 4, + value, } .encode() .as_slice() ); - // No-op if `value` is zero. - assert_ok!(transfer(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); - - // No-op if the caller and `to` is the same address, returns success and no events are emitted. - assert_ok!(transfer(&mut session, contract.clone(), AMOUNT / 4)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); - - // Failed with `InsufficientBalance`. - assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - AMOUNT / 4); - // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. assert_eq!( - transfer(&mut session, BOB, AMOUNT / 4), + transfer(&mut session, BOB, value), Err(PSP22Error::Custom( vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) .unwrap() @@ -214,6 +237,7 @@ fn transfer_from_works(mut session: Session) { vec![TOKEN.to_string(), MIN_BALANCE.to_string()], ) .unwrap(); + let value = AMOUNT / 2; session.set_actor(contract.clone()); // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); @@ -222,36 +246,47 @@ fn transfer_from_works(mut session: Session) { // No-op if `value` is zero. assert_ok!(transfer_from(&mut session, ALICE, BOB, 0)); assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); // No-op if the `from` and `to` is the same address, returns success and no events are emitted. - assert_ok!(transfer_from(&mut session, ALICE, ALICE, AMOUNT / 2)); + assert_ok!(transfer_from(&mut session, ALICE, ALICE, value)); assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); // Not enough balance. Failed with `InsufficientBalance`. assert_eq!( transfer_from(&mut session, ALICE, contract.clone(), AMOUNT + 1), Err(PSP22Error::InsufficientBalance) ); + assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); // Unapproved transfer. Failed with `InsufficientAllowance`. assert_eq!( transfer_from(&mut session, ALICE, contract.clone(), AMOUNT * 2 + 1), Err(PSP22Error::InsufficientAllowance) ); + assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); + assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); // Successful transfer. - assert_ok!(transfer_from(&mut session, ALICE, BOB, AMOUNT / 2)); - assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT + AMOUNT / 2); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT / 2); - assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), AMOUNT / 2); + assert_ok!(transfer_from(&mut session, ALICE, BOB, value)); + assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT + value); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), value); + assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), value); // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), Approval { owner: account_id_from_slice(ALICE.as_ref()), spender: account_id_from_slice(contract.as_ref()), - value: AMOUNT + AMOUNT / 2, + value: AMOUNT + value, } .encode() .as_slice() @@ -261,7 +296,7 @@ fn transfer_from_works(mut session: Session) { assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. assert_eq!( - transfer_from(&mut session, ALICE, BOB, AMOUNT / 2), + transfer_from(&mut session, ALICE, BOB, value), Err(PSP22Error::Custom( vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) .unwrap() @@ -281,41 +316,42 @@ fn approve_works(mut session: Session) { vec![TOKEN.to_string(), MIN_BALANCE.to_string()], ) .unwrap(); + let value = AMOUNT / 2; session.set_actor(contract.clone()); // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); - // Successfully approvals. - assert_ok!(approve(&mut session, ALICE, AMOUNT / 2)); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2); + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. + assert_ok!(approve(&mut session, contract.clone(), value)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), 0); + assert_eq!(last_contract_event(&session), None); // No event emitted. + + // Successfully approve. + assert_ok!(approve(&mut session, ALICE, value)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), value); // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), Approval { owner: account_id_from_slice(contract.clone().as_ref()), spender: account_id_from_slice(ALICE.as_ref()), - value: AMOUNT / 2, + value, } .encode() .as_slice() ); - // No-op if the caller and `spender` is the same address, returns success and no events are - // emitted. - assert_ok!(approve(&mut session, contract.clone(), AMOUNT / 2)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2); - // Non-additive, sets new value. - assert_ok!(approve(&mut session, ALICE, AMOUNT / 2 - 1)); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); + assert_ok!(approve(&mut session, ALICE, value - 1)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), value - 1); // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), Approval { owner: account_id_from_slice(contract.as_ref()), spender: account_id_from_slice(ALICE.as_ref()), - value: AMOUNT / 2 - 1, + value: value - 1, } .encode() .as_slice() @@ -325,7 +361,7 @@ fn approve_works(mut session: Session) { assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. assert_eq!( - approve(&mut session, ALICE, AMOUNT / 2), + approve(&mut session, ALICE, value), Err(PSP22Error::Custom( vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) .unwrap() @@ -345,46 +381,58 @@ fn increase_allowance_works(mut session: Session) { vec![TOKEN.to_string(), MIN_BALANCE.to_string()], ) .unwrap(); + let value = AMOUNT / 2; session.set_actor(contract.clone()); // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); - assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT / 2)); + assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT)); + + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. + assert_ok!(increase_allowance(&mut session, contract.clone(), value)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); + assert_eq!(last_contract_event(&session), None); // No event emitted. - // Successfully approvals. - assert_ok!(increase_allowance(&mut session, ALICE, AMOUNT / 2)); + // No-op if the `value` is zero. + assert_ok!(increase_allowance(&mut session, contract.clone(), 0)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); + assert_eq!(last_contract_event(&session), None); // No event emitted. + + // Successfully approve. + assert_ok!(increase_allowance(&mut session, ALICE, value)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT + value); // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), Approval { owner: account_id_from_slice(contract.as_ref()), spender: account_id_from_slice(ALICE.as_ref()), - value: AMOUNT, + value: AMOUNT + value, } .encode() .as_slice() ); - // No-op if the caller and `spender` is the same address, returns success and no events are - // emitted. - assert_ok!(increase_allowance(&mut session, contract.clone(), AMOUNT / 2)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); - - // No-op if the `value` is zero. - assert_ok!(increase_allowance(&mut session, contract.clone(), 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); - // Additive. - assert_ok!(increase_allowance(&mut session, ALICE, AMOUNT / 2)); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT + AMOUNT / 2); + assert_ok!(increase_allowance(&mut session, ALICE, value)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT + value * 2); + // Successfully emit event. + assert_eq!( + last_contract_event(&session).unwrap(), + Approval { + owner: account_id_from_slice(contract.as_ref()), + spender: account_id_from_slice(ALICE.as_ref()), + value: AMOUNT + value * 2, + } + .encode() + .as_slice() + ); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. assert_eq!( - increase_allowance(&mut session, ALICE, AMOUNT / 2), + increase_allowance(&mut session, ALICE, value), Err(PSP22Error::Custom( vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) .unwrap() @@ -404,44 +452,60 @@ fn decrease_allowance_works(mut session: Session) { vec![TOKEN.to_string(), MIN_BALANCE.to_string()], ) .unwrap(); + let value = 1; session.set_actor(contract.clone()); // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); - assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT / 2)); + assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT)); + + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. + assert_ok!(decrease_allowance(&mut session, contract.clone(), value)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); - // Successfully approvals. - assert_ok!(decrease_allowance(&mut session, ALICE, 1)); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); + // Failed with `InsufficientAllowance`. + assert_eq!( + decrease_allowance(&mut session, ALICE, AMOUNT + value), + Err(PSP22Error::InsufficientAllowance) + ); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); + + // Successfully approve. + assert_ok!(decrease_allowance(&mut session, ALICE, value)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT - value); // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), Approval { owner: account_id_from_slice(contract.as_ref()), spender: account_id_from_slice(ALICE.as_ref()), - value: AMOUNT / 2 - 1, + value: AMOUNT - value, } .encode() .as_slice() ); - // No-op if the caller and `spender` is the same address, returns success and no events are - // emitted. - assert_ok!(decrease_allowance(&mut session, contract.clone(), 1)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); - - // Failed with `InsufficientAllowance`. + // Additive. + assert_ok!(decrease_allowance(&mut session, ALICE, value)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT - value * 2); + // Successfully emit event. assert_eq!( - decrease_allowance(&mut session, ALICE, AMOUNT), - Err(PSP22Error::InsufficientAllowance) + last_contract_event(&session).unwrap(), + Approval { + owner: account_id_from_slice(contract.as_ref()), + spender: account_id_from_slice(ALICE.as_ref()), + value: AMOUNT - value * 2, + } + .encode() + .as_slice() ); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT / 2 - 1); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. assert_eq!( - decrease_allowance(&mut session, ALICE, 1), + decrease_allowance(&mut session, ALICE, value), Err(PSP22Error::Custom( vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) .unwrap() @@ -498,7 +562,7 @@ fn mint_works(mut session: Session) { let _ = env_logger::try_init(); // No permission to mint. assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); // Create a new token owned by `BOB`. - deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()]).unwrap(); + assert_ok!(deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()])); // `pallet-assets` returns `NoPermission` error. assert_eq!( mint(&mut session, BOB, AMOUNT), @@ -515,37 +579,38 @@ fn mint_works(mut session: Session) { vec![TOKEN.to_string(), MIN_BALANCE.to_string()], ) .unwrap(); + let value = AMOUNT; session.set_actor(contract.clone()); + // No-op if minted value is zero. + assert_ok!(mint(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), 0); + // Successfully mint tokens. - assert_ok!(mint(&mut session, ALICE, AMOUNT)); - assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + assert_ok!(mint(&mut session, ALICE, value)); + assert_eq!(session.sandbox().total_supply(&TOKEN), value); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), value); // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), - Transfer { from: None, to: Some(account_id_from_slice(ALICE.as_ref())), value: AMOUNT } + Transfer { from: None, to: Some(account_id_from_slice(ALICE.as_ref())), value } .encode() .as_slice() ); - // No-op if minted value is zero. - assert_ok!(mint(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); - // Total supply increased by `value` exceeds maximal value of `u128` type. assert_eq!( mint(&mut session, ALICE, u128::MAX), Err(PSP22Error::Custom(vec_u8_to_u32(Arithmetic(Overflow).encode()).unwrap().to_string())) ); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), value); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. assert_eq!( - mint(&mut session, ALICE, AMOUNT), + mint(&mut session, ALICE, value), Err(PSP22Error::Custom( vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) .unwrap() @@ -563,7 +628,7 @@ fn burn_works(mut session: Session) { // No permission to burn. assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); // Create a new token owned by `BOB`. assert_ok!(session.sandbox().mint_into(&(TOKEN + 1), &BOB, AMOUNT)); - deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()]).unwrap(); + assert_ok!(deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()])); // `pallet-assets` returns `NoPermission` error. assert_eq!( burn(&mut session, BOB, AMOUNT), @@ -580,36 +645,39 @@ fn burn_works(mut session: Session) { vec![TOKEN.to_string(), MIN_BALANCE.to_string()], ) .unwrap(); + let value = 1; session.set_actor(contract.clone()); // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); + // No-op. + assert_ok!(burn(&mut session, ALICE, 0)); + assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + + // Failed with `InsufficientBalance`. + assert_eq!(burn(&mut session, ALICE, AMOUNT * 2), Err(PSP22Error::InsufficientBalance)); + assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + // Successfully burn tokens. - assert_ok!(burn(&mut session, ALICE, 1)); - assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT - 1); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT - 1); + assert_ok!(burn(&mut session, ALICE, value)); + assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT - value); + assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT - value); // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), - Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value: 1 } + Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value } .encode() .as_slice() ); - // No-op. - assert_ok!(burn(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT - 1); - - // Failed with `InsufficientBalance`. - assert_eq!(burn(&mut session, ALICE, AMOUNT * 2), Err(PSP22Error::InsufficientBalance)); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT - 1); - // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `IncorrectStatus` error. assert_eq!( - burn(&mut session, ALICE, 1), + burn(&mut session, ALICE, value), Err(PSP22Error::Custom( vec_u8_to_u32(Module { index: 52, error: [17, 0] }.encode()) .unwrap() From 7fd18c7dc3d7bf990ded19b6ab031bfe0c3db6ac Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:21:08 +0700 Subject: [PATCH 132/161] fix: comment --- pop-api/examples/fungibles/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 333beefa..8ba75a25 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -31,7 +31,7 @@ static CONTRACT: LazyLock = LazyLock::new(|| BundleProvider::loc #[drink::test(sandbox = Sandbox)] fn new_constructor_works(mut session: Session) { let _ = env_logger::try_init(); - // Fails to deploy contract with a used token ID. + // Fails to deploy contract with an used token ID. let token = TOKEN + 1; assert_ok!(session.sandbox().create(&token, &ALICE, MIN_BALANCE)); // `pallet-assets` returns `InUse` error. From 110ea1e6e46aac445638587851af13341746ebd9 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:25:17 +0700 Subject: [PATCH 133/161] fix: comment --- pop-api/examples/fungibles/tests.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 8ba75a25..ffc7b50e 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -185,17 +185,20 @@ fn transfer_works(mut session: Session) { // No-op if `value` is zero. assert_ok!(transfer(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), 0); + assert_eq!(last_contract_event(&session), None); // No event emitted. // No-op if the caller and `to` is the same address, returns success and no events are emitted. assert_ok!(transfer(&mut session, contract.clone(), value)); - assert_eq!(last_contract_event(&session), None); // No event emitted. assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), 0); + assert_eq!(last_contract_event(&session), None); // No event emitted. // Failed with `InsufficientBalance`. assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT); + assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), 0); // Successfully transfer. assert_ok!(transfer(&mut session, BOB, value)); @@ -245,17 +248,17 @@ fn transfer_from_works(mut session: Session) { // No-op if `value` is zero. assert_ok!(transfer_from(&mut session, ALICE, BOB, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + assert_eq!(last_contract_event(&session), None); // No event emitted. // No-op if the `from` and `to` is the same address, returns success and no events are emitted. assert_ok!(transfer_from(&mut session, ALICE, ALICE, value)); - assert_eq!(last_contract_event(&session), None); // No event emitted. assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + assert_eq!(last_contract_event(&session), None); // No event emitted. // Not enough balance. Failed with `InsufficientBalance`. assert_eq!( @@ -461,8 +464,8 @@ fn decrease_allowance_works(mut session: Session) { // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(decrease_allowance(&mut session, contract.clone(), value)); - assert_eq!(last_contract_event(&session), None); // No event emitted. assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); + assert_eq!(last_contract_event(&session), None); // No event emitted. // Failed with `InsufficientAllowance`. assert_eq!( @@ -584,8 +587,8 @@ fn mint_works(mut session: Session) { // No-op if minted value is zero. assert_ok!(mint(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), 0); + assert_eq!(last_contract_event(&session), None); // No event emitted. // Successfully mint tokens. assert_ok!(mint(&mut session, ALICE, value)); @@ -652,9 +655,9 @@ fn burn_works(mut session: Session) { // No-op. assert_ok!(burn(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT); assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); + assert_eq!(last_contract_event(&session), None); // No event emitted. // Failed with `InsufficientBalance`. assert_eq!(burn(&mut session, ALICE, AMOUNT * 2), Err(PSP22Error::InsufficientBalance)); From 7225416a834118d3ec173275d47759b28a9a8036 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:49:04 +0700 Subject: [PATCH 134/161] refactor: into_psp22_custom --- pop-api/examples/fungibles/tests.rs | 82 ++++++++--------------------- 1 file changed, 22 insertions(+), 60 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index ffc7b50e..d9ced3a4 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -42,9 +42,7 @@ fn new_constructor_works(mut session: Session) { "new", vec![token.to_string(), MIN_BALANCE.to_string()] ), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [5, 0] }.encode()).unwrap().to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [5, 0] })) ); // Deploy a new contract. @@ -175,9 +173,7 @@ fn transfer_works(mut session: Session) { // `pallet-assets` returns `NoAccount` error. assert_eq!( transfer(&mut session, ALICE, value), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [1, 0] }.encode()).unwrap().to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [1, 0] })) ); // Mint tokens. @@ -221,11 +217,7 @@ fn transfer_works(mut session: Session) { // `pallet-assets` returns `AssetNotLive` error. assert_eq!( transfer(&mut session, BOB, value), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) - .unwrap() - .to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) ); } @@ -300,11 +292,7 @@ fn transfer_from_works(mut session: Session) { // `pallet-assets` returns `AssetNotLive` error. assert_eq!( transfer_from(&mut session, ALICE, BOB, value), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) - .unwrap() - .to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) ); } @@ -365,11 +353,7 @@ fn approve_works(mut session: Session) { // `pallet-assets` returns `AssetNotLive` error. assert_eq!( approve(&mut session, ALICE, value), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) - .unwrap() - .to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) ); } @@ -436,11 +420,7 @@ fn increase_allowance_works(mut session: Session) { // `pallet-assets` returns `AssetNotLive` error. assert_eq!( increase_allowance(&mut session, ALICE, value), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) - .unwrap() - .to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) ); } @@ -509,11 +489,7 @@ fn decrease_allowance_works(mut session: Session) { // `pallet-assets` returns `AssetNotLive` error. assert_eq!( decrease_allowance(&mut session, ALICE, value), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) - .unwrap() - .to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) ); } @@ -569,9 +545,7 @@ fn mint_works(mut session: Session) { // `pallet-assets` returns `NoPermission` error. assert_eq!( mint(&mut session, BOB, AMOUNT), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [2, 0] }.encode()).unwrap().to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [2, 0] })) ); // Deploy a new contract. @@ -603,10 +577,7 @@ fn mint_works(mut session: Session) { ); // Total supply increased by `value` exceeds maximal value of `u128` type. - assert_eq!( - mint(&mut session, ALICE, u128::MAX), - Err(PSP22Error::Custom(vec_u8_to_u32(Arithmetic(Overflow).encode()).unwrap().to_string())) - ); + assert_eq!(mint(&mut session, ALICE, u128::MAX), Err(into_psp22_custom(Arithmetic(Overflow)))); assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), value); // Token is not live, i.e. frozen or being destroyed. @@ -614,11 +585,7 @@ fn mint_works(mut session: Session) { // `pallet-assets` returns `AssetNotLive` error. assert_eq!( mint(&mut session, ALICE, value), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [16, 0] }.encode()) - .unwrap() - .to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) ); } @@ -635,9 +602,7 @@ fn burn_works(mut session: Session) { // `pallet-assets` returns `NoPermission` error. assert_eq!( burn(&mut session, BOB, AMOUNT), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [2, 0] }.encode()).unwrap().to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [2, 0] })) ); // Deploy a new contract. @@ -681,11 +646,7 @@ fn burn_works(mut session: Session) { // `pallet-assets` returns `IncorrectStatus` error. assert_eq!( burn(&mut session, ALICE, value), - Err(PSP22Error::Custom( - vec_u8_to_u32(Module { index: 52, error: [17, 0] }.encode()) - .unwrap() - .to_string() - )) + Err(into_psp22_custom(Module { index: 52, error: [17, 0] })) ); } @@ -877,6 +838,16 @@ mod utils { } } + /// Convert into `PSP22Error::Custom` error type. + pub(super) fn into_psp22_custom(err: T) -> PSP22Error { + let mut padded_vec = err.encode().to_vec(); + padded_vec.resize(4, 0); + // Convert the `Vec`` to value of `StatusCode`. + let array: [u8; 4] = padded_vec.try_into().map_err(|_| "Invalid length").unwrap(); + let status_code = u32::from_le_bytes(array); + PSP22Error::Custom(status_code.to_string()) + } + /// This is used to resolve type mismatches between the `AccountId` in the quasi testing /// environment and the contract environment. pub(super) fn account_id_from_slice(s: &[u8; 32]) -> AccountId { @@ -887,13 +858,4 @@ mod utils { pub(super) fn last_contract_event(session: &Session) -> Option> { session.record().last_event_batch().contract_events().last().cloned() } - - /// Convert the Vec to u32. - pub(super) fn vec_u8_to_u32(vec: Vec) -> Result { - let mut padded_vec = vec.to_vec(); - padded_vec.resize(4, 0); - - let array: [u8; 4] = padded_vec.try_into().map_err(|_| "Invalid length")?; - Ok(u32::from_le_bytes(array)) - } } From b77d9487c7dbbdd58bc886f88df3ee066fa0dea3 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:54:53 +0700 Subject: [PATCH 135/161] fix: remove redundant code --- pop-api/examples/fungibles/tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index d9ced3a4..500e1618 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -152,7 +152,6 @@ fn allowance_works(mut session: Session) { assert_eq!(allowance(&mut session, contract.clone(), ALICE), 0); // Tokens in circulation. - assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT / 2)); assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2); } From ea41bcf52c57f898821231ee849a16e10b1561d1 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:02:48 +0700 Subject: [PATCH 136/161] fix: only check state changes if success --- pop-api/examples/fungibles/tests.rs | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 500e1618..dd274a37 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -180,20 +180,14 @@ fn transfer_works(mut session: Session) { // No-op if `value` is zero. assert_ok!(transfer(&mut session, ALICE, 0)); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), 0); assert_eq!(last_contract_event(&session), None); // No event emitted. // No-op if the caller and `to` is the same address, returns success and no events are emitted. assert_ok!(transfer(&mut session, contract.clone(), value)); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), 0); assert_eq!(last_contract_event(&session), None); // No event emitted. // Failed with `InsufficientBalance`. assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), 0); // Successfully transfer. assert_ok!(transfer(&mut session, BOB, value)); @@ -239,16 +233,10 @@ fn transfer_from_works(mut session: Session) { // No-op if `value` is zero. assert_ok!(transfer_from(&mut session, ALICE, BOB, 0)); - assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); assert_eq!(last_contract_event(&session), None); // No event emitted. // No-op if the `from` and `to` is the same address, returns success and no events are emitted. assert_ok!(transfer_from(&mut session, ALICE, ALICE, value)); - assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); assert_eq!(last_contract_event(&session), None); // No event emitted. // Not enough balance. Failed with `InsufficientBalance`. @@ -256,18 +244,12 @@ fn transfer_from_works(mut session: Session) { transfer_from(&mut session, ALICE, contract.clone(), AMOUNT + 1), Err(PSP22Error::InsufficientBalance) ); - assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); // Unapproved transfer. Failed with `InsufficientAllowance`. assert_eq!( transfer_from(&mut session, ALICE, contract.clone(), AMOUNT * 2 + 1), Err(PSP22Error::InsufficientAllowance) ); - assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT * 2); - assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), 0); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); // Successful transfer. assert_ok!(transfer_from(&mut session, ALICE, BOB, value)); @@ -314,7 +296,6 @@ fn approve_works(mut session: Session) { // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(approve(&mut session, contract.clone(), value)); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), 0); assert_eq!(last_contract_event(&session), None); // No event emitted. // Successfully approve. @@ -376,12 +357,10 @@ fn increase_allowance_works(mut session: Session) { // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(increase_allowance(&mut session, contract.clone(), value)); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); assert_eq!(last_contract_event(&session), None); // No event emitted. // No-op if the `value` is zero. assert_ok!(increase_allowance(&mut session, contract.clone(), 0)); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); assert_eq!(last_contract_event(&session), None); // No event emitted. // Successfully approve. @@ -443,7 +422,6 @@ fn decrease_allowance_works(mut session: Session) { // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(decrease_allowance(&mut session, contract.clone(), value)); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); assert_eq!(last_contract_event(&session), None); // No event emitted. // Failed with `InsufficientAllowance`. @@ -451,7 +429,6 @@ fn decrease_allowance_works(mut session: Session) { decrease_allowance(&mut session, ALICE, AMOUNT + value), Err(PSP22Error::InsufficientAllowance) ); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT); // Successfully approve. assert_ok!(decrease_allowance(&mut session, ALICE, value)); @@ -560,7 +537,6 @@ fn mint_works(mut session: Session) { // No-op if minted value is zero. assert_ok!(mint(&mut session, ALICE, 0)); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), 0); assert_eq!(last_contract_event(&session), None); // No event emitted. // Successfully mint tokens. @@ -577,7 +553,6 @@ fn mint_works(mut session: Session) { // Total supply increased by `value` exceeds maximal value of `u128` type. assert_eq!(mint(&mut session, ALICE, u128::MAX), Err(into_psp22_custom(Arithmetic(Overflow)))); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), value); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); @@ -619,14 +594,10 @@ fn burn_works(mut session: Session) { // No-op. assert_ok!(burn(&mut session, ALICE, 0)); - assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); assert_eq!(last_contract_event(&session), None); // No event emitted. // Failed with `InsufficientBalance`. assert_eq!(burn(&mut session, ALICE, AMOUNT * 2), Err(PSP22Error::InsufficientBalance)); - assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT); - assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), AMOUNT); // Successfully burn tokens. assert_ok!(burn(&mut session, ALICE, value)); From 5f8bf7e866cce8cb86156046d497485d7a91a380 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 22:26:52 +0700 Subject: [PATCH 137/161] fix: trait name --- pop-api/examples/fungibles/lib.rs | 10 +++++----- pop-api/examples/fungibles/tests.rs | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 282f3959..2839175b 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -14,7 +14,7 @@ use pop_api::{ v0::fungibles::{ self as api, events::{Approval, Created, Transfer}, - traits::{Psp22, Psp22Burnable, Psp22Metadata, Psp22Mintable}, + traits::{PSP22Burnable, PSP22Metadata, PSP22Mintable, PSP22}, PSP22Error, }, }; @@ -65,7 +65,7 @@ mod fungibles { } } - impl Psp22 for Fungibles { + impl PSP22 for Fungibles { /// Returns the total token supply. #[ink(message)] fn total_supply(&self) -> Balance { @@ -203,7 +203,7 @@ mod fungibles { } } - impl Psp22Metadata for Fungibles { + impl PSP22Metadata for Fungibles { /// Returns the token name. #[ink(message)] fn token_name(&self) -> Option { @@ -229,7 +229,7 @@ mod fungibles { } } - impl Psp22Mintable for Fungibles { + impl PSP22Mintable for Fungibles { /// Mints `value` tokens to the senders account. #[ink(message)] fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { @@ -242,7 +242,7 @@ mod fungibles { } } - impl Psp22Burnable for Fungibles { + impl PSP22Burnable for Fungibles { /// Burns `value` tokens from the senders account. #[ink(message)] fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index dd274a37..8ea0089a 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -649,11 +649,11 @@ mod utils { /// PSP22 test utilities. pub(super) fn total_supply(session: &mut Session) -> Balance { - call::(session, "Psp22::total_supply", vec![], None).unwrap() + call::(session, "PSP22::total_supply", vec![], None).unwrap() } pub(super) fn balance_of(session: &mut Session, owner: AccountId32) -> Balance { - call::(session, "Psp22::balance_of", vec![owner.to_string()], None).unwrap() + call::(session, "PSP22::balance_of", vec![owner.to_string()], None).unwrap() } pub(super) fn allowance( @@ -663,7 +663,7 @@ mod utils { ) -> Balance { call::( session, - "Psp22::allowance", + "PSP22::allowance", vec![owner.to_string(), spender.to_string()], None, ) @@ -677,7 +677,7 @@ mod utils { ) -> Result<(), PSP22Error> { call::<()>( session, - "Psp22::transfer", + "PSP22::transfer", vec![ to.to_string(), amount.to_string(), @@ -695,7 +695,7 @@ mod utils { ) -> Result<(), PSP22Error> { call::<()>( session, - "Psp22::transfer_from", + "PSP22::transfer_from", vec![ from.to_string(), to.to_string(), @@ -711,7 +711,7 @@ mod utils { spender: AccountId32, value: Balance, ) -> Result<(), PSP22Error> { - call::<()>(session, "Psp22::approve", vec![spender.to_string(), value.to_string()], None) + call::<()>(session, "PSP22::approve", vec![spender.to_string(), value.to_string()], None) } pub(super) fn increase_allowance( @@ -721,7 +721,7 @@ mod utils { ) -> Result<(), PSP22Error> { call::<()>( session, - "Psp22::increase_allowance", + "PSP22::increase_allowance", vec![spender.to_string(), value.to_string()], None, ) @@ -734,7 +734,7 @@ mod utils { ) -> Result<(), PSP22Error> { call::<()>( session, - "Psp22::decrease_allowance", + "PSP22::decrease_allowance", vec![spender.to_string(), value.to_string()], None, ) @@ -743,15 +743,15 @@ mod utils { /// PSP22Metadata test utilities. pub(super) fn token_name(session: &mut Session) -> Option { - call::>(session, "Psp22Metadata::token_name", vec![], None).unwrap() + call::>(session, "PSP22Metadata::token_name", vec![], None).unwrap() } pub(super) fn token_symbol(session: &mut Session) -> Option { - call::>(session, "Psp22Metadata::token_symbol", vec![], None).unwrap() + call::>(session, "PSP22Metadata::token_symbol", vec![], None).unwrap() } pub(super) fn token_decimals(session: &mut Session) -> u8 { - call::(session, "Psp22Metadata::token_decimals", vec![], None).unwrap() + call::(session, "PSP22Metadata::token_decimals", vec![], None).unwrap() } /// PSP22Mintable test utilities. @@ -763,7 +763,7 @@ mod utils { ) -> Result<(), PSP22Error> { call::<()>( session, - "Psp22Mintable::mint", + "PSP22Mintable::mint", vec![account.to_string(), amount.to_string()], None, ) @@ -778,7 +778,7 @@ mod utils { ) -> Result<(), PSP22Error> { call::<()>( session, - "Psp22Burnable::burn", + "PSP22Burnable::burn", vec![account.to_string(), amount.to_string()], None, ) From 5e48851d31d77186a45e2bcbe97ccbfecf0ae778 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 22:27:04 +0700 Subject: [PATCH 138/161] fix: trait name --- pop-api/src/v0/fungibles/traits.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 92ad55e3..fd9e6271 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -6,7 +6,7 @@ use ink::prelude::string::String; /// The PSP22 trait. #[ink::trait_definition] -pub trait Psp22 { +pub trait PSP22 { /// Returns the total token supply. #[ink(message)] fn total_supply(&self) -> Balance; @@ -82,7 +82,7 @@ pub trait Psp22 { /// The PSP22 Metadata trait. #[ink::trait_definition] -pub trait Psp22Metadata { +pub trait PSP22Metadata { /// Returns the token name. #[ink(message)] fn token_name(&self) -> Option; @@ -98,7 +98,7 @@ pub trait Psp22Metadata { /// The PSP22 Mintable trait. #[ink::trait_definition] -pub trait Psp22Mintable { +pub trait PSP22Mintable { /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. /// /// # Parameters @@ -110,7 +110,7 @@ pub trait Psp22Mintable { /// The PSP22 Burnable trait. #[ink::trait_definition] -pub trait Psp22Burnable { +pub trait PSP22Burnable { /// Destroys `value` amount of tokens from `account`, reducing the total supply. /// /// # Parameters From af4ec2b44f9fc1353a6be81a0e8cea30ea6a092c Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Thu, 26 Sep 2024 22:32:27 +0700 Subject: [PATCH 139/161] fix: psp22 trait name (#305) --- pop-api/src/v0/fungibles/traits.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 92ad55e3..fd9e6271 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -6,7 +6,7 @@ use ink::prelude::string::String; /// The PSP22 trait. #[ink::trait_definition] -pub trait Psp22 { +pub trait PSP22 { /// Returns the total token supply. #[ink(message)] fn total_supply(&self) -> Balance; @@ -82,7 +82,7 @@ pub trait Psp22 { /// The PSP22 Metadata trait. #[ink::trait_definition] -pub trait Psp22Metadata { +pub trait PSP22Metadata { /// Returns the token name. #[ink(message)] fn token_name(&self) -> Option; @@ -98,7 +98,7 @@ pub trait Psp22Metadata { /// The PSP22 Mintable trait. #[ink::trait_definition] -pub trait Psp22Mintable { +pub trait PSP22Mintable { /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. /// /// # Parameters @@ -110,7 +110,7 @@ pub trait Psp22Mintable { /// The PSP22 Burnable trait. #[ink::trait_definition] -pub trait Psp22Burnable { +pub trait PSP22Burnable { /// Destroys `value` amount of tokens from `account`, reducing the total supply. /// /// # Parameters From bea0e9aa4b9f9e231b2be5ad25f974bf290913fc Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Fri, 27 Sep 2024 15:29:26 +0700 Subject: [PATCH 140/161] feat: return `UnApproved` in `decrease_allowance` instead of `saturating_sub` (#307) --- pallets/api/src/fungibles/mod.rs | 18 ++++++++++----- pallets/api/src/fungibles/tests.rs | 16 ++++++-------- pop-api/examples/fungibles/lib.rs | 22 ++----------------- .../integration-tests/src/fungibles/mod.rs | 7 +++++- 4 files changed, 27 insertions(+), 36 deletions(-) diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index 4c840628..0dd2a461 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -17,6 +17,7 @@ type AccountIdOf = ::AccountId; type TokenIdOf = as Inspect<::AccountId>>::AssetId; type TokenIdParameterOf = >>::AssetIdParameter; type AssetsOf = pallet_assets::Pallet>; +type AssetsErrorOf = pallet_assets::Error>; type AssetsInstanceOf = ::AssetsInstance; type AssetsWeightInfoOf = >>::WeightInfo; type BalanceOf = as Inspect<::AccountId>>::Balance; @@ -33,7 +34,7 @@ pub mod pallet { }; use frame_system::pallet_prelude::*; use sp_runtime::{ - traits::{StaticLookup, Zero}, + traits::{CheckedSub, StaticLookup, Zero}, Saturating, }; use sp_std::vec::Vec; @@ -338,13 +339,16 @@ pub mod pallet { let token_param: TokenIdParameterOf = token.clone().into(); // Cancel the approval and approve `new_allowance` if difference is more than zero. + let new_allowance = match current_allowance.checked_sub(&value) { + Some(allowance) => allowance, + None => return Err(AssetsErrorOf::::Unapproved.into()), + }; AssetsOf::::cancel_approval( origin.clone(), token_param.clone(), spender_source.clone(), ) .map_err(|e| e.with_weight(WeightOf::::approve(0, 1)))?; - let new_allowance = current_allowance.saturating_sub(value); let weight = if new_allowance.is_zero() { WeightOf::::approve(0, 1) } else { @@ -510,10 +514,12 @@ pub mod pallet { use Read::*; match request { TotalSupply(token) => ReadResult::TotalSupply(AssetsOf::::total_supply(token)), - BalanceOf { token, owner } => - ReadResult::BalanceOf(AssetsOf::::balance(token, owner)), - Allowance { token, owner, spender } => - ReadResult::Allowance(AssetsOf::::allowance(token, &owner, &spender)), + BalanceOf { token, owner } => { + ReadResult::BalanceOf(AssetsOf::::balance(token, owner)) + }, + Allowance { token, owner, spender } => { + ReadResult::Allowance(AssetsOf::::allowance(token, &owner, &spender)) + }, TokenName(token) => ReadResult::TokenName( as MetadataInspect< AccountIdOf, >>::name(token)), diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index 2e430ca8..f46f0af3 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -286,6 +286,11 @@ fn decrease_allowance_works() { Ok(Some(WeightInfo::approve(0, 0)).into()) ); assert_eq!(Assets::allowance(token, &owner, &spender), value); + // "Unapproved" error is returned if the current allowance is less than `value`. + assert_noop!( + Fungibles::decrease_allowance(signed(owner), token, spender, value * 2), + AssetsError::Unapproved + ); // Decrease allowance successfully. assert_eq!( Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), @@ -295,13 +300,6 @@ fn decrease_allowance_works() { System::assert_last_event( Event::Approval { token, owner, spender, value: value / 2 }.into(), ); - // Saturating if current allowance is decreased more than the owner balance. - assert_eq!( - Fungibles::decrease_allowance(signed(owner), token, spender, value), - Ok(Some(WeightInfo::approve(0, 1)).into()) - ); - assert_eq!(Assets::allowance(token, &owner, &spender), 0); - System::assert_last_event(Event::Approval { token, owner, spender, value: 0 }.into()); }); } @@ -677,8 +675,8 @@ mod read_weights { } mod ensure_codec_indexes { - use super::{Encode, RuntimeCall, *}; - use crate::{fungibles, fungibles::Call::*, mock::RuntimeCall::Fungibles}; + use super::{Encode, *}; + use crate::{fungibles, mock::RuntimeCall::Fungibles}; #[test] fn ensure_read_variant_indexes() { diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 2839175b..8b49ccaf 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -1,11 +1,3 @@ -// TODO: If `admin` in `create` is different than the contract address, `NoPermission` thrown for -// mint, burn -// TODO: `Fungibles::decrease_allowance()` saturating_sub the value, it should -// `checked_sub` and throw an error instead. Hence, we don't have to handle `InsufficientAllowance` -// on the contract side. -// TODO: `InsufficientBalance` case is not returned in the `burn` pallet api if the `value` exceeds -// the minted value. In `decrease_balance` method of `pallet-assets`, it is also `saturating_sub`. - #![cfg_attr(not(feature = "std"), no_std, no_main)] use ink::prelude::{string::String, vec::Vec}; @@ -185,20 +177,10 @@ mod fungibles { if caller == spender || value == 0 { return Ok(()); } - // Reverts with `InsufficientAllowance` if `spender` and the caller are different - // addresses and the `value` exceeds the allowance granted by the caller to - // `spender`. - let allowance = self.allowance(caller, spender); - if allowance < value { - return Err(PSP22Error::InsufficientAllowance); - } api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; - self.env().emit_event(Approval { - owner: caller, - spender, - value: allowance.saturating_sub(value), - }); + let allowance = self.allowance(caller, spender); + self.env().emit_event(Approval { owner: caller, spender, value: allowance }); Ok(()) } } diff --git a/pop-api/integration-tests/src/fungibles/mod.rs b/pop-api/integration-tests/src/fungibles/mod.rs index d2e06285..f6e83461 100644 --- a/pop-api/integration-tests/src/fungibles/mod.rs +++ b/pop-api/integration-tests/src/fungibles/mod.rs @@ -267,9 +267,14 @@ fn decrease_allowance_works() { Err(Module { index: 52, error: [16, 0] }), ); assets::thaw(&addr, token); + // "Unapproved" error is returned if the current allowance is less than `value`. + assert_eq!( + decrease_allowance(&addr, token, &BOB, amount * 2), + Err(Module { index: 52, error: [10, 0] }), + ); // Successfully decrease allowance. let allowance_before = Assets::allowance(token, &addr, &BOB); - assert_ok!(decrease_allowance(&addr, 0, &BOB, amount / 2 - 1 * UNIT)); + assert_ok!(decrease_allowance(&addr, token, &BOB, amount / 2 - 1 * UNIT)); let allowance_after = Assets::allowance(token, &addr, &BOB); assert_eq!(allowance_before - allowance_after, amount / 2 - 1 * UNIT); // Token is not live, i.e. frozen or being destroyed. From b2fbcd811fa12fa04ef7b5ecef14495a4869c7ab Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 27 Sep 2024 17:32:20 +0700 Subject: [PATCH 141/161] fix: decrease_allowance test --- pallets/api/src/fungibles/tests.rs | 8 +++++--- pop-api/integration-tests/src/fungibles/mod.rs | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index f46f0af3..1a1efa37 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -272,14 +272,16 @@ fn decrease_allowance_works() { BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } + assets::create_mint_and_approve(owner, token, owner, value, spender, value); + assert_eq!(Assets::allowance(token, &owner, &spender), value); // Check error works for `Assets::cancel_approval()`. No error test for `approve_transfer` // because it is not possible. + assert_ok!(Assets::freeze_asset(signed(owner), token)); assert_noop!( Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), - AssetsError::Unknown.with_weight(WeightInfo::approve(0, 1)) + AssetsError::AssetNotLive.with_weight(WeightInfo::approve(0, 1)) ); - assets::create_mint_and_approve(owner, token, owner, value, spender, value); - assert_eq!(Assets::allowance(token, &owner, &spender), value); + assert_ok!(Assets::thaw_asset(signed(owner), token)); // Owner balance is not changed if decreased by zero. assert_eq!( Fungibles::decrease_allowance(signed(owner), token, spender, 0), diff --git a/pop-api/integration-tests/src/fungibles/mod.rs b/pop-api/integration-tests/src/fungibles/mod.rs index f6e83461..99202327 100644 --- a/pop-api/integration-tests/src/fungibles/mod.rs +++ b/pop-api/integration-tests/src/fungibles/mod.rs @@ -256,7 +256,7 @@ fn decrease_allowance_works() { // Token does not exist. assert_eq!( decrease_allowance(&addr, 0, &BOB, amount), - Err(Module { index: 52, error: [3, 0] }), + Err(Module { index: 52, error: [10, 0] }), ); // Create token and mint `amount` to contract address, then approve Bob to spend `amount`. let token = assets::create_mint_and_approve(&addr, 0, &addr, amount, &BOB, amount); @@ -281,7 +281,7 @@ fn decrease_allowance_works() { assets::start_destroy(&addr, token); assert_eq!( decrease_allowance(&addr, token, &BOB, amount), - Err(Module { index: 52, error: [16, 0] }), + Err(Module { index: 52, error: [10, 0] }), ); }); } From e9cc4a587fc71790f09b55ab6d140696219eae11 Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:07:45 +0200 Subject: [PATCH 142/161] refactor: drink (#308) --- pallets/api/src/fungibles/mod.rs | 10 +- pop-api/examples/fungibles/Cargo.toml | 15 +- pop-api/examples/fungibles/lib.rs | 100 ++-- pop-api/examples/fungibles/tests.rs | 599 ++++++++++-------------- pop-sandbox/Cargo.toml | 50 -- pop-sandbox/README.md | 60 --- pop-sandbox/examples/.gitignore | 9 - pop-sandbox/examples/flipper/Cargo.toml | 28 -- pop-sandbox/examples/flipper/lib.rs | 169 ------- pop-sandbox/src/lib.rs | 88 ---- runtime/devnet/src/lib.rs | 3 + 11 files changed, 325 insertions(+), 806 deletions(-) delete mode 100644 pop-sandbox/Cargo.toml delete mode 100644 pop-sandbox/README.md delete mode 100644 pop-sandbox/examples/.gitignore delete mode 100644 pop-sandbox/examples/flipper/Cargo.toml delete mode 100644 pop-sandbox/examples/flipper/lib.rs delete mode 100644 pop-sandbox/src/lib.rs diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index 0dd2a461..3a9fe601 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -514,12 +514,10 @@ pub mod pallet { use Read::*; match request { TotalSupply(token) => ReadResult::TotalSupply(AssetsOf::::total_supply(token)), - BalanceOf { token, owner } => { - ReadResult::BalanceOf(AssetsOf::::balance(token, owner)) - }, - Allowance { token, owner, spender } => { - ReadResult::Allowance(AssetsOf::::allowance(token, &owner, &spender)) - }, + BalanceOf { token, owner } => + ReadResult::BalanceOf(AssetsOf::::balance(token, owner)), + Allowance { token, owner, spender } => + ReadResult::Allowance(AssetsOf::::allowance(token, &owner, &spender)), TokenName(token) => ReadResult::TokenName( as MetadataInspect< AccountIdOf, >>::name(token)), diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 4caf80a1..a07c07f3 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -9,23 +9,13 @@ ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] pop-api = { path = "../../../pop-api", default-features = false, features = [ "fungibles", ] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", -] } -scale-info = { version = "2.6", default-features = false, features = [ - "derive", -], optional = true } [dev-dependencies] env_logger = { version = "0.11.3" } serde_json = "1.0.114" # Local -drink = { path = "../../../../pop-drink/drink" } -pop-sandbox = { path = "../../../pop-sandbox", default-features = false } - -# Substrate -frame-support = { version = "36.0.0", default-features = false } +drink = { package = "pop-drink", path = "../../../../pop-drink/crates/pop-drink" } [lib] path = "lib.rs" @@ -37,7 +27,4 @@ ink-as-dependency = [ ] std = [ "ink/std", "pop-api/std", - "pop-sandbox/std", - "scale-info/std", - "scale/std", ] diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 8b49ccaf..9787a43a 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -19,11 +19,11 @@ mod fungibles { use super::*; #[ink(storage)] - pub struct Fungibles { + pub struct Fungible { id: TokenId, } - impl Fungibles { + impl Fungible { /// Instantiate the contract and wrap around an existing token. /// /// # Parameters @@ -32,10 +32,9 @@ mod fungibles { pub fn existing(id: TokenId) -> Result { // Make sure token exists. if !api::token_exists(id).unwrap_or_default() { - return Err(PSP22Error::Custom(String::from("Unknown"))); + return Err(PSP22Error::Custom(String::from("Token does not exist"))); } - let contract = Self { id }; - Ok(contract) + Ok(Self { id }) } /// Instantiate the contract and create a new token. The token identifier will be stored @@ -43,8 +42,9 @@ mod fungibles { /// /// # Parameters /// * - `id` - The identifier of the token. - /// * - `admin` - The account that will administer the token. /// * - `min_balance` - The minimum balance required for accounts holding this token. + // The `min_balance` ensures accounts hold a minimum amount of tokens, preventing tiny, + // inactive balances from bloating the blockchain state and slowing down the network. #[ink(constructor, payable)] pub fn new(id: TokenId, min_balance: Balance) -> Result { let contract = Self { id }; @@ -57,20 +57,27 @@ mod fungibles { } } - impl PSP22 for Fungibles { + impl PSP22 for Fungible { /// Returns the total token supply. #[ink(message)] fn total_supply(&self) -> Balance { api::total_supply(self.id).unwrap_or_default() } - /// Returns the account balance for the specified `owner` + /// Returns the account balance for the specified `owner`. + /// + /// # Parameters + /// - `owner` - The account whose balance is being queried. #[ink(message)] fn balance_of(&self, owner: AccountId) -> Balance { api::balance_of(self.id, owner).unwrap_or_default() } - /// Returns the amount which `spender` is still allowed to withdraw from `owner` + /// Returns the allowance for a `spender` approved by an `owner`. + /// + /// # Parameters + /// - `owner` - The account that owns the tokens. + /// - `spender` - The account that is allowed to spend the tokens. #[ink(message)] fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance { api::allowance(self.id, owner, spender).unwrap_or_default() @@ -78,6 +85,11 @@ mod fungibles { /// Transfers `value` amount of tokens from the caller's account to account `to` /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// - `data` - Additional data in unspecified format. #[ink(message)] fn transfer( &mut self, @@ -86,8 +98,7 @@ mod fungibles { _data: Vec, ) -> Result<(), PSP22Error> { let caller = self.env().caller(); - // No-op if the caller and `to` is the same address or `value` is zero, returns success - // and no events are emitted. + // No-op if the caller and `to` is the same address or `value` is zero. if caller == to || value == 0 { return Ok(()); } @@ -97,8 +108,14 @@ mod fungibles { Ok(()) } - /// Transfers `value` tokens on the behalf of `from` to the account `to` + /// Transfers `value` tokens on behalf of `from` to the account `to` /// with additional `data` in unspecified format. + /// + /// # Parameters + /// - `from` - The account from which the token balance will be withdrawn. + /// - `to` - The recipient account. + /// - `value` - The number of tokens to transfer. + /// - `data` - Additional data with unspecified format. #[ink(message)] fn transfer_from( &mut self, @@ -108,8 +125,7 @@ mod fungibles { _data: Vec, ) -> Result<(), PSP22Error> { let caller = self.env().caller(); - // No-op if `from` and `to` is the same address or `value` is zero, returns success and - // no events are emitted. + // No-op if `from` and `to` is the same address or `value` is zero. if from == to || value == 0 { return Ok(()); } @@ -118,7 +134,6 @@ mod fungibles { // in decreased allowance by `from` to the caller and an `Approval` event with // the new allowance amount is emitted. api::transfer_from(self.id, from, to, value).map_err(PSP22Error::from)?; - // Emit events. self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); self.env().emit_event(Approval { owner: from, @@ -128,13 +143,17 @@ mod fungibles { Ok(()) } - /// Allows `spender` to withdraw from the caller's account multiple times, up to - /// the total amount of `value`. + /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. + /// + /// Successive calls of this method overwrite previous values. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to approve. #[ink(message)] fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error> { let caller = self.env().caller(); - // No-op if the caller and `spender` is the same address, returns success and no events - // are emitted. + // No-op if the caller and `spender` is the same address. if caller == spender { return Ok(()); } @@ -144,7 +163,11 @@ mod fungibles { Ok(()) } - /// Increases by `value` the allowance granted to `spender` by the caller. + /// Increases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to increase the allowance by. #[ink(message)] fn increase_allowance( &mut self, @@ -152,8 +175,7 @@ mod fungibles { value: Balance, ) -> Result<(), PSP22Error> { let caller = self.env().caller(); - // No-op if the caller and `spender` is the same address or `value` is zero, returns - // success and no events are emitted. + // No-op if the caller and `spender` is the same address or `value` is zero. if caller == spender || value == 0 { return Ok(()); } @@ -164,7 +186,11 @@ mod fungibles { Ok(()) } - /// Decreases by `value` the allowance granted to `spender` by the caller. + /// Decreases the allowance of `spender` by `value` amount of tokens. + /// + /// # Parameters + /// - `spender` - The account that is allowed to spend the tokens. + /// - `value` - The number of tokens to decrease the allowance by. #[ink(message)] fn decrease_allowance( &mut self, @@ -172,20 +198,19 @@ mod fungibles { value: Balance, ) -> Result<(), PSP22Error> { let caller = self.env().caller(); - // No-op if the caller and `spender` is the same address or `value` is zero, returns - // success and no events are emitted. + // No-op if the caller and `spender` is the same address or `value` is zero. if caller == spender || value == 0 { return Ok(()); } api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; - let allowance = self.allowance(caller, spender); - self.env().emit_event(Approval { owner: caller, spender, value: allowance }); + let value = self.allowance(caller, spender); + self.env().emit_event(Approval { owner: caller, spender, value }); Ok(()) } } - impl PSP22Metadata for Fungibles { + impl PSP22Metadata for Fungible { /// Returns the token name. #[ink(message)] fn token_name(&self) -> Option { @@ -211,10 +236,16 @@ mod fungibles { } } - impl PSP22Mintable for Fungibles { - /// Mints `value` tokens to the senders account. + impl PSP22Mintable for Fungible { + /// Creates `value` amount of tokens and assigns them to `account`, increasing the total + /// supply. + /// + /// # Parameters + /// - `account` - The account to be credited with the created tokens. + /// - `value` - The number of tokens to mint. #[ink(message)] fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { + // No-op if `value` is zero. if value == 0 { return Ok(()); } @@ -224,10 +255,15 @@ mod fungibles { } } - impl PSP22Burnable for Fungibles { - /// Burns `value` tokens from the senders account. + impl PSP22Burnable for Fungible { + /// Destroys `value` amount of tokens from `account`, reducing the total supply. + /// + /// # Parameters + /// - `account` - The account from which the tokens will be destroyed. + /// - `value` - The number of tokens to destroy. #[ink(message)] fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { + // No-op if `value` is zero. if value == 0 { return Ok(()); } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 8ea0089a..fd0a8cc4 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -1,9 +1,11 @@ -use super::*; use drink::{ - sandbox_api::assets_api::AssetsAPI, - session::{ContractBundle, Session}, + assert_ok, + devnet::{account_id_from_slice, AccountId, Balance, Runtime}, + session::Session, + utils::{call, last_contract_event}, + AssetsAPI, TestExternalities, NO_SALT, }; -use frame_support::assert_ok; +use ink::scale::Encode; use pop_api::{ primitives::{ ArithmeticError::Overflow, @@ -12,23 +14,46 @@ use pop_api::{ }, v0::fungibles::events::{Approval, Created, Transfer}, }; -use pop_sandbox::{Balance, DevnetSandbox as Sandbox, ALICE, BOB}; -use scale::Encode; -use std::sync::LazyLock; -use utils::*; -#[drink::contract_bundle_provider] -enum BundleProvider {} +use super::*; +const UNIT: Balance = 10_000_000_000; +const INIT_AMOUNT: Balance = 100_000_000 * UNIT; +const INIT_VALUE: Balance = 100 * UNIT; +const ALICE: AccountId = AccountId::new([1u8; 32]); +const BOB: AccountId = AccountId::new([2_u8; 32]); +const CHARLIE: AccountId = AccountId::new([3_u8; 32]); const AMOUNT: Balance = MIN_BALANCE * 4; const MIN_BALANCE: Balance = 10_000; const TOKEN: TokenId = 1; -static CONTRACT: LazyLock = LazyLock::new(|| BundleProvider::local().unwrap()); +// The contract bundle provider. +// +// See https://github.com/r0gue-io/pop-drink/blob/main/drink/test-macro/src/lib.rs for more information. +#[drink::contract_bundle_provider] +enum BundleProvider {} + +/// Sandbox environment for Pop Devnet Runtime. +pub struct Pop { + ext: TestExternalities, +} -/// Deployment and constructor method tests. +impl Default for Pop { + fn default() -> Self { + // Initialising genesis state, providing accounts with an initial balance. + let balances: Vec<(AccountId, u128)> = + vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)]; + let ext = BlockBuilder::::new_ext(balances); + Self { ext } + } +} -#[drink::test(sandbox = Sandbox)] +// Implement core functionalities for the `Pop` sandbox. +drink::impl_sandbox!(Pop, Runtime, ALICE); + +// Deployment and constructor method tests. + +#[drink::test(sandbox = Pop)] fn new_constructor_works(mut session: Session) { let _ = env_logger::try_init(); // Fails to deploy contract with an used token ID. @@ -36,23 +61,13 @@ fn new_constructor_works(mut session: Session) { assert_ok!(session.sandbox().create(&token, &ALICE, MIN_BALANCE)); // `pallet-assets` returns `InUse` error. assert_eq!( - deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![token.to_string(), MIN_BALANCE.to_string()] - ), + deploy(&mut session, "new", vec![token.to_string(), MIN_BALANCE.to_string()],), Err(into_psp22_custom(Module { index: 52, error: [5, 0] })) ); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); // Token exists after the deployment. assert!(session.sandbox().asset_exists(&TOKEN)); // Successfully emit event. @@ -60,50 +75,45 @@ fn new_constructor_works(mut session: Session) { last_contract_event(&session).unwrap(), Created { id: TOKEN, - creator: account_id_from_slice(contract.as_ref()), - admin: account_id_from_slice(contract.as_ref()), + creator: account_id_from_slice(&contract), + admin: account_id_from_slice(&contract), } .encode() .as_slice() ); } -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn existing_constructor_works(mut session: Session) { let _ = env_logger::try_init(); // Fails to deploy contract with a non-existing token ID. assert_eq!( - deploy(&mut session, CONTRACT.clone(), "existing", vec![TOKEN.to_string()]), - Err(PSP22Error::Custom(String::from("Unknown"))) + deploy(&mut session, "existing", vec![TOKEN.to_string()]), + Err(PSP22Error::Custom(String::from("Token does not exist"))) ); // Successfully deploy contract with an existing token ID. let actor = session.get_actor(); assert_ok!(session.sandbox().create(&TOKEN, &actor, MIN_BALANCE)); - assert_ok!(deploy(&mut session, CONTRACT.clone(), "existing", vec![TOKEN.to_string()])); + assert_ok!(deploy(&mut session, "existing", vec![TOKEN.to_string()])); assert!(session.sandbox().asset_exists(&TOKEN)); } -/// 1. PSP-22 Interface: -/// - total_supply -/// - balance_of -/// - allowance -/// - transfer -/// - transfer_from -/// - approve -/// - increase_allowance -/// - decrease_allowance - -#[drink::test(sandbox = Sandbox)] +// 1. PSP-22 Interface: +// - total_supply +// - balance_of +// - allowance +// - transfer +// - transfer_from +// - approve +// - increase_allowance +// - decrease_allowance + +#[drink::test(sandbox = Pop)] fn total_supply_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - assert_ok!(deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()] - )); + assert_ok!(deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()],)); // No tokens in circulation. assert_eq!(total_supply(&mut session), 0); @@ -115,16 +125,11 @@ fn total_supply_works(mut session: Session) { assert_eq!(total_supply(&mut session), session.sandbox().total_supply(&TOKEN)); } -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn balance_of_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - assert_ok!(deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()] - )); + assert_ok!(deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()])); // No tokens in circulation. assert_eq!(balance_of(&mut session, ALICE), 0); @@ -136,17 +141,12 @@ fn balance_of_works(mut session: Session) { assert_eq!(balance_of(&mut session, ALICE), session.sandbox().balance_of(&TOKEN, &ALICE)); } -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn allowance_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); // No tokens in circulation. assert_eq!(allowance(&mut session, contract.clone(), ALICE), 0); @@ -156,17 +156,12 @@ fn allowance_works(mut session: Session) { assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2); } -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn transfer_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); let value = AMOUNT / 4; session.set_actor(contract.clone()); // `pallet-assets` returns `NoAccount` error. @@ -197,8 +192,8 @@ fn transfer_works(mut session: Session) { assert_eq!( last_contract_event(&session).unwrap(), Transfer { - from: Some(account_id_from_slice(contract.as_ref())), - to: Some(account_id_from_slice(BOB.as_ref())), + from: Some(account_id_from_slice(&contract)), + to: Some(account_id_from_slice(&BOB)), value, } .encode() @@ -214,17 +209,12 @@ fn transfer_works(mut session: Session) { ); } -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn transfer_from_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); let value = AMOUNT / 2; session.set_actor(contract.clone()); // Mint tokens and approve. @@ -260,8 +250,8 @@ fn transfer_from_works(mut session: Session) { assert_eq!( last_contract_event(&session).unwrap(), Approval { - owner: account_id_from_slice(ALICE.as_ref()), - spender: account_id_from_slice(contract.as_ref()), + owner: account_id_from_slice(&ALICE), + spender: account_id_from_slice(&contract), value: AMOUNT + value, } .encode() @@ -277,17 +267,12 @@ fn transfer_from_works(mut session: Session) { ); } -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn approve_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); let value = AMOUNT / 2; session.set_actor(contract.clone()); // Mint tokens. @@ -305,8 +290,8 @@ fn approve_works(mut session: Session) { assert_eq!( last_contract_event(&session).unwrap(), Approval { - owner: account_id_from_slice(contract.clone().as_ref()), - spender: account_id_from_slice(ALICE.as_ref()), + owner: account_id_from_slice(&contract), + spender: account_id_from_slice(&ALICE), value, } .encode() @@ -320,8 +305,8 @@ fn approve_works(mut session: Session) { assert_eq!( last_contract_event(&session).unwrap(), Approval { - owner: account_id_from_slice(contract.as_ref()), - spender: account_id_from_slice(ALICE.as_ref()), + owner: account_id_from_slice(&contract), + spender: account_id_from_slice(&ALICE), value: value - 1, } .encode() @@ -337,17 +322,12 @@ fn approve_works(mut session: Session) { ); } -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn increase_allowance_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); let value = AMOUNT / 2; session.set_actor(contract.clone()); // Mint tokens and approve. @@ -370,8 +350,8 @@ fn increase_allowance_works(mut session: Session) { assert_eq!( last_contract_event(&session).unwrap(), Approval { - owner: account_id_from_slice(contract.as_ref()), - spender: account_id_from_slice(ALICE.as_ref()), + owner: account_id_from_slice(&contract), + spender: account_id_from_slice(&ALICE), value: AMOUNT + value, } .encode() @@ -385,8 +365,8 @@ fn increase_allowance_works(mut session: Session) { assert_eq!( last_contract_event(&session).unwrap(), Approval { - owner: account_id_from_slice(contract.as_ref()), - spender: account_id_from_slice(ALICE.as_ref()), + owner: account_id_from_slice(&contract), + spender: account_id_from_slice(&ALICE), value: AMOUNT + value * 2, } .encode() @@ -402,17 +382,12 @@ fn increase_allowance_works(mut session: Session) { ); } -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn decrease_allowance_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); let value = 1; session.set_actor(contract.clone()); // Mint tokens and approve. @@ -437,8 +412,8 @@ fn decrease_allowance_works(mut session: Session) { assert_eq!( last_contract_event(&session).unwrap(), Approval { - owner: account_id_from_slice(contract.as_ref()), - spender: account_id_from_slice(ALICE.as_ref()), + owner: account_id_from_slice(&contract), + spender: account_id_from_slice(&ALICE), value: AMOUNT - value, } .encode() @@ -452,8 +427,8 @@ fn decrease_allowance_works(mut session: Session) { assert_eq!( last_contract_event(&session).unwrap(), Approval { - owner: account_id_from_slice(contract.as_ref()), - spender: account_id_from_slice(ALICE.as_ref()), + owner: account_id_from_slice(&contract), + spender: account_id_from_slice(&ALICE), value: AMOUNT - value * 2, } .encode() @@ -469,22 +444,17 @@ fn decrease_allowance_works(mut session: Session) { ); } -/// 2. PSP-22 Metadata Interface: -/// - token_name -/// - token_symbol -/// - token_decimals +// 2. PSP-22 Metadata Interface: +// - token_name +// - token_symbol +// - token_decimals -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn token_metadata(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); let name: String = String::from("Paseo Token"); let symbol: String = String::from("PAS"); let decimals: u8 = 69; @@ -509,15 +479,16 @@ fn token_metadata(mut session: Session) { assert_eq!(token_decimals(&mut session), decimals); } -/// 3. PSP-22 Mintable Interface: -/// - mint +// 3. PSP-22 Mintable Interface: +// - mint -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn mint_works(mut session: Session) { let _ = env_logger::try_init(); // No permission to mint. - assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); // Create a new token owned by `BOB`. - assert_ok!(deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()])); + // Create a new tokenowned by `BOB`. + assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); + assert_ok!(deploy(&mut session, "existing", vec![(TOKEN + 1).to_string()])); // `pallet-assets` returns `NoPermission` error. assert_eq!( mint(&mut session, BOB, AMOUNT), @@ -525,13 +496,8 @@ fn mint_works(mut session: Session) { ); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); let value = AMOUNT; session.set_actor(contract.clone()); @@ -546,7 +512,7 @@ fn mint_works(mut session: Session) { // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), - Transfer { from: None, to: Some(account_id_from_slice(ALICE.as_ref())), value } + Transfer { from: None, to: Some(account_id_from_slice(&ALICE)), value } .encode() .as_slice() ); @@ -563,16 +529,17 @@ fn mint_works(mut session: Session) { ); } -/// 4. PSP-22 Burnable Interface: -/// - burn +// 4. PSP-22 Burnable Interface: +// - burn -#[drink::test(sandbox = Sandbox)] +#[drink::test(sandbox = Pop)] fn burn_works(mut session: Session) { let _ = env_logger::try_init(); // No permission to burn. - assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); // Create a new token owned by `BOB`. + // Create a new token owned by `BOB`. + assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); assert_ok!(session.sandbox().mint_into(&(TOKEN + 1), &BOB, AMOUNT)); - assert_ok!(deploy(&mut session, CONTRACT.clone(), "existing", vec![(TOKEN + 1).to_string()])); + assert_ok!(deploy(&mut session, "existing", vec![(TOKEN + 1).to_string()])); // `pallet-assets` returns `NoPermission` error. assert_eq!( burn(&mut session, BOB, AMOUNT), @@ -580,13 +547,8 @@ fn burn_works(mut session: Session) { ); // Deploy a new contract. - let contract = deploy( - &mut session, - CONTRACT.clone(), - "new", - vec![TOKEN.to_string(), MIN_BALANCE.to_string()], - ) - .unwrap(); + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); let value = 1; session.set_actor(contract.clone()); // Mint tokens. @@ -606,7 +568,7 @@ fn burn_works(mut session: Session) { // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), - Transfer { from: Some(account_id_from_slice(ALICE.as_ref())), to: None, value } + Transfer { from: Some(account_id_from_slice(&ALICE)), to: None, value } .encode() .as_slice() ); @@ -620,212 +582,149 @@ fn burn_works(mut session: Session) { ); } -/// A set of helper methods to test the contract calls. -mod utils { - use drink::session::{error::SessionError, NO_SALT}; - use pop_api::primitives::AccountId; - use pop_sandbox::{AccountId32, Balance, INIT_VALUE}; - use scale::Decode; - - use super::*; - - /// Deploy test utilities. - - pub(super) fn deploy( - session: &mut Session, - bundle: ContractBundle, - method: &str, - inputs: Vec, - ) -> Result { - let result = session.deploy_bundle(bundle, method, &inputs, NO_SALT, Some(INIT_VALUE)); - if result.is_err() { - let deployment_result = session.record().last_deploy_result().result.clone(); - let error = deployment_result.unwrap().result.data; - return Err(PSP22Error::decode(&mut &error[2..]).unwrap()); - } - Ok(result.unwrap()) - } - - /// PSP22 test utilities. +// Deploy the contract with `NO_SALT and `INIT_VALUE`. +fn deploy( + session: &mut Session, + method: &str, + input: Vec, +) -> Result { + drink::utils::deploy::( + session, + // The local contract (i.e. `fungibles`). + BundleProvider::local().unwrap(), + method, + input, + NO_SALT, + Some(INIT_VALUE), + ) +} - pub(super) fn total_supply(session: &mut Session) -> Balance { - call::(session, "PSP22::total_supply", vec![], None).unwrap() - } +// A set of helper methods to test the contract calls. - pub(super) fn balance_of(session: &mut Session, owner: AccountId32) -> Balance { - call::(session, "PSP22::balance_of", vec![owner.to_string()], None).unwrap() - } +fn total_supply(session: &mut Session) -> Balance { + call::(session, "PSP22::total_supply", vec![], None).unwrap() +} - pub(super) fn allowance( - session: &mut Session, - owner: AccountId32, - spender: AccountId32, - ) -> Balance { - call::( - session, - "PSP22::allowance", - vec![owner.to_string(), spender.to_string()], - None, - ) +fn balance_of(session: &mut Session, owner: AccountId) -> Balance { + call::(session, "PSP22::balance_of", vec![owner.to_string()], None) .unwrap() - } - - pub(super) fn transfer( - session: &mut Session, - to: AccountId32, - amount: Balance, - ) -> Result<(), PSP22Error> { - call::<()>( - session, - "PSP22::transfer", - vec![ - to.to_string(), - amount.to_string(), - serde_json::to_string::<[u8; 0]>(&[]).unwrap(), - ], - None, - ) - } - - pub(super) fn transfer_from( - session: &mut Session, - from: AccountId32, - to: AccountId32, - amount: Balance, - ) -> Result<(), PSP22Error> { - call::<()>( - session, - "PSP22::transfer_from", - vec![ - from.to_string(), - to.to_string(), - amount.to_string(), - serde_json::to_string::<[u8; 0]>(&[]).unwrap(), - ], - None, - ) - } - - pub(super) fn approve( - session: &mut Session, - spender: AccountId32, - value: Balance, - ) -> Result<(), PSP22Error> { - call::<()>(session, "PSP22::approve", vec![spender.to_string(), value.to_string()], None) - } +} - pub(super) fn increase_allowance( - session: &mut Session, - spender: AccountId32, - value: Balance, - ) -> Result<(), PSP22Error> { - call::<()>( - session, - "PSP22::increase_allowance", - vec![spender.to_string(), value.to_string()], - None, - ) - } +fn allowance(session: &mut Session, owner: AccountId, spender: AccountId) -> Balance { + call::( + session, + "PSP22::allowance", + vec![owner.to_string(), spender.to_string()], + None, + ) + .unwrap() +} - pub(super) fn decrease_allowance( - session: &mut Session, - spender: AccountId32, - value: Balance, - ) -> Result<(), PSP22Error> { - call::<()>( - session, - "PSP22::decrease_allowance", - vec![spender.to_string(), value.to_string()], - None, - ) - } +fn transfer(session: &mut Session, to: AccountId, amount: Balance) -> Result<(), PSP22Error> { + call::( + session, + "PSP22::transfer", + vec![to.to_string(), amount.to_string(), serde_json::to_string::<[u8; 0]>(&[]).unwrap()], + None, + ) +} - /// PSP22Metadata test utilities. +fn transfer_from( + session: &mut Session, + from: AccountId, + to: AccountId, + amount: Balance, +) -> Result<(), PSP22Error> { + call::( + session, + "PSP22::transfer_from", + vec![ + from.to_string(), + to.to_string(), + amount.to_string(), + serde_json::to_string::<[u8; 0]>(&[]).unwrap(), + ], + None, + ) +} - pub(super) fn token_name(session: &mut Session) -> Option { - call::>(session, "PSP22Metadata::token_name", vec![], None).unwrap() - } +fn approve( + session: &mut Session, + spender: AccountId, + value: Balance, +) -> Result<(), PSP22Error> { + call::( + session, + "PSP22::approve", + vec![spender.to_string(), value.to_string()], + None, + ) +} - pub(super) fn token_symbol(session: &mut Session) -> Option { - call::>(session, "PSP22Metadata::token_symbol", vec![], None).unwrap() - } +fn increase_allowance( + session: &mut Session, + spender: AccountId, + value: Balance, +) -> Result<(), PSP22Error> { + call::( + session, + "PSP22::increase_allowance", + vec![spender.to_string(), value.to_string()], + None, + ) +} - pub(super) fn token_decimals(session: &mut Session) -> u8 { - call::(session, "PSP22Metadata::token_decimals", vec![], None).unwrap() - } +fn decrease_allowance( + session: &mut Session, + spender: AccountId, + value: Balance, +) -> Result<(), PSP22Error> { + call::( + session, + "PSP22::decrease_allowance", + vec![spender.to_string(), value.to_string()], + None, + ) +} - /// PSP22Mintable test utilities. - - pub(super) fn mint( - session: &mut Session, - account: AccountId32, - amount: Balance, - ) -> Result<(), PSP22Error> { - call::<()>( - session, - "PSP22Mintable::mint", - vec![account.to_string(), amount.to_string()], - None, - ) - } +fn token_name(session: &mut Session) -> Option { + call::, PSP22Error>(session, "PSP22Metadata::token_name", vec![], None) + .unwrap() +} - /// PSP22Burnable test utilities. - - pub(super) fn burn( - session: &mut Session, - account: AccountId32, - amount: Balance, - ) -> Result<(), PSP22Error> { - call::<()>( - session, - "PSP22Burnable::burn", - vec![account.to_string(), amount.to_string()], - None, - ) - } +fn token_symbol(session: &mut Session) -> Option { + call::, PSP22Error>(session, "PSP22Metadata::token_symbol", vec![], None) + .unwrap() +} - /// Call a contract method and decode the returned data. - pub(super) fn call( - session: &mut Session, - func_name: &str, - input: Vec, - endowment: Option, - ) -> Result { - match session.call::(func_name, &input, endowment) { - // If the call is reverted, decode the error into `PSP22Error`. - Err(SessionError::CallReverted(error)) => { - Err(PSP22Error::decode(&mut &error[2..]) - .unwrap_or_else(|_| panic!("Decoding failed"))) - }, - // If the call is successful, decode the last returned value. - Ok(_) => Ok(session - .record() - .last_call_return_decoded::() - .unwrap_or_else(|_| panic!("Expected a return value")) - .unwrap_or_else(|_| panic!("Decoding failed"))), - // Catch-all for unexpected results. - _ => panic!("Expected call to revert or return a value"), - } - } +fn token_decimals(session: &mut Session) -> u8 { + call::(session, "PSP22Metadata::token_decimals", vec![], None).unwrap() +} - /// Convert into `PSP22Error::Custom` error type. - pub(super) fn into_psp22_custom(err: T) -> PSP22Error { - let mut padded_vec = err.encode().to_vec(); - padded_vec.resize(4, 0); - // Convert the `Vec`` to value of `StatusCode`. - let array: [u8; 4] = padded_vec.try_into().map_err(|_| "Invalid length").unwrap(); - let status_code = u32::from_le_bytes(array); - PSP22Error::Custom(status_code.to_string()) - } +fn mint(session: &mut Session, account: AccountId, amount: Balance) -> Result<(), PSP22Error> { + call::( + session, + "PSP22Mintable::mint", + vec![account.to_string(), amount.to_string()], + None, + ) +} - /// This is used to resolve type mismatches between the `AccountId` in the quasi testing - /// environment and the contract environment. - pub(super) fn account_id_from_slice(s: &[u8; 32]) -> AccountId { - AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") - } +fn burn(session: &mut Session, account: AccountId, amount: Balance) -> Result<(), PSP22Error> { + call::( + session, + "PSP22Burnable::burn", + vec![account.to_string(), amount.to_string()], + None, + ) +} - /// Get the last event from pallet contracts. - pub(super) fn last_contract_event(session: &Session) -> Option> { - session.record().last_event_batch().contract_events().last().cloned() - } +// Convert into `PSP22Error::Custom` error type. +fn into_psp22_custom(err: T) -> PSP22Error { + let mut padded_vec = err.encode().to_vec(); + padded_vec.resize(4, 0); + // Convert the `Vec` to value of `StatusCode`. + let array: [u8; 4] = padded_vec.try_into().map_err(|_| "Invalid length").unwrap(); + let status_code = u32::from_le_bytes(array); + PSP22Error::Custom(status_code.to_string()) } diff --git a/pop-sandbox/Cargo.toml b/pop-sandbox/Cargo.toml deleted file mode 100644 index 7a65f593..00000000 --- a/pop-sandbox/Cargo.toml +++ /dev/null @@ -1,50 +0,0 @@ -[package] -authors = [ "[your_name] <[your_email]>" ] -description = "Sandboxing environment for contract quasi testing with Pop Network runtimes." -edition = "2021" -license = "GPL-3.0-only" -name = "pop-sandbox" -version = "0.0.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", -] } -log = { version = "0.4.21", default-features = false } -scale-info = { version = "2.11", default-features = false } - -drink = { path = "../../pop-drink/drink", default-features = true } - -# Substrate -frame-metadata = { version = "16.0.0", default-features = false } -frame-support = { version = "36.0.0", default-features = false } -frame-support-procedural = { version = "=30.0.1", default-features = false } -frame-system = { version = "36.1.0", default-features = false } -pallet-assets = { version = "37.0.0", default-features = false } -pallet-balances = { version = "37.0.0", default-features = false } -pallet-contracts = { version = "35.0.0", default-features = false } -pallet-timestamp = { version = "35.0.0", default-features = false } -pop-runtime-devnet = { path = "../runtime/devnet", default-features = false } -sp-io = { version = "37.0.0", default-features = false } -sp-runtime = { version = "=38.0.0", default-features = false } - -[lib] -crate-type = [ "rlib" ] -name = "pop_sandbox" -path = "src/lib.rs" - -[features] -default = [ "std" ] -std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "pallet-assets/std", - "pallet-balances/std", - "pallet-contracts/std", - "pallet-timestamp/std", - "pop-runtime-devnet/std", - "scale-info/std", - "sp-io/std", - "sp-runtime/std", -] diff --git a/pop-sandbox/README.md b/pop-sandbox/README.md deleted file mode 100644 index cacfdc22..00000000 --- a/pop-sandbox/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Pop Sandbox - -Implementation of the [`pop_drink::Sandbox`](https://github.com/r0gue-io/pop-drink) struct for the Pop Network runtimes (located in `pop-node/runtime`) required for the quasi testing with `drink`. - -In the context of quasi-testing with pop-drink, a sandbox refers to an isolated runtime environment that simulates the behavior of a full node, without requiring an actual node. It can emulate key processes (where runtime `pallets` are involved) such as block initialization, execution, and block finalization. - -## Getting Started - -### Installation - -```toml -pop_drink = { version = "1.0.0", package = "pop-drink" } -``` - -### Import Sandbox for the specific runtime - -- For `devnet` runtime - -Implementation of the sandbox runtime environment for `devnet` runtime located in `pop-node/runtime/devnet` - -```rs -use pop_sandbox::DevnetSandbox; -``` - -- For `testnet` runtime - -Implementation of the sandbox runtime environment for `testnet` runtime located in `pop-node/runtime/testnet` - -```rs -use pop_sandbox::TestnetSandbox; -``` - -- For `mainnet` runtime - -Implementation of the sandbox runtime environment for `mainnet` runtime located in `pop-node/runtime/mainnet` - -```rs -use pop_sandbox::MainnetSandbox; -``` - -### Setup test environment for your contract - -Below is an example for the contract testing with `pop_drink` and `pop_sandbox` for `devnet` environment using `DevnetSandbox`. - -```rs -use pop_drink::session::Session; -use pop_sandbox::DevnetSandbox as Sandbox; - -#[drink::contract_bundle_provider] -enum BundleProvider {} - -#[drink::test(sandbox = Sandbox)] -fn test(mut session: Session) { - // Your test case -} -``` - -## Examples - -Please find more examples of `pop_drink` tests in the [`pop_drink/examples`](https://github.com/r0gue-io/pop-drink/tree/main/examples). diff --git a/pop-sandbox/examples/.gitignore b/pop-sandbox/examples/.gitignore deleted file mode 100644 index d60800c8..00000000 --- a/pop-sandbox/examples/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Ignore build artifacts from the local tests sub-crate. -**/target/ - -# Ignore backup files creates by cargo fmt. -**/*.rs.bk - -# Remove Cargo.lock when creating an executable, leave it for libraries -# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock -**/Cargo.lock diff --git a/pop-sandbox/examples/flipper/Cargo.toml b/pop-sandbox/examples/flipper/Cargo.toml deleted file mode 100644 index 1080f85e..00000000 --- a/pop-sandbox/examples/flipper/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -authors = [ "R0GUE " ] -edition = "2021" -name = "api_example_flipper" -version = "0.1.0" - -[dependencies] -ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } - -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", -] } -scale-info = { version = "2.6", default-features = false, features = [ - "derive", -], optional = true } - -[dev-dependencies] -drink = { path = "../../../../pop-drink/drink" } -env_logger = { version = "0.11.3" } -pop-sandbox = { path = "../../../pop-sandbox", default-features = false } - -[lib] -path = "lib.rs" - -[features] -default = [ "std" ] -ink-as-dependency = [ ] -std = [ "ink/std", "pop-sandbox/std", "scale-info/std", "scale/std" ] diff --git a/pop-sandbox/examples/flipper/lib.rs b/pop-sandbox/examples/flipper/lib.rs deleted file mode 100644 index c26c6ead..00000000 --- a/pop-sandbox/examples/flipper/lib.rs +++ /dev/null @@ -1,169 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -/// This is the classical flipper contract. It stores a single `bool` value in its storage. The -/// contract exposes: -/// - a constructor (`new`) that initializes the `bool` value to the given value, -/// - a message `flip` that flips the stored `bool` value from `true` to `false` or vice versa, -/// - a getter message `get` that returns the current `bool` value. -/// -/// Additionally, we use the `debug_println` macro from the `ink_env` crate to produce some debug -/// logs from the contract. -#[ink::contract] -mod flipper { - use ink::env::debug_println; - - #[ink(storage)] - pub struct Flipper { - value: bool, - } - - impl Flipper { - #[ink(constructor, payable)] - pub fn new(init: bool) -> Self { - debug_println!("Initializing contract with: `{init}`"); - Self { value: init } - } - - #[ink(message)] - pub fn flip(&mut self) { - debug_println!("Previous value: `{}`", self.value); - self.value = !self.value; - debug_println!("Flipped to: `{}`", self.value); - } - - #[ink(message)] - pub fn get(&self) -> bool { - debug_println!("Reading value from storage"); - self.value - } - } -} - -/// We put `drink`-based tests as usual unit tests, into a test module. -#[cfg(test)] -mod tests { - use drink::{ - sandbox_api::contracts_api::decode_debug_buffer, - session::{Session, NO_ARGS, NO_SALT}, - }; - - /// `drink` automatically discovers all the contract projects that your tests will need. For - /// every such dependency (including the contract from the current crate), it will generate a - /// [`ContractBundle`](drink::session::ContractBundle) object that contains the compiled - /// contract's code and a special transcoder, which is used to encode and decode the contract's - /// message arguments. Such a bundle will be useful when deploying a contract. - /// - /// To get a convenient way for obtaining such bundles, we can define an empty enum and mark - /// it with the [`drink::contract_bundle_provider`](drink::contract_bundle_provider) attribute. - /// From now on, we can use it in all testcases in this module. - #[drink::contract_bundle_provider] - enum BundleProvider {} - - /// Now we write the simplest contract test, that will: - /// 1. Deploy the contract. - /// 2. Call its `flip` method. - /// 3. Call its `get` method and ensure that the stored value has been flipped. - /// - /// We can use the [`drink::test`](drink::test) attribute to mark a function as a `drink` test. - /// This way we ensure that all the required contracts are compiled and built, so that we don't - /// have to run `cargo contract build` manually for every contract dependency. - /// - /// For convenience of using `?` operator, we mark the test function as returning a `Result`. - /// - /// `drink::test` will already provide us with a `Session` object. It is a wrapper around a - /// runtime and it exposes a broad API for interacting with it. Session is generic over the - /// runtime type, but usually and by default, we use `MinimalSandbox`, which is a minimalistic - /// runtime that allows using smart contracts. - #[drink::test(sandbox = pop_sandbox::DevnetSandbox)] - fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { - let _ = env_logger::try_init(); - // Now we get the contract bundle from the `BundleProvider` enum. Since the current crate - // comes with a contract, we can use the `local` method to get the bundle for it. - let contract_bundle = BundleProvider::local()?; - - // We can now deploy the contract. - let _contract_address = session.deploy_bundle( - // The bundle that we want to deploy. - contract_bundle, - // The constructor that we want to call. - "new", - // The constructor arguments (as stringish objects). - &["true"], - // Salt for the contract address derivation. - NO_SALT, - // Initial endowment (the amount of tokens that we want to transfer to the contract). - None, - )?; - - // Once the contract is instantiated, we can call the `flip` method on the contract. - session.call( - // The message that we want to call. - "flip", - // The message arguments (as stringish objects). If none, then we can use the `NO_ARGS` - // constant, which spares us from typing `&[]`. - NO_ARGS, - // Endowment (the amount of tokens that we want to transfer to the contract). - None, - )??; - - // Finally, we can call the `get` method on the contract and ensure that the value has been - // flipped. - // - // `Session::call` returns a `Result, SessionError>`, where `T` is the - // type of the message result. In this case, the `get` message returns a `bool`, and we have - // to explicitly hint the compiler about it. - let result: bool = session.call("get", NO_ARGS, None)??; - assert_eq!(result, false); - - Ok(()) - } - - /// In this testcase we will see how to get and read debug logs from the contract. - #[drink::test(sandbox = pop_sandbox::DevnetSandbox)] - fn get_debug_logs(mut session: Session) -> Result<(), Box> { - session.deploy_bundle(BundleProvider::local()?, "new", &["true"], NO_SALT, None)?; - - // `deploy_bundle` returns just a contract address. If we are interested in more details - // about last operation (either deploy or call), we can get a `Record` object and use its - // `last_deploy_result` (or analogously `last_call_result`) method, which will provide us - // with a full report from the last contract interaction. - // - // In particular, we can get the decoded debug buffer from the contract. The buffer is - // just a vector of bytes, which we can decode using the `decode_debug_buffer` function. - let decoded_buffer = &session.record().last_deploy_result().debug_message; - let encoded_buffer = decode_debug_buffer(decoded_buffer); - - assert_eq!(encoded_buffer, vec!["Initializing contract with: `true`"]); - - Ok(()) - } - - /// In this testcase we will see how to work with multiple contracts. - #[drink::test(sandbox = pop_sandbox::DevnetSandbox)] - fn work_with_multiple_contracts( - mut session: Session, - ) -> Result<(), Box> { - let bundle = BundleProvider::local()?; - - // We can deploy the same contract multiple times. However, we have to ensure that the - // derived contract addresses are different. We can do this by providing using different - // arguments for the constructor or by providing a different salt. - let first_address = - session.deploy_bundle(bundle.clone(), "new", &["true"], NO_SALT, None)?; - let _second_address = - session.deploy_bundle(bundle.clone(), "new", &["true"], vec![0], None)?; - let _third_address = session.deploy_bundle(bundle, "new", &["false"], NO_SALT, None)?; - - // By default, when we run `session.call`, `drink` will interact with the last deployed - // contract. - let value_at_third_contract: bool = session.call("get", NO_ARGS, None)??; - assert_eq!(value_at_third_contract, false); - - // However, we can also call a specific contract by providing its address. - let value_at_first_contract: bool = - session.call_with_address(first_address, "get", NO_ARGS, None)??; - assert_eq!(value_at_first_contract, true); - - Ok(()) - } -} diff --git a/pop-sandbox/src/lib.rs b/pop-sandbox/src/lib.rs deleted file mode 100644 index ad15cf90..00000000 --- a/pop-sandbox/src/lib.rs +++ /dev/null @@ -1,88 +0,0 @@ -pub use frame_support::sp_runtime::AccountId32; -use frame_support::{ - sp_runtime::traits::{Header, One}, - traits::Hooks, -}; -use frame_system::pallet_prelude::BlockNumberFor; -pub use pop_runtime_devnet::Balance; -use pop_runtime_devnet::{BuildStorage, Runtime}; - -/// Alias for the account ID type. -pub type AccountIdFor = ::AccountId; - -/// Default initial balance for the default account. -pub const UNIT: Balance = 10_000_000_000; -pub const INIT_AMOUNT: Balance = 100_000_000 * UNIT; -pub const INIT_VALUE: Balance = 100 * UNIT; -pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); -pub const BOB: AccountId32 = AccountId32::new([2_u8; 32]); -pub const CHARLIE: AccountId32 = AccountId32::new([3_u8; 32]); - -/// A helper struct for initializing and finalizing blocks. -pub struct BlockBuilder(std::marker::PhantomData); - -impl< - T: pallet_balances::Config + pallet_timestamp::Config + pallet_contracts::Config, - > BlockBuilder -{ - /// Create a new externalities with the given balances. - pub fn new_ext(balances: Vec<(T::AccountId, T::Balance)>) -> sp_io::TestExternalities { - let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - pallet_balances::GenesisConfig:: { balances } - .assimilate_storage(&mut storage) - .unwrap(); - - let mut ext = sp_io::TestExternalities::new(storage); - - ext.execute_with(|| Self::initialize_block(BlockNumberFor::::one(), Default::default())); - ext - } - - /// Initialize a new block at particular height. - pub fn initialize_block( - height: frame_system::pallet_prelude::BlockNumberFor, - parent_hash: ::Hash, - ) { - frame_system::Pallet::::reset_events(); - frame_system::Pallet::::initialize(&height, &parent_hash, &Default::default()); - pallet_balances::Pallet::::on_initialize(height); - // TODO: Resolve an issue with pallet-aura to simulate the time: Timestamp slot must match `CurrentSlot` - // pallet_timestamp::Pallet::::set_timestamp( - // SystemTime::now() - // .duration_since(SystemTime::UNIX_EPOCH) - // .expect("Time went backwards") - // .as_secs(), - // ); - pallet_timestamp::Pallet::::on_initialize(height); - pallet_contracts::Pallet::::on_initialize(height); - frame_system::Pallet::::note_finished_initialize(); - } - - /// Finalize a block at particular height. - pub fn finalize_block( - height: frame_system::pallet_prelude::BlockNumberFor, - ) -> ::Hash { - pallet_contracts::Pallet::::on_finalize(height); - pallet_timestamp::Pallet::::on_finalize(height); - pallet_balances::Pallet::::on_finalize(height); - frame_system::Pallet::::finalize().hash() - } -} - -/// Sandbox runtime environment for `devnet` runtime. -pub struct DevnetSandbox { - ext: sp_io::TestExternalities, -} - -impl Default for DevnetSandbox { - fn default() -> Self { - let balances: Vec<(AccountId32, u128)> = - vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)]; - let ext = BlockBuilder::::new_ext(balances); - Self { ext } - } -} - -/// Implement core functionalities of the `DevnetSandbox`. -drink::impl_sandbox!(DevnetSandbox, Runtime, BlockBuilder, ALICE); diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 16f168fa..f539cbde 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -291,6 +291,9 @@ impl pallet_timestamp::Config for Runtime { type MinimumPeriod = ConstU64<0>; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; + #[cfg(feature = "std")] + type OnTimestampSet = (); + #[cfg(not(feature = "std"))] type OnTimestampSet = Aura; type WeightInfo = (); } From 1857ea6ec3948f138eb66ac0b1a9aafec7bc87a8 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Tue, 1 Oct 2024 14:12:59 +0700 Subject: [PATCH 143/161] fix: resolve example contract issues (#315) Co-authored-by: Daanvdplas --- pop-api/examples/fungibles/tests.rs | 440 ++++++++++++++++++++-------- pop-api/src/v0/fungibles/errors.rs | 11 +- 2 files changed, 315 insertions(+), 136 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index fd0a8cc4..2c5b490b 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -56,15 +56,6 @@ drink::impl_sandbox!(Pop, Runtime, ALICE); #[drink::test(sandbox = Pop)] fn new_constructor_works(mut session: Session) { let _ = env_logger::try_init(); - // Fails to deploy contract with an used token ID. - let token = TOKEN + 1; - assert_ok!(session.sandbox().create(&token, &ALICE, MIN_BALANCE)); - // `pallet-assets` returns `InUse` error. - assert_eq!( - deploy(&mut session, "new", vec![token.to_string(), MIN_BALANCE.to_string()],), - Err(into_psp22_custom(Module { index: 52, error: [5, 0] })) - ); - // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); @@ -84,14 +75,21 @@ fn new_constructor_works(mut session: Session) { } #[drink::test(sandbox = Pop)] -fn existing_constructor_works(mut session: Session) { +fn new_constructor_fails_with_used_token() { let _ = env_logger::try_init(); - // Fails to deploy contract with a non-existing token ID. + // Fails to deploy contract with an used token ID. + let token = TOKEN + 1; + assert_ok!(session.sandbox().create(&token, &ALICE, MIN_BALANCE)); + // `pallet-assets` returns `InUse` error. assert_eq!( deploy(&mut session, "existing", vec![TOKEN.to_string()]), Err(PSP22Error::Custom(String::from("Token does not exist"))) ); +} +#[drink::test(sandbox = Pop)] +fn existing_constructor_works(mut session: Session) { + let _ = env_logger::try_init(); // Successfully deploy contract with an existing token ID. let actor = session.get_actor(); assert_ok!(session.sandbox().create(&TOKEN, &actor, MIN_BALANCE)); @@ -99,6 +97,16 @@ fn existing_constructor_works(mut session: Session) { assert!(session.sandbox().asset_exists(&TOKEN)); } +#[drink::test(sandbox = Pop)] +fn existing_constructor_fails_with_non_existing_token(&mut session: Session) { + let _ = env_logger::try_init(); + // Fails to deploy contract with a non-existing token ID. + assert_eq!( + deploy(&mut session, "existing", vec![TOKEN.to_string()]), + Err(PSP22Error::Custom(String::from("Token does not exist"))) + ); +} + // 1. PSP-22 Interface: // - total_supply // - balance_of @@ -114,11 +122,9 @@ fn total_supply_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. assert_ok!(deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()],)); - // No tokens in circulation. assert_eq!(total_supply(&mut session), 0); assert_eq!(total_supply(&mut session), session.sandbox().total_supply(&TOKEN)); - // Tokens in circulation. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); assert_eq!(total_supply(&mut session), AMOUNT); @@ -130,11 +136,9 @@ fn balance_of_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. assert_ok!(deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()])); - // No tokens in circulation. assert_eq!(balance_of(&mut session, ALICE), 0); assert_eq!(balance_of(&mut session, ALICE), session.sandbox().balance_of(&TOKEN, &ALICE)); - // Tokens in circulation. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); assert_eq!(balance_of(&mut session, ALICE), AMOUNT); @@ -147,43 +151,83 @@ fn allowance_works(mut session: Session) { // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - // No tokens in circulation. assert_eq!(allowance(&mut session, contract.clone(), ALICE), 0); - // Tokens in circulation. assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT / 2)); assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2); } #[drink::test(sandbox = Pop)] -fn transfer_works(mut session: Session) { +fn transfer_fails_with_no_account() { let _ = env_logger::try_init(); // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - let value = AMOUNT / 4; session.set_actor(contract.clone()); // `pallet-assets` returns `NoAccount` error. assert_eq!( - transfer(&mut session, ALICE, value), + transfer(&mut session, ALICE, AMOUNT), Err(into_psp22_custom(Module { index: 52, error: [1, 0] })) ); +} - // Mint tokens. - assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); - - // No-op if `value` is zero. +#[drink::test(sandbox = Pop)] +fn transfer_noop_works(&mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // No-op if `value` is zero, returns success and no events are emitted. assert_ok!(transfer(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - + assert_eq!(last_contract_event(&session), None); // No-op if the caller and `to` is the same address, returns success and no events are emitted. - assert_ok!(transfer(&mut session, contract.clone(), value)); - assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_ok!(transfer(&mut session, contract.clone(), AMOUNT)); + assert_eq!(last_contract_event(&session), None); +} +#[drink::test(sandbox = Pop)] +fn transfer_fails_with_insufficient_balance() { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // Mint tokens. + assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); // Failed with `InsufficientBalance`. assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); +} +#[drink::test(sandbox = Pop)] +fn transfer_fails_with_token_not_live() { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // Mint tokens. + assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `AssetNotLive` error. + assert_eq!( + transfer(&mut session, BOB, AMOUNT / 2), + Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) + ); +} + +#[drink::test(sandbox = Pop)] +fn transfer_works(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + let value = AMOUNT / 4; + // Mint tokens. + assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); // Successfully transfer. assert_ok!(transfer(&mut session, BOB, value)); assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - value); @@ -199,51 +243,90 @@ fn transfer_works(mut session: Session) { .encode() .as_slice() ); +} - // Token is not live, i.e. frozen or being destroyed. - assert_ok!(session.sandbox().start_destroy(&TOKEN)); - // `pallet-assets` returns `AssetNotLive` error. - assert_eq!( - transfer(&mut session, BOB, value), - Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) - ); +#[drink::test(sandbox = Pop)] +fn transfer_from_noop_works() { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // No-op if `value` is zero, returns success and no events are emitted. + assert_ok!(transfer_from(&mut session, ALICE, BOB, 0)); + assert_eq!(last_contract_event(&session), None); + // No-op if the `from` and `to` is the same address, returns success and no events are emitted. + assert_ok!(transfer_from(&mut session, ALICE, ALICE, AMOUNT)); + assert_eq!(last_contract_event(&session), None); } #[drink::test(sandbox = Pop)] -fn transfer_from_works(mut session: Session) { +fn transfer_from_fails_with_insufficient_balance() { let _ = env_logger::try_init(); // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - let value = AMOUNT / 2; session.set_actor(contract.clone()); // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &ALICE, &contract.clone(), AMOUNT * 2)); - - // No-op if `value` is zero. - assert_ok!(transfer_from(&mut session, ALICE, BOB, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - - // No-op if the `from` and `to` is the same address, returns success and no events are emitted. - assert_ok!(transfer_from(&mut session, ALICE, ALICE, value)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - // Not enough balance. Failed with `InsufficientBalance`. assert_eq!( transfer_from(&mut session, ALICE, contract.clone(), AMOUNT + 1), Err(PSP22Error::InsufficientBalance) ); +} +#[drink::test(sandbox = Pop)] +fn transfer_from_fails_with_insufficient_allowance() { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // Mint tokens and approve. + assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); + assert_ok!(session.sandbox().approve(&TOKEN, &ALICE, &contract.clone(), AMOUNT)); // Unapproved transfer. Failed with `InsufficientAllowance`. assert_eq!( - transfer_from(&mut session, ALICE, contract.clone(), AMOUNT * 2 + 1), + transfer_from(&mut session, ALICE, contract.clone(), AMOUNT + 1), Err(PSP22Error::InsufficientAllowance) ); +} + +#[drink::test(sandbox = Pop)] +fn transfer_from_fails_with_token_not_live() { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // Mint tokens and approve. + assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); + assert_ok!(session.sandbox().approve(&TOKEN, &ALICE, &contract.clone(), AMOUNT)); + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `AssetNotLive` error. + assert_eq!( + transfer_from(&mut session, ALICE, BOB, AMOUNT / 2), + Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) + ); +} +#[drink::test(sandbox = Pop)] +fn transfer_from_works(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + let value = AMOUNT / 2; + // Mint tokens and approve. + assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); + assert_ok!(session.sandbox().approve(&TOKEN, &ALICE, &contract.clone(), AMOUNT)); // Successful transfer. assert_ok!(transfer_from(&mut session, ALICE, BOB, value)); - assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), AMOUNT + value); + assert_eq!(session.sandbox().allowance(&TOKEN, &ALICE, &contract.clone()), value); assert_eq!(session.sandbox().balance_of(&TOKEN, &ALICE), value); assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), value); // Successfully emit event. @@ -252,17 +335,38 @@ fn transfer_from_works(mut session: Session) { Approval { owner: account_id_from_slice(&ALICE), spender: account_id_from_slice(&contract), - value: AMOUNT + value, + value, } .encode() .as_slice() ); +} +#[drink::test(sandbox = Pop)] +fn approve_noop_works(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. + assert_ok!(approve(&mut session, contract.clone(), AMOUNT)); + assert_eq!(last_contract_event(&session), None); +} + +#[drink::test(sandbox = Pop)] +fn approve_fails_with_token_not_live(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. assert_eq!( - transfer_from(&mut session, ALICE, BOB, value), + approve(&mut session, ALICE, AMOUNT), Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) ); } @@ -273,16 +377,10 @@ fn approve_works(mut session: Session) { // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - let value = AMOUNT / 2; session.set_actor(contract.clone()); + let value = AMOUNT / 2; // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); - - // No-op if the caller and `spender` is the same address, returns success and no events are - // emitted. - assert_ok!(approve(&mut session, contract.clone(), value)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - // Successfully approve. assert_ok!(approve(&mut session, ALICE, value)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), value); @@ -297,7 +395,6 @@ fn approve_works(mut session: Session) { .encode() .as_slice() ); - // Non-additive, sets new value. assert_ok!(approve(&mut session, ALICE, value - 1)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), value - 1); @@ -312,12 +409,35 @@ fn approve_works(mut session: Session) { .encode() .as_slice() ); +} + +#[drink::test(sandbox = Pop)] +fn increase_allowance_noop_works(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // No-op if the caller and `spender` is the same address, returns success and no events are emitted. + assert_ok!(increase_allowance(&mut session, contract.clone(), AMOUNT)); + assert_eq!(last_contract_event(&session), None); + // No-op if the `value` is zero, returns success and no events are emitted. + assert_ok!(increase_allowance(&mut session, contract.clone(), 0)); + assert_eq!(last_contract_event(&session), None); +} +#[drink::test(sandbox = Pop)] +fn increase_allowance_fails_with_token_not_live(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. assert_eq!( - approve(&mut session, ALICE, value), + increase_allowance(&mut session, ALICE, AMOUNT), Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) ); } @@ -328,21 +448,11 @@ fn increase_allowance_works(mut session: Session) { // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - let value = AMOUNT / 2; session.set_actor(contract.clone()); + let value = AMOUNT / 2; // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT)); - - // No-op if the caller and `spender` is the same address, returns success and no events are - // emitted. - assert_ok!(increase_allowance(&mut session, contract.clone(), value)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - - // No-op if the `value` is zero. - assert_ok!(increase_allowance(&mut session, contract.clone(), 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - // Successfully approve. assert_ok!(increase_allowance(&mut session, ALICE, value)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT + value); @@ -357,7 +467,6 @@ fn increase_allowance_works(mut session: Session) { .encode() .as_slice() ); - // Additive. assert_ok!(increase_allowance(&mut session, ALICE, value)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT + value * 2); @@ -372,12 +481,50 @@ fn increase_allowance_works(mut session: Session) { .encode() .as_slice() ); +} +#[drink::test(sandbox = Pop)] +fn decrease_allowance_noop_works(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. + assert_ok!(decrease_allowance(&mut session, contract.clone(), AMOUNT)); + assert_eq!(last_contract_event(&session), None); +} + +#[drink::test(sandbox = Pop)] +fn decrease_allowance_fails_with_insufficient_allowance(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // Failed with `InsufficientAllowance`. + assert_eq!( + decrease_allowance(&mut session, ALICE, AMOUNT), + Err(PSP22Error::InsufficientAllowance) + ); +} + +#[drink::test(sandbox = Pop)] +fn decrease_allowance_fails_with_token_not_live(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // Mint tokens and approve. + assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); + assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT)); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. assert_eq!( - increase_allowance(&mut session, ALICE, value), + decrease_allowance(&mut session, ALICE, AMOUNT), Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) ); } @@ -388,23 +535,11 @@ fn decrease_allowance_works(mut session: Session) { // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - let value = 1; session.set_actor(contract.clone()); + let value = 1; // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT)); - - // No-op if the caller and `spender` is the same address, returns success and no events are - // emitted. - assert_ok!(decrease_allowance(&mut session, contract.clone(), value)); - assert_eq!(last_contract_event(&session), None); // No event emitted. - - // Failed with `InsufficientAllowance`. - assert_eq!( - decrease_allowance(&mut session, ALICE, AMOUNT + value), - Err(PSP22Error::InsufficientAllowance) - ); - // Successfully approve. assert_ok!(decrease_allowance(&mut session, ALICE, value)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT - value); @@ -419,7 +554,6 @@ fn decrease_allowance_works(mut session: Session) { .encode() .as_slice() ); - // Additive. assert_ok!(decrease_allowance(&mut session, ALICE, value)); assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), AMOUNT - value * 2); @@ -434,14 +568,6 @@ fn decrease_allowance_works(mut session: Session) { .encode() .as_slice() ); - - // Token is not live, i.e. frozen or being destroyed. - assert_ok!(session.sandbox().start_destroy(&TOKEN)); - // `pallet-assets` returns `AssetNotLive` error. - assert_eq!( - decrease_allowance(&mut session, ALICE, value), - Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) - ); } // 2. PSP-22 Metadata Interface: @@ -455,16 +581,14 @@ fn token_metadata(mut session: Session) { // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); let name: String = String::from("Paseo Token"); let symbol: String = String::from("PAS"); let decimals: u8 = 69; - - session.set_actor(contract.clone()); // Token does not exist. assert_eq!(token_name(&mut session), None); assert_eq!(token_symbol(&mut session), None); assert_eq!(token_decimals(&mut session), 0); - // Set token metadata. let actor = session.get_actor(); assert_ok!(session.sandbox().set_metadata( @@ -483,10 +607,10 @@ fn token_metadata(mut session: Session) { // - mint #[drink::test(sandbox = Pop)] -fn mint_works(mut session: Session) { +fn mint_fails_with_no_permission(mut session: Session) { let _ = env_logger::try_init(); // No permission to mint. - // Create a new tokenowned by `BOB`. + // Create a new token owned by `BOB`. assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); assert_ok!(deploy(&mut session, "existing", vec![(TOKEN + 1).to_string()])); // `pallet-assets` returns `NoPermission` error. @@ -494,17 +618,56 @@ fn mint_works(mut session: Session) { mint(&mut session, BOB, AMOUNT), Err(into_psp22_custom(Module { index: 52, error: [2, 0] })) ); +} +#[drink::test(sandbox = Pop)] +fn mint_noop_works(mut session: Session) { + let _ = env_logger::try_init(); // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - let value = AMOUNT; session.set_actor(contract.clone()); - - // No-op if minted value is zero. + // No-op if minted value is zero, returns success and no events are emitted. assert_ok!(mint(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(last_contract_event(&session), None); +} + +#[drink::test(sandbox = Pop)] +fn mint_fails_with_arithmetic_overflow(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + assert_ok!(mint(&mut session, ALICE, AMOUNT)); + // Total supply increased by `value` exceeds maximal value of `u128` type. + assert_eq!(mint(&mut session, ALICE, u128::MAX), Err(into_psp22_custom(Arithmetic(Overflow)))); +} + +#[drink::test(sandbox = Pop)] +fn mint_fails_with_token_not_live(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `AssetNotLive` error. + assert_eq!( + mint(&mut session, ALICE, AMOUNT), + Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) + ); +} +#[drink::test(sandbox = Pop)] +fn mint_works(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + let value = AMOUNT; // Successfully mint tokens. assert_ok!(mint(&mut session, ALICE, value)); assert_eq!(session.sandbox().total_supply(&TOKEN), value); @@ -516,24 +679,13 @@ fn mint_works(mut session: Session) { .encode() .as_slice() ); - - // Total supply increased by `value` exceeds maximal value of `u128` type. - assert_eq!(mint(&mut session, ALICE, u128::MAX), Err(into_psp22_custom(Arithmetic(Overflow)))); - - // Token is not live, i.e. frozen or being destroyed. - assert_ok!(session.sandbox().start_destroy(&TOKEN)); - // `pallet-assets` returns `AssetNotLive` error. - assert_eq!( - mint(&mut session, ALICE, value), - Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) - ); } // 4. PSP-22 Burnable Interface: // - burn #[drink::test(sandbox = Pop)] -fn burn_works(mut session: Session) { +fn burn_fails_with_no_permission(mut session: Session) { let _ = env_logger::try_init(); // No permission to burn. // Create a new token owned by `BOB`. @@ -545,22 +697,58 @@ fn burn_works(mut session: Session) { burn(&mut session, BOB, AMOUNT), Err(into_psp22_custom(Module { index: 52, error: [2, 0] })) ); +} +#[drink::test(sandbox = Pop)] +fn burn_noop_works(mut session: Session) { + let _ = env_logger::try_init(); // Deploy a new contract. let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - let value = 1; session.set_actor(contract.clone()); - // Mint tokens. - assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); - - // No-op. + // No-op if burned value is zero, returns success and no events are emitted. assert_ok!(burn(&mut session, ALICE, 0)); - assert_eq!(last_contract_event(&session), None); // No event emitted. + assert_eq!(last_contract_event(&session), None); +} +#[drink::test(sandbox = Pop)] +fn burn_fails_with_insufficient_balance(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); // Failed with `InsufficientBalance`. - assert_eq!(burn(&mut session, ALICE, AMOUNT * 2), Err(PSP22Error::InsufficientBalance)); + assert_eq!(burn(&mut session, ALICE, AMOUNT), Err(PSP22Error::InsufficientBalance)); +} +#[drink::test(sandbox = Pop)] +fn burn_fails_with_token_not_live(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); + // Token is not live, i.e. frozen or being destroyed. + assert_ok!(session.sandbox().start_destroy(&TOKEN)); + // `pallet-assets` returns `IncorrectStatus` error. + assert_eq!( + burn(&mut session, ALICE, AMOUNT), + Err(into_psp22_custom(Module { index: 52, error: [17, 0] })) + ); +} + +#[drink::test(sandbox = Pop)] +fn burn_works(mut session: Session) { + let _ = env_logger::try_init(); + // Deploy a new contract. + let contract = + deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + session.set_actor(contract.clone()); + let value = 1; + // Mint tokens. + assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); // Successfully burn tokens. assert_ok!(burn(&mut session, ALICE, value)); assert_eq!(session.sandbox().total_supply(&TOKEN), AMOUNT - value); @@ -572,14 +760,6 @@ fn burn_works(mut session: Session) { .encode() .as_slice() ); - - // Token is not live, i.e. frozen or being destroyed. - assert_ok!(session.sandbox().start_destroy(&TOKEN)); - // `pallet-assets` returns `IncorrectStatus` error. - assert_eq!( - burn(&mut session, ALICE, value), - Err(into_psp22_custom(Module { index: 52, error: [17, 0] })) - ); } // Deploy the contract with `NO_SALT and `INIT_VALUE`. diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 12bc596c..06e7d545 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -2,7 +2,10 @@ //! errors compliant to standards. use super::*; -use ink::prelude::string::{String, ToString}; +use ink::{ + prelude::string::{String, ToString}, + scale::{Decode, Encode}, +}; /// Represents various errors related to fungible tokens. /// @@ -104,7 +107,7 @@ impl From for PSP22Error { #[cfg(test)] mod tests { - use super::{FungiblesError, PSP22Error}; + use super::*; use crate::{ constants::{ASSETS, BALANCES}, primitives::{ @@ -115,10 +118,6 @@ mod tests { }, StatusCode, }; - use ink::{ - prelude::string::String, - scale::{Decode, Encode}, - }; fn error_into_status_code(error: Error) -> StatusCode { let mut encoded_error = error.encode(); From eee369ae90b9350bfeea36a665f70f9472d01483 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Thu, 3 Oct 2024 09:51:57 +0700 Subject: [PATCH 144/161] feat: add function selectors to psp22 trait (#316) Co-authored-by: Daanvdplas --- pop-api/examples/fungibles/lib.rs | 10 +++--- pop-api/examples/fungibles/tests.rs | 26 ++++++++-------- pop-api/src/v0/fungibles/traits.rs | 47 ++++++++++++++++++----------- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 9787a43a..6f894349 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -6,7 +6,7 @@ use pop_api::{ v0::fungibles::{ self as api, events::{Approval, Created, Transfer}, - traits::{PSP22Burnable, PSP22Metadata, PSP22Mintable, PSP22}, + traits::{Psp22, Psp22Burnable, Psp22Metadata, Psp22Mintable}, PSP22Error, }, }; @@ -57,7 +57,7 @@ mod fungibles { } } - impl PSP22 for Fungible { + impl Psp22 for Fungible { /// Returns the total token supply. #[ink(message)] fn total_supply(&self) -> Balance { @@ -210,7 +210,7 @@ mod fungibles { } } - impl PSP22Metadata for Fungible { + impl Psp22Metadata for Fungible { /// Returns the token name. #[ink(message)] fn token_name(&self) -> Option { @@ -236,7 +236,7 @@ mod fungibles { } } - impl PSP22Mintable for Fungible { + impl Psp22Mintable for Fungible { /// Creates `value` amount of tokens and assigns them to `account`, increasing the total /// supply. /// @@ -255,7 +255,7 @@ mod fungibles { } } - impl PSP22Burnable for Fungible { + impl Psp22Burnable for Fungible { /// Destroys `value` amount of tokens from `account`, reducing the total supply. /// /// # Parameters diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 2c5b490b..c985024f 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -782,18 +782,18 @@ fn deploy( // A set of helper methods to test the contract calls. fn total_supply(session: &mut Session) -> Balance { - call::(session, "PSP22::total_supply", vec![], None).unwrap() + call::(session, "Psp22::total_supply", vec![], None).unwrap() } fn balance_of(session: &mut Session, owner: AccountId) -> Balance { - call::(session, "PSP22::balance_of", vec![owner.to_string()], None) + call::(session, "Psp22::balance_of", vec![owner.to_string()], None) .unwrap() } fn allowance(session: &mut Session, owner: AccountId, spender: AccountId) -> Balance { call::( session, - "PSP22::allowance", + "Psp22::allowance", vec![owner.to_string(), spender.to_string()], None, ) @@ -803,7 +803,7 @@ fn allowance(session: &mut Session, owner: AccountId, spender: AccountId) - fn transfer(session: &mut Session, to: AccountId, amount: Balance) -> Result<(), PSP22Error> { call::( session, - "PSP22::transfer", + "Psp22::transfer", vec![to.to_string(), amount.to_string(), serde_json::to_string::<[u8; 0]>(&[]).unwrap()], None, ) @@ -817,7 +817,7 @@ fn transfer_from( ) -> Result<(), PSP22Error> { call::( session, - "PSP22::transfer_from", + "Psp22::transfer_from", vec![ from.to_string(), to.to_string(), @@ -835,7 +835,7 @@ fn approve( ) -> Result<(), PSP22Error> { call::( session, - "PSP22::approve", + "Psp22::approve", vec![spender.to_string(), value.to_string()], None, ) @@ -848,7 +848,7 @@ fn increase_allowance( ) -> Result<(), PSP22Error> { call::( session, - "PSP22::increase_allowance", + "Psp22::increase_allowance", vec![spender.to_string(), value.to_string()], None, ) @@ -861,30 +861,30 @@ fn decrease_allowance( ) -> Result<(), PSP22Error> { call::( session, - "PSP22::decrease_allowance", + "Psp22::decrease_allowance", vec![spender.to_string(), value.to_string()], None, ) } fn token_name(session: &mut Session) -> Option { - call::, PSP22Error>(session, "PSP22Metadata::token_name", vec![], None) + call::, PSP22Error>(session, "Psp22Metadata::token_name", vec![], None) .unwrap() } fn token_symbol(session: &mut Session) -> Option { - call::, PSP22Error>(session, "PSP22Metadata::token_symbol", vec![], None) + call::, PSP22Error>(session, "Psp22Metadata::token_symbol", vec![], None) .unwrap() } fn token_decimals(session: &mut Session) -> u8 { - call::(session, "PSP22Metadata::token_decimals", vec![], None).unwrap() + call::(session, "Psp22Metadata::token_decimals", vec![], None).unwrap() } fn mint(session: &mut Session, account: AccountId, amount: Balance) -> Result<(), PSP22Error> { call::( session, - "PSP22Mintable::mint", + "Psp22Mintable::mint", vec![account.to_string(), amount.to_string()], None, ) @@ -893,7 +893,7 @@ fn mint(session: &mut Session, account: AccountId, amount: Balance) -> Resu fn burn(session: &mut Session, account: AccountId, amount: Balance) -> Result<(), PSP22Error> { call::( session, - "PSP22Burnable::burn", + "Psp22Burnable::burn", vec![account.to_string(), amount.to_string()], None, ) diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index fd9e6271..16867c32 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -1,21 +1,26 @@ //! Traits that can be used by contracts. Including standard compliant traits. -use super::*; use core::result::Result; + use ink::prelude::string::String; +use super::*; + +/// Function selectors as per the PSP22 standard: https://github.com/w3f/PSPs/blob/master/PSPs/psp-22.md. +/// The mint and burn selectors are not defined in the standard, but have been created in the same way. + /// The PSP22 trait. #[ink::trait_definition] -pub trait PSP22 { +pub trait Psp22 { /// Returns the total token supply. - #[ink(message)] + #[ink(message, selector = 0x162df8c2)] fn total_supply(&self) -> Balance; /// Returns the account balance for the specified `owner`. /// /// # Parameters /// - `owner` - The account whose balance is being queried. - #[ink(message)] + #[ink(message, selector = 0x6568382f)] fn balance_of(&self, owner: AccountId) -> Balance; /// Returns the allowance for a `spender` approved by an `owner`. @@ -23,7 +28,7 @@ pub trait PSP22 { /// # Parameters /// - `owner` - The account that owns the tokens. /// - `spender` - The account that is allowed to spend the tokens. - #[ink(message)] + #[ink(message, selector = 0x4d47d921)] fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance; /// Transfers `value` amount of tokens from the caller's account to account `to` @@ -33,7 +38,7 @@ pub trait PSP22 { /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. /// - `data` - Additional data in unspecified format. - #[ink(message)] + #[ink(message, selector = 0xdb20f9f5)] fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<(), PSP22Error>; /// Transfers `value` tokens on behalf of `from` to the account `to` @@ -44,7 +49,7 @@ pub trait PSP22 { /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. /// - `data` - Additional data with unspecified format. - #[ink(message)] + #[ink(message, selector = 0x54b3c76e)] fn transfer_from( &mut self, from: AccountId, @@ -60,7 +65,7 @@ pub trait PSP22 { /// # Parameters /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. - #[ink(message)] + #[ink(message, selector = 0xb20f1bbd)] fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; /// Increases the allowance of `spender` by `value` amount of tokens. @@ -68,7 +73,7 @@ pub trait PSP22 { /// # Parameters /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. - #[ink(message)] + #[ink(message, selector = 0x96d6b57a)] fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; /// Decreases the allowance of `spender` by `value` amount of tokens. @@ -76,46 +81,52 @@ pub trait PSP22 { /// # Parameters /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. - #[ink(message)] + #[ink(message, selector = 0xfecb57d5)] fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; } /// The PSP22 Metadata trait. #[ink::trait_definition] -pub trait PSP22Metadata { +pub trait Psp22Metadata { /// Returns the token name. - #[ink(message)] + #[ink(message, selector = 0x3d261bd4)] fn token_name(&self) -> Option; /// Returns the token symbol. - #[ink(message)] + #[ink(message, selector = 0x34205be5)] fn token_symbol(&self) -> Option; /// Returns the token decimals. - #[ink(message)] + #[ink(message, selector = 0x7271b782)] fn token_decimals(&self) -> u8; } /// The PSP22 Mintable trait. #[ink::trait_definition] -pub trait PSP22Mintable { +pub trait Psp22Mintable { /// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply. /// + /// The selector for this message is `0xfc3c75d4` (first 4 bytes of + /// `blake2b_256("PSP22Mintable::mint")`). + /// /// # Parameters /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. - #[ink(message)] + #[ink(message, selector = 0xfc3c75d4)] fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; } /// The PSP22 Burnable trait. #[ink::trait_definition] -pub trait PSP22Burnable { +pub trait Psp22Burnable { /// Destroys `value` amount of tokens from `account`, reducing the total supply. /// + /// The selector for this message is `0x7a9da510` (first 4 bytes of + /// `blake2b_256("PSP22Burnable::burn")`). + /// /// # Parameters /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. - #[ink(message)] + #[ink(message, selector = 0x7a9da510)] fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; } From 46612fba841c8ea83705290aa1b2890f5c85e4ea Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 3 Oct 2024 13:04:35 +0700 Subject: [PATCH 145/161] chore: merge main --- pallets/api/src/fungibles/mod.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index 28a6f956..bc36936c 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -517,12 +517,10 @@ pub mod pallet { use Read::*; match request { TotalSupply(token) => ReadResult::TotalSupply(AssetsOf::::total_supply(token)), - BalanceOf { token, owner } => { - ReadResult::BalanceOf(AssetsOf::::balance(token, owner)) - }, - Allowance { token, owner, spender } => { - ReadResult::Allowance(AssetsOf::::allowance(token, &owner, &spender)) - }, + BalanceOf { token, owner } => + ReadResult::BalanceOf(AssetsOf::::balance(token, owner)), + Allowance { token, owner, spender } => + ReadResult::Allowance(AssetsOf::::allowance(token, &owner, &spender)), TokenName(token) => ReadResult::TokenName( Some( as MetadataInspect>>::name(token)) .filter(|v| !v.is_empty()), From fd277f7c5ba4da9e0956c45321f2883c4d84b9bc Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 3 Oct 2024 13:26:30 +0700 Subject: [PATCH 146/161] fix: token name & symbol contract function --- pop-api/examples/fungibles/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 6f894349..08d084da 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -216,8 +216,8 @@ mod fungibles { fn token_name(&self) -> Option { api::token_name(self.id) .ok() - .filter(|v| !v.is_empty()) - .and_then(|v| String::from_utf8(v).ok()) + .flatten() + .and_then(|vec| String::from_utf8(vec).ok()) } /// Returns the token symbol. @@ -225,8 +225,8 @@ mod fungibles { fn token_symbol(&self) -> Option { api::token_symbol(self.id) .ok() - .filter(|v| !v.is_empty()) - .and_then(|v| String::from_utf8(v).ok()) + .flatten() + .and_then(|vec| String::from_utf8(vec).ok()) } /// Returns the token decimals. From da513bc8abbecbcc0fd48bc2ea2567ef36614fb2 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:35:51 +0700 Subject: [PATCH 147/161] fix: burn --- Cargo.toml | 1 - pop-api/examples/fungibles/lib.rs | 9 --------- pop-api/examples/fungibles/tests.rs | 3 ++- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cbe062bc..c8ab144a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ repository = "https://github.com/r0gue-io/pop-node/" exclude = [ "extension/contract", "pop-api", - "pop-sandbox", "tests/contracts", ] members = [ diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 08d084da..0f2f17bf 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -102,7 +102,6 @@ mod fungibles { if caller == to || value == 0 { return Ok(()); } - api::transfer(self.id, to, value).map_err(PSP22Error::from)?; self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); Ok(()) @@ -129,7 +128,6 @@ mod fungibles { if from == to || value == 0 { return Ok(()); } - // If `from` and the caller are different addresses, a successful transfer results // in decreased allowance by `from` to the caller and an `Approval` event with // the new allowance amount is emitted. @@ -157,7 +155,6 @@ mod fungibles { if caller == spender { return Ok(()); } - api::approve(self.id, spender, value).map_err(PSP22Error::from)?; self.env().emit_event(Approval { owner: caller, spender, value }); Ok(()) @@ -179,7 +176,6 @@ mod fungibles { if caller == spender || value == 0 { return Ok(()); } - api::increase_allowance(self.id, spender, value).map_err(PSP22Error::from)?; let allowance = self.allowance(caller, spender); self.env().emit_event(Approval { owner: caller, spender, value: allowance }); @@ -202,7 +198,6 @@ mod fungibles { if caller == spender || value == 0 { return Ok(()); } - api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; let value = self.allowance(caller, spender); self.env().emit_event(Approval { owner: caller, spender, value }); @@ -267,10 +262,6 @@ mod fungibles { if value == 0 { return Ok(()); } - let balance = self.balance_of(account); - if balance < value { - return Err(PSP22Error::InsufficientBalance); - } api::burn(self.id, account, value).map_err(PSP22Error::from)?; self.env().emit_event(Transfer { from: Some(account), to: None, value }); Ok(()) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index c985024f..5b9db060 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -418,7 +418,8 @@ fn increase_allowance_noop_works(mut session: Session) { let contract = deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); session.set_actor(contract.clone()); - // No-op if the caller and `spender` is the same address, returns success and no events are emitted. + // No-op if the caller and `spender` is the same address, returns success and no events are + // emitted. assert_ok!(increase_allowance(&mut session, contract.clone(), AMOUNT)); assert_eq!(last_contract_event(&session), None); // No-op if the `value` is zero, returns success and no events are emitted. From 56f1076268e8ea5afdd4c7a9c5262d0bf17d6012 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:54:56 +0700 Subject: [PATCH 148/161] fix: name & symbol --- pop-api/examples/fungibles/lib.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 0f2f17bf..e488fb6a 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -210,18 +210,16 @@ mod fungibles { #[ink(message)] fn token_name(&self) -> Option { api::token_name(self.id) - .ok() - .flatten() - .and_then(|vec| String::from_utf8(vec).ok()) + .unwrap_or_default() + .and_then(|v| String::from_utf8(v).ok()) } /// Returns the token symbol. #[ink(message)] fn token_symbol(&self) -> Option { api::token_symbol(self.id) - .ok() - .flatten() - .and_then(|vec| String::from_utf8(vec).ok()) + .unwrap_or_default() + .and_then(|v| String::from_utf8(v).ok()) } /// Returns the token decimals. From 93de4b87b5a4c6281a8f80d7a30ad1a0b4558728 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:31:29 +0700 Subject: [PATCH 149/161] refactor: `PSP22Error` conversion & assertion (#324) --- pop-api/examples/fungibles/tests.rs | 81 ++++++++++------------------- pop-api/src/v0/fungibles/errors.rs | 10 ++++ 2 files changed, 37 insertions(+), 54 deletions(-) diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 5b9db060..59f94be9 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -1,17 +1,21 @@ use drink::{ - assert_ok, - devnet::{account_id_from_slice, AccountId, Balance, Runtime}, + assert_err, assert_ok, call, + devnet::{ + account_id_from_slice, + error::{ + v0::{ApiError::*, ArithmeticError::*, Error}, + Assets, + AssetsError::*, + }, + AccountId, Balance, Runtime, + }, + last_contract_event, session::Session, - utils::{call, last_contract_event}, AssetsAPI, TestExternalities, NO_SALT, }; use ink::scale::Encode; use pop_api::{ - primitives::{ - ArithmeticError::Overflow, - Error::{Arithmetic, Module}, - TokenId, - }, + primitives::TokenId, v0::fungibles::events::{Approval, Created, Transfer}, }; @@ -166,10 +170,7 @@ fn transfer_fails_with_no_account() { deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); session.set_actor(contract.clone()); // `pallet-assets` returns `NoAccount` error. - assert_eq!( - transfer(&mut session, ALICE, AMOUNT), - Err(into_psp22_custom(Module { index: 52, error: [1, 0] })) - ); + assert_err!(transfer(&mut session, ALICE, AMOUNT), Error::Module(Assets(NoAccount))); } #[drink::test(sandbox = Pop)] @@ -212,10 +213,7 @@ fn transfer_fails_with_token_not_live() { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - assert_eq!( - transfer(&mut session, BOB, AMOUNT / 2), - Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) - ); + assert_err!(transfer(&mut session, BOB, AMOUNT / 2), Error::Module(Assets(AssetNotLive))); } #[drink::test(sandbox = Pop)] @@ -307,9 +305,9 @@ fn transfer_from_fails_with_token_not_live() { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - assert_eq!( + assert_err!( transfer_from(&mut session, ALICE, BOB, AMOUNT / 2), - Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) + Error::Module(Assets(AssetNotLive)) ); } @@ -365,10 +363,7 @@ fn approve_fails_with_token_not_live(mut session: Session) { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - assert_eq!( - approve(&mut session, ALICE, AMOUNT), - Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) - ); + assert_err!(approve(&mut session, ALICE, AMOUNT), Error::Module(Assets(AssetNotLive))); } #[drink::test(sandbox = Pop)] @@ -437,9 +432,9 @@ fn increase_allowance_fails_with_token_not_live(mut session: Session) { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - assert_eq!( + assert_err!( increase_allowance(&mut session, ALICE, AMOUNT), - Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) + Error::Module(Assets(AssetNotLive)) ); } @@ -524,9 +519,9 @@ fn decrease_allowance_fails_with_token_not_live(mut session: Session) { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - assert_eq!( + assert_err!( decrease_allowance(&mut session, ALICE, AMOUNT), - Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) + Error::Module(Assets(AssetNotLive)) ); } @@ -615,10 +610,7 @@ fn mint_fails_with_no_permission(mut session: Session) { assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); assert_ok!(deploy(&mut session, "existing", vec![(TOKEN + 1).to_string()])); // `pallet-assets` returns `NoPermission` error. - assert_eq!( - mint(&mut session, BOB, AMOUNT), - Err(into_psp22_custom(Module { index: 52, error: [2, 0] })) - ); + assert_err!(mint(&mut session, BOB, AMOUNT), Error::Module(Assets(NoPermission))); } #[drink::test(sandbox = Pop)] @@ -642,7 +634,7 @@ fn mint_fails_with_arithmetic_overflow(mut session: Session) { session.set_actor(contract.clone()); assert_ok!(mint(&mut session, ALICE, AMOUNT)); // Total supply increased by `value` exceeds maximal value of `u128` type. - assert_eq!(mint(&mut session, ALICE, u128::MAX), Err(into_psp22_custom(Arithmetic(Overflow)))); + assert_err!(mint(&mut session, ALICE, u128::MAX), Error::Api(Arithmetic(Overflow))); } #[drink::test(sandbox = Pop)] @@ -655,10 +647,7 @@ fn mint_fails_with_token_not_live(mut session: Session) { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. - assert_eq!( - mint(&mut session, ALICE, AMOUNT), - Err(into_psp22_custom(Module { index: 52, error: [16, 0] })) - ); + assert_err!(mint(&mut session, ALICE, AMOUNT), Error::Module(Assets(AssetNotLive))); } #[drink::test(sandbox = Pop)] @@ -694,10 +683,7 @@ fn burn_fails_with_no_permission(mut session: Session) { assert_ok!(session.sandbox().mint_into(&(TOKEN + 1), &BOB, AMOUNT)); assert_ok!(deploy(&mut session, "existing", vec![(TOKEN + 1).to_string()])); // `pallet-assets` returns `NoPermission` error. - assert_eq!( - burn(&mut session, BOB, AMOUNT), - Err(into_psp22_custom(Module { index: 52, error: [2, 0] })) - ); + assert_err!(burn(&mut session, BOB, AMOUNT), Error::Module(Assets(NoPermission))); } #[drink::test(sandbox = Pop)] @@ -734,10 +720,7 @@ fn burn_fails_with_token_not_live(mut session: Session) { // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `IncorrectStatus` error. - assert_eq!( - burn(&mut session, ALICE, AMOUNT), - Err(into_psp22_custom(Module { index: 52, error: [17, 0] })) - ); + assert_err!(burn(&mut session, ALICE, AMOUNT), Error::Module(Assets(IncorrectStatus))); } #[drink::test(sandbox = Pop)] @@ -769,7 +752,7 @@ fn deploy( method: &str, input: Vec, ) -> Result { - drink::utils::deploy::( + drink::deploy::( session, // The local contract (i.e. `fungibles`). BundleProvider::local().unwrap(), @@ -899,13 +882,3 @@ fn burn(session: &mut Session, account: AccountId, amount: Balance) -> Resu None, ) } - -// Convert into `PSP22Error::Custom` error type. -fn into_psp22_custom(err: T) -> PSP22Error { - let mut padded_vec = err.encode().to_vec(); - padded_vec.resize(4, 0); - // Convert the `Vec` to value of `StatusCode`. - let array: [u8; 4] = padded_vec.try_into().map_err(|_| "Invalid length").unwrap(); - let status_code = u32::from_le_bytes(array); - PSP22Error::Custom(status_code.to_string()) -} diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 06e7d545..f65e485e 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -89,6 +89,16 @@ pub enum PSP22Error { SafeTransferCheckFailed(String), } +#[cfg(feature = "std")] +impl From for u32 { + fn from(value: PSP22Error) -> u32 { + match value { + PSP22Error::Custom(value) => value.parse::().expect("Failed to parse"), + _ => unimplemented!("Variant is not supported"), + } + } +} + impl From for PSP22Error { /// Converts a `StatusCode` to a `PSP22Error`. fn from(value: StatusCode) -> Self { From d885b49f7111da52f17f24c0829abf722697991c Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:06:48 +0700 Subject: [PATCH 150/161] fix: pop-drink git path --- pop-api/examples/fungibles/Cargo.toml | 3 ++- pop-api/examples/fungibles/tests.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index a07c07f3..dc647a8b 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -13,9 +13,10 @@ pop-api = { path = "../../../pop-api", default-features = false, features = [ [dev-dependencies] env_logger = { version = "0.11.3" } serde_json = "1.0.114" +staging-xcm = { version = "=14.1.0", default-features = false } # Local -drink = { package = "pop-drink", path = "../../../../pop-drink/crates/pop-drink" } +drink = { package = "pop-drink", git = "https://github.com/r0gue-io/pop-drink", ath = "crates/pop-drink" } [lib] path = "lib.rs" diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 59f94be9..1ddfbd87 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -634,7 +634,7 @@ fn mint_fails_with_arithmetic_overflow(mut session: Session) { session.set_actor(contract.clone()); assert_ok!(mint(&mut session, ALICE, AMOUNT)); // Total supply increased by `value` exceeds maximal value of `u128` type. - assert_err!(mint(&mut session, ALICE, u128::MAX), Error::Api(Arithmetic(Overflow))); + assert_err!(mint(&mut session, ALICE, u128::MAX), Error::Raw(Arithmetic(Overflow))); } #[drink::test(sandbox = Pop)] From d907cb0950780057e40efd4c6b8402f3583087de Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:09:00 +0700 Subject: [PATCH 151/161] fix: contract -> instance --- pop-api/examples/fungibles/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index e488fb6a..73da0431 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -47,13 +47,13 @@ mod fungibles { // inactive balances from bloating the blockchain state and slowing down the network. #[ink(constructor, payable)] pub fn new(id: TokenId, min_balance: Balance) -> Result { - let contract = Self { id }; - let contract_id = contract.env().account_id(); + let instance = Self { id }; + let contract_id = instance.env().account_id(); api::create(id, contract_id, min_balance).map_err(PSP22Error::from)?; - contract + instance .env() .emit_event(Created { id, creator: contract_id, admin: contract_id }); - Ok(contract) + Ok(instance) } } From eec6221d4007caa35f2e351bb604bca1ed501178 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:31:14 +0700 Subject: [PATCH 152/161] fix: pop-drink path --- pop-api/examples/fungibles/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index dc647a8b..1544774d 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -16,7 +16,7 @@ serde_json = "1.0.114" staging-xcm = { version = "=14.1.0", default-features = false } # Local -drink = { package = "pop-drink", git = "https://github.com/r0gue-io/pop-drink", ath = "crates/pop-drink" } +drink = { package = "pop-drink", git = "https://github.com/r0gue-io/pop-drink" } [lib] path = "lib.rs" From ca551b750362f03e7763b9122219d0dd1f1c93f8 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Sun, 20 Oct 2024 11:44:12 +0200 Subject: [PATCH 153/161] refactor: small changes --- pop-api/examples/fungibles/Cargo.toml | 9 +++++---- pop-api/examples/fungibles/tests.rs | 25 ++++--------------------- pop-api/src/v0/fungibles/errors.rs | 12 +++++++----- pop-api/src/v0/fungibles/traits.rs | 5 +++-- 4 files changed, 19 insertions(+), 32 deletions(-) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 1544774d..bbe57c90 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -1,5 +1,5 @@ [package] -authors = [ "[your_name] <[your_email]>" ] +authors = [ "R0GUE " ] edition = "2021" name = "fungibles" version = "0.1.0" @@ -11,12 +11,13 @@ pop-api = { path = "../../../pop-api", default-features = false, features = [ ] } [dev-dependencies] +drink = { package = "pop-drink", git = "https://github.com/r0gue-io/pop-drink" } env_logger = { version = "0.11.3" } serde_json = "1.0.114" -staging-xcm = { version = "=14.1.0", default-features = false } -# Local -drink = { package = "pop-drink", git = "https://github.com/r0gue-io/pop-drink" } +# TODO: due to compilation issues caused by `staging-xcm` this dependency (with specific +# version) has to be added. Will be tackled by #348, please ignore for now. +staging-xcm = { version = "=14.1.0", default-features = false } [lib] path = "lib.rs" diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 1ddfbd87..83600ce4 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -81,7 +81,7 @@ fn new_constructor_works(mut session: Session) { #[drink::test(sandbox = Pop)] fn new_constructor_fails_with_used_token() { let _ = env_logger::try_init(); - // Fails to deploy contract with an used token ID. + // Fails to deploy contract with a used token ID. let token = TOKEN + 1; assert_ok!(session.sandbox().create(&token, &ALICE, MIN_BALANCE)); // `pallet-assets` returns `InUse` error. @@ -111,15 +111,7 @@ fn existing_constructor_fails_with_non_existing_token(&mut session: Session) { ); } -// 1. PSP-22 Interface: -// - total_supply -// - balance_of -// - allowance -// - transfer -// - transfer_from -// - approve -// - increase_allowance -// - decrease_allowance +// PSP-22 tests. #[drink::test(sandbox = Pop)] fn total_supply_works(mut session: Session) { @@ -566,10 +558,7 @@ fn decrease_allowance_works(mut session: Session) { ); } -// 2. PSP-22 Metadata Interface: -// - token_name -// - token_symbol -// - token_decimals +// PSP-22 Metadata tests. #[drink::test(sandbox = Pop)] fn token_metadata(mut session: Session) { @@ -599,13 +588,11 @@ fn token_metadata(mut session: Session) { assert_eq!(token_decimals(&mut session), decimals); } -// 3. PSP-22 Mintable Interface: -// - mint +// PSP-22 Mintable & Burnable tests. #[drink::test(sandbox = Pop)] fn mint_fails_with_no_permission(mut session: Session) { let _ = env_logger::try_init(); - // No permission to mint. // Create a new token owned by `BOB`. assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); assert_ok!(deploy(&mut session, "existing", vec![(TOKEN + 1).to_string()])); @@ -671,13 +658,9 @@ fn mint_works(mut session: Session) { ); } -// 4. PSP-22 Burnable Interface: -// - burn - #[drink::test(sandbox = Pop)] fn burn_fails_with_no_permission(mut session: Session) { let _ = env_logger::try_init(); - // No permission to burn. // Create a new token owned by `BOB`. assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); assert_ok!(session.sandbox().mint_into(&(TOKEN + 1), &BOB, AMOUNT)); diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index f65e485e..306527b4 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,12 +1,13 @@ //! A set of errors for use in smart contracts that interact with the fungibles api. This includes //! errors compliant to standards. -use super::*; use ink::{ prelude::string::{String, ToString}, scale::{Decode, Encode}, }; +use super::*; + /// Represents various errors related to fungible tokens. /// /// The `FungiblesError` provides a detailed and specific set of error types that can occur when @@ -93,6 +94,8 @@ pub enum PSP22Error { impl From for u32 { fn from(value: PSP22Error) -> u32 { match value { + PSP22Error::InsufficientBalance => u32::from_le_bytes([3, ASSETS, 0, 0]), + PSP22Error::InsufficientAllowance => u32::from_le_bytes([3, ASSETS, 10, 0]), PSP22Error::Custom(value) => value.parse::().expect("Failed to parse"), _ => unimplemented!("Variant is not supported"), } @@ -105,11 +108,10 @@ impl From for PSP22Error { let encoded = value.0.to_le_bytes(); match encoded { // BalanceLow. - [_, ASSETS, 0, _] => PSP22Error::InsufficientBalance, + [3, ASSETS, 0, _] => PSP22Error::InsufficientBalance, // Unapproved. - [_, ASSETS, 10, _] => PSP22Error::InsufficientAllowance, - // Unknown. - [_, ASSETS, 3, _] => PSP22Error::Custom(String::from("Unknown")), + [3, ASSETS, 10, _] => PSP22Error::InsufficientAllowance, + // Custom error with status code. _ => PSP22Error::Custom(value.0.to_string()), } } diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 16867c32..4bc2b1cf 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -6,8 +6,9 @@ use ink::prelude::string::String; use super::*; -/// Function selectors as per the PSP22 standard: https://github.com/w3f/PSPs/blob/master/PSPs/psp-22.md. -/// The mint and burn selectors are not defined in the standard, but have been created in the same way. +/// Function selectors as per the PSP22 standard: https://github.com/inkdevhub/standards/blob/master/PSPs/psp-22.md. +/// The mint and burn selectors are not defined in the standard, but have been created in the same +/// way. /// The PSP22 trait. #[ink::trait_definition] From 2f262843bb5b9254d7015a432057c7a8ee581cea Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 21 Oct 2024 13:20:39 +0700 Subject: [PATCH 154/161] fix(api): psp22error test --- pop-api/src/v0/fungibles/errors.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 306527b4..ced8514f 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -255,7 +255,9 @@ mod tests { ); assert_eq!( into_error::(Module { index: ASSETS, error: [3, 0] }), - PSP22Error::Custom(String::from("Unknown")) + PSP22Error::Custom( + error_into_status_code(Module { index: ASSETS, error: [3, 0] }).0.to_string() + ) ); } } From 5acd57269c27313d8f8ae4d2f52eeae8065b73ee Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 22 Oct 2024 23:02:01 +0700 Subject: [PATCH 155/161] fix: alloc --- pop-api/examples/fungibles/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index bbe57c90..d44d71f3 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -17,6 +17,7 @@ serde_json = "1.0.114" # TODO: due to compilation issues caused by `staging-xcm` this dependency (with specific # version) has to be added. Will be tackled by #348, please ignore for now. +sp-runtime = { version = "=38.0.0", default-features = false } staging-xcm = { version = "=14.1.0", default-features = false } [lib] From 2cf0ec83d15e5204729c471270d3ed40196384b9 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 23 Oct 2024 09:53:05 +0700 Subject: [PATCH 156/161] fix: comment --- pop-api/examples/fungibles/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index d44d71f3..decedbe7 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -15,7 +15,7 @@ drink = { package = "pop-drink", git = "https://github.com/r0gue-io/pop-drink" } env_logger = { version = "0.11.3" } serde_json = "1.0.114" -# TODO: due to compilation issues caused by `staging-xcm` this dependency (with specific +# TODO: due to compilation issues caused by `sp-runtime` this dependency (with specific # version) has to be added. Will be tackled by #348, please ignore for now. sp-runtime = { version = "=38.0.0", default-features = false } staging-xcm = { version = "=14.1.0", default-features = false } From 34010520d30ce632843f3f90fef42d788175ed6f Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:21:36 +0700 Subject: [PATCH 157/161] fix: rename PSP22Error to Psp22Error --- pop-api/examples/fungibles/lib.rs | 38 +++++++++--------- pop-api/examples/fungibles/tests.rs | 58 +++++++++++++-------------- pop-api/src/v0/fungibles/errors.rs | 38 +++++++++--------- pop-api/src/v0/fungibles/traits.rs | 14 +++---- pop-api/src/v0/nonfungibles/errors.rs | 35 ++++++++++++++++ 5 files changed, 109 insertions(+), 74 deletions(-) create mode 100644 pop-api/src/v0/nonfungibles/errors.rs diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 73da0431..50a3e3a8 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -7,7 +7,7 @@ use pop_api::{ self as api, events::{Approval, Created, Transfer}, traits::{Psp22, Psp22Burnable, Psp22Metadata, Psp22Mintable}, - PSP22Error, + Psp22Error, }, }; @@ -29,10 +29,10 @@ mod fungibles { /// # Parameters /// * - `token` - The token. #[ink(constructor, payable)] - pub fn existing(id: TokenId) -> Result { + pub fn existing(id: TokenId) -> Result { // Make sure token exists. if !api::token_exists(id).unwrap_or_default() { - return Err(PSP22Error::Custom(String::from("Token does not exist"))); + return Err(Psp22Error::Custom(String::from("Token does not exist"))); } Ok(Self { id }) } @@ -46,10 +46,10 @@ mod fungibles { // The `min_balance` ensures accounts hold a minimum amount of tokens, preventing tiny, // inactive balances from bloating the blockchain state and slowing down the network. #[ink(constructor, payable)] - pub fn new(id: TokenId, min_balance: Balance) -> Result { + pub fn new(id: TokenId, min_balance: Balance) -> Result { let instance = Self { id }; let contract_id = instance.env().account_id(); - api::create(id, contract_id, min_balance).map_err(PSP22Error::from)?; + api::create(id, contract_id, min_balance).map_err(Psp22Error::from)?; instance .env() .emit_event(Created { id, creator: contract_id, admin: contract_id }); @@ -96,13 +96,13 @@ mod fungibles { to: AccountId, value: Balance, _data: Vec, - ) -> Result<(), PSP22Error> { + ) -> Result<(), Psp22Error> { let caller = self.env().caller(); // No-op if the caller and `to` is the same address or `value` is zero. if caller == to || value == 0 { return Ok(()); } - api::transfer(self.id, to, value).map_err(PSP22Error::from)?; + api::transfer(self.id, to, value).map_err(Psp22Error::from)?; self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); Ok(()) } @@ -122,7 +122,7 @@ mod fungibles { to: AccountId, value: Balance, _data: Vec, - ) -> Result<(), PSP22Error> { + ) -> Result<(), Psp22Error> { let caller = self.env().caller(); // No-op if `from` and `to` is the same address or `value` is zero. if from == to || value == 0 { @@ -131,7 +131,7 @@ mod fungibles { // If `from` and the caller are different addresses, a successful transfer results // in decreased allowance by `from` to the caller and an `Approval` event with // the new allowance amount is emitted. - api::transfer_from(self.id, from, to, value).map_err(PSP22Error::from)?; + api::transfer_from(self.id, from, to, value).map_err(Psp22Error::from)?; self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); self.env().emit_event(Approval { owner: from, @@ -149,13 +149,13 @@ mod fungibles { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[ink(message)] - fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error> { + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), Psp22Error> { let caller = self.env().caller(); // No-op if the caller and `spender` is the same address. if caller == spender { return Ok(()); } - api::approve(self.id, spender, value).map_err(PSP22Error::from)?; + api::approve(self.id, spender, value).map_err(Psp22Error::from)?; self.env().emit_event(Approval { owner: caller, spender, value }); Ok(()) } @@ -170,13 +170,13 @@ mod fungibles { &mut self, spender: AccountId, value: Balance, - ) -> Result<(), PSP22Error> { + ) -> Result<(), Psp22Error> { let caller = self.env().caller(); // No-op if the caller and `spender` is the same address or `value` is zero. if caller == spender || value == 0 { return Ok(()); } - api::increase_allowance(self.id, spender, value).map_err(PSP22Error::from)?; + api::increase_allowance(self.id, spender, value).map_err(Psp22Error::from)?; let allowance = self.allowance(caller, spender); self.env().emit_event(Approval { owner: caller, spender, value: allowance }); Ok(()) @@ -192,13 +192,13 @@ mod fungibles { &mut self, spender: AccountId, value: Balance, - ) -> Result<(), PSP22Error> { + ) -> Result<(), Psp22Error> { let caller = self.env().caller(); // No-op if the caller and `spender` is the same address or `value` is zero. if caller == spender || value == 0 { return Ok(()); } - api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?; + api::decrease_allowance(self.id, spender, value).map_err(Psp22Error::from)?; let value = self.allowance(caller, spender); self.env().emit_event(Approval { owner: caller, spender, value }); Ok(()) @@ -237,12 +237,12 @@ mod fungibles { /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[ink(message)] - fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { + fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), Psp22Error> { // No-op if `value` is zero. if value == 0 { return Ok(()); } - api::mint(self.id, account, value).map_err(PSP22Error::from)?; + api::mint(self.id, account, value).map_err(Psp22Error::from)?; self.env().emit_event(Transfer { from: None, to: Some(account), value }); Ok(()) } @@ -255,12 +255,12 @@ mod fungibles { /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[ink(message)] - fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error> { + fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), Psp22Error> { // No-op if `value` is zero. if value == 0 { return Ok(()); } - api::burn(self.id, account, value).map_err(PSP22Error::from)?; + api::burn(self.id, account, value).map_err(Psp22Error::from)?; self.env().emit_event(Transfer { from: Some(account), to: None, value }); Ok(()) } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index 83600ce4..ad429bf6 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -87,7 +87,7 @@ fn new_constructor_fails_with_used_token() { // `pallet-assets` returns `InUse` error. assert_eq!( deploy(&mut session, "existing", vec![TOKEN.to_string()]), - Err(PSP22Error::Custom(String::from("Token does not exist"))) + Err(Psp22Error::Custom(String::from("Token does not exist"))) ); } @@ -107,7 +107,7 @@ fn existing_constructor_fails_with_non_existing_token(&mut session: Session) { // Fails to deploy contract with a non-existing token ID. assert_eq!( deploy(&mut session, "existing", vec![TOKEN.to_string()]), - Err(PSP22Error::Custom(String::from("Token does not exist"))) + Err(Psp22Error::Custom(String::from("Token does not exist"))) ); } @@ -190,7 +190,7 @@ fn transfer_fails_with_insufficient_balance() { // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); // Failed with `InsufficientBalance`. - assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(PSP22Error::InsufficientBalance)); + assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(Psp22Error::InsufficientBalance)); } #[drink::test(sandbox = Pop)] @@ -263,7 +263,7 @@ fn transfer_from_fails_with_insufficient_balance() { // Not enough balance. Failed with `InsufficientBalance`. assert_eq!( transfer_from(&mut session, ALICE, contract.clone(), AMOUNT + 1), - Err(PSP22Error::InsufficientBalance) + Err(Psp22Error::InsufficientBalance) ); } @@ -280,7 +280,7 @@ fn transfer_from_fails_with_insufficient_allowance() { // Unapproved transfer. Failed with `InsufficientAllowance`. assert_eq!( transfer_from(&mut session, ALICE, contract.clone(), AMOUNT + 1), - Err(PSP22Error::InsufficientAllowance) + Err(Psp22Error::InsufficientAllowance) ); } @@ -494,7 +494,7 @@ fn decrease_allowance_fails_with_insufficient_allowance(mut session: Session) { // Failed with `InsufficientAllowance`. assert_eq!( decrease_allowance(&mut session, ALICE, AMOUNT), - Err(PSP22Error::InsufficientAllowance) + Err(Psp22Error::InsufficientAllowance) ); } @@ -689,7 +689,7 @@ fn burn_fails_with_insufficient_balance(mut session: Session) { deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); session.set_actor(contract.clone()); // Failed with `InsufficientBalance`. - assert_eq!(burn(&mut session, ALICE, AMOUNT), Err(PSP22Error::InsufficientBalance)); + assert_eq!(burn(&mut session, ALICE, AMOUNT), Err(Psp22Error::InsufficientBalance)); } #[drink::test(sandbox = Pop)] @@ -734,8 +734,8 @@ fn deploy( session: &mut Session, method: &str, input: Vec, -) -> Result { - drink::deploy::( +) -> Result { + drink::deploy::( session, // The local contract (i.e. `fungibles`). BundleProvider::local().unwrap(), @@ -749,16 +749,16 @@ fn deploy( // A set of helper methods to test the contract calls. fn total_supply(session: &mut Session) -> Balance { - call::(session, "Psp22::total_supply", vec![], None).unwrap() + call::(session, "Psp22::total_supply", vec![], None).unwrap() } fn balance_of(session: &mut Session, owner: AccountId) -> Balance { - call::(session, "Psp22::balance_of", vec![owner.to_string()], None) + call::(session, "Psp22::balance_of", vec![owner.to_string()], None) .unwrap() } fn allowance(session: &mut Session, owner: AccountId, spender: AccountId) -> Balance { - call::( + call::( session, "Psp22::allowance", vec![owner.to_string(), spender.to_string()], @@ -767,8 +767,8 @@ fn allowance(session: &mut Session, owner: AccountId, spender: AccountId) - .unwrap() } -fn transfer(session: &mut Session, to: AccountId, amount: Balance) -> Result<(), PSP22Error> { - call::( +fn transfer(session: &mut Session, to: AccountId, amount: Balance) -> Result<(), Psp22Error> { + call::( session, "Psp22::transfer", vec![to.to_string(), amount.to_string(), serde_json::to_string::<[u8; 0]>(&[]).unwrap()], @@ -781,8 +781,8 @@ fn transfer_from( from: AccountId, to: AccountId, amount: Balance, -) -> Result<(), PSP22Error> { - call::( +) -> Result<(), Psp22Error> { + call::( session, "Psp22::transfer_from", vec![ @@ -799,8 +799,8 @@ fn approve( session: &mut Session, spender: AccountId, value: Balance, -) -> Result<(), PSP22Error> { - call::( +) -> Result<(), Psp22Error> { + call::( session, "Psp22::approve", vec![spender.to_string(), value.to_string()], @@ -812,8 +812,8 @@ fn increase_allowance( session: &mut Session, spender: AccountId, value: Balance, -) -> Result<(), PSP22Error> { - call::( +) -> Result<(), Psp22Error> { + call::( session, "Psp22::increase_allowance", vec![spender.to_string(), value.to_string()], @@ -825,8 +825,8 @@ fn decrease_allowance( session: &mut Session, spender: AccountId, value: Balance, -) -> Result<(), PSP22Error> { - call::( +) -> Result<(), Psp22Error> { + call::( session, "Psp22::decrease_allowance", vec![spender.to_string(), value.to_string()], @@ -835,21 +835,21 @@ fn decrease_allowance( } fn token_name(session: &mut Session) -> Option { - call::, PSP22Error>(session, "Psp22Metadata::token_name", vec![], None) + call::, Psp22Error>(session, "Psp22Metadata::token_name", vec![], None) .unwrap() } fn token_symbol(session: &mut Session) -> Option { - call::, PSP22Error>(session, "Psp22Metadata::token_symbol", vec![], None) + call::, Psp22Error>(session, "Psp22Metadata::token_symbol", vec![], None) .unwrap() } fn token_decimals(session: &mut Session) -> u8 { - call::(session, "Psp22Metadata::token_decimals", vec![], None).unwrap() + call::(session, "Psp22Metadata::token_decimals", vec![], None).unwrap() } -fn mint(session: &mut Session, account: AccountId, amount: Balance) -> Result<(), PSP22Error> { - call::( +fn mint(session: &mut Session, account: AccountId, amount: Balance) -> Result<(), Psp22Error> { + call::( session, "Psp22Mintable::mint", vec![account.to_string(), amount.to_string()], @@ -857,8 +857,8 @@ fn mint(session: &mut Session, account: AccountId, amount: Balance) -> Resu ) } -fn burn(session: &mut Session, account: AccountId, amount: Balance) -> Result<(), PSP22Error> { - call::( +fn burn(session: &mut Session, account: AccountId, amount: Balance) -> Result<(), Psp22Error> { + call::( session, "Psp22Burnable::burn", vec![account.to_string(), amount.to_string()], diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index ced8514f..8ce28758 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -75,7 +75,7 @@ impl From for FungiblesError { // TODO: Issue https://github.com/r0gue-io/pop-node/issues/298 #[derive(Debug, PartialEq, Eq)] #[ink::scale_derive(Encode, Decode, TypeInfo)] -pub enum PSP22Error { +pub enum Psp22Error { /// Custom error type for implementation-based errors. Custom(String), /// Returned when an account does not have enough tokens to complete the operation. @@ -91,28 +91,28 @@ pub enum PSP22Error { } #[cfg(feature = "std")] -impl From for u32 { - fn from(value: PSP22Error) -> u32 { +impl From for u32 { + fn from(value: Psp22Error) -> u32 { match value { - PSP22Error::InsufficientBalance => u32::from_le_bytes([3, ASSETS, 0, 0]), - PSP22Error::InsufficientAllowance => u32::from_le_bytes([3, ASSETS, 10, 0]), - PSP22Error::Custom(value) => value.parse::().expect("Failed to parse"), + Psp22Error::InsufficientBalance => u32::from_le_bytes([3, ASSETS, 0, 0]), + Psp22Error::InsufficientAllowance => u32::from_le_bytes([3, ASSETS, 10, 0]), + Psp22Error::Custom(value) => value.parse::().expect("Failed to parse"), _ => unimplemented!("Variant is not supported"), } } } -impl From for PSP22Error { - /// Converts a `StatusCode` to a `PSP22Error`. +impl From for Psp22Error { + /// Converts a `StatusCode` to a `Psp22Error`. fn from(value: StatusCode) -> Self { let encoded = value.0.to_le_bytes(); match encoded { // BalanceLow. - [3, ASSETS, 0, _] => PSP22Error::InsufficientBalance, + [3, ASSETS, 0, _] => Psp22Error::InsufficientBalance, // Unapproved. - [3, ASSETS, 10, _] => PSP22Error::InsufficientAllowance, + [3, ASSETS, 10, _] => Psp22Error::InsufficientAllowance, // Custom error with status code. - _ => PSP22Error::Custom(value.0.to_string()), + _ => Psp22Error::Custom(value.0.to_string()), } } } @@ -241,21 +241,21 @@ mod tests { ]; for error in other_errors { let status_code: StatusCode = error_into_status_code(error); - let fungibles_error: PSP22Error = status_code.into(); - assert_eq!(fungibles_error, PSP22Error::Custom(status_code.0.to_string())) + let fungibles_error: Psp22Error = status_code.into(); + assert_eq!(fungibles_error, Psp22Error::Custom(status_code.0.to_string())) } assert_eq!( - into_error::(Module { index: ASSETS, error: [0, 0] }), - PSP22Error::InsufficientBalance + into_error::(Module { index: ASSETS, error: [0, 0] }), + Psp22Error::InsufficientBalance ); assert_eq!( - into_error::(Module { index: ASSETS, error: [10, 0] }), - PSP22Error::InsufficientAllowance + into_error::(Module { index: ASSETS, error: [10, 0] }), + Psp22Error::InsufficientAllowance ); assert_eq!( - into_error::(Module { index: ASSETS, error: [3, 0] }), - PSP22Error::Custom( + into_error::(Module { index: ASSETS, error: [3, 0] }), + Psp22Error::Custom( error_into_status_code(Module { index: ASSETS, error: [3, 0] }).0.to_string() ) ); diff --git a/pop-api/src/v0/fungibles/traits.rs b/pop-api/src/v0/fungibles/traits.rs index 4bc2b1cf..e6252233 100644 --- a/pop-api/src/v0/fungibles/traits.rs +++ b/pop-api/src/v0/fungibles/traits.rs @@ -40,7 +40,7 @@ pub trait Psp22 { /// - `value` - The number of tokens to transfer. /// - `data` - Additional data in unspecified format. #[ink(message, selector = 0xdb20f9f5)] - fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<(), PSP22Error>; + fn transfer(&mut self, to: AccountId, value: Balance, data: Vec) -> Result<(), Psp22Error>; /// Transfers `value` tokens on behalf of `from` to the account `to` /// with additional `data` in unspecified format. @@ -57,7 +57,7 @@ pub trait Psp22 { to: AccountId, value: Balance, data: Vec, - ) -> Result<(), PSP22Error>; + ) -> Result<(), Psp22Error>; /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. /// @@ -67,7 +67,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to approve. #[ink(message, selector = 0xb20f1bbd)] - fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; + fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), Psp22Error>; /// Increases the allowance of `spender` by `value` amount of tokens. /// @@ -75,7 +75,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to increase the allowance by. #[ink(message, selector = 0x96d6b57a)] - fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; + fn increase_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), Psp22Error>; /// Decreases the allowance of `spender` by `value` amount of tokens. /// @@ -83,7 +83,7 @@ pub trait Psp22 { /// - `spender` - The account that is allowed to spend the tokens. /// - `value` - The number of tokens to decrease the allowance by. #[ink(message, selector = 0xfecb57d5)] - fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), PSP22Error>; + fn decrease_allowance(&mut self, spender: AccountId, value: Balance) -> Result<(), Psp22Error>; } /// The PSP22 Metadata trait. @@ -114,7 +114,7 @@ pub trait Psp22Mintable { /// - `account` - The account to be credited with the created tokens. /// - `value` - The number of tokens to mint. #[ink(message, selector = 0xfc3c75d4)] - fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; + fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), Psp22Error>; } /// The PSP22 Burnable trait. @@ -129,5 +129,5 @@ pub trait Psp22Burnable { /// - `account` - The account from which the tokens will be destroyed. /// - `value` - The number of tokens to destroy. #[ink(message, selector = 0x7a9da510)] - fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), PSP22Error>; + fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), Psp22Error>; } diff --git a/pop-api/src/v0/nonfungibles/errors.rs b/pop-api/src/v0/nonfungibles/errors.rs new file mode 100644 index 00000000..74db9c47 --- /dev/null +++ b/pop-api/src/v0/nonfungibles/errors.rs @@ -0,0 +1,35 @@ +//! A set of errors for use in smart contracts that interact with the nonfungibles api. This +//! includes errors compliant to standards. + +use ink::prelude::string::{String, ToString}; + +use super::*; + +/// The PSP34 error. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum Psp34Error { + /// Custom error type for cases if writer of traits added own restrictions + Custom(String), + /// Returned if owner approves self + SelfApprove, + /// Returned if the caller doesn't have allowance for transferring. + NotApproved, + /// Returned if the owner already own the token. + TokenExists, + /// Returned if the token doesn't exist + TokenNotExists, + /// Returned if safe transfer check fails + SafeTransferCheckFailed(String), +} + +impl From for Psp34Error { + /// Converts a `StatusCode` to a `Psp22Error`. + fn from(value: StatusCode) -> Self { + let encoded = value.0.to_le_bytes(); + match encoded { + // TODO: Handle conversion. + _ => Psp34Error::Custom(value.0.to_string()), + } + } +} From 9d31d2f854466f43ccd2d6196597355a05d1a292 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:25:12 +0700 Subject: [PATCH 158/161] chore: delete psp34error --- pop-api/src/v0/nonfungibles/errors.rs | 35 --------------------------- 1 file changed, 35 deletions(-) delete mode 100644 pop-api/src/v0/nonfungibles/errors.rs diff --git a/pop-api/src/v0/nonfungibles/errors.rs b/pop-api/src/v0/nonfungibles/errors.rs deleted file mode 100644 index 74db9c47..00000000 --- a/pop-api/src/v0/nonfungibles/errors.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! A set of errors for use in smart contracts that interact with the nonfungibles api. This -//! includes errors compliant to standards. - -use ink::prelude::string::{String, ToString}; - -use super::*; - -/// The PSP34 error. -#[derive(Debug, PartialEq, Eq)] -#[ink::scale_derive(Encode, Decode, TypeInfo)] -pub enum Psp34Error { - /// Custom error type for cases if writer of traits added own restrictions - Custom(String), - /// Returned if owner approves self - SelfApprove, - /// Returned if the caller doesn't have allowance for transferring. - NotApproved, - /// Returned if the owner already own the token. - TokenExists, - /// Returned if the token doesn't exist - TokenNotExists, - /// Returned if safe transfer check fails - SafeTransferCheckFailed(String), -} - -impl From for Psp34Error { - /// Converts a `StatusCode` to a `Psp22Error`. - fn from(value: StatusCode) -> Self { - let encoded = value.0.to_le_bytes(); - match encoded { - // TODO: Handle conversion. - _ => Psp34Error::Custom(value.0.to_string()), - } - } -} From 70d37c9ca0fb5c9faf4dca7313ec0bb069ea3dd5 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:27:10 +0700 Subject: [PATCH 159/161] fix: update comments --- pop-api/examples/fungibles/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index decedbe7..c2013185 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -15,7 +15,7 @@ drink = { package = "pop-drink", git = "https://github.com/r0gue-io/pop-drink" } env_logger = { version = "0.11.3" } serde_json = "1.0.114" -# TODO: due to compilation issues caused by `sp-runtime` this dependency (with specific +# TODO: due to compilation issues caused by `sp-runtime` and `staging-xcm` this dependency (with specific # version) has to be added. Will be tackled by #348, please ignore for now. sp-runtime = { version = "=38.0.0", default-features = false } staging-xcm = { version = "=14.1.0", default-features = false } From 8c72e2c36f247f16a4019b6e1943585bae57e0e1 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:59:48 +0700 Subject: [PATCH 160/161] feat(psp22): protect with `owner` --- Cargo.lock | 8 +- pop-api/examples/fungibles/README.md | 32 +++++ pop-api/examples/fungibles/lib.rs | 107 +++++++++++------ pop-api/examples/fungibles/tests.rs | 172 ++++++++++++--------------- pop-api/src/lib.rs | 3 + pop-api/src/v0/fungibles/errors.rs | 8 +- pop-api/src/v0/fungibles/mod.rs | 2 +- 7 files changed, 193 insertions(+), 139 deletions(-) create mode 100644 pop-api/examples/fungibles/README.md diff --git a/Cargo.lock b/Cargo.lock index 3f1349eb..42f715a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -822,7 +822,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.36.0", + "object 0.36.4", "rustc-demangle", ] @@ -7195,9 +7195,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.0" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] diff --git a/pop-api/examples/fungibles/README.md b/pop-api/examples/fungibles/README.md new file mode 100644 index 00000000..df0b108c --- /dev/null +++ b/pop-api/examples/fungibles/README.md @@ -0,0 +1,32 @@ +# PSP22 Example Contract with Pop Fungibles API + +This contract is an example implementation of the [PSP22 standard](https://github.com/inkdevhub/standards/blob/master/PSPs/psp-22.md), utilizing the Pop API Fungibles module. + +- This contract provides core functionalities to manage a PSP22 standard token that exists as an asset on the Pop Network, rather than being confined solely to the contract. +- Only the contract owner has a permission to call specific methods. + +This design choice is due to the fact that `pop-api` invokes runtime calls with the contract itself as the `origin`. For examples, methods like `transfer` and `transfer_from` will operate on the contract's own account balance, not on the balance of the caller. + +To learn more about Pop API and how Pop API works under the hood: [Read here](/pop-api/README.md) + +## Security risks prevention + +To prevent potential misuse of contract methods by malicious actors—such as using `approve` to grant unauthorized transfer permissions—the contract restricts access exclusively to the `owner` (the account that instantiated the contract). + +```rs +self.ensure_owner()?; +``` + +Only the `owner` is permitted to call these methods, ensuring the contract’s balance remains secure. The owner of the contract can be updated by an existing `owner` by calling the method `transfer_ownership`. + +## What can be improved? + +- Instead of restricting ownership to a single `owner`, the contract could be designed to accommodate multiple owners. Therefore, the `transfer_ownership` is also need to be updated to support this feature. + +## Use cases + +This contract can be used in multiple different real world cases such as: + +- **Use case for a governance token within a [DAO (Decentralized Autonomous Organization)](https://www.investopedia.com/tech/what-dao/)**: The DAO contract performs cross-contract calls to this PSP22 example contract to create a new token, with the DAO authority as the token’s owner. This allows the DAO authority to manage governance tokens for its members by performing actions such as mint and burn. + +- **Staking Rewards Program**: This contract can be used to issue rewards in a staking program, where users lock tokens for network security or liquidity. The staking contract calls this PSP22 contract to mint and burn tokens, allowing the staking authority to manage rewards and ensure distribution only to eligible participants. diff --git a/pop-api/examples/fungibles/lib.rs b/pop-api/examples/fungibles/lib.rs index 50a3e3a8..eaaeac34 100644 --- a/pop-api/examples/fungibles/lib.rs +++ b/pop-api/examples/fungibles/lib.rs @@ -1,8 +1,11 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::prelude::{string::String, vec::Vec}; +use ink::{ + prelude::{string::String, vec::Vec}, + storage::Mapping, +}; use pop_api::{ - primitives::TokenId, + primitives::{AccountId, TokenId}, v0::fungibles::{ self as api, events::{Approval, Created, Transfer}, @@ -21,20 +24,24 @@ mod fungibles { #[ink(storage)] pub struct Fungible { id: TokenId, + owner: Option, } impl Fungible { - /// Instantiate the contract and wrap around an existing token. + /// Instantiate the contract and wrap an existing token. /// /// # Parameters - /// * - `token` - The token. + /// * - `id` - The token. #[ink(constructor, payable)] pub fn existing(id: TokenId) -> Result { // Make sure token exists. if !api::token_exists(id).unwrap_or_default() { return Err(Psp22Error::Custom(String::from("Token does not exist"))); } - Ok(Self { id }) + let mut instance = Self { id, owner: None }; + let contract_id = instance.env().account_id(); + instance.owner = Some(instance.env().caller()); + Ok(instance) } /// Instantiate the contract and create a new token. The token identifier will be stored @@ -47,14 +54,34 @@ mod fungibles { // inactive balances from bloating the blockchain state and slowing down the network. #[ink(constructor, payable)] pub fn new(id: TokenId, min_balance: Balance) -> Result { - let instance = Self { id }; + let mut instance = Self { id, owner: None }; let contract_id = instance.env().account_id(); + instance.owner = Some(instance.env().caller()); api::create(id, contract_id, min_balance).map_err(Psp22Error::from)?; instance .env() .emit_event(Created { id, creator: contract_id, admin: contract_id }); Ok(instance) } + + /// Check if a caller is an owner of the contract. + fn ensure_owner(&self) -> Result<(), Psp22Error> { + if self.owner != Some(self.env().caller()) { + return Err(Psp22Error::Custom(String::from("Not an owner"))); + } + Ok(()) + } + + /// Transfer an ownership of the contract to another accoun. + /// + /// # Parameters + /// - `owner` - New owner account. + #[ink(message)] + pub fn transfer_ownership(&mut self, owner: AccountId) -> Result<(), Psp22Error> { + self.ensure_owner()?; + self.owner = Some(owner); + Ok(()) + } } impl Psp22 for Fungible { @@ -83,8 +110,8 @@ mod fungibles { api::allowance(self.id, owner, spender).unwrap_or_default() } - /// Transfers `value` amount of tokens from the caller's account to account `to` - /// with additional `data` in unspecified format. + /// Transfers `value` amount of tokens from the contract to account `to` with + /// additional `data` in unspecified format. /// /// # Parameters /// - `to` - The recipient account. @@ -97,18 +124,20 @@ mod fungibles { value: Balance, _data: Vec, ) -> Result<(), Psp22Error> { - let caller = self.env().caller(); - // No-op if the caller and `to` is the same address or `value` is zero. - if caller == to || value == 0 { + self.ensure_owner()?; + let contract = self.env().account_id(); + + // No-op if the contract and `to` is the same address or `value` is zero. + if contract == to || value == 0 { return Ok(()); } api::transfer(self.id, to, value).map_err(Psp22Error::from)?; - self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); + self.env().emit_event(Transfer { from: Some(contract), to: Some(to), value }); Ok(()) } /// Transfers `value` tokens on behalf of `from` to the account `to` - /// with additional `data` in unspecified format. + /// with additional `data` in unspecified format. Contract must be pre-approved by `from`. /// /// # Parameters /// - `from` - The account from which the token balance will be withdrawn. @@ -123,25 +152,27 @@ mod fungibles { value: Balance, _data: Vec, ) -> Result<(), Psp22Error> { - let caller = self.env().caller(); + self.ensure_owner()?; + let contract = self.env().account_id(); + // No-op if `from` and `to` is the same address or `value` is zero. if from == to || value == 0 { return Ok(()); } - // If `from` and the caller are different addresses, a successful transfer results - // in decreased allowance by `from` to the caller and an `Approval` event with + // If `from` and the contract are different addresses, a successful transfer results + // in decreased allowance by `from` to the contract and an `Approval` event with // the new allowance amount is emitted. api::transfer_from(self.id, from, to, value).map_err(Psp22Error::from)?; - self.env().emit_event(Transfer { from: Some(caller), to: Some(to), value }); + self.env().emit_event(Transfer { from: Some(contract), to: Some(to), value }); self.env().emit_event(Approval { owner: from, - spender: caller, - value: self.allowance(from, caller), + spender: contract, + value: self.allowance(from, contract), }); Ok(()) } - /// Approves `spender` to spend `value` amount of tokens on behalf of the caller. + /// Approves `spender` to spend `value` amount of tokens on behalf of the contract. /// /// Successive calls of this method overwrite previous values. /// @@ -150,13 +181,15 @@ mod fungibles { /// - `value` - The number of tokens to approve. #[ink(message)] fn approve(&mut self, spender: AccountId, value: Balance) -> Result<(), Psp22Error> { - let caller = self.env().caller(); - // No-op if the caller and `spender` is the same address. - if caller == spender { + self.ensure_owner()?; + let contract = self.env().account_id(); + + // No-op if the contract and `spender` is the same address. + if contract == spender { return Ok(()); } api::approve(self.id, spender, value).map_err(Psp22Error::from)?; - self.env().emit_event(Approval { owner: caller, spender, value }); + self.env().emit_event(Approval { owner: contract, spender, value }); Ok(()) } @@ -171,14 +204,16 @@ mod fungibles { spender: AccountId, value: Balance, ) -> Result<(), Psp22Error> { - let caller = self.env().caller(); - // No-op if the caller and `spender` is the same address or `value` is zero. - if caller == spender || value == 0 { + self.ensure_owner()?; + let contract = self.env().account_id(); + + // No-op if the contract and `spender` is the same address or `value` is zero. + if contract == spender || value == 0 { return Ok(()); } api::increase_allowance(self.id, spender, value).map_err(Psp22Error::from)?; - let allowance = self.allowance(caller, spender); - self.env().emit_event(Approval { owner: caller, spender, value: allowance }); + let allowance = self.allowance(contract, spender); + self.env().emit_event(Approval { owner: contract, spender, value: allowance }); Ok(()) } @@ -193,14 +228,16 @@ mod fungibles { spender: AccountId, value: Balance, ) -> Result<(), Psp22Error> { - let caller = self.env().caller(); - // No-op if the caller and `spender` is the same address or `value` is zero. - if caller == spender || value == 0 { + self.ensure_owner()?; + let contract = self.env().account_id(); + + // No-op if the contract and `spender` is the same address or `value` is zero. + if contract == spender || value == 0 { return Ok(()); } api::decrease_allowance(self.id, spender, value).map_err(Psp22Error::from)?; - let value = self.allowance(caller, spender); - self.env().emit_event(Approval { owner: caller, spender, value }); + let value = self.allowance(contract, spender); + self.env().emit_event(Approval { owner: contract, spender, value }); Ok(()) } } @@ -238,6 +275,7 @@ mod fungibles { /// - `value` - The number of tokens to mint. #[ink(message)] fn mint(&mut self, account: AccountId, value: Balance) -> Result<(), Psp22Error> { + self.ensure_owner()?; // No-op if `value` is zero. if value == 0 { return Ok(()); @@ -256,6 +294,7 @@ mod fungibles { /// - `value` - The number of tokens to destroy. #[ink(message)] fn burn(&mut self, account: AccountId, value: Balance) -> Result<(), Psp22Error> { + self.ensure_owner()?; // No-op if `value` is zero. if value == 0 { return Ok(()); diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index ad429bf6..788adc1c 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -57,12 +57,15 @@ drink::impl_sandbox!(Pop, Runtime, ALICE); // Deployment and constructor method tests. +fn deploy_with_default(session: &mut Session) -> Result { + deploy(session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]) +} + #[drink::test(sandbox = Pop)] fn new_constructor_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + let contract = deploy_with_default(&mut session).unwrap(); // Token exists after the deployment. assert!(session.sandbox().asset_exists(&TOKEN)); // Successfully emit event. @@ -117,7 +120,7 @@ fn existing_constructor_fails_with_non_existing_token(&mut session: Session) { fn total_supply_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - assert_ok!(deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()],)); + assert_ok!(deploy_with_default(&mut session)); // No tokens in circulation. assert_eq!(total_supply(&mut session), 0); assert_eq!(total_supply(&mut session), session.sandbox().total_supply(&TOKEN)); @@ -131,7 +134,7 @@ fn total_supply_works(mut session: Session) { fn balance_of_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - assert_ok!(deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()])); + assert_ok!(deploy_with_default(&mut session)); // No tokens in circulation. assert_eq!(balance_of(&mut session, ALICE), 0); assert_eq!(balance_of(&mut session, ALICE), session.sandbox().balance_of(&TOKEN, &ALICE)); @@ -145,8 +148,7 @@ fn balance_of_works(mut session: Session) { fn allowance_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + let contract = deploy_with_default(&mut session).unwrap(); // No tokens in circulation. assert_eq!(allowance(&mut session, contract.clone(), ALICE), 0); // Tokens in circulation. @@ -158,10 +160,12 @@ fn allowance_works(mut session: Session) { fn transfer_fails_with_no_account() { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // `pallet-assets` returns `NoAccount` error. + assert_ok!(session + .sandbox() + .approve(&TOKEN, &contract.clone(), &contract.clone(), AMOUNT * 2)); assert_err!(transfer(&mut session, ALICE, AMOUNT), Error::Module(Assets(NoAccount))); } @@ -169,9 +173,8 @@ fn transfer_fails_with_no_account() { fn transfer_noop_works(&mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // No-op if `value` is zero, returns success and no events are emitted. assert_ok!(transfer(&mut session, ALICE, 0)); assert_eq!(last_contract_event(&session), None); @@ -184,12 +187,14 @@ fn transfer_noop_works(&mut session: Session) { fn transfer_fails_with_insufficient_balance() { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); // Failed with `InsufficientBalance`. + assert_ok!(session + .sandbox() + .approve(&TOKEN, &contract.clone(), &contract.clone(), AMOUNT * 2)); assert_eq!(transfer(&mut session, BOB, AMOUNT + 1), Err(Psp22Error::InsufficientBalance)); } @@ -197,9 +202,8 @@ fn transfer_fails_with_insufficient_balance() { fn transfer_fails_with_token_not_live() { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); // Token is not live, i.e. frozen or being destroyed. @@ -212,13 +216,13 @@ fn transfer_fails_with_token_not_live() { fn transfer_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); let value = AMOUNT / 4; // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); // Successfully transfer. + assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &contract.clone(), AMOUNT)); assert_ok!(transfer(&mut session, BOB, value)); assert_eq!(session.sandbox().balance_of(&TOKEN, &contract), AMOUNT - value); assert_eq!(session.sandbox().balance_of(&TOKEN, &BOB), value); @@ -239,9 +243,8 @@ fn transfer_works(mut session: Session) { fn transfer_from_noop_works() { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // No-op if `value` is zero, returns success and no events are emitted. assert_ok!(transfer_from(&mut session, ALICE, BOB, 0)); assert_eq!(last_contract_event(&session), None); @@ -254,9 +257,8 @@ fn transfer_from_noop_works() { fn transfer_from_fails_with_insufficient_balance() { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &ALICE, &contract.clone(), AMOUNT * 2)); @@ -271,9 +273,8 @@ fn transfer_from_fails_with_insufficient_balance() { fn transfer_from_fails_with_insufficient_allowance() { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &ALICE, &contract.clone(), AMOUNT)); @@ -288,9 +289,8 @@ fn transfer_from_fails_with_insufficient_allowance() { fn transfer_from_fails_with_token_not_live() { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &ALICE, &contract.clone(), AMOUNT)); @@ -307,9 +307,8 @@ fn transfer_from_fails_with_token_not_live() { fn transfer_from_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); let value = AMOUNT / 2; // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); @@ -336,9 +335,8 @@ fn transfer_from_works(mut session: Session) { fn approve_noop_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(approve(&mut session, contract.clone(), AMOUNT)); @@ -349,9 +347,8 @@ fn approve_noop_works(mut session: Session) { fn approve_fails_with_token_not_live(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. @@ -362,21 +359,20 @@ fn approve_fails_with_token_not_live(mut session: Session) { fn approve_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); let value = AMOUNT / 2; // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); // Successfully approve. - assert_ok!(approve(&mut session, ALICE, value)); - assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &ALICE), value); + assert_ok!(approve(&mut session, BOB, value)); + assert_eq!(session.sandbox().allowance(&TOKEN, &contract, &BOB), value); // Successfully emit event. assert_eq!( last_contract_event(&session).unwrap(), Approval { owner: account_id_from_slice(&contract), - spender: account_id_from_slice(&ALICE), + spender: account_id_from_slice(&BOB), value, } .encode() @@ -402,9 +398,8 @@ fn approve_works(mut session: Session) { fn increase_allowance_noop_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(increase_allowance(&mut session, contract.clone(), AMOUNT)); @@ -418,9 +413,8 @@ fn increase_allowance_noop_works(mut session: Session) { fn increase_allowance_fails_with_token_not_live(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. @@ -434,9 +428,8 @@ fn increase_allowance_fails_with_token_not_live(mut session: Session) { fn increase_allowance_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); let value = AMOUNT / 2; // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); @@ -475,9 +468,8 @@ fn increase_allowance_works(mut session: Session) { fn decrease_allowance_noop_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // No-op if the caller and `spender` is the same address, returns success and no events are // emitted. assert_ok!(decrease_allowance(&mut session, contract.clone(), AMOUNT)); @@ -488,9 +480,8 @@ fn decrease_allowance_noop_works(mut session: Session) { fn decrease_allowance_fails_with_insufficient_allowance(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Failed with `InsufficientAllowance`. assert_eq!( decrease_allowance(&mut session, ALICE, AMOUNT), @@ -502,9 +493,8 @@ fn decrease_allowance_fails_with_insufficient_allowance(mut session: Session) { fn decrease_allowance_fails_with_token_not_live(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); assert_ok!(session.sandbox().approve(&TOKEN, &contract.clone(), &ALICE, AMOUNT)); @@ -521,9 +511,8 @@ fn decrease_allowance_fails_with_token_not_live(mut session: Session) { fn decrease_allowance_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); let value = 1; // Mint tokens and approve. assert_ok!(session.sandbox().mint_into(&TOKEN, &contract.clone(), AMOUNT)); @@ -564,8 +553,7 @@ fn decrease_allowance_works(mut session: Session) { fn token_metadata(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); + let contract = deploy_with_default(&mut session).unwrap(); session.set_actor(contract.clone()); let name: String = String::from("Paseo Token"); let symbol: String = String::from("PAS"); @@ -597,16 +585,15 @@ fn mint_fails_with_no_permission(mut session: Session) { assert_ok!(session.sandbox().create(&(TOKEN + 1), &BOB, MIN_BALANCE)); assert_ok!(deploy(&mut session, "existing", vec![(TOKEN + 1).to_string()])); // `pallet-assets` returns `NoPermission` error. - assert_err!(mint(&mut session, BOB, AMOUNT), Error::Module(Assets(NoPermission))); + assert_err!(mint(&mut session, ALICE, AMOUNT), Error::Module(Assets(NoPermission))); } #[drink::test(sandbox = Pop)] fn mint_noop_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // No-op if minted value is zero, returns success and no events are emitted. assert_ok!(mint(&mut session, ALICE, 0)); assert_eq!(last_contract_event(&session), None); @@ -616,9 +603,8 @@ fn mint_noop_works(mut session: Session) { fn mint_fails_with_arithmetic_overflow(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); assert_ok!(mint(&mut session, ALICE, AMOUNT)); // Total supply increased by `value` exceeds maximal value of `u128` type. assert_err!(mint(&mut session, ALICE, u128::MAX), Error::Raw(Arithmetic(Overflow))); @@ -628,9 +614,8 @@ fn mint_fails_with_arithmetic_overflow(mut session: Session) { fn mint_fails_with_token_not_live(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); // `pallet-assets` returns `AssetNotLive` error. @@ -641,9 +626,8 @@ fn mint_fails_with_token_not_live(mut session: Session) { fn mint_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); let value = AMOUNT; // Successfully mint tokens. assert_ok!(mint(&mut session, ALICE, value)); @@ -673,9 +657,8 @@ fn burn_fails_with_no_permission(mut session: Session) { fn burn_noop_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // No-op if burned value is zero, returns success and no events are emitted. assert_ok!(burn(&mut session, ALICE, 0)); assert_eq!(last_contract_event(&session), None); @@ -685,9 +668,8 @@ fn burn_noop_works(mut session: Session) { fn burn_fails_with_insufficient_balance(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); // Failed with `InsufficientBalance`. assert_eq!(burn(&mut session, ALICE, AMOUNT), Err(Psp22Error::InsufficientBalance)); } @@ -696,9 +678,8 @@ fn burn_fails_with_insufficient_balance(mut session: Session) { fn burn_fails_with_token_not_live(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); // Token is not live, i.e. frozen or being destroyed. assert_ok!(session.sandbox().start_destroy(&TOKEN)); @@ -710,9 +691,8 @@ fn burn_fails_with_token_not_live(mut session: Session) { fn burn_works(mut session: Session) { let _ = env_logger::try_init(); // Deploy a new contract. - let contract = - deploy(&mut session, "new", vec![TOKEN.to_string(), MIN_BALANCE.to_string()]).unwrap(); - session.set_actor(contract.clone()); + let contract = deploy_with_default(&mut session).unwrap(); + session.set_actor(ALICE); let value = 1; // Mint tokens. assert_ok!(session.sandbox().mint_into(&TOKEN, &ALICE, AMOUNT)); diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 546106e5..3607a70d 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -63,6 +63,9 @@ mod constants { // Error. pub(crate) const DECODING_FAILED: u32 = 255; + // Runtime Errors. + pub(crate) const MODULE_ERROR: u8 = 3; + // Function IDs. pub(crate) const DISPATCH: u8 = 0; pub(crate) const READ_STATE: u8 = 1; diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 8ce28758..3080a2c4 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -94,8 +94,8 @@ pub enum Psp22Error { impl From for u32 { fn from(value: Psp22Error) -> u32 { match value { - Psp22Error::InsufficientBalance => u32::from_le_bytes([3, ASSETS, 0, 0]), - Psp22Error::InsufficientAllowance => u32::from_le_bytes([3, ASSETS, 10, 0]), + Psp22Error::InsufficientBalance => u32::from_le_bytes([MODULE_ERROR, ASSETS, 0, 0]), + Psp22Error::InsufficientAllowance => u32::from_le_bytes([MODULE_ERROR, ASSETS, 10, 0]), Psp22Error::Custom(value) => value.parse::().expect("Failed to parse"), _ => unimplemented!("Variant is not supported"), } @@ -108,9 +108,9 @@ impl From for Psp22Error { let encoded = value.0.to_le_bytes(); match encoded { // BalanceLow. - [3, ASSETS, 0, _] => Psp22Error::InsufficientBalance, + [MODULE_ERROR, ASSETS, 0, _] => Psp22Error::InsufficientBalance, // Unapproved. - [3, ASSETS, 10, _] => Psp22Error::InsufficientAllowance, + [MODULE_ERROR, ASSETS, 10, _] => Psp22Error::InsufficientAllowance, // Custom error with status code. _ => Psp22Error::Custom(value.0.to_string()), } diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index 6fc1e9e5..1e147982 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -15,7 +15,7 @@ pub use metadata::*; pub use traits::*; use crate::{ - constants::{ASSETS, BALANCES, FUNGIBLES}, + constants::{ASSETS, BALANCES, FUNGIBLES, MODULE_ERROR}, primitives::{AccountId, Balance, TokenId}, ChainExtensionMethodApi, Result, StatusCode, }; From 192366961ab28d7f7bcfc3465a29d2d821b103a9 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 1 Nov 2024 21:18:13 +0700 Subject: [PATCH 161/161] feat(psp22): protect with `owner` --- pop-api/examples/fungibles/Cargo.toml | 5 +-- pop-api/examples/fungibles/README.md | 45 ++++++++++++++++++--------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index c2013185..1882a879 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -15,8 +15,9 @@ drink = { package = "pop-drink", git = "https://github.com/r0gue-io/pop-drink" } env_logger = { version = "0.11.3" } serde_json = "1.0.114" -# TODO: due to compilation issues caused by `sp-runtime` and `staging-xcm` this dependency (with specific -# version) has to be added. Will be tackled by #348, please ignore for now. +# TODO: due to compilation issues caused by `sp-runtime`, `frame-support-procedural` and `staging-xcm` this dependency +# (with specific version) has to be added. Will be tackled by #348, please ignore for now. +frame-support-procedural = { version = "=30.0.1", default-features = false } sp-runtime = { version = "=38.0.0", default-features = false } staging-xcm = { version = "=14.1.0", default-features = false } diff --git a/pop-api/examples/fungibles/README.md b/pop-api/examples/fungibles/README.md index df0b108c..18f29ccf 100644 --- a/pop-api/examples/fungibles/README.md +++ b/pop-api/examples/fungibles/README.md @@ -1,32 +1,47 @@ -# PSP22 Example Contract with Pop Fungibles API +# PSP22 Fungible Token with Pop API -This contract is an example implementation of the [PSP22 standard](https://github.com/inkdevhub/standards/blob/master/PSPs/psp-22.md), utilizing the Pop API Fungibles module. +PSP22 is a fungible token standard for WebAssembly smart contracts running on blockchains based on the [Substrate][substrate] framework. It is an equivalent of Ethereum's [ERC-20][erc20]. The definition of the PSP22 standard can be found [here][psp22]. -- This contract provides core functionalities to manage a PSP22 standard token that exists as an asset on the Pop Network, rather than being confined solely to the contract. -- Only the contract owner has a permission to call specific methods. +This repository contains a simple, minimal implementation of the PSP22 token in [ink!][ink] smart contract programming language (EDSL based on Rust), utilizing the [Pop API Fungibles][pop-api-fungibles] feature. -This design choice is due to the fact that `pop-api` invokes runtime calls with the contract itself as the `origin`. For examples, methods like `transfer` and `transfer_from` will operate on the contract's own account balance, not on the balance of the caller. +> [!IMPORTANT] > This version of the PSP22 contract is compatible with ink! 5. -To learn more about Pop API and how Pop API works under the hood: [Read here](/pop-api/README.md) +## Design Goals -## Security risks prevention +- Token exists as an asset on the Pop Network via [pallet-assets][pallet-assets], rather than being confined solely to the contract. +- Contract is the `origin` of the calls made by `pop-api`. +- Only the contract owner has a permission to call specific methods. -To prevent potential misuse of contract methods by malicious actors—such as using `approve` to grant unauthorized transfer permissions—the contract restricts access exclusively to the `owner` (the account that instantiated the contract). +[Learn more how Pop API works.](/pop-api/README.md) -```rs -self.ensure_owner()?; -``` +## Test with Pop DR!nk -Only the `owner` is permitted to call these methods, ensuring the contract’s balance remains secure. The owner of the contract can be updated by an existing `owner` by calling the method `transfer_ownership`. +Because the contract uses `pop-api` which calls to the runtime, it requires a special crate called [pop-drink][pop-drink] to test the contract. See how the contract is tested in [tests](./tests.rs). ## What can be improved? -- Instead of restricting ownership to a single `owner`, the contract could be designed to accommodate multiple owners. Therefore, the `transfer_ownership` is also need to be updated to support this feature. +- **Multiple owner management**: Instead of restricting ownership to a single `owner`, the contract could be designed to accommodate multiple owners. ## Use cases This contract can be used in multiple different real world cases such as: -- **Use case for a governance token within a [DAO (Decentralized Autonomous Organization)](https://www.investopedia.com/tech/what-dao/)**: The DAO contract performs cross-contract calls to this PSP22 example contract to create a new token, with the DAO authority as the token’s owner. This allows the DAO authority to manage governance tokens for its members by performing actions such as mint and burn. +- **Governance Token in DAO**: The DAO uses this PSP22 contract to create a governance token, with DAO authority as owner, enabling actions like minting and burning tokens to manage member governance. +- **Staking Rewards**: This contract mints and burns tokens for a staking rewards program, allowing the staking authority to distribute rewards only to eligible participants. + +## Support + +Be part of our passionate community of Web3 builders. [Join our Telegram](https://t.me/onpopio)! + +Feel free to raise issues if anything is unclear, have ideas or want to contribute to Pop! + +For any questions related to ink! you can also go to [Polkadot Stack Exchange](https://polkadot.stackexchange.com/) or +ask the [ink! community](https://t.me/inkathon/1). -- **Staking Rewards Program**: This contract can be used to issue rewards in a staking program, where users lock tokens for network security or liquidity. The staking contract calls this PSP22 contract to mint and burn tokens, allowing the staking authority to manage rewards and ensure distribution only to eligible participants. +[ink]: https://use.ink +[substrate]: https://substrate.io +[erc20]: https://ethereum.org/en/developers/docs/standards/tokens/erc-20/ +[psp22]: https://github.com/inkdevhub/standards/blob/master/PSPs/psp-22.md +[pop-api-fungibles]: https://github.com/r0gue-io/pop-node/tree/main/pop-api/src/v0/fungibles +[pallet-assets]: https://crates.io/crates/pallet-assets +[pop-drink]: https://github.com/r0gue-io/pop-drink