Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Make extrinsics executed as sudo require 0 fees #6657

Closed
lovesh opened this issue Jul 14, 2020 · 9 comments · Fixed by #6749
Closed

Make extrinsics executed as sudo require 0 fees #6657

lovesh opened this issue Jul 14, 2020 · 9 comments · Fixed by #6749
Labels
Z7-question Issue is a question. Closer should answer.

Comments

@lovesh
Copy link
Contributor

lovesh commented Jul 14, 2020

I want to make some extrinsics require 0 fees, these are required to be sent by sudo. For non-sudo extrinsics, I can annotate the extrinsic with #[weight = (0, Pays::No)] and it works. But with sudo, I see the extrinsic call is wrapped with sudo pallet'ssudo dispatchable which itself has non-zero weight and thus the extrinsic ends up having weight. I tried using the sudo pallet's sudo_unchecked_weight and pass 0 weight but still the extrinsic will have some fee due to the length, base fee, etc
My understanding of the weight annotations of the sudo pallet's extrinsics like

#[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)]
fn sudo(origin, call: Box<<T as Trait>::Call>) {

is that the sudo will inherit the DispatchClass of the actual call (from my pallet) being made through get_dispatch_info().class. If it was inheriting the Pays enum as well like this

#[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class, call.get_dispatch_info().pays_fee)]
fn sudo(origin, call: Box<<T as Trait>::Call>) {

then annotating my pallet's extrinsic with Pays::No will work. Is that correct?

Is there another way of achieving my objective?

@github-actions github-actions bot added the J2-unconfirmed Issue might be valid, but it’s not yet known. label Jul 14, 2020
@shawntabrizi
Copy link
Member

shawntabrizi commented Jul 15, 2020

You should simply write your own Sudo pallet which has no fees. Should be very straight forward, probably just copy and paste the code and add the Pays::No annotation you mentioned above.

You will also need to add additional logic that verifies transactions to this pallet before they are propagated to the network. If an extrinsic has zero fees, that means that even "bad calls" to the extrinsic will have zero fees. Imagine I am not the sudo user, and I call the sudo function a million times, each time it tells me "sorry you dont have access", but I fill the block with these txs, I fill the network with propagating these tx, etc..

You need to create a signed extension that does the sudo account verification in the tx queue. Here is an example of such a check in Polkadot for claims, where we also allow a zero fee tx: https://github.com/paritytech/polkadot/blob/master/runtime/common/src/claims.rs#L541

Note you should still keep the Weight information the same. Weight information is used to determine how full your block is, which is important for chains that have a fixed block time.

@shawntabrizi shawntabrizi added Z7-question Issue is a question. Closer should answer. and removed J2-unconfirmed Issue might be valid, but it’s not yet known. labels Jul 15, 2020
@lovesh
Copy link
Contributor Author

lovesh commented Jul 15, 2020

@shawntabrizi Thanks for the reply. So it doesn't help just to have Pays:No in the annotation since anyone can spam the network with like you mentioned and SignedExtension is the way to go. Pays:No is only useful when the extrinsic does no further checks (auth or others) during dispatch that can fail. I had another case where I wanted to make some transactions free only when they were called by certain accounts and reject otherwise (in dispatch) and I was planning to use Pays:No but now I see that SignedExtension should be used.

Note you should still keep the Weight information the same. Weight information is used to determine how full your block is, which is important for chains that have a fixed block time.

I had not realized that. Thanks for pointing out.

@shawntabrizi
Copy link
Member

@lovesh you need both Pays::No + Signed Extension. Not just one. But yes, you seem to understand well the issue 👍

@lovesh
Copy link
Contributor Author

lovesh commented Jul 15, 2020

@shawntabrizi Yes, as you saw, I raised the PR for sudo pallet supporting Pays::No and I will add the SignedExtension to my code.

@lovesh
Copy link
Contributor Author

lovesh commented Jul 15, 2020

@shawntabrizi I understand your comment in the PR that the change could potentially cause spam. Assuming I don't take the Pays:No approach (not forking sudo pallet), does refunding the fees to sudo in the post_dispatch of my SignedExtension makes sense? I haven't tried it yet but I think if I calculate the fee as in transaction-payment pallet's post_dispatch and refund the fees to sudo.

@shawntabrizi
Copy link
Member

shawntabrizi commented Jul 15, 2020

Refunding the fees should work. Also shouldnt be that hard to calculate. The main different here is that a user must have at least enough fees to initially be able to pay the transaction, versus something truly feeless would allow any user, even one with zero balance, to submit the tx.

I think though in general this behavior is strange from a philosophical standpoint. The Sudo user can call balances pallet and mint as much money as they like whenever they want.

Giving them "zero fees" doesn't really accomplish much, and implies to me you might be looking to use sudo in ways it wasnt intended. I really think the solution here is to design your own pallet which builds the correct layers of functionality you need for your scenario, including access to Root dispatch, zero fees, etc...

@shawntabrizi
Copy link
Member

@lovesh Actually there might be a good solution we can implement in Substrate directly. Let me get back to you on this thread once I know more! Feel free to ping me on riot if you want to chat.

@lovesh
Copy link
Contributor Author

lovesh commented Jul 15, 2020

@shawntabrizi

Refunding the fees should work. Also shouldnt be that hard to calculate. The main different here is that a user must have at least enough fees to initially be able to pay the transaction, versus something truly feeless would allow any user, even one with zero balance, to submit the tx.

That does work or me as sudo ends up with the same balance as before.

I think though in general this behavior is strange from a philosophical standpoint. The Sudo user can call balances pallet and mint as much money as they like whenever they want.

I agree, this seems a contrived use-case and in practice might not matter that much. The arbitrary minting has more manual effort (see how much I paid and then mint).

I really think the solution here is to design your own pallet which builds the correct layers of functionality you need for your scenario, including access to Root dispatch, zero fees, etc...

Lets see if I understand. Say I have an extrinsic foo that i want to call as sudo for free. I should have a separate extrinisic say call_foo_as_sudo which is annotated as Pays:No and is only callable by certain account(s). The authorization of caller of call_foo_as_sudo is done in a SignedExtrinsic to prevent spam and call_foo_as_sudo calls foo with origin as RawOrigin::Root?

Will ping you in Riot

@bkchr
Copy link
Member

bkchr commented Jul 26, 2020

Can this be closed?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Z7-question Issue is a question. Closer should answer.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants