-
Notifications
You must be signed in to change notification settings - Fork 452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make ink! contracts viable dependencies for the runtime #1674
Comments
The option of calling SCs from pallets conveniently (as it's possible right now but definitely not conveniently) would be very useful! We were discussing recently several use cases for that, e.g sth similar to this PR paritytech/substrate#13203 but using a SC DEX instead of a DEX pallet. |
@ascjones Please specify this out in a way that an external contributor could work on it. |
We are looking into this as well atm. |
The first thing I would do here is to see what is possible to achieve with the existing
Have a look at this PR which was an experiment I did to see if it was possible to use the existing contract ref messages which return a To get started with experimenting with this, you could reference a contract using Again, ideally I would like to see a unified API for building contract calls for cross contract/e2e testing and calling contracts from substrate pallets. And I believe this will be possible while reusing most of the codegen we already have. |
It is possible to achieve this with minor changes in the call builder and a new trait. The call builder's current implementation(invoking of the contract) only works with the But if we make it configurable, we will be able to work with e2e or substrate runtime through the same API. ![]()
It is clear that we need a selector, arguments, and output type from the The substrate already has access to this information via
Maybe we could have something like this: pub trait InkInvoker {
fn invoke<Input, Output>(&self, selector: Selector, arguments: Input) -> Output {
self.try_invoke(selector, arguments).expect("Got an error durign invoking")
}
fn try_invoke<Input, Output>(&self, selector: Selector, arguments: Input) -> Result<Output, SomeError>;
}
/// `ContractInvoker` has `AccountId`, some configuration about `CallType` and `CallFlags`.
impl<E: Environment> InkInvoker for ContractInvoker<E> {
fn try_invoke<Input, Output>(&self, selector: Selector, arguments: Input) -> Result<Output, SomeError> {
let params = CallParams::from(self, selector, arguments);
<EnvInstance as OnInstance>::on_instance(|instance| {
TypedEnvBackend::invoke_contract::<E, Input, Output>(instance, params)
})
}
}
/// `E2EDryRunInvoker` has `&E2EClient` and dry run configuration.
/// The same ideas is appliable to `E2ECallInvoker`.
impl InkInvoker for E2EDryRunInvoker {
fn try_invoke<Input, Output>(&self, selector: Selector, arguments: Input) -> Result<Output, SomeError> {
let exec_input = ExecInput::from(selector, arguments);
self
.api
.call_dry_run(
Signer::account_id(self.signer).clone(),
dest,
exec_input,
self.value,
self.storage_deposit_limit,
)
}
}
impl InkInvoker for SubstrateInvoker {
...
} Selector, Input, and Output are the core of the any call. Having them, we can create an invoker instance for a specific method in a specific context. The usage transforms only into defining the right type and implementing the |
I’m refactoring the |
When a contract A depends on another contract B and sets the
ink-as-dependency
feature we generate code that allowsA
to easily call intoB
. The generated code is specifically constructed to do a cross contract call and can't be used for other purposes easily. We want to change this.The objective is to generate additional code that is more general and can be consumed by other targets than an ink! contract. The target we have in mind here are substrate runtimes: We want to make it convenient for substrate runtimes to call into ink! contracts.
The idea is that a runtime or pallet can depend on a ink! contract in its
Cargo.toml
just like a contract would. This will enable the runtime to learn about the messages and constructors of the contract and conveniently call these functions.The e2e framework is probably doing something similar. I didn't check. I think it is most easily understood with an example. I wrote some example code how I imagine the system working. It is basically how I think the generated code could look like and how I would integrate it into pallet-contracts. It is by no means perfect. But I think it gets the point across:
https://github.com/athei/call-ink-example/blob/master/src/main.rs
Its quite a bit of code. But it is a complete example.
The text was updated successfully, but these errors were encountered: