Currently, when writing e2e tests for cases when called contract returns a specific set of values is very cumbersome. It requires creating a special contract with fixed execution logic that behaves in a certain way when called with specific arguments (or by pre-specified caller). This is time-consuming and repetitive work which is very daunting.
Imagine the following pseudo-code:
let caller_check: FnOnce<&AccountId> -> bool;
let args_check: FnOnce<&(AccountId, Balance)> -> bool;
let state_check: FnOnce<&PSP22> -> bool;
let psp22_mock = Mock::new(PSP22)
.when(PSP22::transfer)
.with_state(state_check)
.with_caller(caller_check)
.with_args(args_check)
.build();
let mut session = Session::new(...);
session.register_mock(address|code_hash, psp22_mock);
This would be a callback-based mocking, which calls the drink!-side implementation when contract execution hits these lines.
Since the callback execution happens on drink! side of things, we can deserialize input arguments (as well as state probably) and have very granular control over the mock.
The approach taken in https://github.com/paritytech/substrate/pull/14678 , to support debugging contract calls, can be extended to support mocking contract calls as well.
Currently, when writing e2e tests for cases when called contract returns a specific set of values is very cumbersome. It requires creating a special contract with fixed execution logic that behaves in a certain way when called with specific arguments (or by pre-specified caller). This is time-consuming and repetitive work which is very daunting.
Imagine the following pseudo-code:
This would be a callback-based mocking, which calls the drink!-side implementation when contract execution hits these lines.
Since the callback execution happens on drink! side of things, we can deserialize input arguments (as well as state probably) and have very granular control over the mock.