-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Pallet cannot read the origin it defined itself #9899
Comments
I'm going to temporarily use the struct + trait workaround and revisit this later, given that I'm not really familiar with the procedural macro code of this and this seems like a non-trivial work -- one has to define it similar to how I'm planning to go back to this later, but before that, I will un-assign myself. In the mean time, if anyone feels like taking this up, please feel free! |
@thiolliere what say you? |
the dispatchable declared in the pallet implements What you propose is to limit which origin can call into a pallet ? and to limit this to the origin declared by the pallet ? Maybe the pattern you want is indeed similar to Event declare some associated type in order to convert from the pallet origin into the runtime origin. Just to clarify this also wasn't possible with decl_module, isn't it ? What do I miss ? |
I think this was possible with With palletv2, this What I'm doing in Frontier is to define a new origin for signed Ethereum transactions. There are many reasons for this, particularly because we cannot treat an Ethereum transaction as a normal "signed" Substrate extrinsic, but have to have its own type. In the past we just treat them as "unsigned" extrinsics, but there were many drawbacks with that so we're working on defining a custom If you want to see this in practice, it's this PR (polkadot-evm/frontier#482). Related to this particular Substrate bug -- think of the following code snippets:
|
I don't think that works. I checked the code, we have special handle logic only for |
Considering that construct_runtime will implement: impl #scrate::traits::UnfilteredDispatchable for Call {
type Origin = Origin;
fn dispatch_bypass_filter(self, origin: Origin) -> #scrate::dispatch::DispatchResultWithPostInfo {
match self {
#(
#variant_patterns =>
#scrate::traits::UnfilteredDispatchable::dispatch_bypass_filter(call, origin),
)*
}
}
} where Origin is the runtime origin, I don't know how a pallet could work in construct_runtime if it doesn't implement UnfilteredDispatchable for the runtime origin. The way I would solve your example code would be: Solution 1: use the associated type to convert back and forth to the runtime origindiff --git a/snipet.rs b/snipet.rs
index 7ff671e..a73f972 100644
--- a/snipet.rs
+++ b/snipet.rs
@@ -17,14 +17,17 @@ where
pub type Origin = RawOrigin;
#[pallet::config]
-pub trait Config {
- type Origin: Into<Result<crate::RawOrigin, <Self as crate::Config>::Origin>>;
+pub trait Config: frame_system::Config {
+ /// This type is same as frame_system::Config but we use another associated type here to be
+ /// able to have more bounds without having to put a where clause everywhere.
+ type Origin: IsType<<Self as frame_system::Config>::Origin> + Into<Result<crate::RawOrigin, <Self as crate::Config>::Origin>>;
}
#[pallet::call]
impl<T: Config> Pallet<T> {
fn transact(origin: OriginFor<T>, other_parameters) {
- ensure_ethereum_transaction(origin)?; // This line would fail to compile because `Origin` is `frame_system::Config::Origin` and does not implement `Into<Result<crate::RawOrigin, _>>`.
+ let converted_origin = <T as Config>::Origin::from(origin);
+ ensure_ethereum_transaction(converted_origin)?;
// other code
}
} Solution 2: use a where clausediff --git a/snipet.rs b/snipet.rs
index 7ff671e..0385ec8 100644
--- a/snipet.rs
+++ b/snipet.rs
@@ -17,14 +17,13 @@ where
pub type Origin = RawOrigin;
#[pallet::config]
-pub trait Config {
- type Origin: Into<Result<crate::RawOrigin, <Self as crate::Config>::Origin>>;
+pub trait Config where Self::Origin: Into<Result<RawOrigin, OuterOrigin> {
}
#[pallet::call]
-impl<T: Config> Pallet<T> {
+impl<T: Config> Pallet<T> where T::Origin: Into<Result<RawOrigin, OuterOrigin> {
fn transact(origin: OriginFor<T>, other_parameters) {
- ensure_ethereum_transaction(origin)?; // This line would fail to compile because `Origin` is `frame_system::Config::Origin` and does not implement `Into<Result<crate::RawOrigin, _>>`.
+ ensure_ethereum_transaction(origin)?;
// other code
}
} |
Just a note on this. Setting where clause in |
In palletv2 macro code,
Origin
type passed to dispatchable is hard-coded toframe_system::pallet_prelude::OriginFor<T>
, which is always the system origin. This causes the pallet not able to use the origin it defined itself. This needs to be changed to use theT::Origin
type. Functions likepallet_collective::ensure_members
won't work before we fix this.Workaround is to use struct + trait definition and then import it in the top-level runtime, which from what I can see is how all current origin usages work.
blocks polkadot-evm/frontier#482
The text was updated successfully, but these errors were encountered: