# Fees and Metering
Note: We recently started charging fees for using Zoe. The design is still on-going and the following details may change.
Fees are charged in RUN, our stable local currency. These are the Zoe methods that charge fees:
install()
startInstance()
offer()
getPublicFacet()
The specific amount charged for each method can be queried with
E(zoe).getConfiguration()
, which returns a promise for an object. On
that object, the zoeFeesConfig
property gives the fee values in the
smallest unit of RUN.
(The unit of RUN displayed in the wallet and in dapps is
10^decimalPlaces
, usually 10^6).
An example of zoeFeesConfig
:
zoeFeesConfig: {
getPublicFacetFee: 50n,
installFee: 65000n,
startInstanceFee: 5000000n,
offerFee: 65000n,
timeAuthority: chainTimerServiceP,
lowFee: 500000n,
highFee: 5000000n,
shortExp: 300000n,
longExp: 86400000n,
},
Note: the n
is appended to the end of the integer literal to make a
bigint. Bigints are used for arbitrarily large values and therefore
are much safer
than integers.
# Paying Fees and Fee Purses
In order to pay fees, you must create a fee purse. An empty fee purse can be
created by calling E(zoe).makeFeePurse()
. For users on the
testnet/devnet/local development, a fee purse has been created for you
already, and is in your wallet.
A fee purse can be charged in two ways. It can be passed directly to a Zoe method as the last argument, or it can be "bound" to Zoe such that any call made using the returned Zoe will charge the fee purse, without needing to pass it in.
To bind a fee purse to Zoe, call:
const myZoe = E(zoe).bindDefaultFeePurse(feePurse);
Fees must be paid in RUN, so please make sure that your fee purse has a balance of RUN that is sufficient for paying fees.
# Metering and Paying for Execution
Fees are used to pay for the ongoing execution of contract code.
Specifically, the fee purse that the contract owner uses when calling
E(zoe).startInstance
will be charged ongoing fees for chunks of execution.
Execution is measured in computrons
at the JavaScript engine level
(we use XS (opens new window)),
and Zoe charges a fee per computron. Zoe uses a kernel-level
concept called a meter
to keep records of how many computrons have
been paid for, and how many have been used up. When execution uses up
the paid-for computrons, Zoe refills the
meter with computrons by charging a fee to the fee purse.
Contract owners must add RUN to their fee purse on a regular basis to pay for the ongoing execution. The next section explains how contract owners can transfer some of the costs to users.
# Charging Users of Your Contract
To recoup the costs of execution, you can use Zoe to charge your users fees. To do so, when making an invitation in contract code, you can specify a fee in relative terms. For example, in the AMM, the SwapIn invitation specifies a low fee and a short expiry:
const makeSwapInInvitation = () =>
zcf.makeInvitation(
swapIn,
'autoswap swapIn',
undefined,
LOW_FEE,
SHORT_EXP,
);
LOW_FEE
is a constant understood by Zoe. It will be translated by
Zoe from a relative description into an amount of RUN, such that the
invitation that a user receives has the additional details where fee
is an amount of RUN and expiry
is a timestamp:
{ fee, expiry, zoeTimeAuthority }
The relative fee specified by contract code can be either LOW_FEE or HIGH_FEE, and the expiry can be SHORT_EXP or LONG_EXP.
The translation from relative fees and expiries to absolute fees and
expiries can be altered when Zoe is created by changing lowFee
,
highFee
, shortExp
, and longExp
in zoeFeesConfig
.
When a user makes an offer, Zoe checks whether the expiry
in the
invitation has passed and then charges the fee specified in the invitation. This fee,
unlike the other fees, is deposited directly into the feePurse for the
contract owner. This makes it easier for the contract owner to
guarantee that they can pay for the execution of their contract.
# Troubleshooting
If you are experiencing problems running dapps, please make sure your fee purse has enough RUN to pay fees.