1

I have a method that accepts a call (similar to the sudo or recovery pallets) and i want to run some validation on the call before i dispatch it. The validation is mainly around restricting which methods we can call via this method.

Here is an example code i have:

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

        fn deposit_event() = default;

        pub fn foo(origin, call: Box<<T as Trait>::Call>) -> DispatchResult {
            ensure_signed(origin)?;

            let sender = match *call {
                Call::test(x) => Ok(()),
                _ => Err(())
            };

            Ok(())
        }


        pub fn test(origin, x: u32) -> DispatchResult {
            Ok(())
        }
    }
}

In this example i only want this to succeed if the call is calling my test() function.

Unfortunately I get an error about type mismatch and any help would be greatly appreciated, thanks.

the error i get is:

Call::test(x) => Ok(()),
| ^^^^^^^^^^^^^ expected associated type, found enum Call
|
= note: expected associated type <T as Trait>::Call
found enum Call<_>
= note: consider constraining the associated type <T as Trait>::Call to Call<_> or calling a method that returns <T as Trait>::Call
Nahu
  • 143
  • 10
  • If you know the function that you want to call, why does it need to be passed in as a parameter? Why can you not hardcode it into your `foo` function? – Dan Forbes May 06 '20 at 18:02
  • 1
    @DanForbes This is just an example. In reality i will have multiple functions and `foo` will be responsible for doing all the common processing and then dispatch it to the relevant method. – Nahu May 06 '20 at 18:59

1 Answers1

2

If anyone else has the same problem, IsSubType is your friend. You can constrain your Call type with IsSubType

type Call: Parameter + Dispatchable<Origin=<Self as frame_system::Trait>::Origin> + IsSubType<Module<Self>, Self>;

And for the matching you can get the subtype of the call and match on that:

 let call = match call.is_sub_type() {
    Some(call) => call,
    None => return Err(),
 };

 match *call {
    Call::test(x) => return Ok(),
    _ => return Err()
 }
Nahu
  • 143
  • 10