description |
---|
Juno's x/FeeShare module: Gas Fee Split for Contract Developers |
The FeeShare module was proposed in prop 51. If you’re a smart contract developer on Juno, you can now earn a cut of all gas fees generated on your contract.
If a transaction interacts with a smart contract, half of the transaction’s fees are set aside for any contract(s) a wallet has interacted with. The first 50% goes to delegators as usual (community pool), with the other 50% being split among each opted-in contract. This opt-in requirement is only for tax purposes, it is permission-less to do. You can opt-in and set the withdrawal contract to any other wallet, for example, a personal wallet, a DAO treasury, or a module account.
These fees are paid instantly to the withdraw wallet every block (6 seconds) as interactions take place.
{% hint style="info" %} At this time, sub messages are not applicable to feesharing due to possible abuse. The team is working to find a solution to this use case for a future version of the module. {% endhint %}
You can view latest specification in the Juno github. Here it describes how to register and update your contract. It also provides the details on queries, events, and different parameters which can be changed by Juno's governance system.
The junod tx feeshare register
command allows you to register the withdrawal address for a contract. This means that any interaction fees generated by the contract will be sent to the specified address.
To use this command, you need to specify the following parameters:
contract_bech32
: The bech32 address of the contract whose interaction fees will be shared.withdraw_bech32
: The bech32 address where the interaction fees will be sent every block.--from [key]
: The name or address of the key to sign the transaction.
The withdraw_bech32 parameter cannot be set to the community pool address because of an SDK limitation.
Only the contract's admin can use this command. If there's no admin, only the creator can use it.
{% hint style="info" %} junod tx feeshare register [contract] [withdraw] --from [your_address] --generate-only {% endhint %}
{
"@type": "/juno.feeshare.v1.MsgRegisterFeeShare",
"contract_address": "juno1d7yjapmwerm6qxaxtuyefmcns45x9x6d78gys9uhfsdpkfs4dxfssgw7ap",
"deployer_address": "juno10r39fueph9fq7a6lgswu4zdsg8t3gxlq670lt0",
"withdrawer_address": "juno1hj5fveer5cjtn4wd6wstzugjfdxzl0xps73ftl"
}
For contracts created or administered by a contract factory (contract instantiates contract), the withdrawal address can only be registered to itself (the instantiated child contract). This is useful for SubDAOs and public goods to save fees in the treasury / another wallet while still being owned by a contract. \
This can be a little confusing so here is the flow
User -> Factory -> instantiates child contract
-> Register Child to FeeShare CLI command to itself
-> In child contract, set an external address (via a contract manager saved in state)
-> Set a message to move funds from the child contract to external address OR manager
This requires you to set the withdraw address
- via instantiate
- or with a contract manmager who can then set the withdraw address to some account
(If the manager is a DAO, this is the best outcome. else they can withdraw anywhere)
*Manager is some address you save in the contract Config or state. This is entirely
internal for permissioned actions on the contract logic.
Example:
- Factory instantiates Contract A, where the creator and admin is Factory
- Anyone can now
junod tx feeshare register contract-a contract-a
- With this, all feeshare funds are saved in the contract-a balance
- To move these funds, your child contract needs a way to set a withdraw address. For example
ExecuteMsg::SetWithdrawAddress{address:juno123...}}
or do this on instantiate through the factory message payload. Just some other adderss we can withdraw the funds to - The child contract then has
ExecuteMsg::GetFeeShare{}
which takes the contracts balance minus any funds which are meant to be in the contract (ex: proposal deposits), and sends those tokens to thejuno123...
address set earlier
The junod tx feeshare update
command lets you update a contract's withdrawal address, so any interaction fees go to the new address. You must provide:
contract
: The address of the contract whose withdrawal address will be updated.new_withdraw_address
: The new bech32 address where the interaction fees will be sent every block.
Only the contract's admin or creator can use this command. It cannot be used if the contract was created or administered by another factory contract (like a DAO), and contracts cannot change their own withdrawal address directly. If ownership changes, the new owner can update the withdrawal address.
Where deployer_address is the contract admin (or creator if there is no admin), and withdrawal is the address you want funds to go to.
{% hint style="info" %} junod tx feeshare update [contract] [withdraw] --from [your_address] --generate-only {% endhint %}
{
"@type": "/juno.feeshare.v1.MsgUpdateFeeShare",
"contract_address": "contract",
"deployer_address": "your_address",
"withdrawer_address": "withdraw"
}
Juno's FeeShare module lets governance control the distribution of transaction fees to developers of contracts. Key actions include:
- Enable/Disable: Governance can turn the FeeShare module on/off, stopping fees from going to developers and preventing updates to contracts.
- Set Developer Shares: Governance can set the percentage of fees that developers receive, encouraging contract creation and maintenance. The default is 50%.
- Define Allowed Denominations: Governance can specify which coins are allowed for fees and paid to developers. Without any specifications, all fees are split among developers. Currently, only JUNO token is shared.
By managing fees, governance incentivizes developers to create and maintain high-quality contracts, increasing the network's value and attracting more users.