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.