Is there a way to persist event from contract even in case of error? Currently the deposited event seems to disappear when error occurs in contract.
1 Answer
Currently the deposited event seems to disappear when error occurs in contract.
In the following I assume that by "error occurs" you mean that the contract either traps or returns a Result::Err
.
Trapping happens typically when a contract panics on e.g. expect
or unwrap
or reentrancy (which is disabled by default). In the case of the contract trapping all side-effects are rolled back, so no storage changes are persisted and no events are emitted.
Returning a Result::Err
results in the same behavior, the side-effects are rolled back and the Err(…)
is returned in an output buffer, which can be displayed by UI's or CLI clients.
You have two options for your case:
(1) Return a Result<Result<…>>
.
So pseudo-code:
type MyBusinessLogicResult<T> = Result<T, MyErrors>;
#[ink(message)]
pub fn foo(&mut self) -> Result<MyBusinessLogicResult<…>> {
self.env().emit_event(MyEventIndicatingAnError);
Ok(MyBusinessLogicResult::Err(…))
}
It's important to know that here any side-effect before the Ok(…)
would be persisted to chain storage! This is likely not what you want, bringing us to option (2).
(2) Use RPC's for determining if an error would happen on a particular contract call invocation.
This is the preferred method. Your frontend executes an RPC call to dry-run the contract method. This is then synchronous and your UI will immediately know the Result
that the invocation would yield.
You can immediately display an error to the user, enabling adjusting the input so that the call would succeed.
You only submit the extrinsic once this dry-run would yield Result::Ok
.
The advantage here is that the user doesn't have to pay for getting just the error and the result is known immediately. Events are asynchronous, your frontend has to actively listen for them which is not such a nice user experience due to the UI having to display some "waiting" indicator.
If you're using polkadot-js as an API there is documentation on how to dry-run a contract call here.
-
ya this seems to be the only way to get the errors for now only downside being contract will always return ok Aug 12, 2022 at 10:04