Name: Continuous payment of fees
Category: Protocol
Status: Draft - Rejected
Scope: Allow Darknode operators to collect fees second-by-second without needing to submit Ethereum transactions.
Overview
This proposal introduces the Operator Fee Token (OFT). This token is automatically paid to operators per-Darknode per-block. For example, if an operator owns 10 Darknodes, then the operator will receive 10 OFT tokens per block. OFT tokens can be burned for a proportional share of redeemable fees. For example, burning 1% of the OFT supply entitles you to 1% of the redeemable fees.
Fees are paid to a non-redeemable pool. Every block, 0.0002865% of the non-redeemable pool is moved to the redeemable pool. Assuming Ethereum blocks are ~10 seconds, this equals a total payout of ~50% per epoch (the same as it is right now). At any point, Darknode operators are able to burn some or all of their OFT and redeem their share of the redeemable pool.
Background
Right now, Darknode operators collect fees in discrete intervals through a process called “claiming”. Fees are paid to the Darknode Payment contract on Ethereum and at the end of the epoch 50% of the fees in that contract can be claimed by Darknode operators. However, for the claim to happen, each Darknode must explicitly submit an Ethereum transaction to call the claim
function on the Darknode Payment contract.
There are several drawbacks to this approach:
- Darknode operators must wait until the end of the epoch before fees are accessible. This creates opportunity loss, where Darknode operators are unable to utilise fees for an entire epoch.
- Darknode operators are bound to receive the fees. This means that the operators are unable to delegate fee collection to other addresses (for example, one could imagine that it would be desirable for an operator to automatically delegate their collected fees to a contract).
- Darknode operators must spend ETH so that their Darknodes are able to call the
claim
function. In the latest epoch, each Darknode had to spend just under $7 USD toclaim
. This essentially doubles the operating costs of a Darknode, and requires regular attention from the operator. - In the future, we want to be able to compute fees on RenVM instead of on the minting chain (e.g. Ethereum). The use of an explicit Darknode Payment contract, bound to pay fees to an exact address (the operator), does not make for a smooth transition away from Ethereum.
- Darknodes need to claim fees every epoch. This puts restrictions on how often epochs can happen. Having 24 hour epochs would cause Darknode operators to spend $6 per day per node (which is clearly unacceptable). See RFC-000-001: Continuous payment of fees.
Details
The OFT will be an ERC20 with some unique implementation details:
-
No explicit
mint
function. - OFT has a special
balance_of
implementation that deviates from the norm:
This will result in thedef balance_of(addr): return balances[addr] + (now - updated_at[addr]) * num_nodes[addr]
balance_of
function returning different values even when no transfer are made. However, this will only be observed for operator addresses. All other addresses remain unaffected, becausenum_nodes[addr]
would be zero. - OFT transfers must do
balance[addr] = balance_of(addr)
before running the usual transfer logic, for both the sender and receiver, and must setupdated_at[addr]
to the current block for both the sender and receive. - Darknode being de/registered must update
num_nodes[addr]
whereaddr
is the address of the operator. The same transaction must also setbalance[addr] = balance_of(addr)
and setupdated_at[addr]
to the current block.
The FeePool will be the contract that receive all fees from the Gateways (all Gateways for all renTokens will send their fees to the same FeePool contract).
- There will be a
redeem
function that burns the OFT out of existence in exchange for a share of the redeemable fees. This function also updates the redeemable fee amounts. Some pseudo code:def redeem(amount, to): OFT.transferFrom(msg.sender, this, amount) for token in renTokens: redeemable[token] += (token.balance_of(this) - redeemable[token]) * pow(1 + rate, now - updated_at) update_at = now for token in renTokens: token.transfer(to, redeemable[token] * amount / OFT.total_supply())
- The
rate
variable in the FeePool should be subject to governance by RenVM. Initially, the value will be set to 0.0002865% per block so that the payout rate of the FeePool matches the current payment mechanism (50% every 4 weeks).
As is seen in the pseudo-code for the FeePool redeem
function; gas is spent withdrawing every token every time OFT is burned. While this approach might be an acceptable overhead, an alternative is to have a different OFT for every available token that fees can be earned in. See RFC-000-001: Continuous payment of fees.
Implementation
- Develop, test, and audit the OFT contract.
- Develop, test, and audit the FeePool contract.
- Upgrade the Gateway contract to mint fees to the FeePool.