From 22673d1a2374c0df8cc280a2b287fe7788510483 Mon Sep 17 00:00:00 2001 From: deuszx Date: Thu, 5 Jan 2023 18:58:09 +0100 Subject: [PATCH 1/2] Fix the CallBuilder usage pattern. --- contracts/bulletin_board/lib.rs | 44 ++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/contracts/bulletin_board/lib.rs b/contracts/bulletin_board/lib.rs index 6af79bd..5f0ceb2 100755 --- a/contracts/bulletin_board/lib.rs +++ b/contracts/bulletin_board/lib.rs @@ -38,16 +38,19 @@ mod bulletin_board { HighlightedPostsError, HighlightedPostsRef, HIGHLIGHT_POST_SELECTOR, }; - use ink::env::{ - call::{build_call, Call, ExecutionInput, FromAccountId, Selector}, - DefaultEnvironment, Error as InkEnvError, + use ink::{ + env::{ + call::{build_call, Call, ExecutionInput, FromAccountId, Selector}, + DefaultEnvironment, Error as InkEnvError, + }, + LangError, }; use ink::{ codegen::EmitEvent, prelude::{format, string::String, vec::Vec}, reflect::ContractEventBase, - storage::{traits::StorageLayout, Mapping}, + storage::Mapping, ToAccountId, }; /// Errors returned by the contract's methods. @@ -95,7 +98,10 @@ mod bulletin_board { // `Storabe` for `v`'s type, it (`Storable`) has blanket implementation // for all types that implement `scale::Decode` and `scale::Encode`. #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo, StorageLayout))] + #[cfg_attr( + feature = "std", + derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout) + )] pub struct Bulletin { author: AccountId, posted_at: BlockNumber, @@ -432,7 +438,11 @@ mod bulletin_board { cost: u128, ) -> Result<(), BulletinBoardError> { if let Some(highlight_board) = self.highlighted_posts_board { - build_call::() + // Since the introduction of `ink::LangError` we got a new + // "channel" where the contract errors may be pushed into. + // In this particular example we have three layers of `Result` + // types. + let call_result: Result, ink::LangError>, ink::env::Error> = build_call::() .call_type(Call::new().callee(highlight_board)) // Address of the contract we want to call .exec_input( ExecutionInput::new(Selector::new( @@ -444,11 +454,23 @@ mod bulletin_board { .push_arg(id), ) .transferred_value(cost) // We can transfer tokens forward to another contract. - .returns::>() - .fire()??; // Double unwrap: first `?` deals with ink!'s - // native error `InkError`, while the second one - // deals with the result of the call - in this - // case it's `Result<(), HighlightedPostsError>`. + .returns::, LangError>>() + .fire(); + + match call_result { + Err(ink_env_error) => { + return Err(BulletinBoardError::from(ink_env_error)) + } + Ok(Err(lang_error)) => { + panic!("Unexpected ink::LangError: {:?}", lang_error) + } + Ok(Ok(Err(contract_call_error))) => { + return Err(BulletinBoardError::from( + contract_call_error, + )) + } + Ok(Ok(Ok(_unit))) => return Ok(()), + } } Ok(()) } From a44181bbbe84c16c807329c79e3b9c613d6cf4f1 Mon Sep 17 00:00:00 2001 From: deuszx Date: Tue, 10 Jan 2023 10:56:10 +0100 Subject: [PATCH 2/2] Rephrase comment on call_builder return type. --- contracts/bulletin_board/lib.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/contracts/bulletin_board/lib.rs b/contracts/bulletin_board/lib.rs index 5f0ceb2..73806df 100755 --- a/contracts/bulletin_board/lib.rs +++ b/contracts/bulletin_board/lib.rs @@ -438,10 +438,10 @@ mod bulletin_board { cost: u128, ) -> Result<(), BulletinBoardError> { if let Some(highlight_board) = self.highlighted_posts_board { - // Since the introduction of `ink::LangError` we got a new - // "channel" where the contract errors may be pushed into. - // In this particular example we have three layers of `Result` - // types. + // The potential call result here is a three layers of `Result`, + // where each layer has a different error. We're + // handling each explicitly below, for the example purposes, but + // you can also choose to short-circuit with `?`. let call_result: Result, ink::LangError>, ink::env::Error> = build_call::() .call_type(Call::new().callee(highlight_board)) // Address of the contract we want to call .exec_input( @@ -458,12 +458,18 @@ mod bulletin_board { .fire(); match call_result { + // Pallet contracts errors like deserialization error, panic + // in the called contract, etc. Err(ink_env_error) => { return Err(BulletinBoardError::from(ink_env_error)) } + // An error emitted by the smart contracting language. + // For more details see ink::LangError. Ok(Err(lang_error)) => { panic!("Unexpected ink::LangError: {:?}", lang_error) } + // `Result<(), HighlightedPostsError>` is the return type of + // the method we're calling. Ok(Ok(Err(contract_call_error))) => { return Err(BulletinBoardError::from( contract_call_error,