Skip to content

Transcoder withdrawal address #4

@yondonfu

Description

@yondonfu

At the moment, transcoders use a single address for the following purposes:

  • As the on-chain identifier for the transcoder
  • The associated private key signs transactions to invoke contract functions such as BondingManager.reward(), JobsManager.claimWork() and JobsManger.verify() that validate that the sender address is the transcoder's identifier address
  • As the withdrawal address for any LPT earned as rewards and ETH earned as fees

Transcoders can instead use one address as their identifier address (so that contract functions can validate that the transcoder is the sender) and use one address as their withdrawal address.

There are a number of benefits that come with allowing a transcoder to specify a withdrawal address that is distinct from its identifier address

  • The associated private key for the identifier address can be "hot" and the associated private key for the withdrawal address can be "cold". The hot key can hold just enough ETH to submit transactions associated with being an active transcoder and be actively used to sign transactions by an automatic process. The cold key can hold larger amounts of ETH/LPT and can be secured by a hardware wallet since it does not need to be actively used. Note: it will nonetheless be crucial for a transcoder node operator to properly secure the hot key since a compromised hot key can allow an attacker to cause the transcoder node operator to be slashed. However, with this hot key and cold key setup, any of the transcoder node operator's withdrawn ETH/LPT or reserve funds will be safe in the event of a compromised hot key
  • The withdrawal address can be associated with a contract that specifies rules for the use of withdrawn ETH/LPT
    • The contract could be a 2-of-3 multisig wallet - 3 parties could agree to be joint owners of a
      transcoder node and designate one party to be the transcoder node operator with any earnings
      generated being transferred into this multisig wallet. Multisig wallet funds could then be spent if 2 of 3
      parties agree.
    • The contract could be an Aragon DAO - a group of community members
      could agree to be members of the DAO which owns the transcoder node and designate one party to be the transcoder node operator with any earnings being transferred into the DAO. An initial
      implementation of the DAO might use a simple voting application to allow community members to
      authorize the use of DAO funds. The DAO could be upgraded to use alternative applications such as
      liquid democracy to govern the use of DAO funds
    • The contract could define payout logic for a staking service such as 1Protocol

From an implementation point of view this would require an additional withdrawalAddress in the transcoder struct in the BondingManager contract. This value of withdrawalAddress could be specified when invoking the BondingManager.transcoder() function. (One note here is that the BondingManager.transcoder() would become even more overloaded in this case because it is used not only to register as a transcoder, but also for changing rates and now setting a withdrawal address. It might be worth splitting up the function into two separate functions, one for registering with a withdrawal address and one for setting rates).

BondingManager.withdrawStake() would check if the sender has a withdrawalAddress as a transcoder - if so, the function will ask the Minter to transfer LPT rewards to withdrawalAddress, if not the function will ask the Minter to transfer LPT rewards to the sender address. BondingManager.withdrawFees() would work similarly.

BondingManager is delegate proxied meaning any changes during an upgrade will have to be storage layout compatible. At the moment, the addition of withdrawalAddress to the transcoder struct should be acceptable because the transcoder struct is only used in a mapping and not in any arrays and we would be adding an additional storage variable and not deleting or replacing any existing ones (we would need to make sure it comes after all existing variables in the transcoder struct!).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions