1

I am looking to leverage the referendum track in a creative way by assigning the Medium Spender track ownership of an asset on Asset Hub.

In order to do this we need to find an address for the track. I know that DescribeFamily might be relevant.

The goal is to find a public key for the MediumSpender Origin to test this approach.

1 Answer 1

2

There is no correct answer to this question, but it is a very good one, because it highlights the (powerful) account abstractions that FRAME, Substrate and Polkadot give you out of the box.

An Origin in a FRAME-based runtime is by no means a 1-1 mapping to an account-id, and therefore, it need not necessarily have a public key associated with it. This applies to MediumSpender as well.

An origin is an abstract representation of the caller of a particular extrinsic, primarily meant to convey privilege. A normal transfer which starts with ensure_signed() is saying "anyone can access this, as long as they had signed a statement saying so".

In most cases and in most blockchains, that origin is a signed statement from a user, in which case we also call the extrinsic a transaction, but this is not necessarily the case in FRAME. FRAME allows you to describe an extrinsic that require abstract privilege levels, and are not directly link-able to an account-id.

The best example of this system's usage is onchain governance to upgrade the chain. We can imagine an extrinsic like such:

fn enact_upgrade(o: RuntimeOrigin, ...) {
    // Ensure `o` is representing 2/3 of the token holders in the system
} 

How can there be one account-id that is the public key of 2/3 of the token holders? This is very similar to the case for MediumSpender.

Then you might ask how the above extrinsic is ever called? The answer is that the runtime itself is in charge of constructing these abstract origins. In this case, an entire pallet could be dedicated to performing token-based voting, and when this pallet realizes that 2/3 of the token holders have approved an operation, it executes the above extrinsic, with the right origin type.

If you look at the (old) pallet-democracy code, it has a very clear example of this. Once this pallet is happy with a referendum, it will schedule it to execute using the frame_system::RawOrigin::Root. Again, frame_system::RawOrigin::Root is one origin option, but it is not callable by any signature, and the Runtime itself is deciding when to use it.

It is also worth looking at the code for pallet-sudo, which actually maps the Root origin to an account-id. This is useful for testing and permissioned blockchains.

This recent talk from Gavin Wood at ProtocolBerg describes this concept.


The RuntimeOrigin is the top level origin representation in a runtime. If you look at the expanded RuntimeOrigin of a runtime, it looks like this:

enum RuntimeOrigin {
  System(frame_system::Origin),
  OtherPallet(other_pallet::Origin),
  // more 
}

And in frame_system::Origin, one of the variants is Signed.

To take a step back, any extrinsic in FRAME takes a origin: RuntimeOrigin as the first argument, which is more or less the above type. And it can do any check it wishes based on the above RuntimeOrigin, and being Signed(_) is merely one of the many options.

This example is slightly over-simpliefied, as the pallet will not have access to the RuntimeOrigin as a concrete type. This is sensible, as a pallet does not know in which runtime it lives, and which other pallets are surrounding it. In practive, the first argument is an associated type that it uses as <T as frame_system::Config>::RuntimeOrigin, which is only known at the runtime level.

5
  • This is a very useful explanation of FRAME account abstractions, thank you for taking the time. If i can just describe my specific requirement i'm checking whether its possible currently to give for example MediumSpender the Issuer privilege of an asset on asset hub, so that mint can only happen through a referendum track. To mint requires let origin = ensure_signed(origin)?; which then has to be the issuer which must be AccountIdLookupOf<T>,... So i am wondering whether we can get the location of the MediumSpender and make it a AccountIdLookupOf<T> and make it pass as signed? Feb 10 at 18:30
  • And if not, is there any other way to do this where only the polkadot governance can execute the mint function but avoiding Root referendum which requires 100k DOT DD? i have asked this question here: substrate.stackexchange.com/questions/10988/… Feb 10 at 18:30
  • I see, the way pallet-assets is designed right now, it is not possible for it to permit this. Currently, the pallet permits any signed origin to initiate a mint, and later on checks that it matches a given account-id that is stored as a part of an asset. See here.
    – kianenigma
    Feb 12 at 9:01
  • You can represent "the entirety of Polkadot" on AH by assigning the Polkadot svreign account to be the minter in AH. Then, I suppose there is a way to let Polkadot send an XCM to AH with its sovereign account, if it is a mint operation (` Transact { call: pallet_asset::mint { .. } }`). But in general, there is no way to represent Polkadot's Medium Spender track on AH as an origin, as far as I know.
    – kianenigma
    Feb 12 at 9:09
  • I am/was thinking it could it possibly be convertable to an account id with LocationToAcccountId, similar to this test here: : github.com/paritytech/polkadot-sdk/blob/master/cumulus/… Feb 12 at 14:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.