diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2bfc1ef..fce9534 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,6 +16,7 @@ default: stages: - fmt - build-linux + - test-contract-caller-linux - build-mac - publish @@ -80,6 +81,18 @@ build-linux: - mkdir -p ./artifacts/substrate-contracts-node-linux/ - cp target/release/substrate-contracts-node ./artifacts/substrate-contracts-node-linux/substrate-contracts-node +### stage: test-contract-caller-linux + +test-contract-caller-linux: + stage: test-contract-caller-linux + <<: *docker-env + <<: *collect-artifacts + <<: *build-refs + variables: + CONTRACTS_NODE: ./artifacts/substrate-contracts-node-linux/substrate-contracts-node + script: + - cargo test --manifest-path ./pallets/contract-caller/contracts/flipper/Cargo.toml --features e2e-tests + ### stage: build-mac build-mac: diff --git a/Cargo.lock b/Cargo.lock index 7d43c54..8361325 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "approx" @@ -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" @@ -404,7 +410,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -1171,7 +1177,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.0", "terminal_size", ] @@ -1306,6 +1312,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" @@ -1405,6 +1431,7 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-contract-caller", "pallet-contracts", "pallet-grandpa", "pallet-insecure-randomness-collective-flip", @@ -2483,6 +2510,41 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -3167,6 +3229,13 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flipper-traits" +version = "5.0.0" +dependencies = [ + "ink", +] + [[package]] name = "float-cmp" version = "0.9.0" @@ -4114,6 +4183,12 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.3" @@ -4252,6 +4327,194 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "ink" +version = "5.0.0" +source = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +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 = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_codegen" +version = "5.0.0" +source = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +dependencies = [ + "blake2 0.10.6", + "derive_more", + "either", + "heck", + "impl-serde", + "ink_ir", + "ink_primitives", + "itertools 0.12.1", + "parity-scale-codec", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.52", +] + +[[package]] +name = "ink_engine" +version = "5.0.0" +source = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +dependencies = [ + "blake2 0.10.6", + "derive_more", + "ink_primitives", + "pallet-contracts-uapi-next", + "parity-scale-codec", + "secp256k1", + "sha2 0.10.8", + "sha3", +] + +[[package]] +name = "ink_env" +version = "5.0.0" +source = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +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", + "sha2 0.10.8", + "sha3", + "static_assertions", +] + +[[package]] +name = "ink_ir" +version = "5.0.0" +source = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +dependencies = [ + "blake2 0.10.6", + "either", + "impl-serde", + "ink_prelude", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "ink_macro" +version = "5.0.0" +source = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +dependencies = [ + "ink_codegen", + "ink_ir", + "ink_primitives", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.52", + "synstructure 0.13.1", +] + +[[package]] +name = "ink_metadata" +version = "5.0.0" +source = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +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 = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "5.0.0" +source = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +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 = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +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 = "git+https://github.com/paritytech/ink/?branch=master#72a671cd4d736b0c6c3f58e5a28a7c178b94e49a" +dependencies = [ + "ink_metadata", + "ink_prelude", + "ink_primitives", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "inout" version = "0.1.3" @@ -4358,6 +4621,15 @@ 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" @@ -5162,6 +5434,26 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "linkme" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cfee0de9bd869589fb9a015e155946d1be5ff415cb844c2caccc6cc4b5db9" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adf157a4dc5a29b7b464aa8fe7edeff30076e07e13646a1c3874f58477dc99f8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "linregress" version = "0.5.3" @@ -5644,7 +5936,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -5669,7 +5961,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -6379,6 +6671,23 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-contract-caller" +version = "4.0.0-dev" +dependencies = [ + "flipper-traits", + "frame-support", + "frame-system", + "ink", + "pallet-contracts", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-contracts" version = "29.0.0" @@ -6436,6 +6745,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 0.5.0", +] + [[package]] name = "pallet-conviction-voting" version = "30.0.0" @@ -9589,6 +9909,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 = "rocksdb" version = "0.21.0" @@ -11247,17 +11573,81 @@ dependencies = [ "sp-arithmetic", ] +[[package]] +name = "scale-bits" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "036575c29af9b6e4866ffb7fa055dbf623fe7a9cc159b33786de6013a6969d89" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "scale-decode" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7caaf753f8ed1ab4752c6afb20174f03598c664724e0e32628e161c21000ff76" +dependencies = [ + "derive_more", + "parity-scale-codec", + "scale-bits", + "scale-decode-derive", + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3475108a1b62c7efd1b5c65974f30109a598b2f45f23c9ae030acb9686966db" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d70cb4b29360105483fac1ed567ff95d65224a14dd275b6303ed0a654c78de5" +dependencies = [ + "derive_more", + "parity-scale-codec", + "scale-encode-derive", + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-encode-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995491f110efdc6bea96d6a746140e32bfceb4ea47510750a5467295a4707a25" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "2ef2175c2907e7c8bc0a9c3f86aeb5ec1f3b275300ad58a44d0c3ae379a5e52e" dependencies = [ "bitvec", "cfg-if", "derive_more", "parity-scale-codec", "scale-info-derive", + "schemars", "serde", ] @@ -11282,6 +11672,30 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + [[package]] name = "schnellru" version = "0.2.1" @@ -11485,6 +11899,17 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_json" version = "1.0.114" @@ -12819,6 +13244,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.0" @@ -13022,6 +13453,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.52", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -13094,9 +13536,9 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] @@ -13123,9 +13565,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", @@ -14908,6 +15350,12 @@ dependencies = [ "syn 2.0.52", ] +[[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" diff --git a/Cargo.toml b/Cargo.toml index f97a1d1..a169c42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ members = [ "node", "runtime", "parachain-runtime", + "pallets/contract-caller", ] [profile.release] diff --git a/pallets/contract-caller/Cargo.toml b/pallets/contract-caller/Cargo.toml new file mode 100644 index 0000000..a7fedef --- /dev/null +++ b/pallets/contract-caller/Cargo.toml @@ -0,0 +1,51 @@ +[package] +name = "pallet-contract-caller" +version = "4.0.0-dev" +description = "Demonstrate calling an ink! contract from a pallet" +authors = ["Substrate DevHub "] +homepage = "https://substrate.io" +edition.workspace = true +license = "MIT-0" +publish = false +repository = "https://github.com/paritytech/substrate-contracts-node" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +frame-support = { workspace = true, default-features = false } +frame-system = { workspace = true, default-features = false } +sp-std = { workspace = true, default-features = false } + +pallet-contracts = { workspace = true, default-features = false } +flipper-traits = { path = "contracts/flipper/traits", default-features = false } +ink = { git = "https://github.com/paritytech/ink/", branch = "master", default-features = false, features = ["no-panic-handler", "no-allocator"] } + +[dev-dependencies] +sp-core = { workspace = true } +sp-io = { workspace = true } +sp-runtime = { workspace = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "pallet-contracts/std", + "ink/std" +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/pallets/contract-caller/contracts/.gitignore b/pallets/contract-caller/contracts/.gitignore new file mode 100755 index 0000000..4531c3e --- /dev/null +++ b/pallets/contract-caller/contracts/.gitignore @@ -0,0 +1,2 @@ +**/target/ +Cargo.lock diff --git a/pallets/contract-caller/contracts/flipper/Cargo.toml b/pallets/contract-caller/contracts/flipper/Cargo.toml new file mode 100755 index 0000000..cd347e0 --- /dev/null +++ b/pallets/contract-caller/contracts/flipper/Cargo.toml @@ -0,0 +1,31 @@ +[workspace] +members = [ + "traits", +] + +[package] +name = "flipper" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { git = "https://github.com/paritytech/ink/", branch = "master", default-features = false, features = ["no-panic-handler", "no-allocator"] } +flipper-traits = { path = "traits", default-features = false } + +[dev-dependencies] +ink_e2e = { git = "https://github.com/paritytech/ink/", package = "ink_e2e", branch = "master" } +frame-support = { version = "30.0.0", default-features = false } +scale-value = "0.13.0" + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "flipper-traits/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/pallets/contract-caller/contracts/flipper/e2e_tests.rs b/pallets/contract-caller/contracts/flipper/e2e_tests.rs new file mode 100644 index 0000000..62d302a --- /dev/null +++ b/pallets/contract-caller/contracts/flipper/e2e_tests.rs @@ -0,0 +1,46 @@ +use super::flipper::*; +use flipper_traits::Flip; +use ink_e2e::{ChainBackend, ContractsBackend}; + +type E2EResult = Result>; + +#[ink_e2e::test] +async fn instantiate_and_get(mut client: Client) -> E2EResult<()> { + let initial_value = false; + let mut constructor = FlipperRef::new(initial_value); + + let contract = client + .instantiate("flipper", &ink_e2e::alice(), &mut constructor) + .submit() + .await + .expect("instantiate failed"); + + let mut call_builder = contract.call_builder::(); + let flip_dry_run = client.call(&ink_e2e::bob(), &call_builder.flip()).dry_run().await?; + let gas_required = flip_dry_run.exec_result.gas_required; + + // call pallet dispatchable + client + .runtime_call( + &ink_e2e::alice(), + "ContractCaller", + "contract_call_flip", + vec![ + scale_value::Value::from_bytes(contract.account_id), + scale_value::serde::to_value(frame_support::weights::Weight::from_parts( + gas_required.ref_time(), + gas_required.proof_size(), + )) + .unwrap(), + ], + ) + .await + .expect("runtime call failed"); + + // now check that the flip was executed via the pallet + let get_result = client.call(&ink_e2e::alice(), &call_builder.get()).dry_run().await?; + + assert_eq!(get_result.return_value(), !initial_value); + + Ok(()) +} diff --git a/pallets/contract-caller/contracts/flipper/lib.rs b/pallets/contract-caller/contracts/flipper/lib.rs new file mode 100755 index 0000000..307ae9e --- /dev/null +++ b/pallets/contract-caller/contracts/flipper/lib.rs @@ -0,0 +1,41 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +#[ink::contract] +mod flipper { + use flipper_traits::Flip; + + /// Defines the storage of your contract. + /// Add new fields to the below struct in order + /// to add new static storage fields to your contract. + #[ink(storage)] + pub struct Flipper { + /// Stores a single `bool` value on the storage. + value: bool, + } + + impl Flipper { + /// Constructor that initializes the `bool` value to the given `init_value`. + #[ink(constructor)] + pub fn new(init_value: bool) -> Self { + Self { value: init_value } + } + } + + impl Flip for Flipper { + /// Flip the value of the stored `bool` from `true` + /// to `false` and vice versa. + #[ink(message)] + fn flip(&mut self) { + self.value = !self.value; + } + + /// Returns the current value of our `bool`. + #[ink(message)] + fn get(&self) -> bool { + self.value + } + } +} + +#[cfg(all(test, feature = "e2e-tests"))] +mod e2e_tests; diff --git a/pallets/contract-caller/contracts/flipper/traits/Cargo.toml b/pallets/contract-caller/contracts/flipper/traits/Cargo.toml new file mode 100644 index 0000000..55c20f5 --- /dev/null +++ b/pallets/contract-caller/contracts/flipper/traits/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "flipper-traits" +version = "5.0.0" +authors = ["Parity Technologies "] +edition = "2021" +publish = false + +[dependencies] +ink = { git = "https://github.com/paritytech/ink/", branch = "master", default-features = false, features = ["no-panic-handler", "no-allocator"] } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", +] diff --git a/pallets/contract-caller/contracts/flipper/traits/lib.rs b/pallets/contract-caller/contracts/flipper/traits/lib.rs new file mode 100644 index 0000000..a89a05c --- /dev/null +++ b/pallets/contract-caller/contracts/flipper/traits/lib.rs @@ -0,0 +1,14 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +/// Allows to flip and get a bool value. +#[ink::trait_definition] +pub trait Flip { + /// Flip the value of the stored `bool` from `true` + /// to `false` and vice versa. + #[ink(message)] + fn flip(&mut self); + + /// Returns the current value of our `bool`. + #[ink(message)] + fn get(&self) -> bool; +} diff --git a/pallets/contract-caller/src/lib.rs b/pallets/contract-caller/src/lib.rs new file mode 100644 index 0000000..29b25a7 --- /dev/null +++ b/pallets/contract-caller/src/lib.rs @@ -0,0 +1,82 @@ +//! # Contract Caller +//! +//! Demonstrates calling into an `ink!` contract from a pallet. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use flipper_traits::Flip; + use frame_support::{pallet_prelude::*, traits::fungible::Inspect}; + use frame_system::pallet_prelude::*; + use ink::codegen::TraitCallBuilder; + + type AccountIdOf = ::AccountId; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_contracts::Config {} + + #[pallet::error] + pub enum Error {} + + #[pallet::call] + impl Pallet + where + [u8; 32]: From<::AccountId>, + <::Currency as Inspect< + ::AccountId, + >>::Balance: From, + { + /// Call the flip method on the contract at the given `contract` account. + #[pallet::call_index(0)] + #[pallet::weight(::call().saturating_add(*gas_limit))] + pub fn contract_call_flip( + origin: OriginFor, + contract: AccountIdOf, + gas_limit: Weight, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + let ink_account_id = + ink::primitives::AccountId::from(<[u8; 32]>::from(contract.clone())); + let mut flipper: ink::contract_ref!(Flip, ink::env::DefaultEnvironment) = + ink_account_id.into(); + let call_builder = flipper.call_mut(); + + let params = call_builder + .flip() + .ref_time_limit(gas_limit.ref_time()) + .proof_size_limit(gas_limit.proof_size()) + .params(); + + // Next step is to explore ways to encapsulate the following into the call builder. + let value = *params.transferred_value(); + let data = params.exec_input().encode(); + let weight = Weight::from_parts(params.ref_time_limit(), params.proof_size_limit()); + let storage_deposit_limit = params.storage_deposit_limit().map(|limit| (*limit).into()); + + let result = pallet_contracts::Pallet::::bare_call( + who.clone(), + contract.clone(), + value.into(), + weight, + storage_deposit_limit, + data, + pallet_contracts::DebugInfo::Skip, + pallet_contracts::CollectEvents::Skip, + pallet_contracts::Determinism::Enforced, + ) + .result?; + + assert!(!result.did_revert()); + + Ok(()) + } + } +} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 15896f5..e627aa1 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -57,6 +57,9 @@ pallet-utility = { workspace = true } frame-benchmarking = { workspace = true, optional = true } frame-system-benchmarking = { workspace = true , optional = true} +# Local Dependencies +pallet-contract-caller = { path = "../pallets/contract-caller", default-features = false } + [build-dependencies] substrate-wasm-builder = { workspace = true, optional = true } @@ -76,6 +79,7 @@ std = [ "pallet-authorship/std", "pallet-balances/std", "pallet-contracts/std", + "pallet-contract-caller/std", "pallet-grandpa/std", "pallet-insecure-randomness-collective-flip/std", "pallet-sudo/std", diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 0138851..bad9e01 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -266,6 +266,8 @@ impl pallet_utility::Config for Runtime { type WeightInfo = pallet_utility::weights::SubstrateWeight; } +impl pallet_contract_caller::Config for Runtime {} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub struct Runtime { @@ -279,6 +281,7 @@ construct_runtime!( Sudo: pallet_sudo, Contracts: pallet_contracts, Assets: pallet_assets, + ContractCaller: pallet_contract_caller, } );