From c62ea254b3a5a4a8b62e1d1a746ef831a00e663b Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 21 Oct 2022 23:24:16 -0400 Subject: [PATCH 001/102] Add example cross-chain contract --- examples/cross_chain_test/.gitignore | 9 +++++++++ examples/cross_chain_test/Cargo.toml | 28 ++++++++++++++++++++++++++ examples/cross_chain_test/lib.rs | 30 ++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100755 examples/cross_chain_test/.gitignore create mode 100755 examples/cross_chain_test/Cargo.toml create mode 100755 examples/cross_chain_test/lib.rs diff --git a/examples/cross_chain_test/.gitignore b/examples/cross_chain_test/.gitignore new file mode 100755 index 00000000000..8de8f877e47 --- /dev/null +++ b/examples/cross_chain_test/.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/examples/cross_chain_test/Cargo.toml b/examples/cross_chain_test/Cargo.toml new file mode 100755 index 00000000000..5055bb6dc9e --- /dev/null +++ b/examples/cross_chain_test/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "cross_chain_test" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { path = "../../crates/ink", default-features = false } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } + +[lib] +name = "cross_chain_test" +path = "lib.rs" +crate-type = [ + # Used for normal contract Wasm blobs. + "cdylib", +] + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", +] +ink-as-dependency = [] diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs new file mode 100755 index 00000000000..14518e96386 --- /dev/null +++ b/examples/cross_chain_test/lib.rs @@ -0,0 +1,30 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +#[ink::contract] +mod cross_chain_test { + + #[ink(storage)] + pub struct CrossChainTest {} + + impl CrossChainTest { + #[ink(constructor)] + pub fn new() -> Self { + Self {} + } + + #[ink(message)] + pub fn call(&mut self, address: AccountId, selector: [u8; 4]) { + use ink::env::{ + call::{build_call, Call, ExecutionInput, Selector}, + DefaultEnvironment, + }; + + build_call::() + .call_type(Call::new().callee(address)) + .exec_input(ExecutionInput::new(Selector::new(selector))) + .returns::<()>() + .fire() + .unwrap(); + } + } +} From 5e8cd1ea6897263e4f237fd5c4a3cf53525964c1 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 24 Oct 2022 19:02:57 -0400 Subject: [PATCH 002/102] Update `CallBuilder`'s return type to a `Result` We're gonna try and handle an ink! error later --- crates/env/src/call/call_builder.rs | 37 ++++++++++++++----- .../generator/as_dependency/call_builder.rs | 4 +- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs index 60c051f879d..f6d51c28676 100644 --- a/crates/env/src/call/call_builder.rs +++ b/crates/env/src/call/call_builder.rs @@ -42,7 +42,7 @@ where /// The flags used to change the behavior of a contract call. call_flags: CallFlags, /// The expected return type. - _return_type: ReturnType, + _return_type: ReturnType>, /// The inputs to the execution which is a selector and encoded arguments. exec_input: ExecutionInput, /// `Environment` is used by `CallType` for correct types @@ -244,7 +244,7 @@ pub fn build_call() -> CallBuilder< E, Unset>, Unset>, - Unset>, + Unset>>, > where E: Environment, @@ -397,7 +397,7 @@ where } } -impl CallBuilder>> +impl CallBuilder>>> where E: Environment, { @@ -408,7 +408,9 @@ where /// Either use `.returns::<()>` to signal that the call does not return a value /// or use `.returns::` to signal that the call returns a value of type `T`. #[inline] - pub fn returns(self) -> CallBuilder>> { + pub fn returns( + self, + ) -> CallBuilder>>> { CallBuilder { call_type: self.call_type, call_flags: self.call_flags, @@ -509,7 +511,12 @@ where } impl - CallBuilder>, Set>, Set>> + CallBuilder< + E, + Set>, + Set>, + Set>>, + > where E: Environment, { @@ -530,7 +537,7 @@ impl E, Set>, Set>, - Set>, + Set>>, > where E: Environment, @@ -591,7 +598,7 @@ impl E, Set>, Unset>, - Unset>, + Unset>>, > where E: Environment, @@ -607,7 +614,7 @@ impl E, Set>, Unset>, - Unset>, + Unset>>, > where E: Environment, @@ -619,7 +626,12 @@ where } impl - CallBuilder>, Set>, Set>> + CallBuilder< + E, + Set>, + Set>, + Set>>, + > where E: Environment, Args: scale::Encode, @@ -632,7 +644,12 @@ where } impl - CallBuilder>, Set>, Set>> + CallBuilder< + E, + Set>, + Set>, + Set>>, + > where E: Environment, Args: scale::Encode, diff --git a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs index bea33bf0542..81b1c7b78e6 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -378,7 +378,9 @@ impl CallBuilder<'_> { Environment, ::ink::env::call::utils::Set< ::ink::env::call::Call< Environment > >, ::ink::env::call::utils::Set< ::ink::env::call::ExecutionInput<#arg_list> >, - ::ink::env::call::utils::Set< ::ink::env::call::utils::ReturnType<#return_type> >, + ::ink::env::call::utils::Set< ::ink::env::call::utils::ReturnType< + ::core::result::Result<#return_type, ()> + >>, > ); quote_spanned!(span=> From 728c45cda14ea682ffda95afcdfccf8e99dce247 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 25 Oct 2022 15:42:35 -0400 Subject: [PATCH 003/102] Write to output buffer on dispatch error --- crates/env/src/call/call_builder.rs | 37 +++++-------------- crates/env/src/engine/on_chain/ext.rs | 1 + crates/env/src/engine/on_chain/impls.rs | 6 ++- .../generator/as_dependency/call_builder.rs | 2 +- crates/ink/codegen/src/generator/dispatch.rs | 30 ++++++++++----- examples/cross_chain_test/lib.rs | 9 +++-- 6 files changed, 42 insertions(+), 43 deletions(-) diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs index f6d51c28676..60c051f879d 100644 --- a/crates/env/src/call/call_builder.rs +++ b/crates/env/src/call/call_builder.rs @@ -42,7 +42,7 @@ where /// The flags used to change the behavior of a contract call. call_flags: CallFlags, /// The expected return type. - _return_type: ReturnType>, + _return_type: ReturnType, /// The inputs to the execution which is a selector and encoded arguments. exec_input: ExecutionInput, /// `Environment` is used by `CallType` for correct types @@ -244,7 +244,7 @@ pub fn build_call() -> CallBuilder< E, Unset>, Unset>, - Unset>>, + Unset>, > where E: Environment, @@ -397,7 +397,7 @@ where } } -impl CallBuilder>>> +impl CallBuilder>> where E: Environment, { @@ -408,9 +408,7 @@ where /// Either use `.returns::<()>` to signal that the call does not return a value /// or use `.returns::` to signal that the call returns a value of type `T`. #[inline] - pub fn returns( - self, - ) -> CallBuilder>>> { + pub fn returns(self) -> CallBuilder>> { CallBuilder { call_type: self.call_type, call_flags: self.call_flags, @@ -511,12 +509,7 @@ where } impl - CallBuilder< - E, - Set>, - Set>, - Set>>, - > + CallBuilder>, Set>, Set>> where E: Environment, { @@ -537,7 +530,7 @@ impl E, Set>, Set>, - Set>>, + Set>, > where E: Environment, @@ -598,7 +591,7 @@ impl E, Set>, Unset>, - Unset>>, + Unset>, > where E: Environment, @@ -614,7 +607,7 @@ impl E, Set>, Unset>, - Unset>>, + Unset>, > where E: Environment, @@ -626,12 +619,7 @@ where } impl - CallBuilder< - E, - Set>, - Set>, - Set>>, - > + CallBuilder>, Set>, Set>> where E: Environment, Args: scale::Encode, @@ -644,12 +632,7 @@ where } impl - CallBuilder< - E, - Set>, - Set>, - Set>>, - > + CallBuilder>, Set>, Set>> where E: Environment, Args: scale::Encode, diff --git a/crates/env/src/engine/on_chain/ext.rs b/crates/env/src/engine/on_chain/ext.rs index f38f301c6d2..ce78cdd5750 100644 --- a/crates/env/src/engine/on_chain/ext.rs +++ b/crates/env/src/engine/on_chain/ext.rs @@ -28,6 +28,7 @@ macro_rules! define_error_codes { ) => { /// Every error that can be returned to a contract when it calls any of the host functions. #[repr(u32)] + #[derive(::core::fmt::Debug)] pub enum Error { $( $( #[$attr] )* diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 85d7c5f5475..dc1e90bf114 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -425,7 +425,11 @@ impl TypedEnvBackend for EnvInstance { output, ); match call_result { - Ok(()) | Err(ext::Error::CalleeReverted) => { + Ok(()) => { + let decoded = scale::Decode::decode(&mut &output[..])?; + Ok(decoded) + } + Err(ext::Error::CalleeReverted) => { let decoded = scale::Decode::decode(&mut &output[..])?; Ok(decoded) } diff --git a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs index 81b1c7b78e6..4765c3427fd 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -379,7 +379,7 @@ impl CallBuilder<'_> { ::ink::env::call::utils::Set< ::ink::env::call::Call< Environment > >, ::ink::env::call::utils::Set< ::ink::env::call::ExecutionInput<#arg_list> >, ::ink::env::call::utils::Set< ::ink::env::call::utils::ReturnType< - ::core::result::Result<#return_type, ()> + #return_type >>, > ); diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 640383ef0a0..d2a54e6daf1 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -432,16 +432,25 @@ impl Dispatch<'_> { .unwrap_or_else(|error| ::core::panic!("{}", error)) } - ::ink::env::decode_input::< - <#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type>() - .map_err(|_| ::ink::reflect::DispatchError::CouldNotReadInput) - .and_then(|decoder| { - <<#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type - as ::ink::reflect::ExecuteDispatchable>::execute_dispatchable(decoder) - }) - .unwrap_or_else(|error| { - ::core::panic!("dispatching ink! message failed: {}", error) - }) + let result = ::ink::env::decode_input::< + <#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type>(); + ::ink::env::debug_println!("Result from `decode_input` {:?}", &result); + + if result.is_err() { + ::ink::env::return_value::<::core::result::Result<(), u8>>( + ::ink::env::ReturnFlags::default().set_reverted(true), &Err(1234) + ) + } + + // TODO: Stop handling this `DispatchError` + result.map_err(|_| ::ink::reflect::DispatchError::CouldNotReadInput) + .and_then(|decoder| { + <<#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type + as ::ink::reflect::ExecuteDispatchable>::execute_dispatchable(decoder) + }) + .unwrap_or_else(|error| { + ::core::panic!("dispatching ink! message failed: {}", error) + }) } ) } @@ -783,6 +792,7 @@ impl Dispatch<'_> { quote_spanned!(span=> const _: () = { #[allow(non_camel_case_types)] + #[derive(::core::fmt::Debug)] pub enum __ink_MessageDecoder { #( #message_variants ),* } diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 14518e96386..624c09d7f58 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -19,12 +19,13 @@ mod cross_chain_test { DefaultEnvironment, }; - build_call::() + let result = build_call::() .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) - .returns::<()>() - .fire() - .unwrap(); + .returns::>() + .fire(); + + ink::env::debug_println!("cross_contract::call output: {:?}", &result); } } } From 810ea54167b17d0c71d72c7207a2bfe7e736b9b6 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 25 Oct 2022 16:38:45 -0400 Subject: [PATCH 004/102] Whoops, reduce value of `u8` --- crates/ink/codegen/src/generator/dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index d2a54e6daf1..6d8cffd35a8 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -438,7 +438,7 @@ impl Dispatch<'_> { if result.is_err() { ::ink::env::return_value::<::core::result::Result<(), u8>>( - ::ink::env::ReturnFlags::default().set_reverted(true), &Err(1234) + ::ink::env::ReturnFlags::default().set_reverted(true), &Err(123) ) } From 980f6a71f273577ed745ac3c2cbfe73ee3019722 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 25 Oct 2022 18:06:45 -0400 Subject: [PATCH 005/102] Add some `cargo-contract` automation helpers --- call-contract.sh | 27 +++++++++++++++++++++++++++ deploy-contract.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100755 call-contract.sh create mode 100755 deploy-contract.sh diff --git a/call-contract.sh b/call-contract.sh new file mode 100755 index 00000000000..b05d10081ba --- /dev/null +++ b/call-contract.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -ex + +F=$1 +CROSS_CONTRACT_ADDR=$2 +FLIPPER_ADDR=$3 + +SELECTOR="0x633aa551" +BAD_SELECTOR="0x00000000" + +args=() +args+=( --contract ${CROSS_CONTRACT_ADDR} ) +args+=( --message call ) +args+=( --suri //Alice ) +args+=( --manifest-path ./examples/cross_chain_test/Cargo.toml ) +args+=( --verbose ) +args+=( --skip-confirm ) + +case $F in + '--fail') + args+=( --args $FLIPPER_ADDR $BAD_SELECTOR ) ;; + *) + args+=( --args $FLIPPER_ADDR $SELECTOR ) ;; + esac + +cargo contract call "${args[@]}" diff --git a/deploy-contract.sh b/deploy-contract.sh new file mode 100755 index 00000000000..0a689f63cc9 --- /dev/null +++ b/deploy-contract.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -ex + +F=$1 + +cargo contract build --manifest-path examples/flipper/Cargo.toml --skip-linting +cargo contract instantiate \ + --manifest-path examples/flipper/Cargo.toml \ + --suri //Alice --output-json \ + --constructor default \ + --salt $(date +%s) \ + --skip-confirm > /tmp/deployment-output.json + +FLIPPER_ADDRESS=$(tail -n +2 /tmp/deployment-output.json | jq --raw-output .contract) +echo $FLIPPER_ADDRESS + +cargo contract build --manifest-path examples/cross_chain_test/Cargo.toml --skip-linting +cargo contract instantiate \ + --manifest-path examples/cross_chain_test/Cargo.toml \ + --suri //Alice --output-json \ + --salt $(date +%s) \ + --skip-confirm > /tmp/deployment-output.json + + CROSS_ADDRESS=$(tail -n +2 /tmp/deployment-output.json | jq --raw-output .contract) + echo $CROSS_ADDRESS + + ./call-contract.sh $F $CROSS_ADDRESS $FLIPPER_ADDRESS From 6181d9cba9e38b4e950c1e81c0ad31f7a5084736 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 25 Oct 2022 18:22:55 -0400 Subject: [PATCH 006/102] Set default if no input is given --- call-contract.sh | 2 +- deploy-contract.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/call-contract.sh b/call-contract.sh index b05d10081ba..0aab6a12359 100755 --- a/call-contract.sh +++ b/call-contract.sh @@ -2,7 +2,7 @@ set -ex -F=$1 +F="${1:-pass}" CROSS_CONTRACT_ADDR=$2 FLIPPER_ADDR=$3 diff --git a/deploy-contract.sh b/deploy-contract.sh index 0a689f63cc9..5ad4b75e6b6 100755 --- a/deploy-contract.sh +++ b/deploy-contract.sh @@ -2,7 +2,7 @@ set -ex -F=$1 +F="${1:-pass}" cargo contract build --manifest-path examples/flipper/Cargo.toml --skip-linting cargo contract instantiate \ From 63fc94c9f5d8c27ee9e44bbc8bae6d10989ee3df Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 25 Oct 2022 19:07:28 -0400 Subject: [PATCH 007/102] Return type expected by call builder after succesful dispatch --- crates/env/src/engine/on_chain/impls.rs | 18 +++++++++++++---- crates/ink/codegen/src/generator/dispatch.rs | 21 ++++++++++++++------ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index dc1e90bf114..0780e4e8294 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -426,12 +426,22 @@ impl TypedEnvBackend for EnvInstance { ); match call_result { Ok(()) => { - let decoded = scale::Decode::decode(&mut &output[..])?; - Ok(decoded) + // let decoded = scale::Decode::decode(&mut &output[..])?; + // Ok(decoded) + if let Ok(decoded) = scale::Decode::decode(&mut &output[..]) { + Ok(decoded) + } else { + ::core::panic!("failed to decode successful message output"); + } } Err(ext::Error::CalleeReverted) => { - let decoded = scale::Decode::decode(&mut &output[..])?; - Ok(decoded) + // let decoded = scale::Decode::decode(&mut &output[..])?; + // Ok(decoded) + if let Ok(decoded) = scale::Decode::decode(&mut &output[..]) { + Ok(decoded) + } else { + ::core::panic!("failed to decode reverted message output"); + } } Err(actual_error) => Err(actual_error.into()), } diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 6d8cffd35a8..444ad4644d1 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -436,6 +436,8 @@ impl Dispatch<'_> { <#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type>(); ::ink::env::debug_println!("Result from `decode_input` {:?}", &result); + // TOOD: Here will pick out the `Dispatch` error we're interested in telling the + // user about and encode it correctly if result.is_err() { ::ink::env::return_value::<::core::result::Result<(), u8>>( ::ink::env::ReturnFlags::default().set_reverted(true), &Err(123) @@ -779,12 +781,19 @@ impl Dispatch<'_> { push_contract(contract, #mutates_storage); - if ::core::any::TypeId::of::<#message_output>() != ::core::any::TypeId::of::<()>() { - // In case the return type is `()` we do not return a value. - ::ink::env::return_value::<#message_output>( - ::ink::env::ReturnFlags::default(), &result - ) - } + // if ::core::any::TypeId::of::<#message_output>() != ::core::any::TypeId::of::<()>() { + // // In case the return type is `()` we do not return a value. + // ::ink::env::return_value::<#message_output>( + // ::ink::env::ReturnFlags::default(), &result + // ) + // } + + // We manually wrap the message output in a `Result` since that's what the + // `CallBuilder` is expecting, otherwise we can't decode the output correctly + ::ink::env::return_value::<::core::result::Result<#message_output, u8>>( + ::ink::env::ReturnFlags::default(), &Ok(result) + ) + } ) }); From 4280d370d3fdb23508ba85f7243620846aaa778f Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 25 Oct 2022 19:08:38 -0400 Subject: [PATCH 008/102] Fix typo --- crates/ink/codegen/src/generator/dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 444ad4644d1..8bfc6c7ead2 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -436,7 +436,7 @@ impl Dispatch<'_> { <#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type>(); ::ink::env::debug_println!("Result from `decode_input` {:?}", &result); - // TOOD: Here will pick out the `Dispatch` error we're interested in telling the + // TODO: Here will pick out the `Dispatch` error we're interested in telling the // user about and encode it correctly if result.is_err() { ::ink::env::return_value::<::core::result::Result<(), u8>>( From 474133a06f911da9c78d7da409c9dc133f26b5b5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 26 Oct 2022 13:24:52 -0400 Subject: [PATCH 009/102] Return an actual `DispatchError` back to the caller --- .../generator/as_dependency/call_builder.rs | 4 +- crates/ink/codegen/src/generator/dispatch.rs | 38 ++++++++++--------- crates/ink/src/reflect/dispatch.rs | 2 +- examples/cross_chain_test/lib.rs | 3 +- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs index 4765c3427fd..bea33bf0542 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -378,9 +378,7 @@ impl CallBuilder<'_> { Environment, ::ink::env::call::utils::Set< ::ink::env::call::Call< Environment > >, ::ink::env::call::utils::Set< ::ink::env::call::ExecutionInput<#arg_list> >, - ::ink::env::call::utils::Set< ::ink::env::call::utils::ReturnType< - #return_type - >>, + ::ink::env::call::utils::Set< ::ink::env::call::utils::ReturnType<#return_type> >, > ); quote_spanned!(span=> diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 8bfc6c7ead2..0144e822272 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -432,24 +432,28 @@ impl Dispatch<'_> { .unwrap_or_else(|error| ::core::panic!("{}", error)) } - let result = ::ink::env::decode_input::< - <#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type>(); - ::ink::env::debug_println!("Result from `decode_input` {:?}", &result); - - // TODO: Here will pick out the `Dispatch` error we're interested in telling the - // user about and encode it correctly - if result.is_err() { - ::ink::env::return_value::<::core::result::Result<(), u8>>( - ::ink::env::ReturnFlags::default().set_reverted(true), &Err(123) - ) - } + let dispatchable = match ::ink::env::decode_input::< + <#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type>() { + Ok(decoded_dispatchable) => { + ::ink::env::debug_println!("Result from `decode_input` {:?}", &decoded_dispatchable); + decoded_dispatchable + }, + Err(_decoding_error) => { + ::ink::env::debug_println!("Result from `decode_input` {:?}", &_decoding_error); + + // TODO: Here will pick out the `Dispatch` error we're interested in telling the + // user about and encode it correctly + let error = ::core::result::Result::Err( + ::ink::reflect::DispatchError::CouldNotReadInput + ); + ::ink::env::return_value::<::core::result::Result<(), ::ink::reflect::DispatchError>>( + ::ink::env::ReturnFlags::default().set_reverted(true), &error + ); + } + }; - // TODO: Stop handling this `DispatchError` - result.map_err(|_| ::ink::reflect::DispatchError::CouldNotReadInput) - .and_then(|decoder| { - <<#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type - as ::ink::reflect::ExecuteDispatchable>::execute_dispatchable(decoder) - }) + <<#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type + as ::ink::reflect::ExecuteDispatchable>::execute_dispatchable(dispatchable) .unwrap_or_else(|error| { ::core::panic!("dispatching ink! message failed: {}", error) }) diff --git a/crates/ink/src/reflect/dispatch.rs b/crates/ink/src/reflect/dispatch.rs index e5c64e67f63..e517e1aaad3 100644 --- a/crates/ink/src/reflect/dispatch.rs +++ b/crates/ink/src/reflect/dispatch.rs @@ -513,7 +513,7 @@ pub trait ExecuteDispatchable { } /// An error that can occur during dispatch of ink! dispatchables. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, ::scale::Encode, ::scale::Decode)] pub enum DispatchError { /// Failed to decode into a valid dispatch selector. InvalidSelector, diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 624c09d7f58..001610fd243 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -22,7 +22,8 @@ mod cross_chain_test { let result = build_call::() .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) - .returns::>() + .returns::>() + // .returns::<()>() .fire(); ink::env::debug_println!("cross_contract::call output: {:?}", &result); From e3f67ea816dd8b668721fe391ce8c5247243fbb9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 31 Oct 2022 12:23:40 +0100 Subject: [PATCH 010/102] Temporarily stop generating contract ref code --- crates/ink/codegen/src/generator/contract.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/ink/codegen/src/generator/contract.rs b/crates/ink/codegen/src/generator/contract.rs index 1662b826428..75f9a0a41f8 100644 --- a/crates/ink/codegen/src/generator/contract.rs +++ b/crates/ink/codegen/src/generator/contract.rs @@ -42,8 +42,7 @@ impl GenerateCode for Contract<'_> { let dispatch2 = self.generate_code_using::(); let item_impls = self.generate_code_using::(); let metadata = self.generate_code_using::(); - let contract_reference = - self.generate_code_using::(); + // let contract_reference = self.generate_code_using::(); let non_ink_items = self .contract .module() @@ -58,7 +57,7 @@ impl GenerateCode for Contract<'_> { #events #dispatch2 #item_impls - #contract_reference + // #contract_reference #metadata #( #non_ink_items )* } From 6a04bd1115b82c759eb04945dc1cf1da93aafef0 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 31 Oct 2022 12:24:13 +0100 Subject: [PATCH 011/102] Manually change message return type to Result --- crates/ink/codegen/src/generator/dispatch.rs | 5 +++++ .../ink/codegen/src/generator/item_impls.rs | 20 +++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 0144e822272..ab953ec5b93 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -298,10 +298,15 @@ impl Dispatch<'_> { let mutates = message.receiver().is_ref_mut(); let selector_id = message.composed_selector().into_be_u32().hex_padded_suffixed(); let selector_bytes = message.composed_selector().hex_lits(); + let output_tuple_type = message .output() .map(quote::ToTokens::to_token_stream) .unwrap_or_else(|| quote! { () }); + let output_tuple_type = quote! { + ::core::result::Result<#output_tuple_type, u8> + }; + let input_bindings = generator::input_bindings(message.inputs()); let input_tuple_type = generator::input_types_tuple(message.inputs()); let input_tuple_bindings = generator::input_bindings_tuple(message.inputs()); diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index 4122d832519..1aa39c6d24d 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -256,13 +256,25 @@ impl ItemImpls<'_> { let receiver = message.receiver(); let ident = message.ident(); let inputs = message.inputs(); - let output_arrow = message.output().map(|_| quote! { -> }); - let output = message.output(); + // let output_arrow = message.output().map(|_| quote! { -> }); + // let output = message.output(); + + let output = message + .output() + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote! { () }); + let output = quote! { + ::core::result::Result<#output, u8> + }; + let statements = message.statements(); quote_spanned!(span => #( #attrs )* - #vis fn #ident(#receiver #( , #inputs )* ) #output_arrow #output { - #( #statements )* + #vis fn #ident(#receiver #( , #inputs )* ) -> #output { + let mut f = || { #( #statements )* }; + let o = f(); + ::core::result::Result::Ok(o) + } ) } From 5c9d2500254bfaf3116bc1a29d0ccead3e6770cc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 31 Oct 2022 13:12:27 +0100 Subject: [PATCH 012/102] Transform message return type in the IR --- crates/ink/codegen/src/generator/dispatch.rs | 15 +++++++------ .../ink/codegen/src/generator/item_impls.rs | 15 ++++++++----- crates/ink/codegen/src/generator/metadata.rs | 4 +++- crates/ink/ir/src/ir/item_impl/message.rs | 21 +++++++++++++++++++ 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index ab953ec5b93..d94fba32c8e 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -299,13 +299,16 @@ impl Dispatch<'_> { let selector_id = message.composed_selector().into_be_u32().hex_padded_suffixed(); let selector_bytes = message.composed_selector().hex_lits(); - let output_tuple_type = message - .output() - .map(quote::ToTokens::to_token_stream) + let output_tuple_type = message.map_result() + .map(|ty| quote::ToTokens::to_token_stream(&ty)) .unwrap_or_else(|| quote! { () }); - let output_tuple_type = quote! { - ::core::result::Result<#output_tuple_type, u8> - }; + // let output_tuple_type = message + // .output() + // .map(quote::ToTokens::to_token_stream) + // .unwrap_or_else(|| quote! { () }); + // let output_tuple_type = quote! { + // ::core::result::Result<#output_tuple_type, u8> + // }; let input_bindings = generator::input_bindings(message.inputs()); let input_tuple_type = generator::input_types_tuple(message.inputs()); diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index 1aa39c6d24d..f9f13fc8255 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -260,12 +260,17 @@ impl ItemImpls<'_> { // let output = message.output(); let output = message - .output() - .map(quote::ToTokens::to_token_stream) + .map_result() + .map(|ty| quote::ToTokens::to_token_stream(&ty)) .unwrap_or_else(|| quote! { () }); - let output = quote! { - ::core::result::Result<#output, u8> - }; + + // let output = message + // .output() + // .map(quote::ToTokens::to_token_stream) + // .unwrap_or_else(|| quote! { () }); + // let output = quote! { + // ::core::result::Result<#output, u8> + // }; let statements = message.statements(); quote_spanned!(span => diff --git a/crates/ink/codegen/src/generator/metadata.rs b/crates/ink/codegen/src/generator/metadata.rs index 63f477bb232..bb352079b7b 100644 --- a/crates/ink/codegen/src/generator/metadata.rs +++ b/crates/ink/codegen/src/generator/metadata.rs @@ -166,6 +166,7 @@ impl Metadata<'_> { fn without_display_name(ty: &syn::Type) -> TokenStream2 { quote! { ::ink::metadata::TypeSpec::new::<#ty>() } } + if let syn::Type::Path(type_path) = ty { if type_path.qself.is_some() { return without_display_name(ty) @@ -219,7 +220,8 @@ impl Metadata<'_> { let mutates = message.receiver().is_ref_mut(); let ident = message.ident(); let args = message.inputs().map(Self::generate_dispatch_argument); - let ret_ty = Self::generate_return_type(message.output()); + // let ret_ty = Self::generate_return_type(message.output()); + let ret_ty = Self::generate_return_type(message.map_result().as_ref()); quote_spanned!(span => ::ink::metadata::MessageSpec::from_label(::core::stringify!(#ident)) .selector([ diff --git a/crates/ink/ir/src/ir/item_impl/message.rs b/crates/ink/ir/src/ir/item_impl/message.rs index 85ebcb29015..37b4cb61770 100644 --- a/crates/ink/ir/src/ir/item_impl/message.rs +++ b/crates/ink/ir/src/ir/item_impl/message.rs @@ -291,6 +291,27 @@ impl Message { } } + // TODO: Maybe get rid of `Option` here, only keeping for initial compatibility + pub fn map_result(&self) -> Option { + let o = match &self.item.sig.output { + syn::ReturnType::Default => None, + syn::ReturnType::Type(_, return_type) => Some(return_type), + }; + + let return_type = o + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote::quote! { () }); + + let result = quote::quote! { + ::core::result::Result<#return_type, u8> + }; + + let return_type: syn::Type = + syn::parse2::(result).expect("Failed to parse into Type"); + + Some(return_type) + } + /// Returns a local ID unique to the ink! message with respect to its implementation block. /// /// # Note From a989be6c45896ed6b90997d0e94cfe7401618d3d Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 31 Oct 2022 14:29:11 +0100 Subject: [PATCH 013/102] Change message return type when generating contract reference --- .../src/generator/as_dependency/call_builder.rs | 11 ++++++++--- .../src/generator/as_dependency/contract_ref.rs | 5 +++-- crates/ink/codegen/src/generator/contract.rs | 5 +++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs index bea33bf0542..d375b0fc115 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -369,9 +369,14 @@ impl CallBuilder<'_> { let input_types = generator::input_types(message.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = callable.receiver().is_ref_mut().then(|| quote! { mut }); - let output = message.output(); - let return_type = - output.map_or_else(|| quote! { () }, |output| quote! { #output }); + + // let output = message.output(); + // let return_type = + // output.map_or_else(|| quote! { () }, |output| quote! { #output }); + + let output = message.map_result().expect("Always returns Some atm"); + let return_type = output.clone(); + let output_span = output.span(); let output_type = quote_spanned!(output_span=> ::ink::env::call::CallBuilder< diff --git a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs index cfc75401cdd..336740af38d 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -343,14 +343,15 @@ impl ContractRef<'_> { let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let input_types = message.inputs().map(|input| &input.ty).collect::>(); - let output_type = message.output().map(|ty| quote! { -> #ty }); + // let output_type = message.output().map(|ty| quote! { -> #ty }); + let output_type = message.map_result().expect("This always returns Some atm"); quote_spanned!(span=> #( #attrs )* #[inline] pub fn #message_ident( & #mut_token self #( , #input_bindings : #input_types )* - ) #output_type { + ) -> #output_type { ::#call_operator(self) .#message_ident( #( #input_bindings ),* ) .fire() diff --git a/crates/ink/codegen/src/generator/contract.rs b/crates/ink/codegen/src/generator/contract.rs index 75f9a0a41f8..1662b826428 100644 --- a/crates/ink/codegen/src/generator/contract.rs +++ b/crates/ink/codegen/src/generator/contract.rs @@ -42,7 +42,8 @@ impl GenerateCode for Contract<'_> { let dispatch2 = self.generate_code_using::(); let item_impls = self.generate_code_using::(); let metadata = self.generate_code_using::(); - // let contract_reference = self.generate_code_using::(); + let contract_reference = + self.generate_code_using::(); let non_ink_items = self .contract .module() @@ -57,7 +58,7 @@ impl GenerateCode for Contract<'_> { #events #dispatch2 #item_impls - // #contract_reference + #contract_reference #metadata #( #non_ink_items )* } From a9cae76f77fec26e944463f92caeba22b415826f Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 1 Nov 2022 13:06:14 +0100 Subject: [PATCH 014/102] Return message output directly in the codegen --- crates/ink/codegen/src/generator/dispatch.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index d94fba32c8e..b26654c15db 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -454,6 +454,13 @@ impl Dispatch<'_> { let error = ::core::result::Result::Err( ::ink::reflect::DispatchError::CouldNotReadInput ); + + // TODO: We'll need to get the correct output type here, e.g + // #message_output + // + // Don't think we can get the value for `T` here, since if there's no + // dispatchable we don't know what it should be We always return an `Err` + // here anyways, so maybe it's okay? ::ink::env::return_value::<::core::result::Result<(), ::ink::reflect::DispatchError>>( ::ink::env::ReturnFlags::default().set_reverted(true), &error ); @@ -462,6 +469,7 @@ impl Dispatch<'_> { <<#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type as ::ink::reflect::ExecuteDispatchable>::execute_dispatchable(dispatchable) + .unwrap_or_else(|error| { ::core::panic!("dispatching ink! message failed: {}", error) }) @@ -802,8 +810,8 @@ impl Dispatch<'_> { // We manually wrap the message output in a `Result` since that's what the // `CallBuilder` is expecting, otherwise we can't decode the output correctly - ::ink::env::return_value::<::core::result::Result<#message_output, u8>>( - ::ink::env::ReturnFlags::default(), &Ok(result) + ::ink::env::return_value::<#message_output>( + ::ink::env::ReturnFlags::default(), &result ) } From b3e0141eaebc76b4e77a6246a8ba8669ecff89db Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 1 Nov 2022 17:12:07 +0100 Subject: [PATCH 015/102] Add error type for handling language errors --- crates/ink/codegen/src/generator/dispatch.rs | 4 ++-- crates/ink/ir/src/ir/item_impl/message.rs | 2 +- crates/ink/src/lib.rs | 1 + crates/metadata/src/lib.rs | 2 ++ crates/primitives/src/lib.rs | 11 +++++++++++ examples/cross_chain_test/lib.rs | 2 +- 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index b26654c15db..b7fd1216436 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -452,7 +452,7 @@ impl Dispatch<'_> { // TODO: Here will pick out the `Dispatch` error we're interested in telling the // user about and encode it correctly let error = ::core::result::Result::Err( - ::ink::reflect::DispatchError::CouldNotReadInput + ::ink::LangError::CouldNotReadInput ); // TODO: We'll need to get the correct output type here, e.g @@ -461,7 +461,7 @@ impl Dispatch<'_> { // Don't think we can get the value for `T` here, since if there's no // dispatchable we don't know what it should be We always return an `Err` // here anyways, so maybe it's okay? - ::ink::env::return_value::<::core::result::Result<(), ::ink::reflect::DispatchError>>( + ::ink::env::return_value::<::core::result::Result<(), ::ink::LangError>>( ::ink::env::ReturnFlags::default().set_reverted(true), &error ); } diff --git a/crates/ink/ir/src/ir/item_impl/message.rs b/crates/ink/ir/src/ir/item_impl/message.rs index 37b4cb61770..010eef72377 100644 --- a/crates/ink/ir/src/ir/item_impl/message.rs +++ b/crates/ink/ir/src/ir/item_impl/message.rs @@ -303,7 +303,7 @@ impl Message { .unwrap_or_else(|| quote::quote! { () }); let result = quote::quote! { - ::core::result::Result<#return_type, u8> + ::core::result::Result<#return_type, ::ink::LangError> }; let return_type: syn::Type = diff --git a/crates/ink/src/lib.rs b/crates/ink/src/lib.rs index 2f2370b385c..ea252430b8d 100644 --- a/crates/ink/src/lib.rs +++ b/crates/ink/src/lib.rs @@ -71,3 +71,4 @@ pub use ink_macro::{ test, trait_definition, }; +pub use ink_primitives::LangError; diff --git a/crates/metadata/src/lib.rs b/crates/metadata/src/lib.rs index 74bae41240b..e5d26522ff3 100644 --- a/crates/metadata/src/lib.rs +++ b/crates/metadata/src/lib.rs @@ -28,6 +28,8 @@ pub mod layout; mod specs; mod utils; +pub use ink_primitives::LangError; + pub use self::specs::{ ConstructorSpec, ConstructorSpecBuilder, diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 683904c080b..361385424be 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -41,3 +41,14 @@ pub use self::{ Hash, }, }; + +/// An error that comes from the smart contracting language, but not necessarily the smart contract +/// itself nor the underlying execution environment. +#[non_exhaustive] +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, ::scale::Encode, ::scale::Decode)] +#[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] +pub enum LangError { + /// Failed to read execution input for the dispatchable. + CouldNotReadInput = 1, +} diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 001610fd243..0ffb021bb45 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -22,7 +22,7 @@ mod cross_chain_test { let result = build_call::() .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) - .returns::>() + .returns::>() // .returns::<()>() .fire(); From cf332b7a203decc89d76532dfe5f504845e5cda5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 1 Nov 2022 17:44:17 +0100 Subject: [PATCH 016/102] Clean up some things --- .../generator/as_dependency/call_builder.rs | 11 ++++------ .../generator/as_dependency/contract_ref.rs | 4 +++- crates/ink/codegen/src/generator/dispatch.rs | 22 +++++-------------- .../ink/codegen/src/generator/item_impls.rs | 20 +++++------------ crates/ink/codegen/src/generator/metadata.rs | 4 ++-- crates/ink/ir/src/ir/item_impl/message.rs | 20 ++++++++--------- 6 files changed, 29 insertions(+), 52 deletions(-) diff --git a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs index d375b0fc115..54a8dc25df3 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -370,14 +370,11 @@ impl CallBuilder<'_> { let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = callable.receiver().is_ref_mut().then(|| quote! { mut }); - // let output = message.output(); - // let return_type = - // output.map_or_else(|| quote! { () }, |output| quote! { #output }); + let return_type = message + .wrapped_output() + .expect("TODO: Always returns Some atm"); - let output = message.map_result().expect("Always returns Some atm"); - let return_type = output.clone(); - - let output_span = output.span(); + let output_span = message.output().span(); let output_type = quote_spanned!(output_span=> ::ink::env::call::CallBuilder< Environment, diff --git a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs index 336740af38d..474aaff9240 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -344,7 +344,9 @@ impl ContractRef<'_> { let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let input_types = message.inputs().map(|input| &input.ty).collect::>(); // let output_type = message.output().map(|ty| quote! { -> #ty }); - let output_type = message.map_result().expect("This always returns Some atm"); + let output_type = message + .wrapped_output() + .expect("This always returns Some atm"); quote_spanned!(span=> #( #attrs )* #[inline] diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index b7fd1216436..5b43744ba76 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -299,7 +299,7 @@ impl Dispatch<'_> { let selector_id = message.composed_selector().into_be_u32().hex_padded_suffixed(); let selector_bytes = message.composed_selector().hex_lits(); - let output_tuple_type = message.map_result() + let output_tuple_type = message.wrapped_output() .map(|ty| quote::ToTokens::to_token_stream(&ty)) .unwrap_or_else(|| quote! { () }); // let output_tuple_type = message @@ -455,12 +455,12 @@ impl Dispatch<'_> { ::ink::LangError::CouldNotReadInput ); - // TODO: We'll need to get the correct output type here, e.g - // #message_output + // At this point we're unable to set the `Ok` variant to be the any "real" + // message output since we were unable to figure out what the caller wanted + // to dispatch in the first place, so we set it to `()`. // - // Don't think we can get the value for `T` here, since if there's no - // dispatchable we don't know what it should be We always return an `Err` - // here anyways, so maybe it's okay? + // This is okay since we're going to only be encoding the `Err` variant + // into the output buffer anyways. ::ink::env::return_value::<::core::result::Result<(), ::ink::LangError>>( ::ink::env::ReturnFlags::default().set_reverted(true), &error ); @@ -469,7 +469,6 @@ impl Dispatch<'_> { <<#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type as ::ink::reflect::ExecuteDispatchable>::execute_dispatchable(dispatchable) - .unwrap_or_else(|error| { ::core::panic!("dispatching ink! message failed: {}", error) }) @@ -801,15 +800,6 @@ impl Dispatch<'_> { push_contract(contract, #mutates_storage); - // if ::core::any::TypeId::of::<#message_output>() != ::core::any::TypeId::of::<()>() { - // // In case the return type is `()` we do not return a value. - // ::ink::env::return_value::<#message_output>( - // ::ink::env::ReturnFlags::default(), &result - // ) - // } - - // We manually wrap the message output in a `Result` since that's what the - // `CallBuilder` is expecting, otherwise we can't decode the output correctly ::ink::env::return_value::<#message_output>( ::ink::env::ReturnFlags::default(), &result ) diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index f9f13fc8255..d45c899cd73 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -256,29 +256,19 @@ impl ItemImpls<'_> { let receiver = message.receiver(); let ident = message.ident(); let inputs = message.inputs(); - // let output_arrow = message.output().map(|_| quote! { -> }); - // let output = message.output(); let output = message - .map_result() + .wrapped_output() .map(|ty| quote::ToTokens::to_token_stream(&ty)) - .unwrap_or_else(|| quote! { () }); - - // let output = message - // .output() - // .map(quote::ToTokens::to_token_stream) - // .unwrap_or_else(|| quote! { () }); - // let output = quote! { - // ::core::result::Result<#output, u8> - // }; + .expect("This should always be Some atm"); + // TODO: May need to change the `mut` of the function based on the original `receiver` let statements = message.statements(); quote_spanned!(span => #( #attrs )* #vis fn #ident(#receiver #( , #inputs )* ) -> #output { - let mut f = || { #( #statements )* }; - let o = f(); - ::core::result::Result::Ok(o) + let mut message_body = || { #( #statements )* }; + ::core::result::Result::Ok(message_body()) } ) diff --git a/crates/ink/codegen/src/generator/metadata.rs b/crates/ink/codegen/src/generator/metadata.rs index bb352079b7b..e807e185e89 100644 --- a/crates/ink/codegen/src/generator/metadata.rs +++ b/crates/ink/codegen/src/generator/metadata.rs @@ -220,8 +220,8 @@ impl Metadata<'_> { let mutates = message.receiver().is_ref_mut(); let ident = message.ident(); let args = message.inputs().map(Self::generate_dispatch_argument); - // let ret_ty = Self::generate_return_type(message.output()); - let ret_ty = Self::generate_return_type(message.map_result().as_ref()); + let ret_ty = + Self::generate_return_type(message.wrapped_output().as_ref()); quote_spanned!(span => ::ink::metadata::MessageSpec::from_label(::core::stringify!(#ident)) .selector([ diff --git a/crates/ink/ir/src/ir/item_impl/message.rs b/crates/ink/ir/src/ir/item_impl/message.rs index 010eef72377..3e791721af2 100644 --- a/crates/ink/ir/src/ir/item_impl/message.rs +++ b/crates/ink/ir/src/ir/item_impl/message.rs @@ -292,24 +292,22 @@ impl Message { } // TODO: Maybe get rid of `Option` here, only keeping for initial compatibility - pub fn map_result(&self) -> Option { - let o = match &self.item.sig.output { + pub fn wrapped_output(&self) -> Option { + let return_type = match &self.item.sig.output { syn::ReturnType::Default => None, syn::ReturnType::Type(_, return_type) => Some(return_type), - }; - - let return_type = o - .map(quote::ToTokens::to_token_stream) - .unwrap_or_else(|| quote::quote! { () }); + } + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote::quote! { () }); - let result = quote::quote! { + let wrapped_return = quote::quote! { ::core::result::Result<#return_type, ::ink::LangError> }; - let return_type: syn::Type = - syn::parse2::(result).expect("Failed to parse into Type"); + let wrapped_return = syn::parse2::(wrapped_return) + .expect("TODO: Failed to parse into Type"); - Some(return_type) + Some(wrapped_return) } /// Returns a local ID unique to the ink! message with respect to its implementation block. From dc1b7a3f32c7308482e4af64a6e94ead796090b3 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 1 Nov 2022 19:02:31 +0100 Subject: [PATCH 017/102] Remove some unused code --- .../codegen/src/generator/as_dependency/contract_ref.rs | 3 +-- crates/ink/codegen/src/generator/dispatch.rs | 9 +-------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs index 474aaff9240..7a0b0e45c83 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -343,10 +343,9 @@ impl ContractRef<'_> { let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let input_types = message.inputs().map(|input| &input.ty).collect::>(); - // let output_type = message.output().map(|ty| quote! { -> #ty }); let output_type = message .wrapped_output() - .expect("This always returns Some atm"); + .expect("TODO: This always returns Some atm"); quote_spanned!(span=> #( #attrs )* #[inline] diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 0293d446814..d9eaddf3653 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -304,14 +304,7 @@ impl Dispatch<'_> { let output_tuple_type = message.wrapped_output() .map(|ty| quote::ToTokens::to_token_stream(&ty)) - .unwrap_or_else(|| quote! { () }); - // let output_tuple_type = message - // .output() - // .map(quote::ToTokens::to_token_stream) - // .unwrap_or_else(|| quote! { () }); - // let output_tuple_type = quote! { - // ::core::result::Result<#output_tuple_type, u8> - // }; + .expect("TODO: Always returns Some atm"); let input_bindings = generator::input_bindings(message.inputs()); let input_tuple_type = generator::input_types_tuple(message.inputs()); From 2ad4633694cf49c542d2ab3a8c905aa1fbfa4ac6 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 2 Nov 2022 12:22:41 +0000 Subject: [PATCH 018/102] Add DispatchError type metadata --- crates/metadata/src/specs.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/metadata/src/specs.rs b/crates/metadata/src/specs.rs index ad599de8c47..dceb4fe6c25 100644 --- a/crates/metadata/src/specs.rs +++ b/crates/metadata/src/specs.rs @@ -42,6 +42,10 @@ use serde::{ Serialize, }; +// todo: [hc] add docs and impl. +#[derive(Debug, Copy, Clone, PartialEq, Eq, TypeInfo)] // ::scale::Encode, ::scale::Decode)] +pub enum DispatchError {} + /// Describes a contract. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(bound( @@ -49,6 +53,8 @@ use serde::{ deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned" ))] pub struct ContractSpec { + /// todo: [hc] better name? + docs + dispatch_error: F::Type, /// The set of constructors of the contract. constructors: Vec>, /// The external messages of the contract. @@ -64,6 +70,7 @@ impl IntoPortable for ContractSpec { fn into_portable(self, registry: &mut Registry) -> Self::Output { ContractSpec { + dispatch_error: registry.register_type(&self.dispatch_error), constructors: self .constructors .into_iter() @@ -207,6 +214,7 @@ impl ContractSpec { pub fn new() -> ContractSpecBuilder { ContractSpecBuilder { spec: Self { + dispatch_error: meta_type::(), constructors: Vec::new(), messages: Vec::new(), events: Vec::new(), From 14b5875808e4925e108b60a215c8f8f1b06a5dec Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 2 Nov 2022 16:31:59 +0100 Subject: [PATCH 019/102] Use language error over dispatch error --- crates/metadata/src/specs.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/crates/metadata/src/specs.rs b/crates/metadata/src/specs.rs index dceb4fe6c25..7e49c75772b 100644 --- a/crates/metadata/src/specs.rs +++ b/crates/metadata/src/specs.rs @@ -42,10 +42,6 @@ use serde::{ Serialize, }; -// todo: [hc] add docs and impl. -#[derive(Debug, Copy, Clone, PartialEq, Eq, TypeInfo)] // ::scale::Encode, ::scale::Decode)] -pub enum DispatchError {} - /// Describes a contract. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(bound( @@ -53,8 +49,6 @@ pub enum DispatchError {} deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned" ))] pub struct ContractSpec { - /// todo: [hc] better name? + docs - dispatch_error: F::Type, /// The set of constructors of the contract. constructors: Vec>, /// The external messages of the contract. @@ -63,6 +57,8 @@ pub struct ContractSpec { events: Vec>, /// The contract documentation. docs: Vec, + /// The language specific error type. + lang_error: F::Type, } impl IntoPortable for ContractSpec { @@ -70,7 +66,6 @@ impl IntoPortable for ContractSpec { fn into_portable(self, registry: &mut Registry) -> Self::Output { ContractSpec { - dispatch_error: registry.register_type(&self.dispatch_error), constructors: self .constructors .into_iter() @@ -87,6 +82,7 @@ impl IntoPortable for ContractSpec { .map(|event| event.into_portable(registry)) .collect::>(), docs: registry.map_into_portable(self.docs), + lang_error: registry.register_type(&self.lang_error), } } } @@ -214,11 +210,11 @@ impl ContractSpec { pub fn new() -> ContractSpecBuilder { ContractSpecBuilder { spec: Self { - dispatch_error: meta_type::(), constructors: Vec::new(), messages: Vec::new(), events: Vec::new(), docs: Vec::new(), + lang_error: meta_type::(), }, marker: PhantomData, } From a38a395d3de08c98ce5f837d78c0a1224dcd7fca Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 2 Nov 2022 16:41:41 +0100 Subject: [PATCH 020/102] Change message body's visibility based on message signature --- crates/ink/codegen/src/generator/item_impls.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index d2c1917d420..fc5d325cc73 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -255,20 +255,18 @@ impl ItemImpls<'_> { let attrs = message.attrs(); let vis = message.visibility(); let receiver = message.receiver(); + let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let ident = message.ident(); let inputs = message.inputs(); - let output = message .wrapped_output() .map(|ty| quote::ToTokens::to_token_stream(&ty)) .expect("This should always be Some atm"); - - // TODO: May need to change the `mut` of the function based on the original `receiver` let statements = message.statements(); quote_spanned!(span => #( #attrs )* #vis fn #ident(#receiver #( , #inputs )* ) -> #output { - let mut message_body = || { #( #statements )* }; + let #mut_token message_body = || { #( #statements )* }; ::core::result::Result::Ok(message_body()) } From a4d653b8482f6bc26c038177895a8ed119eff39f Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 2 Nov 2022 17:06:59 +0100 Subject: [PATCH 021/102] Fix unreachable code warning --- crates/ink/codegen/src/generator/dispatch.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index d9eaddf3653..efb7c7d4ae7 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -870,8 +870,6 @@ impl Dispatch<'_> { match self { #( #message_execute ),* }; - - ::core::result::Result::Ok(()) } } From fc42d667d5aee28306a753149bca9c432ee81e5d Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 2 Nov 2022 17:14:22 +0100 Subject: [PATCH 022/102] Appease Clippy --- crates/primitives/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 361385424be..dc976a8e50b 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -50,5 +50,5 @@ pub use self::{ #[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] pub enum LangError { /// Failed to read execution input for the dispatchable. - CouldNotReadInput = 1, + CouldNotReadInput = 1u32, } From 9705ff30382f11753e75cd26a4cfda6be5b499c9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 2 Nov 2022 17:16:55 +0100 Subject: [PATCH 023/102] Rustfmt cross-contract example --- examples/cross_chain_test/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 0ffb021bb45..496ba5d16fd 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -15,7 +15,12 @@ mod cross_chain_test { #[ink(message)] pub fn call(&mut self, address: AccountId, selector: [u8; 4]) { use ink::env::{ - call::{build_call, Call, ExecutionInput, Selector}, + call::{ + build_call, + Call, + ExecutionInput, + Selector, + }, DefaultEnvironment, }; From a6680182ba0e2d23391694df059145384c47547f Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 15:07:43 +0100 Subject: [PATCH 024/102] Fix formatting --- crates/metadata/src/specs.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/crates/metadata/src/specs.rs b/crates/metadata/src/specs.rs index 585d6df0e94..87a6d964946 100644 --- a/crates/metadata/src/specs.rs +++ b/crates/metadata/src/specs.rs @@ -14,15 +14,33 @@ #![allow(clippy::new_ret_no_self)] -use crate::{serde_hex, utils::trim_extra_whitespace}; +use crate::{ + serde_hex, + utils::trim_extra_whitespace, +}; #[cfg(not(feature = "std"))] -use alloc::{format, vec, vec::Vec}; +use alloc::{ + format, + vec, + vec::Vec, +}; use core::marker::PhantomData; use scale_info::{ - form::{Form, MetaForm, PortableForm}, - meta_type, IntoPortable, Registry, TypeInfo, + form::{ + Form, + MetaForm, + PortableForm, + }, + meta_type, + IntoPortable, + Registry, + TypeInfo, +}; +use serde::{ + de::DeserializeOwned, + Deserialize, + Serialize, }; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; /// Describes a contract. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] From 89d2cf568eeca51892d275d634c176ce3f9b83e8 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 15:11:41 +0100 Subject: [PATCH 025/102] Write `lang_error` into metadata using spec builder --- crates/ink/codegen/src/generator/metadata.rs | 7 +++++++ crates/metadata/src/specs.rs | 8 ++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/ink/codegen/src/generator/metadata.rs b/crates/ink/codegen/src/generator/metadata.rs index c090f19179a..75b7c7f1f59 100644 --- a/crates/ink/codegen/src/generator/metadata.rs +++ b/crates/ink/codegen/src/generator/metadata.rs @@ -89,6 +89,10 @@ impl Metadata<'_> { .attrs() .iter() .filter_map(|attr| attr.extract_docs()); + let error_ty = syn::parse_quote! { + ::ink::LangError + }; + let error = Self::generate_type_spec(&error_ty); quote! { ::ink::metadata::ContractSpec::new() .constructors([ @@ -103,6 +107,9 @@ impl Metadata<'_> { .docs([ #( #docs ),* ]) + .lang_error( + #error + ) .done() } } diff --git a/crates/metadata/src/specs.rs b/crates/metadata/src/specs.rs index 87a6d964946..6f113788f47 100644 --- a/crates/metadata/src/specs.rs +++ b/crates/metadata/src/specs.rs @@ -81,7 +81,7 @@ impl IntoPortable for ContractSpec { .into_iter() .map(|event| event.into_portable(registry)) .collect::>(), - docs: self.docs.into_iter().map(|s| s.into()).collect(), + docs: registry.map_into_portable(self.docs), lang_error: self.lang_error.into_portable(registry), } } @@ -110,6 +110,11 @@ where pub fn docs(&self) -> &[F::String] { &self.docs } + + /// Returns the contract error type. + pub fn lang_error(&self) -> &TypeSpec { + &self.lang_error + } } /// The message builder is ready to finalize construction. @@ -199,7 +204,6 @@ where /// Sets the language error of the contract specification pub fn lang_error(self, lang_error: TypeSpec) -> Self { - debug_assert!(self.spec.docs.is_empty()); Self { spec: ContractSpec { lang_error, From 68417b707a9c48c3f625acde1639684d1de6c80a Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 15:20:07 +0100 Subject: [PATCH 026/102] Use `parse_quote` macro over the `syn::parse` function --- crates/ink/ir/src/ir/item_impl/message.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/ink/ir/src/ir/item_impl/message.rs b/crates/ink/ir/src/ir/item_impl/message.rs index 3e791721af2..3c8fb0a4a12 100644 --- a/crates/ink/ir/src/ir/item_impl/message.rs +++ b/crates/ink/ir/src/ir/item_impl/message.rs @@ -300,13 +300,10 @@ impl Message { .map(quote::ToTokens::to_token_stream) .unwrap_or_else(|| quote::quote! { () }); - let wrapped_return = quote::quote! { + let wrapped_return = syn::parse_quote! { ::core::result::Result<#return_type, ::ink::LangError> }; - let wrapped_return = syn::parse2::(wrapped_return) - .expect("TODO: Failed to parse into Type"); - Some(wrapped_return) } From f2ef955739129c4c9c9e5cef209d89c877fd91ed Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 15:27:21 +0100 Subject: [PATCH 027/102] Use correct span in call builder --- .../ink/codegen/src/generator/as_dependency/call_builder.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs index 54a8dc25df3..16f9a91085d 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -369,12 +369,10 @@ impl CallBuilder<'_> { let input_types = generator::input_types(message.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = callable.receiver().is_ref_mut().then(|| quote! { mut }); - let return_type = message .wrapped_output() .expect("TODO: Always returns Some atm"); - - let output_span = message.output().span(); + let output_span = return_type.span(); let output_type = quote_spanned!(output_span=> ::ink::env::call::CallBuilder< Environment, From 183dc112f0b0aae6963024498d299f34f88f9ff0 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 15:43:47 +0100 Subject: [PATCH 028/102] Always return `Type` instead of `Option` from `wrapped_output` --- .../generator/as_dependency/call_builder.rs | 4 +-- .../generator/as_dependency/contract_ref.rs | 4 +-- crates/ink/codegen/src/generator/dispatch.rs | 6 +---- .../ink/codegen/src/generator/item_impls.rs | 5 +--- crates/ink/codegen/src/generator/metadata.rs | 3 +-- crates/ink/ir/src/ir/item_impl/message.rs | 25 +++++++++---------- 6 files changed, 17 insertions(+), 30 deletions(-) diff --git a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs index 16f9a91085d..9d3232133f8 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -369,9 +369,7 @@ impl CallBuilder<'_> { let input_types = generator::input_types(message.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = callable.receiver().is_ref_mut().then(|| quote! { mut }); - let return_type = message - .wrapped_output() - .expect("TODO: Always returns Some atm"); + let return_type = message.wrapped_output(); let output_span = return_type.span(); let output_type = quote_spanned!(output_span=> ::ink::env::call::CallBuilder< diff --git a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs index 7a0b0e45c83..90007c979f1 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -343,9 +343,7 @@ impl ContractRef<'_> { let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let input_types = message.inputs().map(|input| &input.ty).collect::>(); - let output_type = message - .wrapped_output() - .expect("TODO: This always returns Some atm"); + let output_type = message.wrapped_output(); quote_spanned!(span=> #( #attrs )* #[inline] diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index ad66fe94fba..61393853456 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -299,11 +299,7 @@ impl Dispatch<'_> { let mutates = message.receiver().is_ref_mut(); let selector_id = message.composed_selector().into_be_u32().hex_padded_suffixed(); let selector_bytes = message.composed_selector().hex_lits(); - - let output_tuple_type = message.wrapped_output() - .map(|ty| quote::ToTokens::to_token_stream(&ty)) - .expect("TODO: Always returns Some atm"); - + let output_tuple_type = message.wrapped_output(); let input_bindings = generator::input_bindings(message.inputs()); let input_tuple_type = generator::input_types_tuple(message.inputs()); let input_tuple_bindings = generator::input_bindings_tuple(message.inputs()); diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index fc5d325cc73..5601c0d6715 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -258,10 +258,7 @@ impl ItemImpls<'_> { let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let ident = message.ident(); let inputs = message.inputs(); - let output = message - .wrapped_output() - .map(|ty| quote::ToTokens::to_token_stream(&ty)) - .expect("This should always be Some atm"); + let output = message.wrapped_output(); let statements = message.statements(); quote_spanned!(span => #( #attrs )* diff --git a/crates/ink/codegen/src/generator/metadata.rs b/crates/ink/codegen/src/generator/metadata.rs index 75b7c7f1f59..79bc8a89c94 100644 --- a/crates/ink/codegen/src/generator/metadata.rs +++ b/crates/ink/codegen/src/generator/metadata.rs @@ -227,8 +227,7 @@ impl Metadata<'_> { let mutates = message.receiver().is_ref_mut(); let ident = message.ident(); let args = message.inputs().map(Self::generate_dispatch_argument); - let ret_ty = - Self::generate_return_type(message.wrapped_output().as_ref()); + let ret_ty = Self::generate_return_type(Some(&message.wrapped_output())); quote_spanned!(span => ::ink::metadata::MessageSpec::from_label(::core::stringify!(#ident)) .selector([ diff --git a/crates/ink/ir/src/ir/item_impl/message.rs b/crates/ink/ir/src/ir/item_impl/message.rs index 3c8fb0a4a12..c30ad95a46a 100644 --- a/crates/ink/ir/src/ir/item_impl/message.rs +++ b/crates/ink/ir/src/ir/item_impl/message.rs @@ -291,20 +291,19 @@ impl Message { } } - // TODO: Maybe get rid of `Option` here, only keeping for initial compatibility - pub fn wrapped_output(&self) -> Option { - let return_type = match &self.item.sig.output { - syn::ReturnType::Default => None, - syn::ReturnType::Type(_, return_type) => Some(return_type), - } - .map(quote::ToTokens::to_token_stream) - .unwrap_or_else(|| quote::quote! { () }); - - let wrapped_return = syn::parse_quote! { + /// Returns the return type of the message, but wrapped within a `Result`. + /// + /// This is used to to allow callers to handle certain types of errors which are not exposed + /// by messages. + pub fn wrapped_output(&self) -> syn::Type { + let return_type = self + .output() + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote::quote! { () }); + + syn::parse_quote! { ::core::result::Result<#return_type, ::ink::LangError> - }; - - Some(wrapped_return) + } } /// Returns a local ID unique to the ink! message with respect to its implementation block. From ae116330f7de2ecef9ea0da28c57dea220f7151c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 17:33:29 +0100 Subject: [PATCH 029/102] Temporarily appease Clippy --- crates/ink/tests/unique_topics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ink/tests/unique_topics.rs b/crates/ink/tests/unique_topics.rs index 8234d8470fa..6d12c670036 100644 --- a/crates/ink/tests/unique_topics.rs +++ b/crates/ink/tests/unique_topics.rs @@ -68,7 +68,7 @@ mod my_contract { let my_contract = MyContract::new(); // when - MyContract::emit_my_event(&my_contract); + MyContract::emit_my_event(&my_contract).expect("TODO"); // then // all topics must be unique From 1630b3d71b9a9501f753caff431ead55fe1287eb Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 17:40:51 +0100 Subject: [PATCH 030/102] Another temporary Clippy fix --- examples/contract-terminate/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/contract-terminate/lib.rs b/examples/contract-terminate/lib.rs index 72f675b88a2..4331fc5f6bd 100644 --- a/examples/contract-terminate/lib.rs +++ b/examples/contract-terminate/lib.rs @@ -42,7 +42,7 @@ pub mod just_terminates { let mut contract = JustTerminate::new(); // when - let should_terminate = move || contract.terminate_me(); + let should_terminate = move || contract.terminate_me().expect("TODO"); // then ink::env::test::assert_contract_termination::( From 2e7b5bce1c2638168cb6cb19aef210da5709fff8 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 18:32:55 +0100 Subject: [PATCH 031/102] Generate checked and unchecked versions of contract messages We're now able to specify if we want to use an unchecked or checked version of the message functions in our code. This means that existing code, such as in tests, doesn't need to worry about the new wrapped `Result` type. At the same time, as far as external callers are concerned they are always calling the checked version of the messages. --- crates/ink/codegen/src/generator/dispatch.rs | 3 ++- crates/ink/codegen/src/generator/item_impls.rs | 16 +++++++++++++--- examples/contract-terminate/lib.rs | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 61393853456..2a4396efd33 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -295,6 +295,7 @@ impl Dispatch<'_> { .map(|message| { let message_span = message.span(); let message_ident = message.ident(); + let checked_message_ident = format_ident!("{}_checked", message_ident); let payable = message.is_payable(); let mutates = message.receiver().is_ref_mut(); let selector_id = message.composed_selector().into_be_u32().hex_padded_suffixed(); @@ -310,7 +311,7 @@ impl Dispatch<'_> { type Storage = #storage_ident; const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = |storage, #input_tuple_bindings| { - #storage_ident::#message_ident( storage #( , #input_bindings )* ) + #storage_ident::#checked_message_ident( storage #( , #input_bindings )* ) }; const SELECTOR: [::core::primitive::u8; 4usize] = [ #( #selector_bytes ),* ]; const PAYABLE: ::core::primitive::bool = #payable; diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index 5601c0d6715..e4e8a39c349 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -257,13 +257,23 @@ impl ItemImpls<'_> { let receiver = message.receiver(); let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let ident = message.ident(); + let checked_ident = format_ident!("{}_checked", ident); let inputs = message.inputs(); - let output = message.wrapped_output(); + let wrapped_inputs = message.inputs(); + let output_arrow = message.output().map(|_| quote! { -> }); + let output = message.output(); + let wrapped_output = message.wrapped_output(); let statements = message.statements(); + quote_spanned!(span => #( #attrs )* - #vis fn #ident(#receiver #( , #inputs )* ) -> #output { - let #mut_token message_body = || { #( #statements )* }; + #vis fn #ident(#receiver #( , #inputs )* ) #output_arrow #output { + #( #statements )* + } + + #( #attrs )* + #vis fn #checked_ident(#receiver #( , #wrapped_inputs )* ) -> #wrapped_output { + let #mut_token message_body = || { #( #statements )* }; ::core::result::Result::Ok(message_body()) } diff --git a/examples/contract-terminate/lib.rs b/examples/contract-terminate/lib.rs index 4331fc5f6bd..72f675b88a2 100644 --- a/examples/contract-terminate/lib.rs +++ b/examples/contract-terminate/lib.rs @@ -42,7 +42,7 @@ pub mod just_terminates { let mut contract = JustTerminate::new(); // when - let should_terminate = move || contract.terminate_me().expect("TODO"); + let should_terminate = move || contract.terminate_me(); // then ink::env::test::assert_contract_termination::( From 87ca72122b9fb470f2970b9e947df3f75cfc94a0 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 19:05:17 +0100 Subject: [PATCH 032/102] Use non-checked message as checked message implementation --- crates/ink/codegen/src/generator/item_impls.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index e4e8a39c349..aecd2338e36 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -255,10 +255,10 @@ impl ItemImpls<'_> { let attrs = message.attrs(); let vis = message.visibility(); let receiver = message.receiver(); - let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let ident = message.ident(); let checked_ident = format_ident!("{}_checked", ident); let inputs = message.inputs(); + let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let wrapped_inputs = message.inputs(); let output_arrow = message.output().map(|_| quote! { -> }); let output = message.output(); @@ -273,8 +273,7 @@ impl ItemImpls<'_> { #( #attrs )* #vis fn #checked_ident(#receiver #( , #wrapped_inputs )* ) -> #wrapped_output { - let #mut_token message_body = || { #( #statements )* }; - ::core::result::Result::Ok(message_body()) + ::core::result::Result::Ok(self.#ident( #( #input_bindings , )* )) } ) From 66dd9d18efc69c7aee1a8496b28007c61d2361ff Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Nov 2022 19:08:25 +0100 Subject: [PATCH 033/102] Remove error handling from test --- crates/ink/tests/unique_topics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ink/tests/unique_topics.rs b/crates/ink/tests/unique_topics.rs index 6d12c670036..8234d8470fa 100644 --- a/crates/ink/tests/unique_topics.rs +++ b/crates/ink/tests/unique_topics.rs @@ -68,7 +68,7 @@ mod my_contract { let my_contract = MyContract::new(); // when - MyContract::emit_my_event(&my_contract).expect("TODO"); + MyContract::emit_my_event(&my_contract); // then // all topics must be unique From 517d4085ccf67fdfc2b9b54d93ec60be1ff7ed81 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 8 Nov 2022 18:02:46 +0100 Subject: [PATCH 034/102] Add method for generating checked message idents --- crates/ink/codegen/src/generator/dispatch.rs | 2 +- crates/ink/codegen/src/generator/item_impls.rs | 2 +- crates/ink/ir/src/ir/item_impl/message.rs | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 2a4396efd33..175cd9d5895 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -295,7 +295,7 @@ impl Dispatch<'_> { .map(|message| { let message_span = message.span(); let message_ident = message.ident(); - let checked_message_ident = format_ident!("{}_checked", message_ident); + let checked_message_ident = message.checked_ident(); let payable = message.is_payable(); let mutates = message.receiver().is_ref_mut(); let selector_id = message.composed_selector().into_be_u32().hex_padded_suffixed(); diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index aecd2338e36..ca93ee0a16a 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -256,7 +256,7 @@ impl ItemImpls<'_> { let vis = message.visibility(); let receiver = message.receiver(); let ident = message.ident(); - let checked_ident = format_ident!("{}_checked", ident); + let checked_ident = message.checked_ident(); let inputs = message.inputs(); let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let wrapped_inputs = message.inputs(); diff --git a/crates/ink/ir/src/ir/item_impl/message.rs b/crates/ink/ir/src/ir/item_impl/message.rs index c30ad95a46a..ff38eaca8de 100644 --- a/crates/ink/ir/src/ir/item_impl/message.rs +++ b/crates/ink/ir/src/ir/item_impl/message.rs @@ -316,6 +316,11 @@ impl Message { pub fn local_id(&self) -> u32 { utils::local_message_id(self.ident()) } + + /// Returns the identifier of the message with an additional `_checked` suffix attached. + pub fn checked_ident(&self) -> Ident { + quote::format_ident!("{}_checked", self.ident()) + } } #[cfg(test)] From 150e4d3e5c1070871b7a99d3374094b7d6785777 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 9 Nov 2022 11:59:26 +0100 Subject: [PATCH 035/102] Fix UI tests related to `no_implicit_prelude` --- crates/ink/codegen/src/generator/dispatch.rs | 21 ++++++++++---------- crates/ink/codegen/src/generator/metadata.rs | 3 +++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 233a935a39a..66d1656b01d 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -434,19 +434,19 @@ impl Dispatch<'_> { } let dispatchable = match ::ink::env::decode_input::< - <#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type>() { - Ok(decoded_dispatchable) => { - ::ink::env::debug_println!("Result from `decode_input` {:?}", &decoded_dispatchable); - decoded_dispatchable - }, - Err(_decoding_error) => { + <#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type, + >() { + ::core::result::Result::Ok(decoded_dispatchable) => { + ::ink::env::debug_println!("Result from `decode_input` {:?}", &decoded_dispatchable); + decoded_dispatchable + } + ::core::result::Result::Err(_decoding_error) => { + use ::core::default::Default; ::ink::env::debug_println!("Result from `decode_input` {:?}", &_decoding_error); // TODO: Here will pick out the `Dispatch` error we're interested in telling the // user about and encode it correctly - let error = ::core::result::Result::Err( - ::ink::LangError::CouldNotReadInput - ); + let error = ::core::result::Result::Err(::ink::LangError::CouldNotReadInput); // At this point we're unable to set the `Ok` variant to be the any "real" // message output since we were unable to figure out what the caller wanted @@ -455,7 +455,8 @@ impl Dispatch<'_> { // This is okay since we're going to only be encoding the `Err` variant // into the output buffer anyways. ::ink::env::return_value::<::core::result::Result<(), ::ink::LangError>>( - ::ink::env::ReturnFlags::default().set_reverted(true), &error + ::ink::env::ReturnFlags::default().set_reverted(true), + &error, ); } }; diff --git a/crates/ink/codegen/src/generator/metadata.rs b/crates/ink/codegen/src/generator/metadata.rs index 7254a571715..98371262502 100644 --- a/crates/ink/codegen/src/generator/metadata.rs +++ b/crates/ink/codegen/src/generator/metadata.rs @@ -50,6 +50,9 @@ impl GenerateCode for Metadata<'_> { #[no_mangle] pub fn __ink_generate_metadata() -> ::ink::metadata::InkProject { + // TODO: Use changes from #1486 + use ::core::iter::Iterator; + let layout = #layout; ::ink::metadata::layout::ValidateLayout::validate(&layout).unwrap_or_else(|error| { ::core::panic!("metadata ink! generation failed: {}", error) From d68777e12c5f879575dc6e22dd95de080249cd34 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 9 Nov 2022 16:50:11 +0100 Subject: [PATCH 036/102] Remove unneccessary import --- crates/ink/codegen/src/generator/metadata.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/ink/codegen/src/generator/metadata.rs b/crates/ink/codegen/src/generator/metadata.rs index 0458781a672..3f7cdc2aa60 100644 --- a/crates/ink/codegen/src/generator/metadata.rs +++ b/crates/ink/codegen/src/generator/metadata.rs @@ -50,9 +50,6 @@ impl GenerateCode for Metadata<'_> { #[no_mangle] pub fn __ink_generate_metadata() -> ::ink::metadata::InkProject { - // TODO: Use changes from #1486 - use ::core::iter::Iterator; - let layout = #layout; ::ink::metadata::layout::ValidateLayout::validate(&layout).unwrap_or_else(|error| { ::core::panic!("metadata ink! generation failed: {}", error) From 4f2caada5fdccca25fad6e1fcfe462912def4fd3 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 9 Nov 2022 16:58:51 +0100 Subject: [PATCH 037/102] Add `Default` implementation for `cross_chain_test` --- examples/cross_chain_test/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 496ba5d16fd..e61d0941d98 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -4,6 +4,7 @@ mod cross_chain_test { #[ink(storage)] + #[derive(Default)] pub struct CrossChainTest {} impl CrossChainTest { From f617a0c4563e7c8c874fb980cb81064b4914bcad Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 9 Nov 2022 17:23:32 +0100 Subject: [PATCH 038/102] Bless some UI tests --- .../fail/impl-block-for-non-storage-01.stderr | 6 ++-- .../fail/message-input-non-codec.stderr | 21 +++++++++-- .../fail/message-returns-non-codec.stderr | 35 ++++++------------- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/crates/ink/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr b/crates/ink/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr index 53823fe552c..17af341d831 100644 --- a/crates/ink/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr +++ b/crates/ink/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr @@ -19,14 +19,14 @@ error[E0599]: no function or associated item named `constructor_2` found for str | function or associated item not found in `Contract` | help: there is an associated function with a similar name: `constructor_1` -error[E0599]: no function or associated item named `message_2` found for struct `Contract` in the current scope +error[E0599]: no function or associated item named `message_2_checked` found for struct `Contract` in the current scope --> tests/ui/contract/fail/impl-block-for-non-storage-01.rs:25:16 | 4 | pub struct Contract {} - | --- function or associated item `message_2` not found for this struct + | --- function or associated item `message_2_checked` not found for this struct ... 25 | pub fn message_2(&self) {} | ^^^^^^^^^ | | | function or associated item not found in `Contract` - | help: there is a method with a similar name: `message_1` + | help: there is a method with a similar name: `message_1_checked` diff --git a/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr index 3c4f440e322..622e6abf3ad 100644 --- a/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr +++ b/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr @@ -15,6 +15,23 @@ note: required by a bound in `DispatchInput` | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` +error[E0277]: `NonCodecType` doesn't implement `Debug` + --> tests/ui/contract/fail/message-input-non-codec.rs:16:9 + | +7 | pub struct Contract {} + | --- in this derive macro expansion +... +16 | pub fn message(&self, _input: NonCodecType) {} + | ^^^ `NonCodecType` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `NonCodecType` + = note: add `#[derive(Debug)]` to `NonCodecType` or manually `impl Debug for NonCodecType` + = note: this error originates in the derive macro `::core::fmt::Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NonCodecType` with `#[derive(Debug)]` + | +4 | #[derive(Debug)] + | + error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied --> tests/ui/contract/fail/message-input-non-codec.rs:16:9 | @@ -53,11 +70,11 @@ note: required by a bound in `ExecutionInput::>::push_arg` -error[E0599]: the method `fire` exists for struct `ink::ink_env::call::CallBuilder>, Set, ArgumentList>>>, Set>>`, but its trait bounds were not satisfied +error[E0599]: the method `fire` exists for struct `ink::ink_env::call::CallBuilder>, Set, ArgumentList>>>, Set>>>`, but its trait bounds were not satisfied --> tests/ui/contract/fail/message-input-non-codec.rs:16:9 | 16 | pub fn message(&self, _input: NonCodecType) {} - | ^^^ method cannot be called on `ink::ink_env::call::CallBuilder>, Set, ArgumentList>>>, Set>>` due to unsatisfied trait bounds + | ^^^ method cannot be called on `ink::ink_env::call::CallBuilder>, Set, ArgumentList>>>, Set>>>` due to unsatisfied trait bounds | ::: $WORKSPACE/crates/env/src/call/execution_input.rs | diff --git a/crates/ink/tests/ui/contract/fail/message-returns-non-codec.stderr b/crates/ink/tests/ui/contract/fail/message-returns-non-codec.stderr index 273267d8c2d..b5565368175 100644 --- a/crates/ink/tests/ui/contract/fail/message-returns-non-codec.stderr +++ b/crates/ink/tests/ui/contract/fail/message-returns-non-codec.stderr @@ -21,42 +21,29 @@ note: required by a bound in `DispatchOutput` | T: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` -error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied +error[E0277]: the trait bound `Result: Encode` is not satisfied --> tests/ui/contract/fail/message-returns-non-codec.rs:16:9 | 16 | pub fn message(&self) -> NonCodecType { - | ^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` + | ^^^ the trait `Encode` is not implemented for `Result` | - = help: the following other types implement trait `WrapperTypeEncode`: - &T - &mut T - Arc - Box - Cow<'a, T> - Rc - String - Vec - parity_scale_codec::Ref<'a, T, U> - = note: required for `NonCodecType` to implement `Encode` + = help: the trait `Encode` is implemented for `Result` note: required by a bound in `return_value` --> $WORKSPACE/crates/env/src/api.rs | | R: scale::Encode, | ^^^^^^^^^^^^^ required by this bound in `return_value` -error[E0599]: the method `fire` exists for struct `ink::ink_env::call::CallBuilder>, Set>>, Set>>`, but its trait bounds were not satisfied +error[E0599]: the method `fire` exists for struct `ink::ink_env::call::CallBuilder>, Set>>, Set>>>`, but its trait bounds were not satisfied --> tests/ui/contract/fail/message-returns-non-codec.rs:16:9 | -4 | pub struct NonCodecType; - | ----------------------- doesn't satisfy `NonCodecType: parity_scale_codec::Decode` -... 16 | pub fn message(&self) -> NonCodecType { - | ^^^ method cannot be called on `ink::ink_env::call::CallBuilder>, Set>>, Set>>` due to unsatisfied trait bounds + | ^^^ method cannot be called on `ink::ink_env::call::CallBuilder>, Set>>, Set>>>` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `NonCodecType: parity_scale_codec::Decode` -note: the following trait must be implemented - --> $CARGO/parity-scale-codec-3.2.1/src/codec.rs + ::: $RUST/core/src/result.rs + | + | pub enum Result { + | --------------------- doesn't satisfy `_: parity_scale_codec::Decode` | - | pub trait Decode: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: the following trait bounds were not satisfied: + `Result: parity_scale_codec::Decode` From 105fe23c639d025344cd6cdcdd5fbc855b1f35ad Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 9 Nov 2022 17:26:42 +0100 Subject: [PATCH 039/102] Update `Output` type for doc test --- crates/ink/src/reflect/dispatch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ink/src/reflect/dispatch.rs b/crates/ink/src/reflect/dispatch.rs index cb917735f47..7582d09a07c 100644 --- a/crates/ink/src/reflect/dispatch.rs +++ b/crates/ink/src/reflect/dispatch.rs @@ -224,10 +224,10 @@ pub trait ContractDispatchableConstructors { /// } /// /// fn main() { -/// assert_message_info::<(), (), {selector_id!("message1")}>( +/// assert_message_info::<(), Result<(), ink::LangError>, {selector_id!("message1")}>( /// false, false, selector_bytes!("message1"), "message1" /// ); -/// assert_message_info::<(i32, i64), (bool, i32), 0xC0DECAFE_u32>( +/// assert_message_info::<(i32, i64), Result<(bool, i32), ink::LangError>, 0xC0DECAFE_u32>( /// true, true, [0xC0, 0xDE, 0xCA, 0xFE], "message2" /// ); /// } From 90cf477e36f25ae237c42e560b52a353a464a7c8 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 9 Nov 2022 17:33:38 +0100 Subject: [PATCH 040/102] Update `cross_chain_test` to appease Clippy --- examples/cross_chain_test/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index e61d0941d98..f509ebd9576 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -25,14 +25,14 @@ mod cross_chain_test { DefaultEnvironment, }; - let result = build_call::() + let _result = build_call::() .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) .returns::>() // .returns::<()>() .fire(); - ink::env::debug_println!("cross_contract::call output: {:?}", &result); + ink::env::debug_println!("cross_contract::call output: {:?}", &_result); } } } From 3774d29687d9b0b1f55c0b9746bf28cf26d17232 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 12:24:16 +0100 Subject: [PATCH 041/102] Generate `*_checked` functions for `ContractRef` calls --- .../generator/as_dependency/contract_ref.rs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs index 90007c979f1..9200faf0d89 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -336,6 +336,7 @@ impl ContractRef<'_> { .filter_attr(message.attrs().to_vec()); let storage_ident = self.contract.module().storage().ident(); let message_ident = message.ident(); + let checked_message_ident = message.checked_ident(); let call_operator = match message.receiver() { ir::Receiver::Ref => quote! { call }, ir::Receiver::RefMut => quote! { call_mut }, @@ -343,14 +344,31 @@ impl ContractRef<'_> { let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let input_types = message.inputs().map(|input| &input.ty).collect::>(); - let output_type = message.wrapped_output(); + let output_arrow = message.output().map(|_| quote! { -> }); + let output_type = message.output(); + let wrapped_output_type = message.wrapped_output(); quote_spanned!(span=> #( #attrs )* #[inline] pub fn #message_ident( & #mut_token self #( , #input_bindings : #input_types )* - ) -> #output_type { + ) #output_arrow #output_type { + self.#checked_message_ident( #( #input_bindings, )* ) + .unwrap_or_else(|error| ::core::panic!( + "encountered error while calling {}::{}: {:?}", + ::core::stringify!(#storage_ident), + ::core::stringify!(#message_ident), + error, + )) + } + + #( #attrs )* + #[inline] + pub fn #checked_message_ident( + & #mut_token self + #( , #input_bindings : #input_types )* + ) -> #wrapped_output_type { ::#call_operator(self) .#message_ident( #( #input_bindings ),* ) .fire() From 13d7a42e6956d9fa03b89a1f544eb2292b131c7b Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 13:03:03 +0100 Subject: [PATCH 042/102] Implement `Debug` for Multisig Wasm builds --- examples/multisig/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/multisig/lib.rs b/examples/multisig/lib.rs index 16a35430528..788b28e3c69 100755 --- a/examples/multisig/lib.rs +++ b/examples/multisig/lib.rs @@ -110,11 +110,13 @@ mod multisig { /// A Transaction is what every `owner` can submit for confirmation by other owners. /// If enough owners agree it will be executed by the contract. - #[derive(scale::Decode, scale::Encode)] + /// + /// TODO: Figure out where this is being pulled in + #[derive(scale::Decode, scale::Encode, ::core::fmt::Debug)] #[cfg_attr( feature = "std", derive( - Debug, + // Debug, PartialEq, Eq, scale_info::TypeInfo, From 892923451e54804149c29709ffad700edd2875b1 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 15:32:16 +0100 Subject: [PATCH 043/102] Add another `Debug` impl --- crates/ink/macro/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ink/macro/src/lib.rs b/crates/ink/macro/src/lib.rs index 04b7deed98c..01ad27c16ce 100644 --- a/crates/ink/macro/src/lib.rs +++ b/crates/ink/macro/src/lib.rs @@ -1218,7 +1218,8 @@ pub fn test(attr: TokenStream, item: TokenStream) -> TokenStream { /// # panic!("encountered unexpected invalid SCALE encoding") /// # } /// # } -/// # #[derive(scale::Encode, scale::Decode, scale_info::TypeInfo)] +/// # // TODO: Remove Debug impl +/// # #[derive(scale::Encode, scale::Decode, scale_info::TypeInfo, ::core::fmt::Debug)] /// # pub enum Access { /// # ReadWrite, /// # ReadOnly, From bb6c4454d6fe71af4901cac52fad300a73c91a21 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 15:45:47 +0100 Subject: [PATCH 044/102] Add `lang_error` to metadata tests --- crates/metadata/Cargo.toml | 1 + crates/metadata/src/tests.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/crates/metadata/Cargo.toml b/crates/metadata/Cargo.toml index b67e6ffd354..7fc22dc5509 100644 --- a/crates/metadata/Cargo.toml +++ b/crates/metadata/Cargo.toml @@ -34,6 +34,7 @@ default = [ ] std = [ "ink_prelude/std", + "ink_primitives/std", "serde/std", "scale-info/std", ] diff --git a/crates/metadata/src/tests.rs b/crates/metadata/src/tests.rs index f1b2b1fb9db..ad396a5ef2e 100644 --- a/crates/metadata/src/tests.rs +++ b/crates/metadata/src/tests.rs @@ -112,6 +112,12 @@ fn spec_contract_json() { .done(), ]) .events(Vec::new()) + .lang_error(TypeSpec::with_name_segs::( + ::core::iter::Iterator::map( + ::core::iter::IntoIterator::into_iter(["ink", "LangError"]), + ::core::convert::AsRef::as_ref, + ), + )) .done(); let mut registry = Registry::new(); @@ -168,6 +174,13 @@ fn spec_contract_json() { ], "docs": [], "events": [], + "lang_error": { + "displayName": [ + "ink", + "LangError" + ], + "type": 3 + }, "messages": [ { "args": [ From 10c9e7d8a9e9b4278a1749f5f35c67254b8705fe Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 16:23:21 +0100 Subject: [PATCH 045/102] Add example which uses ContractRefs --- examples/cross_chain_ref/.gitignore | 9 ++++++ examples/cross_chain_ref/Cargo.toml | 32 +++++++++++++++++++ examples/cross_chain_ref/lib.rs | 48 +++++++++++++++++++++++++++++ examples/flipper/Cargo.toml | 7 ++++- examples/flipper/lib.rs | 5 +++ 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100755 examples/cross_chain_ref/.gitignore create mode 100755 examples/cross_chain_ref/Cargo.toml create mode 100755 examples/cross_chain_ref/lib.rs diff --git a/examples/cross_chain_ref/.gitignore b/examples/cross_chain_ref/.gitignore new file mode 100755 index 00000000000..8de8f877e47 --- /dev/null +++ b/examples/cross_chain_ref/.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/examples/cross_chain_ref/Cargo.toml b/examples/cross_chain_ref/Cargo.toml new file mode 100755 index 00000000000..ab083f9d35c --- /dev/null +++ b/examples/cross_chain_ref/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "cross_chain_ref" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { path = "../../crates/ink", default-features = false } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } + +flipper = { path = "../flipper", default-features = false, features = ["ink-as-dependency"] } + +[lib] +name = "cross_chain_ref" +path = "lib.rs" +crate-type = [ + # Used for normal contract Wasm blobs. + "cdylib", +] + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "flipper/std", +] +ink-as-dependency = [] diff --git a/examples/cross_chain_ref/lib.rs b/examples/cross_chain_ref/lib.rs new file mode 100755 index 00000000000..850811b198a --- /dev/null +++ b/examples/cross_chain_ref/lib.rs @@ -0,0 +1,48 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +#[ink::contract] +mod cross_chain_ref { + use flipper::FlipperRef; + + #[ink(storage)] + pub struct CrossChainRef { + flipper: FlipperRef, + } + + impl CrossChainRef { + #[ink(constructor)] + pub fn new(version: u32, flipper_code_hash: Hash) -> Self { + let salt = version.to_le_bytes(); + let flipper = FlipperRef::default() + .endowment(0) + .code_hash(flipper_code_hash) + .salt_bytes(salt) + .instantiate() + .unwrap_or_else(|error| { + panic!("failed at instantiating the Flipper contract: {:?}", error) + }); + + Self { flipper } + } + + #[ink(message)] + pub fn flip(&mut self) { + self.flipper.flip(); + } + + #[ink(message)] + pub fn flip_check(&mut self) { + self.flipper.flip_checked().unwrap(); + } + + #[ink(message)] + pub fn get(&mut self) -> bool { + self.flipper.get() + } + + #[ink(message)] + pub fn get_check(&mut self) -> bool { + self.flipper.get_checked().unwrap() + } + } +} diff --git a/examples/flipper/Cargo.toml b/examples/flipper/Cargo.toml index ec8865dcb56..aa00382d671 100644 --- a/examples/flipper/Cargo.toml +++ b/examples/flipper/Cargo.toml @@ -14,7 +14,12 @@ scale-info = { version = "2.3", default-features = false, features = ["derive"], [lib] name = "flipper" path = "lib.rs" -crate-type = ["cdylib"] +crate-type = [ + # Used for normal contract Wasm blobs. + "cdylib", + # Used for ABI generation. + "rlib", +] [features] default = ["std"] diff --git a/examples/flipper/lib.rs b/examples/flipper/lib.rs index 58f191054d6..208e098efda 100644 --- a/examples/flipper/lib.rs +++ b/examples/flipper/lib.rs @@ -1,5 +1,10 @@ #![cfg_attr(not(feature = "std"), no_std)] +pub use self::flipper::{ + Flipper, + FlipperRef, +}; + #[ink::contract] pub mod flipper { #[ink(storage)] From 57ddec7e264ec481ca461bb3e9717842e20ea3bd Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 17:02:01 +0100 Subject: [PATCH 046/102] Handle dispatch error in example --- examples/cross_chain_test/lib.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index f509ebd9576..36c9e2cb3c8 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -25,14 +25,22 @@ mod cross_chain_test { DefaultEnvironment, }; - let _result = build_call::() + let result = build_call::() .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) .returns::>() // .returns::<()>() - .fire(); + .fire() + .expect("seal error"); - ink::env::debug_println!("cross_contract::call output: {:?}", &_result); + ink::env::debug_println!("cross_contract::call output: {:?}", &result); + match result { + Ok(_) => (), + Err(ink::LangError::CouldNotReadInput) => { + ink::env::debug_println!("CouldNotReadInput") + } + Err(_) => unimplemented!(), + } } } } From 077d15b0c337fb51dc9b0a75b779f152ec759df8 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 17:10:37 +0100 Subject: [PATCH 047/102] Add UI test for checking that messages now return `Result`s --- .../contract/pass/message-returns-result.rs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 crates/ink/tests/ui/contract/pass/message-returns-result.rs diff --git a/crates/ink/tests/ui/contract/pass/message-returns-result.rs b/crates/ink/tests/ui/contract/pass/message-returns-result.rs new file mode 100644 index 00000000000..1961afe5273 --- /dev/null +++ b/crates/ink/tests/ui/contract/pass/message-returns-result.rs @@ -0,0 +1,56 @@ +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message, selector = 0)] + pub fn message(&self) {} + + #[ink(message, selector = 1)] + pub fn message_1(&self) -> Result<(), ()> { + Ok(()) + } + } +} + +use contract::Contract; + +fn main() { + assert_eq!( + ::core::any::TypeId::of::< + ::MESSAGES + }, + >>::IDS[0usize] + }, + >>::Output, + >(), + ::core::any::TypeId::of::<::core::result::Result<(), ::ink::LangError>>() + ); + + assert_eq!( + ::core::any::TypeId::of::< + ::MESSAGES + }, + >>::IDS[1usize] + }, + >>::Output, + >(), + ::core::any::TypeId::of::< + ::core::result::Result<::core::result::Result<(), ()>, ::ink::LangError>, + >() + ); +} From 816f31291745a1c747ae043cb5ba60dd2f5f9934 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 17:42:07 +0100 Subject: [PATCH 048/102] Add test for message hygiene (or lack thereof) --- .../contract/fail/message-hygiene-checked.rs | 20 +++++++++++++++++++ .../fail/message-hygiene-checked.stderr | 8 ++++++++ 2 files changed, 28 insertions(+) create mode 100644 crates/ink/tests/ui/contract/fail/message-hygiene-checked.rs create mode 100644 crates/ink/tests/ui/contract/fail/message-hygiene-checked.stderr diff --git a/crates/ink/tests/ui/contract/fail/message-hygiene-checked.rs b/crates/ink/tests/ui/contract/fail/message-hygiene-checked.rs new file mode 100644 index 00000000000..4f1c844ceb1 --- /dev/null +++ b/crates/ink/tests/ui/contract/fail/message-hygiene-checked.rs @@ -0,0 +1,20 @@ +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + + #[ink(message)] + pub fn message_checked(&self) {} + } +} + +fn main() {} diff --git a/crates/ink/tests/ui/contract/fail/message-hygiene-checked.stderr b/crates/ink/tests/ui/contract/fail/message-hygiene-checked.stderr new file mode 100644 index 00000000000..cce9b1f97a6 --- /dev/null +++ b/crates/ink/tests/ui/contract/fail/message-hygiene-checked.stderr @@ -0,0 +1,8 @@ +error[E0201]: duplicate definitions with name `message_checked`: + --> tests/ui/contract/fail/message-hygiene-checked.rs:16:9 + | +1 | #[ink::contract] + | ---------------- previous definition of `message_checked` here +... +16 | pub fn message_checked(&self) {} + | ^^^ duplicate definition From 636e7c975be2274f63b122973e206062864d536d Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 17:42:41 +0100 Subject: [PATCH 049/102] Add test to check that `*_checked` messages are generated --- .../contract/pass/message-checked-variant.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 crates/ink/tests/ui/contract/pass/message-checked-variant.rs diff --git a/crates/ink/tests/ui/contract/pass/message-checked-variant.rs b/crates/ink/tests/ui/contract/pass/message-checked-variant.rs new file mode 100644 index 00000000000..7c5a8250516 --- /dev/null +++ b/crates/ink/tests/ui/contract/pass/message-checked-variant.rs @@ -0,0 +1,24 @@ +#[ink::contract] +mod contract { + #[ink(storage)] + #[derive(Default)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::default() + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +use contract::Contract; + +fn main() { + let contract = Contract::default(); + contract.message(); + contract.message_checked().unwrap(); +} From e2d81944bbfc524d788bd5e31d133a0b8063e3d6 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 18:50:44 +0100 Subject: [PATCH 050/102] Remove debug logging from macro code --- crates/env/src/engine/on_chain/ext.rs | 1 - crates/env/src/engine/on_chain/impls.rs | 20 +++---------------- crates/ink/codegen/src/generator/dispatch.rs | 6 ------ crates/ink/macro/src/lib.rs | 3 +-- crates/ink/src/reflect/dispatch.rs | 2 +- .../fail/message-input-non-codec.stderr | 17 ---------------- examples/multisig/lib.rs | 6 ++---- 7 files changed, 7 insertions(+), 48 deletions(-) diff --git a/crates/env/src/engine/on_chain/ext.rs b/crates/env/src/engine/on_chain/ext.rs index 6511780a1ad..b4c906e2a55 100644 --- a/crates/env/src/engine/on_chain/ext.rs +++ b/crates/env/src/engine/on_chain/ext.rs @@ -28,7 +28,6 @@ macro_rules! define_error_codes { ) => { /// Every error that can be returned to a contract when it calls any of the host functions. #[repr(u32)] - #[derive(::core::fmt::Debug)] pub enum Error { $( $( #[$attr] )* diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index be7319fc179..036bb16d877 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -442,23 +442,9 @@ impl TypedEnvBackend for EnvInstance { output, ); match call_result { - Ok(()) => { - // let decoded = scale::Decode::decode(&mut &output[..])?; - // Ok(decoded) - if let Ok(decoded) = scale::Decode::decode(&mut &output[..]) { - Ok(decoded) - } else { - ::core::panic!("failed to decode successful message output"); - } - } - Err(ext::Error::CalleeReverted) => { - // let decoded = scale::Decode::decode(&mut &output[..])?; - // Ok(decoded) - if let Ok(decoded) = scale::Decode::decode(&mut &output[..]) { - Ok(decoded) - } else { - ::core::panic!("failed to decode reverted message output"); - } + Ok(()) | Err(ext::Error::CalleeReverted) => { + let decoded = scale::Decode::decode(&mut &output[..])?; + Ok(decoded) } Err(actual_error) => Err(actual_error.into()), } diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 66d1656b01d..b9aaf1cafe1 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -437,15 +437,10 @@ impl Dispatch<'_> { <#storage_ident as ::ink::reflect::ContractMessageDecoder>::Type, >() { ::core::result::Result::Ok(decoded_dispatchable) => { - ::ink::env::debug_println!("Result from `decode_input` {:?}", &decoded_dispatchable); decoded_dispatchable } ::core::result::Result::Err(_decoding_error) => { use ::core::default::Default; - ::ink::env::debug_println!("Result from `decode_input` {:?}", &_decoding_error); - - // TODO: Here will pick out the `Dispatch` error we're interested in telling the - // user about and encode it correctly let error = ::core::result::Result::Err(::ink::LangError::CouldNotReadInput); // At this point we're unable to set the `Ok` variant to be the any "real" @@ -804,7 +799,6 @@ impl Dispatch<'_> { quote_spanned!(span=> const _: () = { #[allow(non_camel_case_types)] - #[derive(::core::fmt::Debug)] pub enum __ink_MessageDecoder { #( #message_variants ),* } diff --git a/crates/ink/macro/src/lib.rs b/crates/ink/macro/src/lib.rs index 01ad27c16ce..04b7deed98c 100644 --- a/crates/ink/macro/src/lib.rs +++ b/crates/ink/macro/src/lib.rs @@ -1218,8 +1218,7 @@ pub fn test(attr: TokenStream, item: TokenStream) -> TokenStream { /// # panic!("encountered unexpected invalid SCALE encoding") /// # } /// # } -/// # // TODO: Remove Debug impl -/// # #[derive(scale::Encode, scale::Decode, scale_info::TypeInfo, ::core::fmt::Debug)] +/// # #[derive(scale::Encode, scale::Decode, scale_info::TypeInfo)] /// # pub enum Access { /// # ReadWrite, /// # ReadOnly, diff --git a/crates/ink/src/reflect/dispatch.rs b/crates/ink/src/reflect/dispatch.rs index 7582d09a07c..735007d4a35 100644 --- a/crates/ink/src/reflect/dispatch.rs +++ b/crates/ink/src/reflect/dispatch.rs @@ -515,7 +515,7 @@ pub trait ExecuteDispatchable { } /// An error that can occur during dispatch of ink! dispatchables. -#[derive(Debug, Copy, Clone, PartialEq, Eq, ::scale::Encode, ::scale::Decode)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum DispatchError { /// Failed to decode into a valid dispatch selector. InvalidSelector, diff --git a/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr index 622e6abf3ad..e6c2260060a 100644 --- a/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr +++ b/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr @@ -15,23 +15,6 @@ note: required by a bound in `DispatchInput` | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` -error[E0277]: `NonCodecType` doesn't implement `Debug` - --> tests/ui/contract/fail/message-input-non-codec.rs:16:9 - | -7 | pub struct Contract {} - | --- in this derive macro expansion -... -16 | pub fn message(&self, _input: NonCodecType) {} - | ^^^ `NonCodecType` cannot be formatted using `{:?}` - | - = help: the trait `Debug` is not implemented for `NonCodecType` - = note: add `#[derive(Debug)]` to `NonCodecType` or manually `impl Debug for NonCodecType` - = note: this error originates in the derive macro `::core::fmt::Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider annotating `NonCodecType` with `#[derive(Debug)]` - | -4 | #[derive(Debug)] - | - error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied --> tests/ui/contract/fail/message-input-non-codec.rs:16:9 | diff --git a/examples/multisig/lib.rs b/examples/multisig/lib.rs index 788b28e3c69..16a35430528 100755 --- a/examples/multisig/lib.rs +++ b/examples/multisig/lib.rs @@ -110,13 +110,11 @@ mod multisig { /// A Transaction is what every `owner` can submit for confirmation by other owners. /// If enough owners agree it will be executed by the contract. - /// - /// TODO: Figure out where this is being pulled in - #[derive(scale::Decode, scale::Encode, ::core::fmt::Debug)] + #[derive(scale::Decode, scale::Encode)] #[cfg_attr( feature = "std", derive( - // Debug, + Debug, PartialEq, Eq, scale_info::TypeInfo, From 94449dd0c2062222cf254569f54f8f3ed7927c27 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Nov 2022 18:54:41 +0100 Subject: [PATCH 051/102] Appease Clippy --- examples/cross_chain_test/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 36c9e2cb3c8..031b1e77a35 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -37,7 +37,7 @@ mod cross_chain_test { match result { Ok(_) => (), Err(ink::LangError::CouldNotReadInput) => { - ink::env::debug_println!("CouldNotReadInput") + ink::env::debug_println!("CouldNotReadInput"); } Err(_) => unimplemented!(), } From f1137a7228ccb3ec6e376d7cf80be45300060b4e Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 11 Nov 2022 18:26:42 +0100 Subject: [PATCH 052/102] Remove `--skip-linting` from scripts This is because I've updated my local version of `cargo-contract` --- deploy-contract.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy-contract.sh b/deploy-contract.sh index 5ad4b75e6b6..0cb6f395ab3 100755 --- a/deploy-contract.sh +++ b/deploy-contract.sh @@ -4,7 +4,7 @@ set -ex F="${1:-pass}" -cargo contract build --manifest-path examples/flipper/Cargo.toml --skip-linting +cargo contract build --manifest-path examples/flipper/Cargo.toml cargo contract instantiate \ --manifest-path examples/flipper/Cargo.toml \ --suri //Alice --output-json \ @@ -15,7 +15,7 @@ cargo contract instantiate \ FLIPPER_ADDRESS=$(tail -n +2 /tmp/deployment-output.json | jq --raw-output .contract) echo $FLIPPER_ADDRESS -cargo contract build --manifest-path examples/cross_chain_test/Cargo.toml --skip-linting +cargo contract build --manifest-path examples/cross_chain_test/Cargo.toml cargo contract instantiate \ --manifest-path examples/cross_chain_test/Cargo.toml \ --suri //Alice --output-json \ From 2afef50d148f1c07ea0b8e3b0d2e5619d3a1d7c5 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 11 Nov 2022 17:50:01 +0000 Subject: [PATCH 053/102] Fix fallible constructor revert, make `Ok` explicit --- crates/ink/codegen/src/generator/dispatch.rs | 21 ++++++++++++------- .../ink/codegen/src/generator/item_impls.rs | 11 ---------- .../contract/pass/message-checked-variant.rs | 1 - 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index b9aaf1cafe1..809a5346ce0 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -297,12 +297,14 @@ impl Dispatch<'_> { .map(|message| { let message_span = message.span(); let message_ident = message.ident(); - let checked_message_ident = message.checked_ident(); let payable = message.is_payable(); let mutates = message.receiver().is_ref_mut(); let selector_id = message.composed_selector().into_be_u32().hex_padded_suffixed(); let selector_bytes = message.composed_selector().hex_lits(); - let output_tuple_type = message.wrapped_output(); + let output_tuple_type = message + .output() + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote! { () }); let input_bindings = generator::input_bindings(message.inputs()); let input_tuple_type = generator::input_types_tuple(message.inputs()); let input_tuple_bindings = generator::input_bindings_tuple(message.inputs()); @@ -314,7 +316,7 @@ impl Dispatch<'_> { const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = |storage, #input_tuple_bindings| { - #storage_ident::#checked_message_ident( storage #( , #input_bindings )* ) + #storage_ident::#message_ident( storage #( , #input_bindings )* ) }; const SELECTOR: [::core::primitive::u8; 4usize] = [ #( #selector_bytes ),* ]; const PAYABLE: ::core::primitive::bool = #payable; @@ -777,21 +779,24 @@ impl Dispatch<'_> { let failure = ::ink::is_result_type!(#message_output) && ::ink::is_result_err!(result); + // Currently no `LangError`s are raised at this level of the dispatch logic + // so `Ok` is always returned to the caller. + let return_value = ::core::result::Result::Ok(result); + if failure { // We return early here since there is no need to push back the // intermediate results of the contract - the transaction is going to be // reverted anyways. - ::ink::env::return_value::<#message_output>( - ::ink::env::ReturnFlags::default().set_reverted(true), &result + ::ink::env::return_value::<::core::result::Result::<#message_output, ::ink::LangError>>( + ::ink::env::ReturnFlags::default().set_reverted(true), &return_value ) } push_contract(contract, #mutates_storage); - ::ink::env::return_value::<#message_output>( - ::ink::env::ReturnFlags::default(), &result + ::ink::env::return_value::<::core::result::Result::<#message_output, ::ink::LangError>>( + ::ink::env::ReturnFlags::default(), &return_value ) - } ) }); diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index ca93ee0a16a..673c6fe9779 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -256,26 +256,15 @@ impl ItemImpls<'_> { let vis = message.visibility(); let receiver = message.receiver(); let ident = message.ident(); - let checked_ident = message.checked_ident(); let inputs = message.inputs(); - let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); - let wrapped_inputs = message.inputs(); let output_arrow = message.output().map(|_| quote! { -> }); let output = message.output(); - let wrapped_output = message.wrapped_output(); let statements = message.statements(); - quote_spanned!(span => #( #attrs )* #vis fn #ident(#receiver #( , #inputs )* ) #output_arrow #output { #( #statements )* } - - #( #attrs )* - #vis fn #checked_ident(#receiver #( , #wrapped_inputs )* ) -> #wrapped_output { - ::core::result::Result::Ok(self.#ident( #( #input_bindings , )* )) - - } ) } diff --git a/crates/ink/tests/ui/contract/pass/message-checked-variant.rs b/crates/ink/tests/ui/contract/pass/message-checked-variant.rs index 7c5a8250516..13c42a4f2dc 100644 --- a/crates/ink/tests/ui/contract/pass/message-checked-variant.rs +++ b/crates/ink/tests/ui/contract/pass/message-checked-variant.rs @@ -20,5 +20,4 @@ use contract::Contract; fn main() { let contract = Contract::default(); contract.message(); - contract.message_checked().unwrap(); } From ed1aeeccf2384a701cb12e4f903b28106dc7d7d6 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 11 Nov 2022 19:42:56 +0100 Subject: [PATCH 054/102] Hack together E2E test example for `LangError` --- examples/cross_chain_test/Cargo.toml | 7 +++ examples/cross_chain_test/lib.rs | 88 +++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/examples/cross_chain_test/Cargo.toml b/examples/cross_chain_test/Cargo.toml index 5055bb6dc9e..69bf95b24aa 100755 --- a/examples/cross_chain_test/Cargo.toml +++ b/examples/cross_chain_test/Cargo.toml @@ -10,6 +10,11 @@ ink = { path = "../../crates/ink", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } +flipper = { path = "../flipper", default-features = false, features = ["ink-as-dependency"] } + +[dev-dependencies] +ink_e2e = { path = "../../crates/e2e" } + [lib] name = "cross_chain_test" path = "lib.rs" @@ -24,5 +29,7 @@ std = [ "ink/std", "scale/std", "scale-info/std", + + "flipper/std", ] ink-as-dependency = [] diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 031b1e77a35..170f970cbb3 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -14,7 +14,11 @@ mod cross_chain_test { } #[ink(message)] - pub fn call(&mut self, address: AccountId, selector: [u8; 4]) { + pub fn call( + &mut self, + address: AccountId, + selector: [u8; 4], + ) -> Result<(), ::ink::LangError> { use ink::env::{ call::{ build_call, @@ -35,12 +39,90 @@ mod cross_chain_test { ink::env::debug_println!("cross_contract::call output: {:?}", &result); match result { - Ok(_) => (), - Err(ink::LangError::CouldNotReadInput) => { + Ok(_) => Ok(()), + Err(e @ ink::LangError::CouldNotReadInput) => { ink::env::debug_println!("CouldNotReadInput"); + Err(e) } Err(_) => unimplemented!(), } } } + + #[cfg(test)] + mod e2e_tests { + type E2EResult = std::result::Result>; + + #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] + async fn e2e_cross_chain_test( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = cross_chain_test::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::alice(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let flipper_constructor = flipper::constructors::default(); + let flipper_acc_id = client + .instantiate(&mut ink_e2e::alice(), flipper_constructor, 0, None) + .await + .expect("instantiate `flipper` failed") + .account_id; + let flipper_ink_acc_id = + cross_chain_test::contract_types::ink_primitives::types::AccountId( + flipper_acc_id.clone().into(), + ); + + let valid_selector = [0x63, 0x3A, 0xA5, 0x51]; + let invalid_selector = [0x00, 0x00, 0x00, 0x00]; + + let call_result = client + .call( + &mut ink_e2e::bob(), + contract_acc_id.clone(), + cross_chain_test::messages::call(flipper_ink_acc_id, valid_selector), + 0, + None, + ) + .await + .expect("calling `cross_chain_test::call` failed"); + assert!(call_result.value.is_ok()); + dbg!(&call_result.value); + + // TODO: Figure out `Clone` impl for AccountId + let flipper_ink_acc_id = + cross_chain_test::contract_types::ink_primitives::types::AccountId( + flipper_acc_id.into(), + ); + + let call_result = client + .call( + &mut ink_e2e::bob(), + contract_acc_id.clone(), + cross_chain_test::messages::call( + flipper_ink_acc_id, + invalid_selector, + ), + 0, + None, + ) + .await + .expect("calling `cross_chain_test::call` failed"); + dbg!(&call_result.value); + + // TODO: Need to figure out how to derive `PartialEq` for `e2e::LangError` + match call_result.value.unwrap() { + Ok(_) => panic!("should've been an error"), + Err(cross_chain_test::contract_types::ink_primitives::LangError::CouldNotReadInput) => { + } + // TODO: Need to figure out how to make `e2e::LangError` `non_exhaustive` + #[allow(unreachable_patterns)] + Err(_) => panic!("should've been a different error"), + }; + + Ok(()) + } + } } From ed60df82e63759b7e5abc995547ed517db33efbd Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 13 Nov 2022 19:41:20 +0100 Subject: [PATCH 055/102] Add a couple of type aliases to E2E test --- examples/cross_chain_test/lib.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 170f970cbb3..d3ee8c813ac 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -57,6 +57,11 @@ mod cross_chain_test { async fn e2e_cross_chain_test( mut client: ink_e2e::Client, ) -> E2EResult<()> { + use cross_chain_test::contract_types::ink_primitives::{ + types::AccountId as E2EAccountId, + LangError as E2ELangError, + }; + let constructor = cross_chain_test::constructors::new(); let contract_acc_id = client .instantiate(&mut ink_e2e::alice(), constructor, 0, None) @@ -70,10 +75,7 @@ mod cross_chain_test { .await .expect("instantiate `flipper` failed") .account_id; - let flipper_ink_acc_id = - cross_chain_test::contract_types::ink_primitives::types::AccountId( - flipper_acc_id.clone().into(), - ); + let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); let valid_selector = [0x63, 0x3A, 0xA5, 0x51]; let invalid_selector = [0x00, 0x00, 0x00, 0x00]; @@ -91,11 +93,8 @@ mod cross_chain_test { assert!(call_result.value.is_ok()); dbg!(&call_result.value); - // TODO: Figure out `Clone` impl for AccountId - let flipper_ink_acc_id = - cross_chain_test::contract_types::ink_primitives::types::AccountId( - flipper_acc_id.into(), - ); + // TODO: Figure out `Clone` impl for E2EAccountId + let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); let call_result = client .call( @@ -115,8 +114,7 @@ mod cross_chain_test { // TODO: Need to figure out how to derive `PartialEq` for `e2e::LangError` match call_result.value.unwrap() { Ok(_) => panic!("should've been an error"), - Err(cross_chain_test::contract_types::ink_primitives::LangError::CouldNotReadInput) => { - } + Err(E2ELangError::CouldNotReadInput) => {} // TODO: Need to figure out how to make `e2e::LangError` `non_exhaustive` #[allow(unreachable_patterns)] Err(_) => panic!("should've been a different error"), From 8cea958736be332fb21eeabf963c75b80f2cedf4 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 13 Nov 2022 20:38:13 +0100 Subject: [PATCH 056/102] Add E2E test which demonstrates write-on-err bug Currently using a single test for all E2E tests since there seems to be some problem with the nonce management that isn't letting me split the tests out into seperate functions. --- examples/cross_chain_test/lib.rs | 133 +++++++++++++++++++++++++++---- examples/flipper/lib.rs | 9 +++ 2 files changed, 128 insertions(+), 14 deletions(-) diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index d3ee8c813ac..bbc6860a748 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -75,27 +75,68 @@ mod cross_chain_test { .await .expect("instantiate `flipper` failed") .account_id; - let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); - let valid_selector = [0x63, 0x3A, 0xA5, 0x51]; - let invalid_selector = [0x00, 0x00, 0x00, 0x00]; + // --- Can Flip Correctly --- - let call_result = client + let get_call_result = client .call( &mut ink_e2e::bob(), - contract_acc_id.clone(), - cross_chain_test::messages::call(flipper_ink_acc_id, valid_selector), + flipper_acc_id.clone(), + flipper::messages::get(), 0, None, ) .await - .expect("calling `cross_chain_test::call` failed"); - assert!(call_result.value.is_ok()); - dbg!(&call_result.value); + .expect("Calling `flipper::get` failed"); + let initial_value = get_call_result + .value + .expect("Shouldn't fail since input is valid"); - // TODO: Figure out `Clone` impl for E2EAccountId - let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); + let flip_call_result = client + .call( + &mut ink_e2e::bob(), + flipper_acc_id.clone(), + flipper::messages::flip(), + 0, + None, + ) + .await + .expect("Calling `flipper::flip` failed"); + assert!(flip_call_result.value.is_ok()); + let get_call_result = client + .call( + &mut ink_e2e::bob(), + flipper_acc_id.clone(), + flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `flipper::get` failed"); + let flipped_value = get_call_result + .value + .expect("Shouldn't fail since input is valid"); + assert!(flipped_value == !initial_value); + + // --- Invalid Selector Can Be Handled --- + + let get_call_result = client + .call( + &mut ink_e2e::bob(), + flipper_acc_id.clone(), + flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `flipper::get` failed"); + let initial_value = get_call_result + .value + .expect("Shouldn't fail since input is valid"); + + let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); + let invalid_selector = [0x00, 0x00, 0x00, 0x00]; let call_result = client .call( &mut ink_e2e::bob(), @@ -108,11 +149,14 @@ mod cross_chain_test { None, ) .await - .expect("calling `cross_chain_test::call` failed"); - dbg!(&call_result.value); + .expect("Calling `cross_chain_test::call` failed"); + + let flipper_result = call_result + .value + .expect("Call to `cross_chain_test::call` failed"); // TODO: Need to figure out how to derive `PartialEq` for `e2e::LangError` - match call_result.value.unwrap() { + match flipper_result { Ok(_) => panic!("should've been an error"), Err(E2ELangError::CouldNotReadInput) => {} // TODO: Need to figure out how to make `e2e::LangError` `non_exhaustive` @@ -120,6 +164,67 @@ mod cross_chain_test { Err(_) => panic!("should've been a different error"), }; + let get_call_result = client + .call( + &mut ink_e2e::bob(), + flipper_acc_id.clone(), + flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `flipper::get` failed"); + let flipped_value = get_call_result + .value + .expect("Shouldn't fail since input is valid"); + assert!(flipped_value == initial_value); + + // --- State is Reverted on Message Error --- + + let get_call_result = client + .call( + &mut ink_e2e::bob(), + flipper_acc_id.clone(), + flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `flipper::get` failed"); + let initial_value = get_call_result + .value + .expect("Shouldn't fail since input is valid"); + + let err_flip_call_result = client + .call( + &mut ink_e2e::bob(), + flipper_acc_id.clone(), + flipper::messages::err_flip(), + 0, + None, + ) + .await + .expect("Calling `flipper::err_flip` failed"); + let flipper_result = err_flip_call_result + .value + .expect("Call to `flipper::err_flip` failed"); + assert!(flipper_result.is_err()); + + let get_call_result = client + .call( + &mut ink_e2e::bob(), + flipper_acc_id.clone(), + flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `flipper::get` failed"); + let flipped_value = get_call_result + .value + .expect("Shouldn't fail since input is valid"); + assert!(flipped_value == initial_value); + Ok(()) } } diff --git a/examples/flipper/lib.rs b/examples/flipper/lib.rs index 208e098efda..4b17c4a3382 100644 --- a/examples/flipper/lib.rs +++ b/examples/flipper/lib.rs @@ -36,6 +36,15 @@ pub mod flipper { pub fn get(&self) -> bool { self.value } + + /// Flips the current value of the Flipper's boolean. + /// + /// We should see the state being reverted here, no write should occur. + #[ink(message)] + pub fn err_flip(&mut self) -> Result<(), ()> { + self.value = !self.value; + Err(()) + } } #[cfg(test)] From 2488761dfa6aad2b6bcb7a150e0447d1a3bdeadc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 13 Nov 2022 20:58:47 +0100 Subject: [PATCH 057/102] Split out E2E tests into seperate functions Had to use make calls using different accounts --- examples/cross_chain_test/lib.rs | 123 +++++++++++++++++++------------ 1 file changed, 75 insertions(+), 48 deletions(-) diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index bbc6860a748..62c538e6800 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -54,21 +54,9 @@ mod cross_chain_test { type E2EResult = std::result::Result>; #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] - async fn e2e_cross_chain_test( + async fn e2e_can_flip_correctly( mut client: ink_e2e::Client, ) -> E2EResult<()> { - use cross_chain_test::contract_types::ink_primitives::{ - types::AccountId as E2EAccountId, - LangError as E2ELangError, - }; - - let constructor = cross_chain_test::constructors::new(); - let contract_acc_id = client - .instantiate(&mut ink_e2e::alice(), constructor, 0, None) - .await - .expect("instantiate failed") - .account_id; - let flipper_constructor = flipper::constructors::default(); let flipper_acc_id = client .instantiate(&mut ink_e2e::alice(), flipper_constructor, 0, None) @@ -76,11 +64,9 @@ mod cross_chain_test { .expect("instantiate `flipper` failed") .account_id; - // --- Can Flip Correctly --- - let get_call_result = client .call( - &mut ink_e2e::bob(), + &mut ink_e2e::alice(), flipper_acc_id.clone(), flipper::messages::get(), 0, @@ -94,7 +80,7 @@ mod cross_chain_test { let flip_call_result = client .call( - &mut ink_e2e::bob(), + &mut ink_e2e::alice(), flipper_acc_id.clone(), flipper::messages::flip(), 0, @@ -106,7 +92,7 @@ mod cross_chain_test { let get_call_result = client .call( - &mut ink_e2e::bob(), + &mut ink_e2e::alice(), flipper_acc_id.clone(), flipper::messages::get(), 0, @@ -119,7 +105,24 @@ mod cross_chain_test { .expect("Shouldn't fail since input is valid"); assert!(flipped_value == !initial_value); - // --- Invalid Selector Can Be Handled --- + Ok(()) + } + + #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] + async fn e2e_message_error_reverts_state( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + // TODO: If I use the same account here as in the above test (so `ink_e2e::alice()`) + // then there's a problem with the tranaction priority which causes the test to panic. + // + // We should allow the same account to be used in tests, or at least do something + // better than just panicking with an obscure message. + let flipper_constructor = flipper::constructors::default(); + let flipper_acc_id = client + .instantiate(&mut ink_e2e::bob(), flipper_constructor, 0, None) + .await + .expect("instantiate `flipper` failed") + .account_id; let get_call_result = client .call( @@ -135,34 +138,20 @@ mod cross_chain_test { .value .expect("Shouldn't fail since input is valid"); - let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); - let invalid_selector = [0x00, 0x00, 0x00, 0x00]; - let call_result = client + let err_flip_call_result = client .call( &mut ink_e2e::bob(), - contract_acc_id.clone(), - cross_chain_test::messages::call( - flipper_ink_acc_id, - invalid_selector, - ), + flipper_acc_id.clone(), + flipper::messages::err_flip(), 0, None, ) .await - .expect("Calling `cross_chain_test::call` failed"); - - let flipper_result = call_result + .expect("Calling `flipper::err_flip` failed"); + let flipper_result = err_flip_call_result .value - .expect("Call to `cross_chain_test::call` failed"); - - // TODO: Need to figure out how to derive `PartialEq` for `e2e::LangError` - match flipper_result { - Ok(_) => panic!("should've been an error"), - Err(E2ELangError::CouldNotReadInput) => {} - // TODO: Need to figure out how to make `e2e::LangError` `non_exhaustive` - #[allow(unreachable_patterns)] - Err(_) => panic!("should've been a different error"), - }; + .expect("Call to `flipper::err_flip` failed"); + assert!(flipper_result.is_err()); let get_call_result = client .call( @@ -179,7 +168,31 @@ mod cross_chain_test { .expect("Shouldn't fail since input is valid"); assert!(flipped_value == initial_value); - // --- State is Reverted on Message Error --- + Ok(()) + } + + #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] + async fn e2e_invalid_selector_can_be_handled( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + use cross_chain_test::contract_types::ink_primitives::{ + types::AccountId as E2EAccountId, + LangError as E2ELangError, + }; + + let constructor = cross_chain_test::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::charlie(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let flipper_constructor = flipper::constructors::default(); + let flipper_acc_id = client + .instantiate(&mut ink_e2e::alice(), flipper_constructor, 0, None) + .await + .expect("instantiate `flipper` failed") + .account_id; let get_call_result = client .call( @@ -195,20 +208,34 @@ mod cross_chain_test { .value .expect("Shouldn't fail since input is valid"); - let err_flip_call_result = client + let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); + let invalid_selector = [0x00, 0x00, 0x00, 0x00]; + let call_result = client .call( &mut ink_e2e::bob(), - flipper_acc_id.clone(), - flipper::messages::err_flip(), + contract_acc_id.clone(), + cross_chain_test::messages::call( + flipper_ink_acc_id, + invalid_selector, + ), 0, None, ) .await - .expect("Calling `flipper::err_flip` failed"); - let flipper_result = err_flip_call_result + .expect("Calling `cross_chain_test::call` failed"); + + let flipper_result = call_result .value - .expect("Call to `flipper::err_flip` failed"); - assert!(flipper_result.is_err()); + .expect("Call to `cross_chain_test::call` failed"); + + // TODO: Need to figure out how to derive `PartialEq` for `e2e::LangError` + match flipper_result { + Ok(_) => panic!("should've been an error"), + Err(E2ELangError::CouldNotReadInput) => {} + // TODO: Need to figure out how to make `e2e::LangError` `non_exhaustive` + #[allow(unreachable_patterns)] + Err(_) => panic!("should've been a different error"), + }; let get_call_result = client .call( From 412c9aca924033b5f98a879612a006b87716cde8 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 13 Nov 2022 21:58:22 +0100 Subject: [PATCH 058/102] Tweak E2E tests to make them pass given Andrew's fixes --- examples/cross_chain_test/lib.rs | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 62c538e6800..30e316df82d 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -18,7 +18,7 @@ mod cross_chain_test { &mut self, address: AccountId, selector: [u8; 4], - ) -> Result<(), ::ink::LangError> { + ) -> Option<::ink::LangError> { use ink::env::{ call::{ build_call, @@ -39,10 +39,10 @@ mod cross_chain_test { ink::env::debug_println!("cross_contract::call output: {:?}", &result); match result { - Ok(_) => Ok(()), + Ok(_) => None, Err(e @ ink::LangError::CouldNotReadInput) => { ink::env::debug_println!("CouldNotReadInput"); - Err(e) + Some(e) } Err(_) => unimplemented!(), } @@ -146,12 +146,12 @@ mod cross_chain_test { 0, None, ) - .await - .expect("Calling `flipper::err_flip` failed"); - let flipper_result = err_flip_call_result - .value - .expect("Call to `flipper::err_flip` failed"); - assert!(flipper_result.is_err()); + .await; + + assert!(matches!( + err_flip_call_result, + Err(ink_e2e::Error::CallExtrinsic(_)) + )); let get_call_result = client .call( @@ -228,14 +228,10 @@ mod cross_chain_test { .value .expect("Call to `cross_chain_test::call` failed"); - // TODO: Need to figure out how to derive `PartialEq` for `e2e::LangError` - match flipper_result { - Ok(_) => panic!("should've been an error"), - Err(E2ELangError::CouldNotReadInput) => {} - // TODO: Need to figure out how to make `e2e::LangError` `non_exhaustive` - #[allow(unreachable_patterns)] - Err(_) => panic!("should've been a different error"), - }; + assert!(matches!( + flipper_result, + Some(E2ELangError::CouldNotReadInput) + )); let get_call_result = client .call( From 59bde0ea96e31dd85803f3854233bf2f8173deae Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 13 Nov 2022 23:24:54 +0100 Subject: [PATCH 059/102] Remove outdated UI test --- .../contract/pass/message-returns-result.rs | 56 ------------------- 1 file changed, 56 deletions(-) delete mode 100644 crates/ink/tests/ui/contract/pass/message-returns-result.rs diff --git a/crates/ink/tests/ui/contract/pass/message-returns-result.rs b/crates/ink/tests/ui/contract/pass/message-returns-result.rs deleted file mode 100644 index 1961afe5273..00000000000 --- a/crates/ink/tests/ui/contract/pass/message-returns-result.rs +++ /dev/null @@ -1,56 +0,0 @@ -#[ink::contract] -mod contract { - #[ink(storage)] - pub struct Contract {} - - impl Contract { - #[ink(constructor)] - pub fn constructor() -> Self { - Self {} - } - - #[ink(message, selector = 0)] - pub fn message(&self) {} - - #[ink(message, selector = 1)] - pub fn message_1(&self) -> Result<(), ()> { - Ok(()) - } - } -} - -use contract::Contract; - -fn main() { - assert_eq!( - ::core::any::TypeId::of::< - ::MESSAGES - }, - >>::IDS[0usize] - }, - >>::Output, - >(), - ::core::any::TypeId::of::<::core::result::Result<(), ::ink::LangError>>() - ); - - assert_eq!( - ::core::any::TypeId::of::< - ::MESSAGES - }, - >>::IDS[1usize] - }, - >>::Output, - >(), - ::core::any::TypeId::of::< - ::core::result::Result<::core::result::Result<(), ()>, ::ink::LangError>, - >() - ); -} From 6eea67ee9de00046f5f85e0d6d9bd598b0e2b3e1 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 13 Nov 2022 23:35:29 +0100 Subject: [PATCH 060/102] Fix a couple more tests --- crates/ink/src/reflect/dispatch.rs | 4 ++-- .../ui/contract/fail/impl-block-for-non-storage-01.stderr | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ink/src/reflect/dispatch.rs b/crates/ink/src/reflect/dispatch.rs index 735007d4a35..832cefeb249 100644 --- a/crates/ink/src/reflect/dispatch.rs +++ b/crates/ink/src/reflect/dispatch.rs @@ -224,10 +224,10 @@ pub trait ContractDispatchableConstructors { /// } /// /// fn main() { -/// assert_message_info::<(), Result<(), ink::LangError>, {selector_id!("message1")}>( +/// assert_message_info::<(), (), {selector_id!("message1")}>( /// false, false, selector_bytes!("message1"), "message1" /// ); -/// assert_message_info::<(i32, i64), Result<(bool, i32), ink::LangError>, 0xC0DECAFE_u32>( +/// assert_message_info::<(i32, i64), (bool, i32), 0xC0DECAFE_u32>( /// true, true, [0xC0, 0xDE, 0xCA, 0xFE], "message2" /// ); /// } diff --git a/crates/ink/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr b/crates/ink/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr index 17af341d831..53823fe552c 100644 --- a/crates/ink/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr +++ b/crates/ink/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr @@ -19,14 +19,14 @@ error[E0599]: no function or associated item named `constructor_2` found for str | function or associated item not found in `Contract` | help: there is an associated function with a similar name: `constructor_1` -error[E0599]: no function or associated item named `message_2_checked` found for struct `Contract` in the current scope +error[E0599]: no function or associated item named `message_2` found for struct `Contract` in the current scope --> tests/ui/contract/fail/impl-block-for-non-storage-01.rs:25:16 | 4 | pub struct Contract {} - | --- function or associated item `message_2_checked` not found for this struct + | --- function or associated item `message_2` not found for this struct ... 25 | pub fn message_2(&self) {} | ^^^^^^^^^ | | | function or associated item not found in `Contract` - | help: there is a method with a similar name: `message_1_checked` + | help: there is a method with a similar name: `message_1` From a78b0422924beb5a327e8e1aa823ab67bb8d262c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Nov 2022 11:35:41 -0500 Subject: [PATCH 061/102] Unify output type and arrow in codegen --- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs index 9200faf0d89..588d14fd8af 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -344,8 +344,7 @@ impl ContractRef<'_> { let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let input_types = message.inputs().map(|input| &input.ty).collect::>(); - let output_arrow = message.output().map(|_| quote! { -> }); - let output_type = message.output(); + let output_type = message.output().map(|ty| quote! { -> #ty }); let wrapped_output_type = message.wrapped_output(); quote_spanned!(span=> #( #attrs )* @@ -353,7 +352,7 @@ impl ContractRef<'_> { pub fn #message_ident( & #mut_token self #( , #input_bindings : #input_types )* - ) #output_arrow #output_type { + ) #output_type { self.#checked_message_ident( #( #input_bindings, )* ) .unwrap_or_else(|error| ::core::panic!( "encountered error while calling {}::{}: {:?}", From 96c9c427a0230957e6d98bfe6a45e57c9ba3bcfc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Nov 2022 11:41:07 -0500 Subject: [PATCH 062/102] Allow `result_unit_err` Clippy lint --- examples/flipper/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/flipper/lib.rs b/examples/flipper/lib.rs index 4b17c4a3382..4da7ac1ea18 100644 --- a/examples/flipper/lib.rs +++ b/examples/flipper/lib.rs @@ -41,6 +41,7 @@ pub mod flipper { /// /// We should see the state being reverted here, no write should occur. #[ink(message)] + #[allow(clippy::result_unit_err)] pub fn err_flip(&mut self) -> Result<(), ()> { self.value = !self.value; Err(()) From f113dc286ba9e7776982ef9e27e145b151a30ea6 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Nov 2022 18:48:47 -0500 Subject: [PATCH 063/102] Move `Flipper` functionality into integration example --- examples/cross_chain_test/Cargo.toml | 4 - examples/cross_chain_test/lib.rs | 106 +++++++++++++++++---------- examples/flipper/lib.rs | 10 --- 3 files changed, 67 insertions(+), 53 deletions(-) diff --git a/examples/cross_chain_test/Cargo.toml b/examples/cross_chain_test/Cargo.toml index 69bf95b24aa..b9086a1214b 100755 --- a/examples/cross_chain_test/Cargo.toml +++ b/examples/cross_chain_test/Cargo.toml @@ -10,8 +10,6 @@ ink = { path = "../../crates/ink", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } -flipper = { path = "../flipper", default-features = false, features = ["ink-as-dependency"] } - [dev-dependencies] ink_e2e = { path = "../../crates/e2e" } @@ -29,7 +27,5 @@ std = [ "ink/std", "scale/std", "scale-info/std", - - "flipper/std", ] ink-as-dependency = [] diff --git a/examples/cross_chain_test/lib.rs b/examples/cross_chain_test/lib.rs index 30e316df82d..0318965f9f7 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/cross_chain_test/lib.rs @@ -5,12 +5,14 @@ mod cross_chain_test { #[ink(storage)] #[derive(Default)] - pub struct CrossChainTest {} + pub struct CrossChainTest { + value: bool, + } impl CrossChainTest { #[ink(constructor)] pub fn new() -> Self { - Self {} + Default::default() } #[ink(message)] @@ -47,68 +49,94 @@ mod cross_chain_test { Err(_) => unimplemented!(), } } + + /// Returns the current value of the Flipper's boolean. + #[ink(message)] + pub fn get(&self) -> bool { + self.value + } + + /// Flips the current value of the Flipper's boolean. + #[ink(message)] + pub fn flip(&mut self) { + self.value = !self.value; + } + + /// Flips the current value of the Flipper's boolean. + /// + /// We should see the state being reverted here, no write should occur. + #[ink(message)] + #[allow(clippy::result_unit_err)] + pub fn err_flip(&mut self) -> Result<(), ()> { + self.flip(); + Err(()) + } } #[cfg(test)] mod e2e_tests { type E2EResult = std::result::Result>; + // TODO: Log issue about macro ordering #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] async fn e2e_can_flip_correctly( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let flipper_constructor = flipper::constructors::default(); - let flipper_acc_id = client - .instantiate(&mut ink_e2e::alice(), flipper_constructor, 0, None) + let constructor = cross_chain_test::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::alice(), constructor, 0, None) .await - .expect("instantiate `flipper` failed") + .expect("Instantiate `cross_chain_test` failed") .account_id; let get_call_result = client .call( &mut ink_e2e::alice(), - flipper_acc_id.clone(), - flipper::messages::get(), + contract_acc_id.clone(), + cross_chain_test::messages::get(), 0, None, ) .await - .expect("Calling `flipper::get` failed"); + .expect("Calling `get` failed"); let initial_value = get_call_result .value - .expect("Shouldn't fail since input is valid"); + .expect("Input is valid, call must not fail."); let flip_call_result = client .call( &mut ink_e2e::alice(), - flipper_acc_id.clone(), - flipper::messages::flip(), + contract_acc_id.clone(), + cross_chain_test::messages::flip(), 0, None, ) .await - .expect("Calling `flipper::flip` failed"); - assert!(flip_call_result.value.is_ok()); + .expect("Calling `flip` failed"); + assert!( + flip_call_result.value.is_ok(), + "Messages now return a `Result`, which should be `Ok` here." + ); let get_call_result = client .call( &mut ink_e2e::alice(), - flipper_acc_id.clone(), - flipper::messages::get(), + contract_acc_id.clone(), + cross_chain_test::messages::get(), 0, None, ) .await - .expect("Calling `flipper::get` failed"); + .expect("Calling `get` failed"); let flipped_value = get_call_result .value - .expect("Shouldn't fail since input is valid"); + .expect("Input is valid, call must not fail."); assert!(flipped_value == !initial_value); Ok(()) } - #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] + #[ink_e2e::test] async fn e2e_message_error_reverts_state( mut client: ink_e2e::Client, ) -> E2EResult<()> { @@ -117,32 +145,32 @@ mod cross_chain_test { // // We should allow the same account to be used in tests, or at least do something // better than just panicking with an obscure message. - let flipper_constructor = flipper::constructors::default(); - let flipper_acc_id = client - .instantiate(&mut ink_e2e::bob(), flipper_constructor, 0, None) + let constructor = cross_chain_test::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::bob(), constructor, 0, None) .await - .expect("instantiate `flipper` failed") + .expect("instantiate failed") .account_id; let get_call_result = client .call( &mut ink_e2e::bob(), - flipper_acc_id.clone(), - flipper::messages::get(), + contract_acc_id.clone(), + cross_chain_test::messages::get(), 0, None, ) .await - .expect("Calling `flipper::get` failed"); + .expect("Calling `get` failed"); let initial_value = get_call_result .value - .expect("Shouldn't fail since input is valid"); + .expect("Input is valid, call must not fail."); let err_flip_call_result = client .call( &mut ink_e2e::bob(), - flipper_acc_id.clone(), - flipper::messages::err_flip(), + contract_acc_id.clone(), + cross_chain_test::messages::err_flip(), 0, None, ) @@ -156,16 +184,16 @@ mod cross_chain_test { let get_call_result = client .call( &mut ink_e2e::bob(), - flipper_acc_id.clone(), - flipper::messages::get(), + contract_acc_id.clone(), + cross_chain_test::messages::get(), 0, None, ) .await - .expect("Calling `flipper::get` failed"); + .expect("Calling `get` failed"); let flipped_value = get_call_result .value - .expect("Shouldn't fail since input is valid"); + .expect("Input is valid, call must not fail."); assert!(flipped_value == initial_value); Ok(()) @@ -189,14 +217,14 @@ mod cross_chain_test { let flipper_constructor = flipper::constructors::default(); let flipper_acc_id = client - .instantiate(&mut ink_e2e::alice(), flipper_constructor, 0, None) + .instantiate(&mut ink_e2e::charlie(), flipper_constructor, 0, None) .await .expect("instantiate `flipper` failed") .account_id; let get_call_result = client .call( - &mut ink_e2e::bob(), + &mut ink_e2e::charlie(), flipper_acc_id.clone(), flipper::messages::get(), 0, @@ -206,13 +234,13 @@ mod cross_chain_test { .expect("Calling `flipper::get` failed"); let initial_value = get_call_result .value - .expect("Shouldn't fail since input is valid"); + .expect("Input is valid, call must not fail."); let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); let invalid_selector = [0x00, 0x00, 0x00, 0x00]; let call_result = client .call( - &mut ink_e2e::bob(), + &mut ink_e2e::charlie(), contract_acc_id.clone(), cross_chain_test::messages::call( flipper_ink_acc_id, @@ -235,7 +263,7 @@ mod cross_chain_test { let get_call_result = client .call( - &mut ink_e2e::bob(), + &mut ink_e2e::charlie(), flipper_acc_id.clone(), flipper::messages::get(), 0, @@ -245,7 +273,7 @@ mod cross_chain_test { .expect("Calling `flipper::get` failed"); let flipped_value = get_call_result .value - .expect("Shouldn't fail since input is valid"); + .expect("Input is valid, call must not fail."); assert!(flipped_value == initial_value); Ok(()) diff --git a/examples/flipper/lib.rs b/examples/flipper/lib.rs index 4da7ac1ea18..208e098efda 100644 --- a/examples/flipper/lib.rs +++ b/examples/flipper/lib.rs @@ -36,16 +36,6 @@ pub mod flipper { pub fn get(&self) -> bool { self.value } - - /// Flips the current value of the Flipper's boolean. - /// - /// We should see the state being reverted here, no write should occur. - #[ink(message)] - #[allow(clippy::result_unit_err)] - pub fn err_flip(&mut self) -> Result<(), ()> { - self.value = !self.value; - Err(()) - } } #[cfg(test)] From f6b4c10b4fbcb6207e58b15280dff76f8a450acc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Nov 2022 19:30:09 -0500 Subject: [PATCH 064/102] Rename `cross_chain_test` to indicate that its an integration test --- call-contract.sh | 2 +- deploy-contract.sh | 12 +++--- .../.gitignore | 0 .../Cargo.toml | 9 +++-- .../lib.rs | 39 ++++++++++--------- 5 files changed, 33 insertions(+), 29 deletions(-) rename examples/{cross_chain_test => lang_err_integration_tests}/.gitignore (100%) rename examples/{cross_chain_test => lang_err_integration_tests}/Cargo.toml (77%) rename examples/{cross_chain_test => lang_err_integration_tests}/lib.rs (87%) diff --git a/call-contract.sh b/call-contract.sh index 0aab6a12359..c38d2490cf3 100755 --- a/call-contract.sh +++ b/call-contract.sh @@ -13,7 +13,7 @@ args=() args+=( --contract ${CROSS_CONTRACT_ADDR} ) args+=( --message call ) args+=( --suri //Alice ) -args+=( --manifest-path ./examples/cross_chain_test/Cargo.toml ) +args+=( --manifest-path ./examples/lang_err_integration_tests/Cargo.toml ) args+=( --verbose ) args+=( --skip-confirm ) diff --git a/deploy-contract.sh b/deploy-contract.sh index 0cb6f395ab3..ef74dd0ef65 100755 --- a/deploy-contract.sh +++ b/deploy-contract.sh @@ -4,7 +4,7 @@ set -ex F="${1:-pass}" -cargo contract build --manifest-path examples/flipper/Cargo.toml +cargo contract build --manifest-path examples/flipper/Cargo.toml --offline cargo contract instantiate \ --manifest-path examples/flipper/Cargo.toml \ --suri //Alice --output-json \ @@ -15,14 +15,14 @@ cargo contract instantiate \ FLIPPER_ADDRESS=$(tail -n +2 /tmp/deployment-output.json | jq --raw-output .contract) echo $FLIPPER_ADDRESS -cargo contract build --manifest-path examples/cross_chain_test/Cargo.toml +cargo contract build --manifest-path examples/lang_err_integration_tests/Cargo.toml --offline cargo contract instantiate \ - --manifest-path examples/cross_chain_test/Cargo.toml \ + --manifest-path examples/lang_err_integration_tests/Cargo.toml \ --suri //Alice --output-json \ --salt $(date +%s) \ --skip-confirm > /tmp/deployment-output.json - CROSS_ADDRESS=$(tail -n +2 /tmp/deployment-output.json | jq --raw-output .contract) - echo $CROSS_ADDRESS + INTEGRATION_ADDRESS=$(tail -n +2 /tmp/deployment-output.json | jq --raw-output .contract) + echo $INTEGRATION_ADDRESS - ./call-contract.sh $F $CROSS_ADDRESS $FLIPPER_ADDRESS + ./call-contract.sh $F $INTEGRATION_ADDRESS $FLIPPER_ADDRESS diff --git a/examples/cross_chain_test/.gitignore b/examples/lang_err_integration_tests/.gitignore similarity index 100% rename from examples/cross_chain_test/.gitignore rename to examples/lang_err_integration_tests/.gitignore diff --git a/examples/cross_chain_test/Cargo.toml b/examples/lang_err_integration_tests/Cargo.toml similarity index 77% rename from examples/cross_chain_test/Cargo.toml rename to examples/lang_err_integration_tests/Cargo.toml index b9086a1214b..5c83f3c0e8a 100755 --- a/examples/cross_chain_test/Cargo.toml +++ b/examples/lang_err_integration_tests/Cargo.toml @@ -1,8 +1,9 @@ [package] -name = "cross_chain_test" -version = "0.1.0" -authors = ["[your_name] <[your_email]>"] +name = "lang_err_integration_tests" +version = "4.0.0-alpha.3" +authors = ["Parity Technologies "] edition = "2021" +publish = false [dependencies] ink = { path = "../../crates/ink", default-features = false } @@ -14,7 +15,7 @@ scale-info = { version = "2", default-features = false, features = ["derive"], o ink_e2e = { path = "../../crates/e2e" } [lib] -name = "cross_chain_test" +name = "lang_err_integration_tests" path = "lib.rs" crate-type = [ # Used for normal contract Wasm blobs. diff --git a/examples/cross_chain_test/lib.rs b/examples/lang_err_integration_tests/lib.rs similarity index 87% rename from examples/cross_chain_test/lib.rs rename to examples/lang_err_integration_tests/lib.rs index 0318965f9f7..b1a55e2e0e7 100755 --- a/examples/cross_chain_test/lib.rs +++ b/examples/lang_err_integration_tests/lib.rs @@ -1,15 +1,15 @@ #![cfg_attr(not(feature = "std"), no_std)] #[ink::contract] -mod cross_chain_test { +mod lang_err_integration_tests { #[ink(storage)] #[derive(Default)] - pub struct CrossChainTest { + pub struct LangErrIntegrationTests { value: bool, } - impl CrossChainTest { + impl LangErrIntegrationTests { #[ink(constructor)] pub fn new() -> Self { Default::default() @@ -39,7 +39,10 @@ mod cross_chain_test { .fire() .expect("seal error"); - ink::env::debug_println!("cross_contract::call output: {:?}", &result); + ink::env::debug_println!( + "lang_err_integration_tests::call output: {:?}", + &result + ); match result { Ok(_) => None, Err(e @ ink::LangError::CouldNotReadInput) => { @@ -82,18 +85,18 @@ mod cross_chain_test { async fn e2e_can_flip_correctly( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let constructor = cross_chain_test::constructors::new(); + let constructor = lang_err_integration_tests::constructors::new(); let contract_acc_id = client .instantiate(&mut ink_e2e::alice(), constructor, 0, None) .await - .expect("Instantiate `cross_chain_test` failed") + .expect("Instantiate `lang_err_integration_tests` failed") .account_id; let get_call_result = client .call( &mut ink_e2e::alice(), contract_acc_id.clone(), - cross_chain_test::messages::get(), + lang_err_integration_tests::messages::get(), 0, None, ) @@ -107,7 +110,7 @@ mod cross_chain_test { .call( &mut ink_e2e::alice(), contract_acc_id.clone(), - cross_chain_test::messages::flip(), + lang_err_integration_tests::messages::flip(), 0, None, ) @@ -122,7 +125,7 @@ mod cross_chain_test { .call( &mut ink_e2e::alice(), contract_acc_id.clone(), - cross_chain_test::messages::get(), + lang_err_integration_tests::messages::get(), 0, None, ) @@ -145,7 +148,7 @@ mod cross_chain_test { // // We should allow the same account to be used in tests, or at least do something // better than just panicking with an obscure message. - let constructor = cross_chain_test::constructors::new(); + let constructor = lang_err_integration_tests::constructors::new(); let contract_acc_id = client .instantiate(&mut ink_e2e::bob(), constructor, 0, None) .await @@ -156,7 +159,7 @@ mod cross_chain_test { .call( &mut ink_e2e::bob(), contract_acc_id.clone(), - cross_chain_test::messages::get(), + lang_err_integration_tests::messages::get(), 0, None, ) @@ -170,7 +173,7 @@ mod cross_chain_test { .call( &mut ink_e2e::bob(), contract_acc_id.clone(), - cross_chain_test::messages::err_flip(), + lang_err_integration_tests::messages::err_flip(), 0, None, ) @@ -185,7 +188,7 @@ mod cross_chain_test { .call( &mut ink_e2e::bob(), contract_acc_id.clone(), - cross_chain_test::messages::get(), + lang_err_integration_tests::messages::get(), 0, None, ) @@ -203,12 +206,12 @@ mod cross_chain_test { async fn e2e_invalid_selector_can_be_handled( mut client: ink_e2e::Client, ) -> E2EResult<()> { - use cross_chain_test::contract_types::ink_primitives::{ + use lang_err_integration_tests::contract_types::ink_primitives::{ types::AccountId as E2EAccountId, LangError as E2ELangError, }; - let constructor = cross_chain_test::constructors::new(); + let constructor = lang_err_integration_tests::constructors::new(); let contract_acc_id = client .instantiate(&mut ink_e2e::charlie(), constructor, 0, None) .await @@ -242,7 +245,7 @@ mod cross_chain_test { .call( &mut ink_e2e::charlie(), contract_acc_id.clone(), - cross_chain_test::messages::call( + lang_err_integration_tests::messages::call( flipper_ink_acc_id, invalid_selector, ), @@ -250,11 +253,11 @@ mod cross_chain_test { None, ) .await - .expect("Calling `cross_chain_test::call` failed"); + .expect("Calling `lang_err_integration_tests::call` failed"); let flipper_result = call_result .value - .expect("Call to `cross_chain_test::call` failed"); + .expect("Call to `lang_err_integration_tests::call` failed"); assert!(matches!( flipper_result, From 8b8eec8cd93e3fd2b4acf58b36ce028e91c24c12 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Nov 2022 19:36:43 -0500 Subject: [PATCH 065/102] Remove test helper scripts --- call-contract.sh | 27 --------------------------- deploy-contract.sh | 28 ---------------------------- 2 files changed, 55 deletions(-) delete mode 100755 call-contract.sh delete mode 100755 deploy-contract.sh diff --git a/call-contract.sh b/call-contract.sh deleted file mode 100755 index c38d2490cf3..00000000000 --- a/call-contract.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -set -ex - -F="${1:-pass}" -CROSS_CONTRACT_ADDR=$2 -FLIPPER_ADDR=$3 - -SELECTOR="0x633aa551" -BAD_SELECTOR="0x00000000" - -args=() -args+=( --contract ${CROSS_CONTRACT_ADDR} ) -args+=( --message call ) -args+=( --suri //Alice ) -args+=( --manifest-path ./examples/lang_err_integration_tests/Cargo.toml ) -args+=( --verbose ) -args+=( --skip-confirm ) - -case $F in - '--fail') - args+=( --args $FLIPPER_ADDR $BAD_SELECTOR ) ;; - *) - args+=( --args $FLIPPER_ADDR $SELECTOR ) ;; - esac - -cargo contract call "${args[@]}" diff --git a/deploy-contract.sh b/deploy-contract.sh deleted file mode 100755 index ef74dd0ef65..00000000000 --- a/deploy-contract.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -set -ex - -F="${1:-pass}" - -cargo contract build --manifest-path examples/flipper/Cargo.toml --offline -cargo contract instantiate \ - --manifest-path examples/flipper/Cargo.toml \ - --suri //Alice --output-json \ - --constructor default \ - --salt $(date +%s) \ - --skip-confirm > /tmp/deployment-output.json - -FLIPPER_ADDRESS=$(tail -n +2 /tmp/deployment-output.json | jq --raw-output .contract) -echo $FLIPPER_ADDRESS - -cargo contract build --manifest-path examples/lang_err_integration_tests/Cargo.toml --offline -cargo contract instantiate \ - --manifest-path examples/lang_err_integration_tests/Cargo.toml \ - --suri //Alice --output-json \ - --salt $(date +%s) \ - --skip-confirm > /tmp/deployment-output.json - - INTEGRATION_ADDRESS=$(tail -n +2 /tmp/deployment-output.json | jq --raw-output .contract) - echo $INTEGRATION_ADDRESS - - ./call-contract.sh $F $INTEGRATION_ADDRESS $FLIPPER_ADDRESS From 6c245439bc019bc0e06fb602fa9aa1d08bc0f8d5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Nov 2022 19:40:32 -0500 Subject: [PATCH 066/102] Remove `ContractRef` example/compile test It would be nice to have this as a proper compile test at some point, but right now the set of delegator contracts can be used as an indication for breakages. --- examples/cross_chain_ref/.gitignore | 9 ------ examples/cross_chain_ref/Cargo.toml | 32 ------------------- examples/cross_chain_ref/lib.rs | 48 ----------------------------- 3 files changed, 89 deletions(-) delete mode 100755 examples/cross_chain_ref/.gitignore delete mode 100755 examples/cross_chain_ref/Cargo.toml delete mode 100755 examples/cross_chain_ref/lib.rs diff --git a/examples/cross_chain_ref/.gitignore b/examples/cross_chain_ref/.gitignore deleted file mode 100755 index 8de8f877e47..00000000000 --- a/examples/cross_chain_ref/.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/examples/cross_chain_ref/Cargo.toml b/examples/cross_chain_ref/Cargo.toml deleted file mode 100755 index ab083f9d35c..00000000000 --- a/examples/cross_chain_ref/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "cross_chain_ref" -version = "0.1.0" -authors = ["[your_name] <[your_email]>"] -edition = "2021" - -[dependencies] -ink = { path = "../../crates/ink", default-features = false } - -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } - -flipper = { path = "../flipper", default-features = false, features = ["ink-as-dependency"] } - -[lib] -name = "cross_chain_ref" -path = "lib.rs" -crate-type = [ - # Used for normal contract Wasm blobs. - "cdylib", -] - -[features] -default = ["std"] -std = [ - "ink/std", - "scale/std", - "scale-info/std", - - "flipper/std", -] -ink-as-dependency = [] diff --git a/examples/cross_chain_ref/lib.rs b/examples/cross_chain_ref/lib.rs deleted file mode 100755 index 850811b198a..00000000000 --- a/examples/cross_chain_ref/lib.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -#[ink::contract] -mod cross_chain_ref { - use flipper::FlipperRef; - - #[ink(storage)] - pub struct CrossChainRef { - flipper: FlipperRef, - } - - impl CrossChainRef { - #[ink(constructor)] - pub fn new(version: u32, flipper_code_hash: Hash) -> Self { - let salt = version.to_le_bytes(); - let flipper = FlipperRef::default() - .endowment(0) - .code_hash(flipper_code_hash) - .salt_bytes(salt) - .instantiate() - .unwrap_or_else(|error| { - panic!("failed at instantiating the Flipper contract: {:?}", error) - }); - - Self { flipper } - } - - #[ink(message)] - pub fn flip(&mut self) { - self.flipper.flip(); - } - - #[ink(message)] - pub fn flip_check(&mut self) { - self.flipper.flip_checked().unwrap(); - } - - #[ink(message)] - pub fn get(&mut self) -> bool { - self.flipper.get() - } - - #[ink(message)] - pub fn get_check(&mut self) -> bool { - self.flipper.get_checked().unwrap() - } - } -} From ce67e879229a859138ed7bad81c6da71f949434c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Nov 2022 19:45:38 -0500 Subject: [PATCH 067/102] Appease Clippy --- examples/lang_err_integration_tests/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lang_err_integration_tests/lib.rs b/examples/lang_err_integration_tests/lib.rs index b1a55e2e0e7..98fd4075985 100755 --- a/examples/lang_err_integration_tests/lib.rs +++ b/examples/lang_err_integration_tests/lib.rs @@ -134,7 +134,7 @@ mod lang_err_integration_tests { let flipped_value = get_call_result .value .expect("Input is valid, call must not fail."); - assert!(flipped_value == !initial_value); + assert!(flipped_value != initial_value); Ok(()) } From f5b5ae4cc1dc365a0b29ff9cf4c854c86a799679 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Nov 2022 20:29:35 -0500 Subject: [PATCH 068/102] Add `MessageResult` type alias --- crates/ink/codegen/src/generator/dispatch.rs | 4 ++-- crates/ink/ir/src/ir/item_impl/message.rs | 2 +- crates/ink/src/lib.rs | 5 ++++- crates/primitives/src/lib.rs | 11 +++++++++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 809a5346ce0..f66a7eb92c7 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -787,14 +787,14 @@ impl Dispatch<'_> { // We return early here since there is no need to push back the // intermediate results of the contract - the transaction is going to be // reverted anyways. - ::ink::env::return_value::<::core::result::Result::<#message_output, ::ink::LangError>>( + ::ink::env::return_value::<::ink::MessageResult::<#message_output>>( ::ink::env::ReturnFlags::default().set_reverted(true), &return_value ) } push_contract(contract, #mutates_storage); - ::ink::env::return_value::<::core::result::Result::<#message_output, ::ink::LangError>>( + ::ink::env::return_value::<::ink::MessageResult::<#message_output>>( ::ink::env::ReturnFlags::default(), &return_value ) } diff --git a/crates/ink/ir/src/ir/item_impl/message.rs b/crates/ink/ir/src/ir/item_impl/message.rs index ff38eaca8de..f48814b4274 100644 --- a/crates/ink/ir/src/ir/item_impl/message.rs +++ b/crates/ink/ir/src/ir/item_impl/message.rs @@ -302,7 +302,7 @@ impl Message { .unwrap_or_else(|| quote::quote! { () }); syn::parse_quote! { - ::core::result::Result<#return_type, ::ink::LangError> + ::ink::MessageResult<#return_type> } } diff --git a/crates/ink/src/lib.rs b/crates/ink/src/lib.rs index ea252430b8d..a426811b119 100644 --- a/crates/ink/src/lib.rs +++ b/crates/ink/src/lib.rs @@ -71,4 +71,7 @@ pub use ink_macro::{ test, trait_definition, }; -pub use ink_primitives::LangError; +pub use ink_primitives::{ + LangError, + MessageResult, +}; diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index dc976a8e50b..e4d5608e2b9 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -42,8 +42,11 @@ pub use self::{ }, }; -/// An error that comes from the smart contracting language, but not necessarily the smart contract -/// itself nor the underlying execution environment. +/// An error emitted by the smart contracting language. +/// +/// This is different than errors from: +/// - Errors from the contract, which are programmer defined +/// - Errors from the underlying execution environment (e.g `pallet-contracts`) #[non_exhaustive] #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, ::scale::Encode, ::scale::Decode)] @@ -52,3 +55,7 @@ pub enum LangError { /// Failed to read execution input for the dispatchable. CouldNotReadInput = 1u32, } + +/// The `Result` type for ink! messages. +#[doc(hidden)] +pub type MessageResult = ::core::result::Result; From 0fbbae1b8bcfed1d78ef3fb2a51c0fc3539c1dbb Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Nov 2022 20:36:53 -0500 Subject: [PATCH 069/102] Remove `Ref` re-export from Flipper --- examples/flipper/Cargo.toml | 7 +------ examples/flipper/lib.rs | 5 ----- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/examples/flipper/Cargo.toml b/examples/flipper/Cargo.toml index aa00382d671..ec8865dcb56 100644 --- a/examples/flipper/Cargo.toml +++ b/examples/flipper/Cargo.toml @@ -14,12 +14,7 @@ scale-info = { version = "2.3", default-features = false, features = ["derive"], [lib] name = "flipper" path = "lib.rs" -crate-type = [ - # Used for normal contract Wasm blobs. - "cdylib", - # Used for ABI generation. - "rlib", -] +crate-type = ["cdylib"] [features] default = ["std"] diff --git a/examples/flipper/lib.rs b/examples/flipper/lib.rs index 208e098efda..58f191054d6 100644 --- a/examples/flipper/lib.rs +++ b/examples/flipper/lib.rs @@ -1,10 +1,5 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use self::flipper::{ - Flipper, - FlipperRef, -}; - #[ink::contract] pub mod flipper { #[ink(storage)] From 894e8989efae1cce1f522851377c55b2128bc509 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 11:40:00 -0500 Subject: [PATCH 070/102] Remove TODOs related to E2E issues These have now been logged in the issue tracker. --- examples/lang_err_integration_tests/lib.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/lang_err_integration_tests/lib.rs b/examples/lang_err_integration_tests/lib.rs index 98fd4075985..9a36d903569 100755 --- a/examples/lang_err_integration_tests/lib.rs +++ b/examples/lang_err_integration_tests/lib.rs @@ -80,7 +80,6 @@ mod lang_err_integration_tests { mod e2e_tests { type E2EResult = std::result::Result>; - // TODO: Log issue about macro ordering #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] async fn e2e_can_flip_correctly( mut client: ink_e2e::Client, @@ -143,11 +142,6 @@ mod lang_err_integration_tests { async fn e2e_message_error_reverts_state( mut client: ink_e2e::Client, ) -> E2EResult<()> { - // TODO: If I use the same account here as in the above test (so `ink_e2e::alice()`) - // then there's a problem with the tranaction priority which causes the test to panic. - // - // We should allow the same account to be used in tests, or at least do something - // better than just panicking with an obscure message. let constructor = lang_err_integration_tests::constructors::new(); let contract_acc_id = client .instantiate(&mut ink_e2e::bob(), constructor, 0, None) From fa9d57bca195a1045f86f735086f325db4609fd9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 11:41:57 -0500 Subject: [PATCH 071/102] Work around `additional_contracts` bug by moving tests --- examples/lang_err_integration_tests/lib.rs | 148 ++++++++++----------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/examples/lang_err_integration_tests/lib.rs b/examples/lang_err_integration_tests/lib.rs index 9a36d903569..bfa4ae0e9d4 100755 --- a/examples/lang_err_integration_tests/lib.rs +++ b/examples/lang_err_integration_tests/lib.rs @@ -81,77 +81,99 @@ mod lang_err_integration_tests { type E2EResult = std::result::Result>; #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] - async fn e2e_can_flip_correctly( + async fn e2e_invalid_selector_can_be_handled( mut client: ink_e2e::Client, ) -> E2EResult<()> { + use lang_err_integration_tests::contract_types::ink_primitives::{ + types::AccountId as E2EAccountId, + LangError as E2ELangError, + }; + let constructor = lang_err_integration_tests::constructors::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::alice(), constructor, 0, None) + .instantiate(&mut ink_e2e::charlie(), constructor, 0, None) .await - .expect("Instantiate `lang_err_integration_tests` failed") + .expect("instantiate failed") + .account_id; + + let flipper_constructor = flipper::constructors::default(); + let flipper_acc_id = client + .instantiate(&mut ink_e2e::charlie(), flipper_constructor, 0, None) + .await + .expect("instantiate `flipper` failed") .account_id; let get_call_result = client .call( - &mut ink_e2e::alice(), - contract_acc_id.clone(), - lang_err_integration_tests::messages::get(), + &mut ink_e2e::charlie(), + flipper_acc_id.clone(), + flipper::messages::get(), 0, None, ) .await - .expect("Calling `get` failed"); + .expect("Calling `flipper::get` failed"); let initial_value = get_call_result .value .expect("Input is valid, call must not fail."); - let flip_call_result = client + let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); + let invalid_selector = [0x00, 0x00, 0x00, 0x00]; + let call_result = client .call( - &mut ink_e2e::alice(), + &mut ink_e2e::charlie(), contract_acc_id.clone(), - lang_err_integration_tests::messages::flip(), + lang_err_integration_tests::messages::call( + flipper_ink_acc_id, + invalid_selector, + ), 0, None, ) .await - .expect("Calling `flip` failed"); - assert!( - flip_call_result.value.is_ok(), - "Messages now return a `Result`, which should be `Ok` here." - ); + .expect("Calling `lang_err_integration_tests::call` failed"); + + let flipper_result = call_result + .value + .expect("Call to `lang_err_integration_tests::call` failed"); + + assert!(matches!( + flipper_result, + Some(E2ELangError::CouldNotReadInput) + )); let get_call_result = client .call( - &mut ink_e2e::alice(), - contract_acc_id.clone(), - lang_err_integration_tests::messages::get(), + &mut ink_e2e::charlie(), + flipper_acc_id.clone(), + flipper::messages::get(), 0, None, ) .await - .expect("Calling `get` failed"); + .expect("Calling `flipper::get` failed"); let flipped_value = get_call_result .value .expect("Input is valid, call must not fail."); - assert!(flipped_value != initial_value); + assert!(flipped_value == initial_value); Ok(()) } #[ink_e2e::test] - async fn e2e_message_error_reverts_state( + async fn e2e_can_flip_correctly( mut client: ink_e2e::Client, ) -> E2EResult<()> { let constructor = lang_err_integration_tests::constructors::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::bob(), constructor, 0, None) + .instantiate(&mut ink_e2e::alice(), constructor, 0, None) .await - .expect("instantiate failed") + .expect("Instantiate `lang_err_integration_tests` failed") .account_id; let get_call_result = client .call( - &mut ink_e2e::bob(), + &mut ink_e2e::alice(), contract_acc_id.clone(), lang_err_integration_tests::messages::get(), 0, @@ -163,24 +185,24 @@ mod lang_err_integration_tests { .value .expect("Input is valid, call must not fail."); - let err_flip_call_result = client + let flip_call_result = client .call( - &mut ink_e2e::bob(), + &mut ink_e2e::alice(), contract_acc_id.clone(), - lang_err_integration_tests::messages::err_flip(), + lang_err_integration_tests::messages::flip(), 0, None, ) - .await; - - assert!(matches!( - err_flip_call_result, - Err(ink_e2e::Error::CallExtrinsic(_)) - )); + .await + .expect("Calling `flip` failed"); + assert!( + flip_call_result.value.is_ok(), + "Messages now return a `Result`, which should be `Ok` here." + ); let get_call_result = client .call( - &mut ink_e2e::bob(), + &mut ink_e2e::alice(), contract_acc_id.clone(), lang_err_integration_tests::messages::get(), 0, @@ -191,83 +213,61 @@ mod lang_err_integration_tests { let flipped_value = get_call_result .value .expect("Input is valid, call must not fail."); - assert!(flipped_value == initial_value); + assert!(flipped_value != initial_value); Ok(()) } - #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] - async fn e2e_invalid_selector_can_be_handled( + #[ink_e2e::test] + async fn e2e_message_error_reverts_state( mut client: ink_e2e::Client, ) -> E2EResult<()> { - use lang_err_integration_tests::contract_types::ink_primitives::{ - types::AccountId as E2EAccountId, - LangError as E2ELangError, - }; - let constructor = lang_err_integration_tests::constructors::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::charlie(), constructor, 0, None) + .instantiate(&mut ink_e2e::bob(), constructor, 0, None) .await .expect("instantiate failed") .account_id; - let flipper_constructor = flipper::constructors::default(); - let flipper_acc_id = client - .instantiate(&mut ink_e2e::charlie(), flipper_constructor, 0, None) - .await - .expect("instantiate `flipper` failed") - .account_id; - let get_call_result = client .call( - &mut ink_e2e::charlie(), - flipper_acc_id.clone(), - flipper::messages::get(), + &mut ink_e2e::bob(), + contract_acc_id.clone(), + lang_err_integration_tests::messages::get(), 0, None, ) .await - .expect("Calling `flipper::get` failed"); + .expect("Calling `get` failed"); let initial_value = get_call_result .value .expect("Input is valid, call must not fail."); - let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); - let invalid_selector = [0x00, 0x00, 0x00, 0x00]; - let call_result = client + let err_flip_call_result = client .call( - &mut ink_e2e::charlie(), + &mut ink_e2e::bob(), contract_acc_id.clone(), - lang_err_integration_tests::messages::call( - flipper_ink_acc_id, - invalid_selector, - ), + lang_err_integration_tests::messages::err_flip(), 0, None, ) - .await - .expect("Calling `lang_err_integration_tests::call` failed"); - - let flipper_result = call_result - .value - .expect("Call to `lang_err_integration_tests::call` failed"); + .await; assert!(matches!( - flipper_result, - Some(E2ELangError::CouldNotReadInput) + err_flip_call_result, + Err(ink_e2e::Error::CallExtrinsic(_)) )); let get_call_result = client .call( - &mut ink_e2e::charlie(), - flipper_acc_id.clone(), - flipper::messages::get(), + &mut ink_e2e::bob(), + contract_acc_id.clone(), + lang_err_integration_tests::messages::get(), 0, None, ) .await - .expect("Calling `flipper::get` failed"); + .expect("Calling `get` failed"); let flipped_value = get_call_result .value .expect("Input is valid, call must not fail."); From 51dec24ecf5a88b0ee4fc48ba3a2652f9ed78d50 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 11:49:57 -0500 Subject: [PATCH 072/102] Clean up `lang_err_integration_tests` a bit --- examples/lang_err_integration_tests/lib.rs | 31 +++++++++++++--------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/examples/lang_err_integration_tests/lib.rs b/examples/lang_err_integration_tests/lib.rs index bfa4ae0e9d4..0a5a8fc88c3 100755 --- a/examples/lang_err_integration_tests/lib.rs +++ b/examples/lang_err_integration_tests/lib.rs @@ -1,3 +1,10 @@ +//! # Integration Tests for `LangError` +//! +//! This contract is used to ensure that the behaviour around `LangError`s works as expected. +//! +//! It makes use of ink!'s end-to-end testing features, so ensure that you have a node which +//! includes the Contract's pallet running alongside your tests. + #![cfg_attr(not(feature = "std"), no_std)] #[ink::contract] @@ -15,6 +22,10 @@ mod lang_err_integration_tests { Default::default() } + /// Call a contract using the `CallBuilder`. + /// + /// Since we can't use the `CallBuilder` in a test environment directly we need this + /// wrapper to test things like crafting calls with invalid selectors. #[ink(message)] pub fn call( &mut self, @@ -35,37 +46,31 @@ mod lang_err_integration_tests { .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) .returns::>() - // .returns::<()>() .fire() - .expect("seal error"); + .expect("Error from the Contracts pallet."); - ink::env::debug_println!( - "lang_err_integration_tests::call output: {:?}", - &result - ); match result { Ok(_) => None, - Err(e @ ink::LangError::CouldNotReadInput) => { - ink::env::debug_println!("CouldNotReadInput"); - Some(e) + Err(e @ ink::LangError::CouldNotReadInput) => Some(e), + Err(_) => { + unimplemented!("No other `LangError` variants exist at the moment.") } - Err(_) => unimplemented!(), } } - /// Returns the current value of the Flipper's boolean. + /// Returns the current value of the LangErrIntegrationTests's boolean. #[ink(message)] pub fn get(&self) -> bool { self.value } - /// Flips the current value of the Flipper's boolean. + /// Flips the current value of the LangErrIntegrationTests's boolean. #[ink(message)] pub fn flip(&mut self) { self.value = !self.value; } - /// Flips the current value of the Flipper's boolean. + /// Flips the current value of the LangErrIntegrationTests's boolean. /// /// We should see the state being reverted here, no write should occur. #[ink(message)] From cee90d7981d3265489f8cdec6bc10e788061cdad Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 11:52:25 -0500 Subject: [PATCH 073/102] Fix spellcheck lint --- examples/lang_err_integration_tests/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/lang_err_integration_tests/lib.rs b/examples/lang_err_integration_tests/lib.rs index 0a5a8fc88c3..970ed2f8fdc 100755 --- a/examples/lang_err_integration_tests/lib.rs +++ b/examples/lang_err_integration_tests/lib.rs @@ -1,6 +1,6 @@ //! # Integration Tests for `LangError` //! -//! This contract is used to ensure that the behaviour around `LangError`s works as expected. +//! This contract is used to ensure that the behavior around `LangError`s works as expected. //! //! It makes use of ink!'s end-to-end testing features, so ensure that you have a node which //! includes the Contract's pallet running alongside your tests. @@ -58,19 +58,19 @@ mod lang_err_integration_tests { } } - /// Returns the current value of the LangErrIntegrationTests's boolean. + /// Returns the current value of the `LangErrIntegrationTests`'s boolean. #[ink(message)] pub fn get(&self) -> bool { self.value } - /// Flips the current value of the LangErrIntegrationTests's boolean. + /// Flips the current value of the `LangErrIntegrationTests`'s boolean. #[ink(message)] pub fn flip(&mut self) { self.value = !self.value; } - /// Flips the current value of the LangErrIntegrationTests's boolean. + /// Flips the current value of the `LangErrIntegrationTests`'s boolean. /// /// We should see the state being reverted here, no write should occur. #[ink(message)] From 1870988d2c55b12492b03ffb21a22126c136014f Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 14:53:53 -0500 Subject: [PATCH 074/102] Place E2E tests behind feature flag --- examples/lang_err_integration_tests/Cargo.toml | 1 + examples/lang_err_integration_tests/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/lang_err_integration_tests/Cargo.toml b/examples/lang_err_integration_tests/Cargo.toml index 5c83f3c0e8a..a27b3c4c398 100755 --- a/examples/lang_err_integration_tests/Cargo.toml +++ b/examples/lang_err_integration_tests/Cargo.toml @@ -30,3 +30,4 @@ std = [ "scale-info/std", ] ink-as-dependency = [] +e2e-tests = [] diff --git a/examples/lang_err_integration_tests/lib.rs b/examples/lang_err_integration_tests/lib.rs index 970ed2f8fdc..5b332d3e7c9 100755 --- a/examples/lang_err_integration_tests/lib.rs +++ b/examples/lang_err_integration_tests/lib.rs @@ -81,7 +81,7 @@ mod lang_err_integration_tests { } } - #[cfg(test)] + #[cfg(all(test, feature = "e2e-tests"))] mod e2e_tests { type E2EResult = std::result::Result>; From 476ed6515aeffc04f92d4dbd73aa1fec1dcf61b2 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 15:04:05 -0500 Subject: [PATCH 075/102] Apply suggestions from code review Co-authored-by: Andrew Jones --- crates/metadata/src/specs.rs | 2 +- examples/lang_err_integration_tests/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/metadata/src/specs.rs b/crates/metadata/src/specs.rs index 477cd55f69e..25c6e72d8ce 100644 --- a/crates/metadata/src/specs.rs +++ b/crates/metadata/src/specs.rs @@ -111,7 +111,7 @@ where &self.docs } - /// Returns the contract error type. + /// Returns the language error type. pub fn lang_error(&self) -> &TypeSpec { &self.lang_error } diff --git a/examples/lang_err_integration_tests/Cargo.toml b/examples/lang_err_integration_tests/Cargo.toml index a27b3c4c398..9c35cb7a26f 100755 --- a/examples/lang_err_integration_tests/Cargo.toml +++ b/examples/lang_err_integration_tests/Cargo.toml @@ -9,7 +9,7 @@ publish = false ink = { path = "../../crates/ink", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } +scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true } [dev-dependencies] ink_e2e = { path = "../../crates/e2e" } From 2ce36776477054ee798def7c899249b37930a136 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 15:21:32 -0500 Subject: [PATCH 076/102] Unwrap message result in delegator E2E tests --- examples/delegator/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/delegator/lib.rs b/examples/delegator/lib.rs index dbc65516bca..d3e105a0fde 100644 --- a/examples/delegator/lib.rs +++ b/examples/delegator/lib.rs @@ -181,7 +181,8 @@ mod delegator { ) .await .expect("calling `get` failed") - .value; + .value + .expect("calling `get` returned a `LangError`"); assert_eq!(value, 1234); let _ = client .call( @@ -205,7 +206,8 @@ mod delegator { ) .await .expect("calling `get` failed") - .value; + .value + .expect("calling `get` returned a `LangError`"); assert_eq!(value, 1234 + 6); // when @@ -241,7 +243,8 @@ mod delegator { ) .await .expect("calling `get` failed") - .value; + .value + .expect("calling `get` returned a `LangError`"); assert_eq!(value, 1234 + 6 - 3); Ok(()) From 34102243759276796b8a03e5b8cf1591102d2a82 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 15:27:52 -0500 Subject: [PATCH 077/102] Revert "Remove `ContractRef` example/compile test" This reverts commit 6c245439bc019bc0e06fb602fa9aa1d08bc0f8d5. --- examples/cross_chain_ref/.gitignore | 9 ++++++ examples/cross_chain_ref/Cargo.toml | 32 +++++++++++++++++++ examples/cross_chain_ref/lib.rs | 48 +++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100755 examples/cross_chain_ref/.gitignore create mode 100755 examples/cross_chain_ref/Cargo.toml create mode 100755 examples/cross_chain_ref/lib.rs diff --git a/examples/cross_chain_ref/.gitignore b/examples/cross_chain_ref/.gitignore new file mode 100755 index 00000000000..8de8f877e47 --- /dev/null +++ b/examples/cross_chain_ref/.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/examples/cross_chain_ref/Cargo.toml b/examples/cross_chain_ref/Cargo.toml new file mode 100755 index 00000000000..ab083f9d35c --- /dev/null +++ b/examples/cross_chain_ref/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "cross_chain_ref" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { path = "../../crates/ink", default-features = false } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } + +flipper = { path = "../flipper", default-features = false, features = ["ink-as-dependency"] } + +[lib] +name = "cross_chain_ref" +path = "lib.rs" +crate-type = [ + # Used for normal contract Wasm blobs. + "cdylib", +] + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "flipper/std", +] +ink-as-dependency = [] diff --git a/examples/cross_chain_ref/lib.rs b/examples/cross_chain_ref/lib.rs new file mode 100755 index 00000000000..850811b198a --- /dev/null +++ b/examples/cross_chain_ref/lib.rs @@ -0,0 +1,48 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +#[ink::contract] +mod cross_chain_ref { + use flipper::FlipperRef; + + #[ink(storage)] + pub struct CrossChainRef { + flipper: FlipperRef, + } + + impl CrossChainRef { + #[ink(constructor)] + pub fn new(version: u32, flipper_code_hash: Hash) -> Self { + let salt = version.to_le_bytes(); + let flipper = FlipperRef::default() + .endowment(0) + .code_hash(flipper_code_hash) + .salt_bytes(salt) + .instantiate() + .unwrap_or_else(|error| { + panic!("failed at instantiating the Flipper contract: {:?}", error) + }); + + Self { flipper } + } + + #[ink(message)] + pub fn flip(&mut self) { + self.flipper.flip(); + } + + #[ink(message)] + pub fn flip_check(&mut self) { + self.flipper.flip_checked().unwrap(); + } + + #[ink(message)] + pub fn get(&mut self) -> bool { + self.flipper.get() + } + + #[ink(message)] + pub fn get_check(&mut self) -> bool { + self.flipper.get_checked().unwrap() + } + } +} From 98aa04f940d080006e577d2918cdda143e0dfcc0 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 16:29:24 -0500 Subject: [PATCH 078/102] Move `LangError` integration tests into single workspace --- examples/cross_chain_ref/lib.rs | 48 --- .../lang_err_integration_tests/Cargo.toml | 20 +- .../call_builder/Cargo.toml | 33 ++ .../call_builder/lib.rs | 281 +++++++++++++++++ .../contract_ref}/Cargo.toml | 18 +- .../contract_ref/lib.rs | 119 ++++++++ examples/lang_err_integration_tests/lib.rs | 289 ++---------------- 7 files changed, 488 insertions(+), 320 deletions(-) delete mode 100755 examples/cross_chain_ref/lib.rs mode change 100755 => 100644 examples/lang_err_integration_tests/Cargo.toml create mode 100755 examples/lang_err_integration_tests/call_builder/Cargo.toml create mode 100755 examples/lang_err_integration_tests/call_builder/lib.rs rename examples/{cross_chain_ref => lang_err_integration_tests/contract_ref}/Cargo.toml (55%) create mode 100755 examples/lang_err_integration_tests/contract_ref/lib.rs mode change 100755 => 100644 examples/lang_err_integration_tests/lib.rs diff --git a/examples/cross_chain_ref/lib.rs b/examples/cross_chain_ref/lib.rs deleted file mode 100755 index 850811b198a..00000000000 --- a/examples/cross_chain_ref/lib.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -#[ink::contract] -mod cross_chain_ref { - use flipper::FlipperRef; - - #[ink(storage)] - pub struct CrossChainRef { - flipper: FlipperRef, - } - - impl CrossChainRef { - #[ink(constructor)] - pub fn new(version: u32, flipper_code_hash: Hash) -> Self { - let salt = version.to_le_bytes(); - let flipper = FlipperRef::default() - .endowment(0) - .code_hash(flipper_code_hash) - .salt_bytes(salt) - .instantiate() - .unwrap_or_else(|error| { - panic!("failed at instantiating the Flipper contract: {:?}", error) - }); - - Self { flipper } - } - - #[ink(message)] - pub fn flip(&mut self) { - self.flipper.flip(); - } - - #[ink(message)] - pub fn flip_check(&mut self) { - self.flipper.flip_checked().unwrap(); - } - - #[ink(message)] - pub fn get(&mut self) -> bool { - self.flipper.get() - } - - #[ink(message)] - pub fn get_check(&mut self) -> bool { - self.flipper.get_checked().unwrap() - } - } -} diff --git a/examples/lang_err_integration_tests/Cargo.toml b/examples/lang_err_integration_tests/Cargo.toml old mode 100755 new mode 100644 index 9c35cb7a26f..21fabe82d41 --- a/examples/lang_err_integration_tests/Cargo.toml +++ b/examples/lang_err_integration_tests/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "lang_err_integration_tests" +name = "integration_flipper" version = "4.0.0-alpha.3" authors = ["Parity Technologies "] edition = "2021" @@ -11,15 +11,14 @@ ink = { path = "../../crates/ink", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true } -[dev-dependencies] -ink_e2e = { path = "../../crates/e2e" } - [lib] -name = "lang_err_integration_tests" +name = "integration_flipper" path = "lib.rs" crate-type = [ - # Used for normal contract Wasm blobs. - "cdylib", + # Used for normal contract Wasm blobs. + "cdylib", + # Used for ABI generation. + "rlib", ] [features] @@ -30,4 +29,9 @@ std = [ "scale-info/std", ] ink-as-dependency = [] -e2e-tests = [] + +[workspace] +members = [ + "call_builder", + "contract_ref", +] diff --git a/examples/lang_err_integration_tests/call_builder/Cargo.toml b/examples/lang_err_integration_tests/call_builder/Cargo.toml new file mode 100755 index 00000000000..18a6b128722 --- /dev/null +++ b/examples/lang_err_integration_tests/call_builder/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "call_builder" +version = "4.0.0-alpha.3" +authors = ["Parity Technologies "] +edition = "2021" +publish = false + +[dependencies] +ink = { path = "../../../crates/ink", default-features = false } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = { path = "../../../crates/e2e" } + +[lib] +name = "call_builder" +path = "lib.rs" +crate-type = [ + # Used for normal contract Wasm blobs. + "cdylib", +] + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/examples/lang_err_integration_tests/call_builder/lib.rs b/examples/lang_err_integration_tests/call_builder/lib.rs new file mode 100755 index 00000000000..3bf7af3454f --- /dev/null +++ b/examples/lang_err_integration_tests/call_builder/lib.rs @@ -0,0 +1,281 @@ +//! # Integration Tests for `LangError` +//! +//! This contract is used to ensure that the behavior around `LangError`s works as expected. +//! +//! It makes use of ink!'s end-to-end testing features, so ensure that you have a node which +//! includes the Contract's pallet running alongside your tests. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[ink::contract] +mod call_builder { + + #[ink(storage)] + #[derive(Default)] + pub struct CallBuilderTest { + value: bool, + } + + impl CallBuilderTest { + #[ink(constructor)] + pub fn new() -> Self { + Default::default() + } + + /// Call a contract using the `CallBuilder`. + /// + /// Since we can't use the `CallBuilder` in a test environment directly we need this + /// wrapper to test things like crafting calls with invalid selectors. + #[ink(message)] + pub fn call( + &mut self, + address: AccountId, + selector: [u8; 4], + ) -> Option<::ink::LangError> { + use ink::env::{ + call::{ + build_call, + Call, + ExecutionInput, + Selector, + }, + DefaultEnvironment, + }; + + let result = build_call::() + .call_type(Call::new().callee(address)) + .exec_input(ExecutionInput::new(Selector::new(selector))) + .returns::>() + .fire() + .expect("Error from the Contracts pallet."); + + match result { + Ok(_) => None, + Err(e @ ink::LangError::CouldNotReadInput) => Some(e), + Err(_) => { + unimplemented!("No other `LangError` variants exist at the moment.") + } + } + } + + /// Returns the current value of the `CallBuilder`'s boolean. + #[ink(message)] + pub fn get(&self) -> bool { + self.value + } + + /// Flips the current value of the `CallBuilder`'s boolean. + #[ink(message)] + pub fn flip(&mut self) { + self.value = !self.value; + } + + /// Flips the current value of the `CallBuilder`'s boolean. + /// + /// We should see the state being reverted here, no write should occur. + #[ink(message)] + #[allow(clippy::result_unit_err)] + pub fn err_flip(&mut self) -> Result<(), ()> { + self.flip(); + Err(()) + } + } + + #[cfg(all(test, feature = "e2e-tests"))] + mod e2e_tests { + type E2EResult = std::result::Result>; + + #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] + async fn e2e_invalid_selector_can_be_handled( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + use call_builder::contract_types::ink_primitives::{ + types::AccountId as E2EAccountId, + LangError as E2ELangError, + }; + + let constructor = call_builder::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::charlie(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let flipper_constructor = flipper::constructors::default(); + let flipper_acc_id = client + .instantiate(&mut ink_e2e::charlie(), flipper_constructor, 0, None) + .await + .expect("instantiate `flipper` failed") + .account_id; + + let get_call_result = client + .call( + &mut ink_e2e::charlie(), + flipper_acc_id.clone(), + flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `flipper::get` failed"); + let initial_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + + let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); + let invalid_selector = [0x00, 0x00, 0x00, 0x00]; + let call_result = client + .call( + &mut ink_e2e::charlie(), + contract_acc_id.clone(), + call_builder::messages::call(flipper_ink_acc_id, invalid_selector), + 0, + None, + ) + .await + .expect("Calling `call_builder::call` failed"); + + let flipper_result = call_result + .value + .expect("Call to `call_builder::call` failed"); + + assert!(matches!( + flipper_result, + Some(E2ELangError::CouldNotReadInput) + )); + + let get_call_result = client + .call( + &mut ink_e2e::charlie(), + flipper_acc_id.clone(), + flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `flipper::get` failed"); + let flipped_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + assert!(flipped_value == initial_value); + + Ok(()) + } + + #[ink_e2e::test] + async fn e2e_can_flip_correctly( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = call_builder::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::alice(), constructor, 0, None) + .await + .expect("Instantiate `call_builder` failed") + .account_id; + + let get_call_result = client + .call( + &mut ink_e2e::alice(), + contract_acc_id.clone(), + call_builder::messages::get(), + 0, + None, + ) + .await + .expect("Calling `get` failed"); + let initial_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + + let flip_call_result = client + .call( + &mut ink_e2e::alice(), + contract_acc_id.clone(), + call_builder::messages::flip(), + 0, + None, + ) + .await + .expect("Calling `flip` failed"); + assert!( + flip_call_result.value.is_ok(), + "Messages now return a `Result`, which should be `Ok` here." + ); + + let get_call_result = client + .call( + &mut ink_e2e::alice(), + contract_acc_id.clone(), + call_builder::messages::get(), + 0, + None, + ) + .await + .expect("Calling `get` failed"); + let flipped_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + assert!(flipped_value != initial_value); + + Ok(()) + } + + #[ink_e2e::test] + async fn e2e_message_error_reverts_state( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = call_builder::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::bob(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let get_call_result = client + .call( + &mut ink_e2e::bob(), + contract_acc_id.clone(), + call_builder::messages::get(), + 0, + None, + ) + .await + .expect("Calling `get` failed"); + let initial_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + + let err_flip_call_result = client + .call( + &mut ink_e2e::bob(), + contract_acc_id.clone(), + call_builder::messages::err_flip(), + 0, + None, + ) + .await; + + assert!(matches!( + err_flip_call_result, + Err(ink_e2e::Error::CallExtrinsic(_)) + )); + + let get_call_result = client + .call( + &mut ink_e2e::bob(), + contract_acc_id.clone(), + call_builder::messages::get(), + 0, + None, + ) + .await + .expect("Calling `get` failed"); + let flipped_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + assert!(flipped_value == initial_value); + + Ok(()) + } + } +} diff --git a/examples/cross_chain_ref/Cargo.toml b/examples/lang_err_integration_tests/contract_ref/Cargo.toml similarity index 55% rename from examples/cross_chain_ref/Cargo.toml rename to examples/lang_err_integration_tests/contract_ref/Cargo.toml index ab083f9d35c..23dd26a1823 100755 --- a/examples/cross_chain_ref/Cargo.toml +++ b/examples/lang_err_integration_tests/contract_ref/Cargo.toml @@ -1,23 +1,26 @@ [package] -name = "cross_chain_ref" +name = "contract_ref" version = "0.1.0" authors = ["[your_name] <[your_email]>"] edition = "2021" [dependencies] -ink = { path = "../../crates/ink", default-features = false } +ink = { path = "../../../crates/ink", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } -flipper = { path = "../flipper", default-features = false, features = ["ink-as-dependency"] } +integration_flipper = { path = "../", default-features = false, features = ["ink-as-dependency"] } + +[dev-dependencies] +ink_e2e = { path = "../../../crates/e2e" } [lib] -name = "cross_chain_ref" +name = "contract_ref" path = "lib.rs" crate-type = [ - # Used for normal contract Wasm blobs. - "cdylib", + # Used for normal contract Wasm blobs. + "cdylib", ] [features] @@ -27,6 +30,7 @@ std = [ "scale/std", "scale-info/std", - "flipper/std", + "integration_flipper/std", ] ink-as-dependency = [] +e2e-tests = [] diff --git a/examples/lang_err_integration_tests/contract_ref/lib.rs b/examples/lang_err_integration_tests/contract_ref/lib.rs new file mode 100755 index 00000000000..fb43cb39644 --- /dev/null +++ b/examples/lang_err_integration_tests/contract_ref/lib.rs @@ -0,0 +1,119 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +#[ink::contract] +mod contract_ref { + use integration_flipper::FlipperRef; + + #[ink(storage)] + pub struct CrossChainRef { + flipper: FlipperRef, + } + + impl CrossChainRef { + #[ink(constructor)] + pub fn new(version: u32, flipper_code_hash: Hash) -> Self { + let salt = version.to_le_bytes(); + let flipper = FlipperRef::default() + .endowment(0) + .code_hash(flipper_code_hash) + .salt_bytes(salt) + .instantiate() + .unwrap_or_else(|error| { + panic!("failed at instantiating the Flipper contract: {:?}", error) + }); + + Self { flipper } + } + + #[ink(message)] + pub fn flip(&mut self) { + self.flipper.flip(); + } + + #[ink(message)] + pub fn flip_check(&mut self) { + self.flipper.flip_checked().unwrap(); + } + + #[ink(message)] + pub fn get(&mut self) -> bool { + self.flipper.get() + } + + #[ink(message)] + pub fn get_check(&mut self) -> bool { + self.flipper.get_checked().unwrap() + } + } + + #[cfg(all(test, feature = "e2e-tests"))] + mod e2e_tests { + type E2EResult = std::result::Result>; + + #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] + async fn e2e_contract_ref(mut client: ink_e2e::Client) -> E2EResult<()> { + let flipper_hash: ink_e2e::H256 = client + .upload(&mut ink_e2e::alice(), flipper::CONTRACT_PATH, None) + .await + .expect("uploading `flipper` failed") + .code_hash; + let flipper_hash = ink_e2e::utils::runtime_hash_to_ink_hash::< + ink::env::DefaultEnvironment, + >(&flipper_hash); + + let constructor = + contract_ref::constructors::new(Default::default(), flipper_hash); + let contract_acc_id = client + .instantiate(&mut ink_e2e::alice(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let get_call_result = client + .call( + &mut ink_e2e::alice(), + contract_acc_id.clone(), + contract_ref::messages::get_check(), + 0, + None, + ) + .await + .expect("Calling `get_check` failed"); + let initial_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + + let flip_call_result = client + .call( + &mut ink_e2e::alice(), + contract_acc_id.clone(), + contract_ref::messages::flip_check(), + 0, + None, + ) + .await + .expect("Calling `flip` failed"); + assert!( + flip_call_result.value.is_ok(), + "Messages now return a `Result`, which should be `Ok` here." + ); + + let get_call_result = client + .call( + &mut ink_e2e::alice(), + contract_acc_id.clone(), + contract_ref::messages::get_check(), + 0, + None, + ) + .await + .expect("Calling `get` failed"); + let flipped_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + assert!(flipped_value != initial_value); + + Ok(()) + } + } +} diff --git a/examples/lang_err_integration_tests/lib.rs b/examples/lang_err_integration_tests/lib.rs old mode 100755 new mode 100644 index 5b332d3e7c9..208e098efda --- a/examples/lang_err_integration_tests/lib.rs +++ b/examples/lang_err_integration_tests/lib.rs @@ -1,284 +1,59 @@ -//! # Integration Tests for `LangError` -//! -//! This contract is used to ensure that the behavior around `LangError`s works as expected. -//! -//! It makes use of ink!'s end-to-end testing features, so ensure that you have a node which -//! includes the Contract's pallet running alongside your tests. - #![cfg_attr(not(feature = "std"), no_std)] -#[ink::contract] -mod lang_err_integration_tests { +pub use self::flipper::{ + Flipper, + FlipperRef, +}; +#[ink::contract] +pub mod flipper { #[ink(storage)] - #[derive(Default)] - pub struct LangErrIntegrationTests { + pub struct Flipper { value: bool, } - impl LangErrIntegrationTests { + impl Flipper { + /// Creates a new flipper smart contract initialized with the given value. #[ink(constructor)] - pub fn new() -> Self { - Default::default() + pub fn new(init_value: bool) -> Self { + Self { value: init_value } } - /// Call a contract using the `CallBuilder`. - /// - /// Since we can't use the `CallBuilder` in a test environment directly we need this - /// wrapper to test things like crafting calls with invalid selectors. - #[ink(message)] - pub fn call( - &mut self, - address: AccountId, - selector: [u8; 4], - ) -> Option<::ink::LangError> { - use ink::env::{ - call::{ - build_call, - Call, - ExecutionInput, - Selector, - }, - DefaultEnvironment, - }; - - let result = build_call::() - .call_type(Call::new().callee(address)) - .exec_input(ExecutionInput::new(Selector::new(selector))) - .returns::>() - .fire() - .expect("Error from the Contracts pallet."); - - match result { - Ok(_) => None, - Err(e @ ink::LangError::CouldNotReadInput) => Some(e), - Err(_) => { - unimplemented!("No other `LangError` variants exist at the moment.") - } - } - } - - /// Returns the current value of the `LangErrIntegrationTests`'s boolean. - #[ink(message)] - pub fn get(&self) -> bool { - self.value + /// Creates a new flipper smart contract initialized to `false`. + #[ink(constructor)] + pub fn default() -> Self { + Self::new(Default::default()) } - /// Flips the current value of the `LangErrIntegrationTests`'s boolean. + /// Flips the current value of the Flipper's boolean. #[ink(message)] pub fn flip(&mut self) { self.value = !self.value; } - /// Flips the current value of the `LangErrIntegrationTests`'s boolean. - /// - /// We should see the state being reverted here, no write should occur. + /// Returns the current value of the Flipper's boolean. #[ink(message)] - #[allow(clippy::result_unit_err)] - pub fn err_flip(&mut self) -> Result<(), ()> { - self.flip(); - Err(()) + pub fn get(&self) -> bool { + self.value } } - #[cfg(all(test, feature = "e2e-tests"))] - mod e2e_tests { - type E2EResult = std::result::Result>; - - #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] - async fn e2e_invalid_selector_can_be_handled( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - use lang_err_integration_tests::contract_types::ink_primitives::{ - types::AccountId as E2EAccountId, - LangError as E2ELangError, - }; - - let constructor = lang_err_integration_tests::constructors::new(); - let contract_acc_id = client - .instantiate(&mut ink_e2e::charlie(), constructor, 0, None) - .await - .expect("instantiate failed") - .account_id; - - let flipper_constructor = flipper::constructors::default(); - let flipper_acc_id = client - .instantiate(&mut ink_e2e::charlie(), flipper_constructor, 0, None) - .await - .expect("instantiate `flipper` failed") - .account_id; + #[cfg(test)] + mod tests { + use super::*; - let get_call_result = client - .call( - &mut ink_e2e::charlie(), - flipper_acc_id.clone(), - flipper::messages::get(), - 0, - None, - ) - .await - .expect("Calling `flipper::get` failed"); - let initial_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - - let flipper_ink_acc_id = E2EAccountId(flipper_acc_id.clone().into()); - let invalid_selector = [0x00, 0x00, 0x00, 0x00]; - let call_result = client - .call( - &mut ink_e2e::charlie(), - contract_acc_id.clone(), - lang_err_integration_tests::messages::call( - flipper_ink_acc_id, - invalid_selector, - ), - 0, - None, - ) - .await - .expect("Calling `lang_err_integration_tests::call` failed"); - - let flipper_result = call_result - .value - .expect("Call to `lang_err_integration_tests::call` failed"); - - assert!(matches!( - flipper_result, - Some(E2ELangError::CouldNotReadInput) - )); - - let get_call_result = client - .call( - &mut ink_e2e::charlie(), - flipper_acc_id.clone(), - flipper::messages::get(), - 0, - None, - ) - .await - .expect("Calling `flipper::get` failed"); - let flipped_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - assert!(flipped_value == initial_value); - - Ok(()) - } - - #[ink_e2e::test] - async fn e2e_can_flip_correctly( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let constructor = lang_err_integration_tests::constructors::new(); - let contract_acc_id = client - .instantiate(&mut ink_e2e::alice(), constructor, 0, None) - .await - .expect("Instantiate `lang_err_integration_tests` failed") - .account_id; - - let get_call_result = client - .call( - &mut ink_e2e::alice(), - contract_acc_id.clone(), - lang_err_integration_tests::messages::get(), - 0, - None, - ) - .await - .expect("Calling `get` failed"); - let initial_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - - let flip_call_result = client - .call( - &mut ink_e2e::alice(), - contract_acc_id.clone(), - lang_err_integration_tests::messages::flip(), - 0, - None, - ) - .await - .expect("Calling `flip` failed"); - assert!( - flip_call_result.value.is_ok(), - "Messages now return a `Result`, which should be `Ok` here." - ); - - let get_call_result = client - .call( - &mut ink_e2e::alice(), - contract_acc_id.clone(), - lang_err_integration_tests::messages::get(), - 0, - None, - ) - .await - .expect("Calling `get` failed"); - let flipped_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - assert!(flipped_value != initial_value); - - Ok(()) + #[ink::test] + fn default_works() { + let flipper = Flipper::default(); + assert!(!flipper.get()); } - #[ink_e2e::test] - async fn e2e_message_error_reverts_state( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let constructor = lang_err_integration_tests::constructors::new(); - let contract_acc_id = client - .instantiate(&mut ink_e2e::bob(), constructor, 0, None) - .await - .expect("instantiate failed") - .account_id; - - let get_call_result = client - .call( - &mut ink_e2e::bob(), - contract_acc_id.clone(), - lang_err_integration_tests::messages::get(), - 0, - None, - ) - .await - .expect("Calling `get` failed"); - let initial_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - - let err_flip_call_result = client - .call( - &mut ink_e2e::bob(), - contract_acc_id.clone(), - lang_err_integration_tests::messages::err_flip(), - 0, - None, - ) - .await; - - assert!(matches!( - err_flip_call_result, - Err(ink_e2e::Error::CallExtrinsic(_)) - )); - - let get_call_result = client - .call( - &mut ink_e2e::bob(), - contract_acc_id.clone(), - lang_err_integration_tests::messages::get(), - 0, - None, - ) - .await - .expect("Calling `get` failed"); - let flipped_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - assert!(flipped_value == initial_value); - - Ok(()) + #[ink::test] + fn it_works() { + let mut flipper = Flipper::new(false); + assert!(!flipper.get()); + flipper.flip(); + assert!(flipper.get()); } } } From 0164c010bd20ae5b1ff38e6cbb4424a9efc5fdd9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 16:39:45 -0500 Subject: [PATCH 079/102] Move flip related E2E tests to `integration_flipper` --- .../lang_err_integration_tests/Cargo.toml | 4 + .../call_builder/lib.rs | 142 +---------------- examples/lang_err_integration_tests/lib.rs | 146 ++++++++++++++++-- 3 files changed, 134 insertions(+), 158 deletions(-) diff --git a/examples/lang_err_integration_tests/Cargo.toml b/examples/lang_err_integration_tests/Cargo.toml index 21fabe82d41..2709d5ffdf7 100644 --- a/examples/lang_err_integration_tests/Cargo.toml +++ b/examples/lang_err_integration_tests/Cargo.toml @@ -11,6 +11,9 @@ ink = { path = "../../crates/ink", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true } +[dev-dependencies] +ink_e2e = { path = "../../crates/e2e" } + [lib] name = "integration_flipper" path = "lib.rs" @@ -29,6 +32,7 @@ std = [ "scale-info/std", ] ink-as-dependency = [] +e2e-tests = [] [workspace] members = [ diff --git a/examples/lang_err_integration_tests/call_builder/lib.rs b/examples/lang_err_integration_tests/call_builder/lib.rs index 3bf7af3454f..b67e37b1d88 100755 --- a/examples/lang_err_integration_tests/call_builder/lib.rs +++ b/examples/lang_err_integration_tests/call_builder/lib.rs @@ -12,9 +12,7 @@ mod call_builder { #[ink(storage)] #[derive(Default)] - pub struct CallBuilderTest { - value: bool, - } + pub struct CallBuilderTest {} impl CallBuilderTest { #[ink(constructor)] @@ -57,28 +55,6 @@ mod call_builder { } } } - - /// Returns the current value of the `CallBuilder`'s boolean. - #[ink(message)] - pub fn get(&self) -> bool { - self.value - } - - /// Flips the current value of the `CallBuilder`'s boolean. - #[ink(message)] - pub fn flip(&mut self) { - self.value = !self.value; - } - - /// Flips the current value of the `CallBuilder`'s boolean. - /// - /// We should see the state being reverted here, no write should occur. - #[ink(message)] - #[allow(clippy::result_unit_err)] - pub fn err_flip(&mut self) -> Result<(), ()> { - self.flip(); - Err(()) - } } #[cfg(all(test, feature = "e2e-tests"))] @@ -161,121 +137,5 @@ mod call_builder { Ok(()) } - - #[ink_e2e::test] - async fn e2e_can_flip_correctly( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let constructor = call_builder::constructors::new(); - let contract_acc_id = client - .instantiate(&mut ink_e2e::alice(), constructor, 0, None) - .await - .expect("Instantiate `call_builder` failed") - .account_id; - - let get_call_result = client - .call( - &mut ink_e2e::alice(), - contract_acc_id.clone(), - call_builder::messages::get(), - 0, - None, - ) - .await - .expect("Calling `get` failed"); - let initial_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - - let flip_call_result = client - .call( - &mut ink_e2e::alice(), - contract_acc_id.clone(), - call_builder::messages::flip(), - 0, - None, - ) - .await - .expect("Calling `flip` failed"); - assert!( - flip_call_result.value.is_ok(), - "Messages now return a `Result`, which should be `Ok` here." - ); - - let get_call_result = client - .call( - &mut ink_e2e::alice(), - contract_acc_id.clone(), - call_builder::messages::get(), - 0, - None, - ) - .await - .expect("Calling `get` failed"); - let flipped_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - assert!(flipped_value != initial_value); - - Ok(()) - } - - #[ink_e2e::test] - async fn e2e_message_error_reverts_state( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let constructor = call_builder::constructors::new(); - let contract_acc_id = client - .instantiate(&mut ink_e2e::bob(), constructor, 0, None) - .await - .expect("instantiate failed") - .account_id; - - let get_call_result = client - .call( - &mut ink_e2e::bob(), - contract_acc_id.clone(), - call_builder::messages::get(), - 0, - None, - ) - .await - .expect("Calling `get` failed"); - let initial_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - - let err_flip_call_result = client - .call( - &mut ink_e2e::bob(), - contract_acc_id.clone(), - call_builder::messages::err_flip(), - 0, - None, - ) - .await; - - assert!(matches!( - err_flip_call_result, - Err(ink_e2e::Error::CallExtrinsic(_)) - )); - - let get_call_result = client - .call( - &mut ink_e2e::bob(), - contract_acc_id.clone(), - call_builder::messages::get(), - 0, - None, - ) - .await - .expect("Calling `get` failed"); - let flipped_value = get_call_result - .value - .expect("Input is valid, call must not fail."); - assert!(flipped_value == initial_value); - - Ok(()) - } } } diff --git a/examples/lang_err_integration_tests/lib.rs b/examples/lang_err_integration_tests/lib.rs index 208e098efda..72691708810 100644 --- a/examples/lang_err_integration_tests/lib.rs +++ b/examples/lang_err_integration_tests/lib.rs @@ -1,25 +1,25 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use self::flipper::{ +pub use self::integration_flipper::{ Flipper, FlipperRef, }; #[ink::contract] -pub mod flipper { +pub mod integration_flipper { #[ink(storage)] pub struct Flipper { value: bool, } impl Flipper { - /// Creates a new flipper smart contract initialized with the given value. + /// Creates a new integration_flipper smart contract initialized with the given value. #[ink(constructor)] pub fn new(init_value: bool) -> Self { Self { value: init_value } } - /// Creates a new flipper smart contract initialized to `false`. + /// Creates a new integration_flipper smart contract initialized to `false`. #[ink(constructor)] pub fn default() -> Self { Self::new(Default::default()) @@ -36,24 +36,136 @@ pub mod flipper { pub fn get(&self) -> bool { self.value } + + /// Flips the current value of the `CallBuilder`'s boolean. + /// + /// We should see the state being reverted here, no write should occur. + #[ink(message)] + #[allow(clippy::result_unit_err)] + pub fn err_flip(&mut self) -> Result<(), ()> { + self.flip(); + Err(()) + } } - #[cfg(test)] - mod tests { - use super::*; + #[cfg(all(test, feature = "e2e-tests"))] + mod e2e_tests { + type E2EResult = std::result::Result>; + + #[ink_e2e::test] + async fn e2e_can_flip_correctly( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = integration_flipper::constructors::default(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::alice(), constructor, 0, None) + .await + .expect("Instantiate `integration_flipper` failed") + .account_id; + + let get_call_result = client + .call( + &mut ink_e2e::alice(), + contract_acc_id.clone(), + integration_flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `get` failed"); + let initial_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + + let flip_call_result = client + .call( + &mut ink_e2e::alice(), + contract_acc_id.clone(), + integration_flipper::messages::flip(), + 0, + None, + ) + .await + .expect("Calling `flip` failed"); + assert!( + flip_call_result.value.is_ok(), + "Messages now return a `Result`, which should be `Ok` here." + ); - #[ink::test] - fn default_works() { - let flipper = Flipper::default(); - assert!(!flipper.get()); + let get_call_result = client + .call( + &mut ink_e2e::alice(), + contract_acc_id.clone(), + integration_flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `get` failed"); + let flipped_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + assert!(flipped_value != initial_value); + + Ok(()) } - #[ink::test] - fn it_works() { - let mut flipper = Flipper::new(false); - assert!(!flipper.get()); - flipper.flip(); - assert!(flipper.get()); + #[ink_e2e::test] + async fn e2e_message_error_reverts_state( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = integration_flipper::constructors::default(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::bob(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let get_call_result = client + .call( + &mut ink_e2e::bob(), + contract_acc_id.clone(), + integration_flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `get` failed"); + let initial_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + + let err_flip_call_result = client + .call( + &mut ink_e2e::bob(), + contract_acc_id.clone(), + integration_flipper::messages::err_flip(), + 0, + None, + ) + .await; + + assert!(matches!( + err_flip_call_result, + Err(ink_e2e::Error::CallExtrinsic(_)) + )); + + let get_call_result = client + .call( + &mut ink_e2e::bob(), + contract_acc_id.clone(), + integration_flipper::messages::get(), + 0, + None, + ) + .await + .expect("Calling `get` failed"); + let flipped_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + assert!(flipped_value == initial_value); + + Ok(()) } } } From 3ed652128223cd5cbb7584475d78b50a448c247a Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 16:48:24 -0500 Subject: [PATCH 080/102] Move `integration_flipper` into its own folder This way we can refer to it from the `additional_contracts` argument of the `ink_e2e::test` macro. --- .../{ => integration_flipper}/Cargo.toml | 10 ++-------- .../{ => integration_flipper}/lib.rs | 0 2 files changed, 2 insertions(+), 8 deletions(-) rename examples/lang_err_integration_tests/{ => integration_flipper}/Cargo.toml (80%) rename examples/lang_err_integration_tests/{ => integration_flipper}/lib.rs (100%) diff --git a/examples/lang_err_integration_tests/Cargo.toml b/examples/lang_err_integration_tests/integration_flipper/Cargo.toml similarity index 80% rename from examples/lang_err_integration_tests/Cargo.toml rename to examples/lang_err_integration_tests/integration_flipper/Cargo.toml index 2709d5ffdf7..7ca0071a078 100644 --- a/examples/lang_err_integration_tests/Cargo.toml +++ b/examples/lang_err_integration_tests/integration_flipper/Cargo.toml @@ -6,13 +6,13 @@ edition = "2021" publish = false [dependencies] -ink = { path = "../../crates/ink", default-features = false } +ink = { path = "../../../crates/ink", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true } [dev-dependencies] -ink_e2e = { path = "../../crates/e2e" } +ink_e2e = { path = "../../../crates/e2e" } [lib] name = "integration_flipper" @@ -33,9 +33,3 @@ std = [ ] ink-as-dependency = [] e2e-tests = [] - -[workspace] -members = [ - "call_builder", - "contract_ref", -] diff --git a/examples/lang_err_integration_tests/lib.rs b/examples/lang_err_integration_tests/integration_flipper/lib.rs similarity index 100% rename from examples/lang_err_integration_tests/lib.rs rename to examples/lang_err_integration_tests/integration_flipper/lib.rs From a82346ede4428da2775718e5bc8e69f83f385c7e Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 16:49:34 -0500 Subject: [PATCH 081/102] Update `call_builder` test to use `integration_flipper` --- examples/lang_err_integration_tests/call_builder/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/lang_err_integration_tests/call_builder/lib.rs b/examples/lang_err_integration_tests/call_builder/lib.rs index b67e37b1d88..064be3ab1ea 100755 --- a/examples/lang_err_integration_tests/call_builder/lib.rs +++ b/examples/lang_err_integration_tests/call_builder/lib.rs @@ -61,7 +61,7 @@ mod call_builder { mod e2e_tests { type E2EResult = std::result::Result>; - #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] + #[ink_e2e::test(additional_contracts = "../integration_flipper/Cargo.toml")] async fn e2e_invalid_selector_can_be_handled( mut client: ink_e2e::Client, ) -> E2EResult<()> { @@ -77,7 +77,7 @@ mod call_builder { .expect("instantiate failed") .account_id; - let flipper_constructor = flipper::constructors::default(); + let flipper_constructor = integration_flipper::constructors::default(); let flipper_acc_id = client .instantiate(&mut ink_e2e::charlie(), flipper_constructor, 0, None) .await @@ -88,7 +88,7 @@ mod call_builder { .call( &mut ink_e2e::charlie(), flipper_acc_id.clone(), - flipper::messages::get(), + integration_flipper::messages::get(), 0, None, ) @@ -124,7 +124,7 @@ mod call_builder { .call( &mut ink_e2e::charlie(), flipper_acc_id.clone(), - flipper::messages::get(), + integration_flipper::messages::get(), 0, None, ) From 50c5f4eac57edd67b47f2e891b781f6dff9c82ea Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 17:10:55 -0500 Subject: [PATCH 082/102] Get `contract_ref` E2E test working again --- .../contract_ref/Cargo.toml | 2 +- .../contract_ref/lib.rs | 22 ++++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/examples/lang_err_integration_tests/contract_ref/Cargo.toml b/examples/lang_err_integration_tests/contract_ref/Cargo.toml index 23dd26a1823..abbdd25a2a1 100755 --- a/examples/lang_err_integration_tests/contract_ref/Cargo.toml +++ b/examples/lang_err_integration_tests/contract_ref/Cargo.toml @@ -10,7 +10,7 @@ ink = { path = "../../../crates/ink", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } -integration_flipper = { path = "../", default-features = false, features = ["ink-as-dependency"] } +integration_flipper = { path = "../integration_flipper", default-features = false, features = ["ink-as-dependency"] } [dev-dependencies] ink_e2e = { path = "../../../crates/e2e" } diff --git a/examples/lang_err_integration_tests/contract_ref/lib.rs b/examples/lang_err_integration_tests/contract_ref/lib.rs index fb43cb39644..45421e9213d 100755 --- a/examples/lang_err_integration_tests/contract_ref/lib.rs +++ b/examples/lang_err_integration_tests/contract_ref/lib.rs @@ -32,7 +32,9 @@ mod contract_ref { #[ink(message)] pub fn flip_check(&mut self) { - self.flipper.flip_checked().unwrap(); + self.flipper + .flip_checked() + .expect("The ink! codegen should've produced a valid call."); } #[ink(message)] @@ -42,7 +44,9 @@ mod contract_ref { #[ink(message)] pub fn get_check(&mut self) -> bool { - self.flipper.get_checked().unwrap() + self.flipper + .get_checked() + .expect("The ink! codegen should've produced a valid call.") } } @@ -50,10 +54,16 @@ mod contract_ref { mod e2e_tests { type E2EResult = std::result::Result>; - #[ink_e2e::test(additional_contracts = "../flipper/Cargo.toml")] - async fn e2e_contract_ref(mut client: ink_e2e::Client) -> E2EResult<()> { + #[ink_e2e::test(additional_contracts = "../integration_flipper/Cargo.toml")] + async fn e2e_ref_can_flip_correctly( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { let flipper_hash: ink_e2e::H256 = client - .upload(&mut ink_e2e::alice(), flipper::CONTRACT_PATH, None) + .upload( + &mut ink_e2e::alice(), + integration_flipper::CONTRACT_PATH, + None, + ) .await .expect("uploading `flipper` failed") .code_hash; @@ -107,7 +117,7 @@ mod contract_ref { None, ) .await - .expect("Calling `get` failed"); + .expect("Calling `get_check` failed"); let flipped_value = get_call_result .value .expect("Input is valid, call must not fail."); From d63cae1e39a1150dcb1baf50ec17e84e58c5c59d Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 17:12:33 -0500 Subject: [PATCH 083/102] Fill out author and version metadata --- examples/lang_err_integration_tests/call_builder/Cargo.toml | 4 ++-- examples/lang_err_integration_tests/contract_ref/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/lang_err_integration_tests/call_builder/Cargo.toml b/examples/lang_err_integration_tests/call_builder/Cargo.toml index 18a6b128722..25aaf12a4e3 100755 --- a/examples/lang_err_integration_tests/call_builder/Cargo.toml +++ b/examples/lang_err_integration_tests/call_builder/Cargo.toml @@ -18,8 +18,8 @@ ink_e2e = { path = "../../../crates/e2e" } name = "call_builder" path = "lib.rs" crate-type = [ - # Used for normal contract Wasm blobs. - "cdylib", + # Used for normal contract Wasm blobs. + "cdylib", ] [features] diff --git a/examples/lang_err_integration_tests/contract_ref/Cargo.toml b/examples/lang_err_integration_tests/contract_ref/Cargo.toml index abbdd25a2a1..a8d474d246a 100755 --- a/examples/lang_err_integration_tests/contract_ref/Cargo.toml +++ b/examples/lang_err_integration_tests/contract_ref/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "contract_ref" -version = "0.1.0" -authors = ["[your_name] <[your_email]>"] +version = "4.0.0-alpha.3" +authors = ["Parity Technologies "] edition = "2021" [dependencies] From 55c4f3c8a6c683b01fdc6ab89d507144c064f913 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 17:23:01 -0500 Subject: [PATCH 084/102] Add integration tests to CI --- .gitlab-ci.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 37c0a4b9474..4243944d27d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,6 +34,7 @@ variables: ALL_CRATES: "${PURELY_STD_CRATES} ${ALSO_WASM_CRATES}" DELEGATOR_SUBCONTRACTS: "accumulator adder subber" UPGRADEABLE_CONTRACTS: "forward-calls set-code-hash" + LANG_ERR_INTEGRATION_CONTRACTS: "integration_flipper call_builder contract_ref" # TODO `cargo clippy --verbose --all-targets --all-features` for this crate # currently fails on `stable`, but succeeds on `nightly`. This is due to # this fix not yet in stable: https://github.com/rust-lang/rust-clippy/issues/8895. @@ -130,6 +131,9 @@ examples-fmt: - for contract in ${UPGRADEABLE_CONTRACTS}; do cargo +nightly fmt --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml -- --check; done + - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do + cargo +nightly fmt --verbose --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml -- --check; + done - cargo +nightly fmt --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -- --check # This file is not a part of the cargo project, so it wouldn't be formatted the usual way - rustfmt +nightly --verbose --check ./examples/psp22-extension/runtime/psp22-extension-example.rs @@ -169,6 +173,9 @@ examples-clippy-std: - for contract in ${UPGRADEABLE_CONTRACTS}; do cargo clippy --verbose --all-targets --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; done + - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do + cargo clippy --verbose --all-targets --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; + done - cargo clippy --verbose --all-targets --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; allow_failure: true @@ -187,6 +194,9 @@ examples-clippy-wasm: - for contract in ${UPGRADEABLE_CONTRACTS}; do cargo clippy --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings -A $CLIPPY_ALLOWED; done + - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do + cargo clippy --verbose --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings -A $CLIPPY_ALLOWED; + done - cargo clippy --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings -A $CLIPPY_ALLOWED; allow_failure: true @@ -375,6 +385,9 @@ examples-test: - for contract in ${UPGRADEABLE_CONTRACTS}; do cargo test --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done + - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do + cargo test --verbose --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml; + done - cargo test --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml; examples-contract-build: @@ -394,6 +407,9 @@ examples-contract-build: - for contract in ${UPGRADEABLE_CONTRACTS}; do cargo +stable contract build --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done + - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do + cargo +stable contract build --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml; + done - cargo +stable contract build --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml examples-docs: @@ -417,6 +433,9 @@ examples-docs: - for contract in ${UPGRADEABLE_CONTRACTS}; do cargo doc --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml --document-private-items --verbose --no-deps; done + - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do + cargo doc --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml --document-private-items --verbose --no-deps; + done - cargo doc --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml --document-private-items --verbose --no-deps From 671377e16ba2d592074a49688a74d12334871e52 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 17:27:25 -0500 Subject: [PATCH 085/102] Remove leftover .gitignore --- examples/cross_chain_ref/.gitignore | 9 --------- 1 file changed, 9 deletions(-) delete mode 100755 examples/cross_chain_ref/.gitignore diff --git a/examples/cross_chain_ref/.gitignore b/examples/cross_chain_ref/.gitignore deleted file mode 100755 index 8de8f877e47..00000000000 --- a/examples/cross_chain_ref/.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 From c7b8b07cacc3f255ec230335ffec041bba090baf Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 17:35:45 -0500 Subject: [PATCH 086/102] Skip default checks if it's a lang error integration test --- .gitlab-ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4243944d27d..3e09dc82961 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -123,6 +123,7 @@ examples-fmt: # Note that we disable the license header check for the examples, since they are unlicensed. - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; + if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; cargo +nightly fmt --verbose --manifest-path ${example}/Cargo.toml -- --check; done - for contract in ${DELEGATOR_SUBCONTRACTS}; do @@ -165,6 +166,7 @@ examples-clippy-std: script: - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; + if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; cargo clippy --verbose --all-targets --manifest-path ${example}/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; done - for contract in ${DELEGATOR_SUBCONTRACTS}; do @@ -186,6 +188,7 @@ examples-clippy-wasm: script: - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; + if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; cargo clippy --verbose --manifest-path ${example}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings -A $CLIPPY_ALLOWED; done - for contract in ${DELEGATOR_SUBCONTRACTS}; do @@ -373,6 +376,7 @@ examples-test: - *start-substrate-contracts-node - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; + if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; if grep -q "e2e-tests = \[\]" "${example}/Cargo.toml"; then cargo test --verbose --manifest-path ${example}/Cargo.toml --features e2e-tests; else @@ -399,6 +403,7 @@ examples-contract-build: - cargo contract -V - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; + if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; pushd $example && cargo +stable contract build && popd; @@ -425,6 +430,7 @@ examples-docs: # of this flag. - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; + if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; cargo doc --manifest-path ${example}/Cargo.toml --document-private-items --verbose --no-deps; done - for contract in ${DELEGATOR_SUBCONTRACTS}; do From ed6a6d659bb6e5fcd4d5bb8be4679b1210bebb1b Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 17:50:31 -0500 Subject: [PATCH 087/102] Fix UI test --- .../fail/constructor-return-result-non-codec-error.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr b/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr index f26d2e4579f..cfcd17fdb11 100644 --- a/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr +++ b/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr @@ -36,6 +36,6 @@ error[E0277]: the trait bound `contract::Error: TypeInfo` is not satisfied (A, B, C, D) (A, B, C, D, E) (A, B, C, D, E, F) - and 64 others + and $N others = note: required for `Result<(), contract::Error>` to implement `ConstructorReturnSpec` = note: this error originates in the attribute macro `ink::contract` (in Nightly builds, run with -Z macro-backtrace for more info) From 1a74375cec234a9b935bf63eabe4d7e459208bf1 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 17:54:19 -0500 Subject: [PATCH 088/102] Skip a few CI stages --- .gitlab-ci.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3e09dc82961..d8e612c7132 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -115,7 +115,7 @@ fmt: - cargo +nightly fmt --verbose --all -- --check ./crates/ink/tests/ui/trait_def/{pass,fail}/*.rs allow_failure: true -examples-fmt: +.examples-fmt: stage: lint <<: *docker-env <<: *test-refs @@ -140,7 +140,7 @@ examples-fmt: - rustfmt +nightly --verbose --check ./examples/psp22-extension/runtime/psp22-extension-example.rs allow_failure: true -clippy-std: +.clippy-std: stage: lint <<: *docker-env <<: *test-refs @@ -149,7 +149,7 @@ clippy-std: cargo clippy --verbose --all-targets --all-features --manifest-path ./crates/${crate}/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; done -clippy-wasm: +.clippy-wasm: stage: lint <<: *docker-env <<: *test-refs @@ -159,7 +159,7 @@ clippy-wasm: done allow_failure: true -examples-clippy-std: +.examples-clippy-std: stage: lint <<: *docker-env <<: *test-refs @@ -181,7 +181,7 @@ examples-clippy-std: - cargo clippy --verbose --all-targets --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; allow_failure: true -examples-clippy-wasm: +.examples-clippy-wasm: stage: lint <<: *docker-env <<: *test-refs @@ -206,7 +206,7 @@ examples-clippy-wasm: #### stage: check -check-std: +.check-std: stage: check <<: *docker-env <<: *test-refs @@ -215,7 +215,7 @@ check-std: cargo check --verbose --all-features --manifest-path ./crates/${crate}/Cargo.toml; done -check-wasm: +.check-wasm: stage: check <<: *docker-env <<: *test-refs @@ -224,7 +224,7 @@ check-wasm: cargo check --verbose --no-default-features --target wasm32-unknown-unknown --manifest-path ./crates/${crate}/Cargo.toml; done -dylint: +.dylint: stage: check <<: *docker-env <<: *test-refs @@ -242,7 +242,7 @@ dylint: #### stage: workspace -build-std: +.build-std: stage: workspace <<: *docker-env <<: *test-refs @@ -254,7 +254,7 @@ build-std: cargo build --verbose --all-features --release --manifest-path ./crates/${crate}/Cargo.toml; done -build-wasm: +.build-wasm: stage: workspace <<: *docker-env <<: *test-refs @@ -283,7 +283,7 @@ test: - cargo test --verbose --all-features --no-fail-fast --workspace - cargo test --verbose --all-features --no-fail-fast --workspace --doc -docs: +.docs: stage: workspace <<: *docker-env <<: *test-refs @@ -316,7 +316,7 @@ docs: - chown -R nonroot:nonroot ./crate-docs -codecov: +.codecov: stage: workspace <<: *docker-env <<: *test-refs @@ -417,7 +417,7 @@ examples-contract-build: done - cargo +stable contract build --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -examples-docs: +.examples-docs: stage: examples <<: *docker-env <<: *test-refs @@ -447,7 +447,7 @@ examples-docs: #### stage: ink-waterfall -ink-waterfall: +.ink-waterfall: stage: ink-waterfall image: paritytech/tools:latest <<: *kubernetes-env @@ -464,7 +464,7 @@ ink-waterfall: #### stage: publish -publish-docs: +.publish-docs: stage: publish <<: *kubernetes-env image: paritytech/tools:latest From dff5adaca30f5e41e1b32a7c62cb12a1d31c2eb0 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 17:58:39 -0500 Subject: [PATCH 089/102] Add back Clippy stage --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d8e612c7132..de1ac9143e0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -140,7 +140,7 @@ fmt: - rustfmt +nightly --verbose --check ./examples/psp22-extension/runtime/psp22-extension-example.rs allow_failure: true -.clippy-std: +clippy-std: stage: lint <<: *docker-env <<: *test-refs From 26e2e37e2d62cb71d085999065a325e0a07017d2 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 18:02:00 -0500 Subject: [PATCH 090/102] Revert "Skip a few CI stages" This reverts commit 1a74375cec234a9b935bf63eabe4d7e459208bf1. --- .gitlab-ci.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index de1ac9143e0..3e09dc82961 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -115,7 +115,7 @@ fmt: - cargo +nightly fmt --verbose --all -- --check ./crates/ink/tests/ui/trait_def/{pass,fail}/*.rs allow_failure: true -.examples-fmt: +examples-fmt: stage: lint <<: *docker-env <<: *test-refs @@ -149,7 +149,7 @@ clippy-std: cargo clippy --verbose --all-targets --all-features --manifest-path ./crates/${crate}/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; done -.clippy-wasm: +clippy-wasm: stage: lint <<: *docker-env <<: *test-refs @@ -159,7 +159,7 @@ clippy-std: done allow_failure: true -.examples-clippy-std: +examples-clippy-std: stage: lint <<: *docker-env <<: *test-refs @@ -181,7 +181,7 @@ clippy-std: - cargo clippy --verbose --all-targets --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; allow_failure: true -.examples-clippy-wasm: +examples-clippy-wasm: stage: lint <<: *docker-env <<: *test-refs @@ -206,7 +206,7 @@ clippy-std: #### stage: check -.check-std: +check-std: stage: check <<: *docker-env <<: *test-refs @@ -215,7 +215,7 @@ clippy-std: cargo check --verbose --all-features --manifest-path ./crates/${crate}/Cargo.toml; done -.check-wasm: +check-wasm: stage: check <<: *docker-env <<: *test-refs @@ -224,7 +224,7 @@ clippy-std: cargo check --verbose --no-default-features --target wasm32-unknown-unknown --manifest-path ./crates/${crate}/Cargo.toml; done -.dylint: +dylint: stage: check <<: *docker-env <<: *test-refs @@ -242,7 +242,7 @@ clippy-std: #### stage: workspace -.build-std: +build-std: stage: workspace <<: *docker-env <<: *test-refs @@ -254,7 +254,7 @@ clippy-std: cargo build --verbose --all-features --release --manifest-path ./crates/${crate}/Cargo.toml; done -.build-wasm: +build-wasm: stage: workspace <<: *docker-env <<: *test-refs @@ -283,7 +283,7 @@ test: - cargo test --verbose --all-features --no-fail-fast --workspace - cargo test --verbose --all-features --no-fail-fast --workspace --doc -.docs: +docs: stage: workspace <<: *docker-env <<: *test-refs @@ -316,7 +316,7 @@ test: - chown -R nonroot:nonroot ./crate-docs -.codecov: +codecov: stage: workspace <<: *docker-env <<: *test-refs @@ -417,7 +417,7 @@ examples-contract-build: done - cargo +stable contract build --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -.examples-docs: +examples-docs: stage: examples <<: *docker-env <<: *test-refs @@ -447,7 +447,7 @@ examples-contract-build: #### stage: ink-waterfall -.ink-waterfall: +ink-waterfall: stage: ink-waterfall image: paritytech/tools:latest <<: *kubernetes-env @@ -464,7 +464,7 @@ examples-contract-build: #### stage: publish -.publish-docs: +publish-docs: stage: publish <<: *kubernetes-env image: paritytech/tools:latest From 49d2ee45ca1327069d9102aafd57dd48b9b51a8b Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 18:37:27 -0500 Subject: [PATCH 091/102] Run `LangError` E2E tests in CI --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3e09dc82961..27c6825cb70 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -390,7 +390,7 @@ examples-test: cargo test --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - cargo test --verbose --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml; + cargo test --verbose --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml --features e2e-tests; done - cargo test --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml; From 5785eb02c1c19e7a728b00838f5fd7aeb9ed30e5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 15 Nov 2022 18:51:30 -0500 Subject: [PATCH 092/102] Rename tests using kabob-case instead of snake_case --- .gitlab-ci.yml | 26 +++++++++---------- .../.gitignore | 0 .../call-builder}/Cargo.toml | 0 .../call-builder}/lib.rs | 2 +- .../contract-ref}/Cargo.toml | 2 +- .../contract-ref}/lib.rs | 6 ++--- .../integration-flipper}/Cargo.toml | 0 .../integration-flipper}/lib.rs | 0 8 files changed, 18 insertions(+), 18 deletions(-) rename examples/{lang_err_integration_tests => lang-err-integration-tests}/.gitignore (100%) rename examples/{lang_err_integration_tests/call_builder => lang-err-integration-tests/call-builder}/Cargo.toml (100%) rename examples/{lang_err_integration_tests/call_builder => lang-err-integration-tests/call-builder}/lib.rs (98%) rename examples/{lang_err_integration_tests/contract_ref => lang-err-integration-tests/contract-ref}/Cargo.toml (92%) rename examples/{lang_err_integration_tests/contract_ref => lang-err-integration-tests/contract-ref}/lib.rs (97%) rename examples/{lang_err_integration_tests/integration_flipper => lang-err-integration-tests/integration-flipper}/Cargo.toml (100%) rename examples/{lang_err_integration_tests/integration_flipper => lang-err-integration-tests/integration-flipper}/lib.rs (100%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 27c6825cb70..885f2fecb25 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,7 +34,7 @@ variables: ALL_CRATES: "${PURELY_STD_CRATES} ${ALSO_WASM_CRATES}" DELEGATOR_SUBCONTRACTS: "accumulator adder subber" UPGRADEABLE_CONTRACTS: "forward-calls set-code-hash" - LANG_ERR_INTEGRATION_CONTRACTS: "integration_flipper call_builder contract_ref" + LANG_ERR_INTEGRATION_CONTRACTS: "integration-flipper call-builder contract-ref" # TODO `cargo clippy --verbose --all-targets --all-features` for this crate # currently fails on `stable`, but succeeds on `nightly`. This is due to # this fix not yet in stable: https://github.com/rust-lang/rust-clippy/issues/8895. @@ -123,7 +123,7 @@ examples-fmt: # Note that we disable the license header check for the examples, since they are unlicensed. - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; - if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; + if [ "$example" = "examples/lang-err-integration-tests/" ]; then continue; fi; cargo +nightly fmt --verbose --manifest-path ${example}/Cargo.toml -- --check; done - for contract in ${DELEGATOR_SUBCONTRACTS}; do @@ -133,7 +133,7 @@ examples-fmt: cargo +nightly fmt --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml -- --check; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - cargo +nightly fmt --verbose --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml -- --check; + cargo +nightly fmt --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml -- --check; done - cargo +nightly fmt --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -- --check # This file is not a part of the cargo project, so it wouldn't be formatted the usual way @@ -166,7 +166,7 @@ examples-clippy-std: script: - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; - if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; + if [ "$example" = "examples/lang-err-integration-tests/" ]; then continue; fi; cargo clippy --verbose --all-targets --manifest-path ${example}/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; done - for contract in ${DELEGATOR_SUBCONTRACTS}; do @@ -176,7 +176,7 @@ examples-clippy-std: cargo clippy --verbose --all-targets --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - cargo clippy --verbose --all-targets --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; + cargo clippy --verbose --all-targets --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; done - cargo clippy --verbose --all-targets --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -- -D warnings -A $CLIPPY_ALLOWED; allow_failure: true @@ -188,7 +188,7 @@ examples-clippy-wasm: script: - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; - if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; + if [ "$example" = "examples/lang-err-integration-tests/" ]; then continue; fi; cargo clippy --verbose --manifest-path ${example}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings -A $CLIPPY_ALLOWED; done - for contract in ${DELEGATOR_SUBCONTRACTS}; do @@ -198,7 +198,7 @@ examples-clippy-wasm: cargo clippy --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings -A $CLIPPY_ALLOWED; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - cargo clippy --verbose --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings -A $CLIPPY_ALLOWED; + cargo clippy --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings -A $CLIPPY_ALLOWED; done - cargo clippy --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings -A $CLIPPY_ALLOWED; allow_failure: true @@ -376,7 +376,7 @@ examples-test: - *start-substrate-contracts-node - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; - if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; + if [ "$example" = "examples/lang-err-integration-tests/" ]; then continue; fi; if grep -q "e2e-tests = \[\]" "${example}/Cargo.toml"; then cargo test --verbose --manifest-path ${example}/Cargo.toml --features e2e-tests; else @@ -390,7 +390,7 @@ examples-test: cargo test --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - cargo test --verbose --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml --features e2e-tests; + cargo test --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml --features e2e-tests; done - cargo test --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml; @@ -403,7 +403,7 @@ examples-contract-build: - cargo contract -V - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; - if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; + if [ "$example" = "examples/lang-err-integration-tests/" ]; then continue; fi; pushd $example && cargo +stable contract build && popd; @@ -413,7 +413,7 @@ examples-contract-build: cargo +stable contract build --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - cargo +stable contract build --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml; + cargo +stable contract build --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml; done - cargo +stable contract build --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml @@ -430,7 +430,7 @@ examples-docs: # of this flag. - for example in examples/*/; do if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi; - if [ "$example" = "examples/lang_err_integration_tests/" ]; then continue; fi; + if [ "$example" = "examples/lang-err-integration-tests/" ]; then continue; fi; cargo doc --manifest-path ${example}/Cargo.toml --document-private-items --verbose --no-deps; done - for contract in ${DELEGATOR_SUBCONTRACTS}; do @@ -440,7 +440,7 @@ examples-docs: cargo doc --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml --document-private-items --verbose --no-deps; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - cargo doc --manifest-path ./examples/lang_err_integration_tests/${contract}/Cargo.toml --document-private-items --verbose --no-deps; + cargo doc --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml --document-private-items --verbose --no-deps; done - cargo doc --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml --document-private-items --verbose --no-deps diff --git a/examples/lang_err_integration_tests/.gitignore b/examples/lang-err-integration-tests/.gitignore similarity index 100% rename from examples/lang_err_integration_tests/.gitignore rename to examples/lang-err-integration-tests/.gitignore diff --git a/examples/lang_err_integration_tests/call_builder/Cargo.toml b/examples/lang-err-integration-tests/call-builder/Cargo.toml similarity index 100% rename from examples/lang_err_integration_tests/call_builder/Cargo.toml rename to examples/lang-err-integration-tests/call-builder/Cargo.toml diff --git a/examples/lang_err_integration_tests/call_builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs similarity index 98% rename from examples/lang_err_integration_tests/call_builder/lib.rs rename to examples/lang-err-integration-tests/call-builder/lib.rs index 064be3ab1ea..a56fc3b5f36 100755 --- a/examples/lang_err_integration_tests/call_builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -61,7 +61,7 @@ mod call_builder { mod e2e_tests { type E2EResult = std::result::Result>; - #[ink_e2e::test(additional_contracts = "../integration_flipper/Cargo.toml")] + #[ink_e2e::test(additional_contracts = "../integration-flipper/Cargo.toml")] async fn e2e_invalid_selector_can_be_handled( mut client: ink_e2e::Client, ) -> E2EResult<()> { diff --git a/examples/lang_err_integration_tests/contract_ref/Cargo.toml b/examples/lang-err-integration-tests/contract-ref/Cargo.toml similarity index 92% rename from examples/lang_err_integration_tests/contract_ref/Cargo.toml rename to examples/lang-err-integration-tests/contract-ref/Cargo.toml index a8d474d246a..0c00cff43e5 100755 --- a/examples/lang_err_integration_tests/contract_ref/Cargo.toml +++ b/examples/lang-err-integration-tests/contract-ref/Cargo.toml @@ -10,7 +10,7 @@ ink = { path = "../../../crates/ink", default-features = false } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2", default-features = false, features = ["derive"], optional = true } -integration_flipper = { path = "../integration_flipper", default-features = false, features = ["ink-as-dependency"] } +integration_flipper = { path = "../integration-flipper", default-features = false, features = ["ink-as-dependency"] } [dev-dependencies] ink_e2e = { path = "../../../crates/e2e" } diff --git a/examples/lang_err_integration_tests/contract_ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs similarity index 97% rename from examples/lang_err_integration_tests/contract_ref/lib.rs rename to examples/lang-err-integration-tests/contract-ref/lib.rs index 45421e9213d..5bd914278a0 100755 --- a/examples/lang_err_integration_tests/contract_ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -5,11 +5,11 @@ mod contract_ref { use integration_flipper::FlipperRef; #[ink(storage)] - pub struct CrossChainRef { + pub struct ContractRef { flipper: FlipperRef, } - impl CrossChainRef { + impl ContractRef { #[ink(constructor)] pub fn new(version: u32, flipper_code_hash: Hash) -> Self { let salt = version.to_le_bytes(); @@ -54,7 +54,7 @@ mod contract_ref { mod e2e_tests { type E2EResult = std::result::Result>; - #[ink_e2e::test(additional_contracts = "../integration_flipper/Cargo.toml")] + #[ink_e2e::test(additional_contracts = "../integration-flipper/Cargo.toml")] async fn e2e_ref_can_flip_correctly( mut client: ink_e2e::Client, ) -> E2EResult<()> { diff --git a/examples/lang_err_integration_tests/integration_flipper/Cargo.toml b/examples/lang-err-integration-tests/integration-flipper/Cargo.toml similarity index 100% rename from examples/lang_err_integration_tests/integration_flipper/Cargo.toml rename to examples/lang-err-integration-tests/integration-flipper/Cargo.toml diff --git a/examples/lang_err_integration_tests/integration_flipper/lib.rs b/examples/lang-err-integration-tests/integration-flipper/lib.rs similarity index 100% rename from examples/lang_err_integration_tests/integration_flipper/lib.rs rename to examples/lang-err-integration-tests/integration-flipper/lib.rs From 7d57f8c2e4c07e9d7737ee5adc186491c7c1b3ac Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 10:20:56 -0500 Subject: [PATCH 093/102] Try running with `staging` image --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 885f2fecb25..43cc50f674d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -28,7 +28,7 @@ variables: CARGO_TARGET_DIR: "/ci-cache/${CI_PROJECT_NAME}/targets/${CI_COMMIT_REF_NAME}/${CI_JOB_NAME}" # CI_IMAGE is changed to "-:staging" when the CI image gets rebuilt # read more https://github.com/paritytech/scripts/pull/244 - CI_IMAGE: "paritytech/ink-ci-linux:production" + CI_IMAGE: "paritytech/ink-ci-linux:staging" PURELY_STD_CRATES: "ink/codegen metadata engine" ALSO_WASM_CRATES: "env storage storage/traits allocator prelude primitives ink ink/macro ink/ir" ALL_CRATES: "${PURELY_STD_CRATES} ${ALSO_WASM_CRATES}" From 2b05e593874269599de95d0b35f748bad39ac989 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 10:48:41 -0500 Subject: [PATCH 094/102] Change image back to `production` Didn't help either way --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 43cc50f674d..885f2fecb25 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -28,7 +28,7 @@ variables: CARGO_TARGET_DIR: "/ci-cache/${CI_PROJECT_NAME}/targets/${CI_COMMIT_REF_NAME}/${CI_JOB_NAME}" # CI_IMAGE is changed to "-:staging" when the CI image gets rebuilt # read more https://github.com/paritytech/scripts/pull/244 - CI_IMAGE: "paritytech/ink-ci-linux:staging" + CI_IMAGE: "paritytech/ink-ci-linux:production" PURELY_STD_CRATES: "ink/codegen metadata engine" ALSO_WASM_CRATES: "env storage storage/traits allocator prelude primitives ink ink/macro ink/ir" ALL_CRATES: "${PURELY_STD_CRATES} ${ALSO_WASM_CRATES}" From 80a27a77362da3195cd836e7a5bc4eef25e8af29 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 10:52:11 -0500 Subject: [PATCH 095/102] Try cleaning some things --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 885f2fecb25..ab3ee97496c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -390,6 +390,8 @@ examples-test: cargo test --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do + rm ./examples/lang-err-integration-tests/${contract}/Cargo.lock; + cargo clean --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml; cargo test --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml --features e2e-tests; done - cargo test --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml; From 0212c90bd5c1bb1967dd60c8a73d46108ffe8213 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 11:55:05 -0500 Subject: [PATCH 096/102] Guess there was no lockfile --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ab3ee97496c..993f6d72c12 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -390,7 +390,6 @@ examples-test: cargo test --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - rm ./examples/lang-err-integration-tests/${contract}/Cargo.lock; cargo clean --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml; cargo test --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml --features e2e-tests; done From 12bc8249ac20c8e4e9733f78a000bf08a1b63ec7 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 12:22:56 -0500 Subject: [PATCH 097/102] Clean up the cleanup --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 993f6d72c12..885f2fecb25 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -390,7 +390,6 @@ examples-test: cargo test --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - cargo clean --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml; cargo test --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml --features e2e-tests; done - cargo test --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml; From 55b4e4f37a96f7c7c17fb80eb061dac84b06ca56 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 14:22:54 -0500 Subject: [PATCH 098/102] Clean em up again --- .gitlab-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 885f2fecb25..b4c30da30a4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -390,6 +390,9 @@ examples-test: cargo test --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do + # TODO (#1502): We need to clean before running, otherwise the CI fails with a + # linking error. + cargo clean --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml; cargo test --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml --features e2e-tests; done - cargo test --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml; From 16443438a7b99e4e436456e74a94569849c05e8e Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 14:24:32 -0500 Subject: [PATCH 099/102] Use `MessageResult` typedef in one more place --- crates/ink/codegen/src/generator/dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index f66a7eb92c7..8875fd8d513 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -451,7 +451,7 @@ impl Dispatch<'_> { // // This is okay since we're going to only be encoding the `Err` variant // into the output buffer anyways. - ::ink::env::return_value::<::core::result::Result<(), ::ink::LangError>>( + ::ink::env::return_value::<::ink::MessageResult<()>>( ::ink::env::ReturnFlags::default().set_reverted(true), &error, ); From f1211ba866f466656e0e528b38aeede021b38e81 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 14:52:04 -0500 Subject: [PATCH 100/102] Poke CI From 9a1e41fb49bb888fd636471de6b7e79e86a18a12 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 14:54:45 -0500 Subject: [PATCH 101/102] Move comment location --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b4c30da30a4..84742f40914 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -389,9 +389,9 @@ examples-test: - for contract in ${UPGRADEABLE_CONTRACTS}; do cargo test --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml; done + # TODO (#1502): We need to clean before running, otherwise the CI fails with a + # linking error. - for contract in ${LANG_ERR_INTEGRATION_CONTRACTS}; do - # TODO (#1502): We need to clean before running, otherwise the CI fails with a - # linking error. cargo clean --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml; cargo test --verbose --manifest-path ./examples/lang-err-integration-tests/${contract}/Cargo.toml --features e2e-tests; done From 40577907f8efd5967687fe4ad6721ad7c414b4c0 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Nov 2022 14:54:55 -0500 Subject: [PATCH 102/102] Update contract name --- examples/lang-err-integration-tests/integration-flipper/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lang-err-integration-tests/integration-flipper/lib.rs b/examples/lang-err-integration-tests/integration-flipper/lib.rs index 72691708810..a33d95cce84 100644 --- a/examples/lang-err-integration-tests/integration-flipper/lib.rs +++ b/examples/lang-err-integration-tests/integration-flipper/lib.rs @@ -37,7 +37,7 @@ pub mod integration_flipper { self.value } - /// Flips the current value of the `CallBuilder`'s boolean. + /// Flips the current value of the Flipper's boolean. /// /// We should see the state being reverted here, no write should occur. #[ink(message)]