RFC-000-001: Continuous payment of fees

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:

  1. 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.
  2. 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).
  3. 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 to claim. This essentially doubles the operating costs of a Darknode, and requires regular attention from the operator.
  4. 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.
  5. 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:
    def balance_of(addr):
      return balances[addr] + (now - updated_at[addr]) * num_nodes[addr]
    
    This will result in the 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, because num_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 set updated_at[addr] to the current block for both the sender and receive.
  • Darknode being de/registered must update num_nodes[addr] where addr is the address of the operator. The same transaction must also set balance[addr] = balance_of(addr) and set updated_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

  1. Develop, test, and audit the OFT contract.
  2. Develop, test, and audit the FeePool contract.
  3. Upgrade the Gateway contract to mint fees to the FeePool.
17 Likes