-
Notifications
You must be signed in to change notification settings - Fork 392
Description
Problem
In order to pass in all the external deps, we currently use:
pub struct Extern<S: Storage, A: Api, Q: Querier> {
pub storage: S,
pub api: A,
pub querier: Q,
}and pass in either &mut Extern (handle, init, migrate) or &Extern (query).
This is great for tests and for linking to relatively stateless handlers. Now, I am working to build a integration test framework for contracts to redeploy messages and router querier to the real contracts and their state - held by the same object that is running the query itself.
The current definition means I need to pass in self, when all that is really needed is &self. I start defining impl Querier for &Router (rather than Router) and got into all kinds of lifetime issues. I also could not accept &Q, as I need Q for building Extern.
Proposal
What we really need inside the contracts is:
pub struct ExternMut<S: Storage, A: Api, Q: Querier> {
pub storage: &mut S,
pub api: &A,
pub querier: &Q,
}
pub struct ExternRef<S: Storage, A: Api, Q: Querier> {
pub storage: &S,
pub api: &A,
pub querier: &Q,
}and can use handle(deps: ExternMut<S, A, Q>, ..) and query(deps: ExternRef<S, A, Q>, ...)
Impact
We could easily implement Extern::as_ref() and Extern::as_mut() to produce these from one owned Extern. This would be used almost identically inside the contract code (probably less typing - deps.storage rather than &mut deps.storage), but would make a bit more typing in the test code (mock_dependencies must return Extern for ownership, then all calls would be like: handle(deps.as_mut(), ...)
I do believe this would not change the wasm<->Rust API, just the unit tests, so pre-compiled 0.11 wasm binaries would be drop-in compatible with a new network with this change. You could just update the code in the next version of each contract, without requiring an upgrade of every contract to use the new network.