This is actually very easy with Substrate.
You simply pass Pays::No to the weight of the function.
Like so:
#[weight = (100_000, DispatchClass::Normal, Pays::No)]
Here the tuple describes:
- The weight of the function. You should put a real value here to represent how complex this function is for your blockhain's computation.
- The
DispatchClass of this function. The default choice is Normal
- The
Pays option which determines if the caller will pay a fee or not.
Note that if you create an extrinsic that a user does not pay any fees, your blockchain is immediately vulnerable to DDOS attacks, as any user could spam this function at no cost.
You will need to build other layers of verification at your blockchain to make sure only valid calls to this function are propagated to other nodes.
Take a look here:
https://github.com/paritytech/polkadot/blob/master/runtime/common/src/claims.rs#L386
In this case, we have some statement which we verify is correctly signed by the user making the call before the call is passed to other nodes:
https://github.com/paritytech/polkadot/blob/master/runtime/common/src/claims.rs#L592
So you must do the same if you want your blockchain to be safe with a free function like this.