Skip to content

Commit

Permalink
Merge branch 'instantiate_contract'
Browse files Browse the repository at this point in the history
  • Loading branch information
Helios-vmg committed Sep 11, 2023
2 parents 44e3b32 + 2d8ce59 commit 7d6e6a4
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 0 deletions.
35 changes: 35 additions & 0 deletions test-cases/instantiate-contract/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[package]
name = "instantiate_contract"
version = "0.1.0"
edition = "2021"
authors = ["[your_name] <[your_email]>"]

[lib]
path = "lib.rs"

[features]
default = ["std"]
std = ["ink/std", "scale/std", "scale-info/std", "other_contract/std"]
ink-as-dependency = []
e2e-tests = []

[dependencies]
ink = { version = "4.2.1", default-features = false }
scale = { package = "parity-scale-codec", version = "=3.6.5", default-features = false, features = [
"derive",
] }
scale-info = { version = "2.6", default-features = false, features = [
"derive",
], optional = true }
other_contract = { path = "./other_contract", default-features = false, features = [
"ink-as-dependency",
] }

[dev-dependencies]
ink_e2e = "4.2.1"

[profile.dev]
overflow-checks = false

[profile.release]
overflow-checks = false
37 changes: 37 additions & 0 deletions test-cases/instantiate-contract/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Template

```rust
pub fn instantiate_contract<E, ContractRef, Args, Salt, R>(
params: &CreateParams<E, ContractRef, Args, Salt, R>
) -> Result<ConstructorResult<<R as ConstructorReturnType<ContractRef>>::Output>>
where
E: Environment,
ContractRef: FromAccountId<E>,
Args: Encode,
Salt: AsRef<[u8]>,
R: ConstructorReturnType<ContractRef>,
```

## Description

`instantiate_contract` is a low level way to instantiate another smart contract.

## Related ink! functions

- [instantiate_contract](https://paritytech.github.io/ink/ink_env/fn.instantiate_contract.html)

## Test case



## Comparison Integration vs E2E

The End-to-End test works correctly since it invokes successfully the call to the second contract. In Integration did not work since it's [unimplemented](https://github.com/paritytech/ink/blob/c2af39883aab48c71dc09dac5d06583f2e84dc54/crates/env/src/engine/off_chain/impls.rs#L464).

| \# | Test | Integration | E2E |
| --- | --------------------------------------------------------------- | :---------: | :-: |
| 1 | Attempts to instantiate a contract. |||

## Result

The implementation of invoke_contract() is somewhat tied to that of code_hash and own_code_hash(). The strategy picked for one will condition the solution for the other. The simpler of the two may take up to roughly 15 days. There are some things to work out, such as how to call the required function, that add some uncertainty to the estimate.
104 changes: 104 additions & 0 deletions test-cases/instantiate-contract/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#![cfg_attr(not(feature = "std"), no_std, no_main)]

#[ink::contract]
mod instantiate_contract {
use other_contract::OtherContractRef;

#[ink(storage)]
pub struct InstantiateContract {}

impl InstantiateContract {
#[ink(constructor)]
pub fn new() -> Self {
Self {}
}

#[ink(message)]
pub fn instantiate_other_contract(&self, code_hash: Hash) -> OtherContractRef {
let create_params = ink::env::call::build_create::<OtherContractRef>()
.code_hash(code_hash)
.gas_limit(0)
.endowment(0)
.exec_input(ink::env::call::ExecutionInput::new(
ink::env::call::Selector::new(ink::selector_bytes!("new")),
))
.salt_bytes(&[0x0; 4])
.returns::<OtherContractRef>()
.params();

self.env()
.instantiate_contract(&create_params)
.unwrap_or_else(|error| {
panic!(
"Received an error from the Contracts pallet while instantiating: {:?}",
error
)
})
.unwrap_or_else(|error| {
panic!("Received a `LangError` while instatiating: {:?}", error)
})
}
}

impl Default for InstantiateContract {
fn default() -> Self {
Self::new()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[ink::test]
fn instantiate_other_contract() {
let contract = InstantiateContract::new();
let code_hash = Hash::from([0x42; 32]);
let _ = contract.instantiate_other_contract(code_hash);
}
}

#[cfg(all(test, feature = "e2e-tests"))]
mod e2e_tests {
use ink_e2e::build_message;

use super::*;

type E2EResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;

#[ink_e2e::test(additional_contracts = "other_contract/Cargo.toml")]
async fn instantiate_other_contract(mut client: ink_e2e::Client<C, E>) -> E2EResult<()> {
let constructor = InstantiateContractRef::new();

let contract_acc_id = client
.instantiate(
"instantiate_contract",
&ink_e2e::bob(),
constructor,
0,
None,
)
.await
.expect("instantiate failed")
.account_id;

let other_contract_code_hash = client
.upload("other_contract", &ink_e2e::bob(), None)
.await
.expect("instantiate failed")
.code_hash;

let instantiate_other_contract =
build_message::<InstantiateContractRef>(contract_acc_id.clone())
.call(|contract| contract.instantiate_other_contract(other_contract_code_hash));

let instantiate_other_contract_res = client
.call_dry_run(&ink_e2e::bob(), &instantiate_other_contract, 0, None)
.await;

assert!(instantiate_other_contract_res.exec_result.result.is_ok());

Ok(())
}
}
}
32 changes: 32 additions & 0 deletions test-cases/instantiate-contract/other_contract/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[package]
name = "other_contract"
version = "0.1.0"
edition = "2021"
authors = ["[your_name] <[your_email]>"]

[lib]
path = "lib.rs"

[features]
default = ["std"]
std = ["ink/std", "scale/std", "scale-info/std"]
ink-as-dependency = []
e2e-tests = []

[dependencies]
ink = { version = "4.2.1", default-features = false }
scale = { package = "parity-scale-codec", version = "=3.6.5", default-features = false, features = [
"derive",
] }
scale-info = { version = "2.6", default-features = false, features = [
"derive",
], optional = true }

[dev-dependencies]
ink_e2e = "4.2.1"

[profile.dev]
overflow-checks = false

[profile.release]
overflow-checks = false
30 changes: 30 additions & 0 deletions test-cases/instantiate-contract/other_contract/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#![cfg_attr(not(feature = "std"), no_std, no_main)]

pub use self::other_contract::OtherContractRef;

#[ink::contract()]
mod other_contract {

#[ink(storage)]
pub struct OtherContract {}

impl OtherContract {
/// Creates a new Template contract.
#[ink(constructor)]
pub fn new() -> Self {
Self {}
}

/// Returns the hash code of the contract through the function 'own_code_hash'.
#[ink(message)]
pub fn own_code_hash(&self) -> Hash {
self.env().own_code_hash().unwrap()
}
}

impl Default for OtherContract {
fn default() -> Self {
Self::new()
}
}
}

0 comments on commit 7d6e6a4

Please sign in to comment.