Lido Token Reward Program (TRP) vesting contract discussion

Disclaimer
In this doc, we describe only tech specs and requirements for the vesting escrow smart contracts that might be used for Lido TRP in the future.
This doc has nothing to do with Lido TRP policy.

Abstract

To make Token Reward Program (TRP) vesting for the Lido DAO contributors transparent, accessible, and tax optimized, we need a smart contract(s) that will control all TRP vesting operations.

Stakeholders

  • Konstantin L - leadership
  • Vasily S - leadership
  • Eugene P - protocol
  • Eric H - legal
  • Adrian C - finance
  • Izzy - consultant

Stakeholders' requirements

TRP vesting contract should:

  • Handle vesting with cliff (ex. 1-year cliff + 4 years vesting) of multiple TRP packages for each contributor individually
  • Actual vesting params should be configurable at the start and immutable in the future
  • Allow tax-optimized withdrawals as an option.
    • Contributors can choose to use tax optimization or not.
    • Tax optimization should allow a contributor to prove that vested tokens do not belong to him/her until the withdrawal. One of the options is to add an admin method that will enable DAO to revoke all tokens from the vesting contract.
  • Allow contributor to obtain the currently available amount of the tokens awailable for claim
  • Allow delegation of the voting power of the tokens under vesting
  • Allow termination of the vesting in the case when the contributor terminates relations with DAO
  • Allow contributor to obtain all current vesting (in the case of Factory, there will be a new contract per each vesting)

Also, it is worth having TRP UI for contributors' comfort. TRP UI should:

  • Allow connecting wallet to:
    • View all vesting data. Locked tokens, vested tokens, cliff time, etc.
    • Claim vested tokens

Analysis

Possible caveats

  • Handling withdrawals from multiple TRP packets
  • Changing recipient address to withdraw tokens. Should we do it, or should we not?
  • Unblocking quantization (per month, per block, etc.). By default, it will be per block. We need to confirm with Legal that it works for us

Existing solutions to consider

Summary

Yearn vesting escrow seems to fit most of our needs. It already has the following:

  • Vesting
  • Cliff
  • View methods to obtain currently locked and vested amounts
  • Vesting termination mechanism with the withdrawal of unvested tokens (required for cases when contributor terminates relations with DAO)

What is missing:

  • Tax-optimized withdrawals
  • Voting delegation

Proposed solution

The solution is proposed based on the internal discussion with Protocol and Automation teams.

Contracts

Use Yearn vesting escrow as a base.

Proposed changes:

  • Rename rug_pull to revoke_unvested
  • Add a second type of vesting escrow with the revoke_all method that will allow DAO to withdraw all the funds from the escrow
  • Add a aragon_vote method for Aragon voting, a snapshot_set_delegate method for Snapshot voting delegation, and a delegate method for further voting power delegation with all available tokens on the contract's balance. Make these methods operate over upgradable middleware to encounter possible changes in voting interfaces
  • Refine events and existing methods

A detailed description of the contracts with proposed changes can be found here

UI

After contracts deployment, implement UI for contributors' comfort that will:

  • Suitable for upload on IPFS
  • Allow connecting wallet to:
    • Claim vested tokens
    • View all vesting data
      • Locked tokens
      • Vested tokens (available for claiming)
      • Overall vesting graph (time/vested) displaying all vesting periods with current DateTime point marked
      ​​​​​​​​  //  #Graph example#
      ​​​​​​​​  //
      ​​​​​​​​  //  available tokens
      ​​​​​​​​  //   |                                     _/------------
      ​​​​​​​​  //   |                                   _/
      ​​​​​​​​  //   |                                 _/
      ​​​​​​​​  //   |                               _/
      ​​​​​​​​  //   |                             _X - you are here
      ​​​​​​​​  //   |                           _/
      ​​​​​​​​  //   |                         _/
      ​​​​​​​​  //   |                        /
      ​​​​​​​​  //   |                      .|
      ​​​​​​​​  //   |                    .  |
      ​​​​​​​​  //   |                  .    |
      ​​​​​​​​  //   |                .      |
      ​​​​​​​​  //   +==============+========+==============+============---> time
      ​​​​​​​​  //        vesting start    cliff end      vesting end        
      

Note: Yearn contracts already have events for each new vesting deployed, so there is no need to implement the view method for all recipient vestings

Select a repo