Search code examples
substrate

Is it possible to read an SRML error message in Substrate UI, when a transaction fails?


I am not sure of the behaviour of error messages in Substrate runtimes in relation to Substrate UI, and if they inherently cause a transaction failure or not.

For example in the democracy SRML I see the following line:

ensure!(!<Cancellations<T>>::exists(h), "cannot cancel the same proposal twice");

Which presumably is a macro that ensures that the transaction fails or stops processing if the h (the proposal hash) already exists. There is clearly a message associated with this error.

Am I right to assume that the transaction fails (without the rest of the SRML code being executed) when this test fails?

If so, how do I detect the failure in Substrate UI, and possibly see the message itself?

If not, then presumably some further code is necessary in the runtime module which explicitly creates an error. I have seen Err() - but not in conjunction with ensure!()


Solution

  • As https://github.com/paritytech/substrate/pull/3433 is merged, the ExtrinsicFailed event now includes a DispatchError, which will provide additional error code.

    There isn't much documentations available so I will just use system module as example.

    First you need to decl_error, note the error variants can only be simple C like enum

    https://github.com/paritytech/substrate/blob/5420de3face1349a97eb954ae71c5b0b940c31de/srml/system/src/lib.rs#L334

    decl_error! {
        /// Error for the System module
        pub enum Error {
            BadSignature,
            BlockFull,
            RequireSignedOrigin,
            RequireRootOrigin,
            RequireNoOrigin,
        }
    }
    

    Then you need to associate the declared Error type https://github.com/paritytech/substrate/blob/5420de3face1349a97eb954ae71c5b0b940c31de/srml/system/src/lib.rs#L253

    decl_module! {
        pub struct Module<T: Trait> for enum Call where origin: T::Origin {
            type Error = Error;
    

    Then you can just return your Error in dispatch calls when things failed

    https://github.com/paritytech/substrate/blob/5420de3face1349a97eb954ae71c5b0b940c31de/srml/system/src/lib.rs#L543

    pub fn ensure_root<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), Error>
        where OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>
    {
        match o.into() {
            Ok(RawOrigin::Root) => Ok(()),
            _ => Err(Error::RequireRootOrigin),
        }
    }
    

    Right now you will only able to see a two numbers, module index and error code from JS side. Later there could be support to include the error details in metadata so that frontend will be able to provide a better response.

    Related issue: https://github.com/paritytech/substrate/issues/2954