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.