-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
} | ||
} | ||
} |