0

I've been trying for a few days now to implement cross contract calls but somehow I can't seem to make it right. So here is my code and I hope one of you can point out my mistake to me.

I want to call on a smart contract which is already deployed on chain. Here is an example how that would look like, utilizing the openbrush wrapper.

As far as I understand it, works by importing the trait of the smart contract which is to be called on and then using the AccountId of the smart contract to point to the right instance, deployed on the chain.

Here is an example of how I tried to implement this myself. There are two contracts:

  • Incrementer Contract

    • has one value which is 0 at the start
    • inc() <- method to increase the value by 0.1
    • balance() <- method to check the value
  • Caller Contract

    • has the AccountId of Incrementer
    • call() <- method to call inc()

Code:

Incrementer trait:

#[openbrush::wrapper]
pub type IncRef = dyn Inc;

#[openbrush::trait_definition]
pub trait Inc {

    #[ink(message)]
    fn inc(&mut self);

    #[ink(message)]
    fn balance(&self) -> u128;
}

Incrementer code:

#![cfg_attr(not(feature = "std"), no_std)]
#![feature(min_specialization)]

#[openbrush::contract]
mod inc {

    use project::traits::inc::*;

    #[ink(storage)]
    pub struct Inc {
        value: u128,
    }

    impl Inc {
        
        #[ink(constructor)]
        pub fn new() -> Self {
            Self { value: 0 }
        }


        #[ink(message)]
        pub fn inc(&mut self) {
            self.value += 1;
        }

        #[ink(message)]
        pub fn balance(&self) -> u128 {
            self.value
        }
    }
}

Caller Code:

#![cfg_attr(not(feature = "std"), no_std)]
#![feature(min_specialization)]

#[openbrush::contract]
mod caller {
    use project::traits::inc::IncRef;
    
    #[ink(storage)]
    pub struct Caller {
        contract: AccountId
    }

    impl Caller {
        
        #[ink(constructor)]
        pub fn new(
            contract: AccountId
        ) -> Self {
            Self { contract: contract}
        }


        #[ink(message)]
        pub fn call(){
            IncRef::inc(&self.contract);
        }
    }
}

Incrementer Cargo.toml

[package]
name = "inc"
version = "0.1.0"
authors = ["[your_name] <[your_email]>"]
edition = "2021"

[dependencies]
ink_primitives = { version = "3", default-features = false }
ink_metadata = { version = "3", default-features = false, features = ["derive"], optional = true }
ink_env = { version = "3", default-features = false }
ink_storage = { version = "3", default-features = false }
ink_lang = { version = "3", 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 }

project = { path = "../..", default-features = false }
openbrush = { version="~2.1.0", default-features = false}

[lib]
name = "inc"
path = "lib.rs"
crate-type = [
    "cdylib",
    "rlib"
]

[features]
default = ["std"]
std = [
    "ink_metadata/std",
    "ink_env/std",
    "ink_storage/std",
    "ink_primitives/std",
    "scale/std",
    "scale-info/std",

    "project/std",
    "openbrush/std"
]
ink-as-dependency = []

Caller Cargo.toml

[package]
name = "caller"
version = "0.1.0"
authors = ["[your_name] <[your_email]>"]
edition = "2021"

[lib]
name = "caller"
path = "lib.rs"
crate-type = [
    "cdylib",
]


[dependencies]
ink_primitives = { version = "~3.3.0", default-features = false }
ink_metadata = { version = "~3.3.0", default-features = false, features = ["derive"], optional = true }
ink_env = { version = "~3.3.0", default-features = false }
ink_storage = { version = "~3.3.0", default-features = false }
ink_lang = { version = "~3.3.0", default-features = false }
ink_prelude = { version = "~3.3.0", default-features = false }
ink_engine = { version = "~3.3.0", default-features = false, optional = true }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2", default-features = false, features = ["derive"], optional = true }


project = { path = "../..", default-features = false }
openbrush = { version="~2.1.0", default-features = false}
inc = { path = "../inc", default-features = false, features = ["ink-as-dependency"] }

[features]
default = ["std"]
std = [
    "ink_primitives/std",
    "ink_metadata",
    "ink_metadata/std",
    "ink_env/std",
    "ink_storage/std",
    "ink_lang/std",
    "scale/std",
    "scale-info",
    "scale-info/std",

    "openbrush/std",
    "inc/std",
    "project/std",
]
ink-as-dependency = []

[profile.dev]
codegen-units = 16

[profile.release]
overflow-checks = false

Since there also seems to be no way to adequatly test smart contracts which utilize cross contract calls I am a bit lost at which could be the mistake. I tried testing this implementation by uploading the contracts to a private node. But the only info I got was the following, when the call() call failed:

9/15/2022, 12:25:17 AM call()

balances:Withdraw

system:ExtrinsicFailed contracts:ContractTrapped

Contract trapped during execution.

2 Answers 2

0

I could not get the openbrush apporach get to work by using a wrapper. However I found a low level approach (here) which works just fine for now.

let method_selector = [0xDE, 0xAD, 0xBE, 0xEF];

build_call::<DefaultEnvironment>()
    .call_type(Call::new().callee(self.contract))
    .exec_input(
         ExecutionInput::new(Selector::new(method_selector)))
         .call_flags(CallFlags::default()
         .returns::<()>()
         .fire()
         .unwrap();
-2

OpenBrush use both {}Ref and wrapper in the example. {}Ref is used to instantiate the contracts. Wrapper is used to do cross contract calls. There is already this question asked here

2
  • The question you refer to is mine. And it is a different one.
    – rajohs
    Sep 16 at 14:51
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Sep 18 at 1:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.