Skip to content

General Distribution Agreement

Miao ZhiCheng edited this page Oct 4, 2023 · 19 revisions

Overview

GDA (General Distribution Agreement) generalizes the Instant Distribution Agreement by offering many-to-many constant flow distribution in addition to the one-to-many instant distribution.

GDA is implemented using the Superfluid agreement framework, however it does not currently provide callbacks unlike the IDA.

Implementation Guide

Usage of Semantic Money Library (Limited Functional Programming)

TODO miao

Code Structure

The code structure of the GDA deviates from the two existing agreements in that it leverages the TokenMonad abstract contract which leverages the Semantic Money Library (under packages/solidity-semantic-money).

SemanticMoney.sol: This is a library that contains the low-level building blocks of the Superfluid payment primitives. That is, the data structures and the pure functions that operate on them.

TokenMonad.sol: TokenMonad is an abstract contract that contains:

  • a set of virtual getter/setter functions to be implemented by the inheriting contract:
    • _getUIndex/_setUIndex
    • _getPDPIndex/_setPDPIndex
    • _getFlowRate
    • _setFlowInfo
    • _getPoolAdjustmentFlowRate/_setPoolAdjustmentFlowRate
  • the core logic for the different types of agreement operations:
    • _doShift (instant transfer)
    • _doFlow (1-to-1 flow)
    • _doDistributeViaPool (1-to-n instant transfer)
    • _doDistributeFlowViaPool (1-to-n flow)

The core logic functions utilize the SemanticMoney library and the virtual functions to enact side effects on the state of the inheriting contract.

GeneralDistributionAgreementV1.sol: The GDA contract inherits from ISuperAgreement (similar to the CFA and the IDA) and TokenMonad. This contract can be thought of as the interface between the TokenMonad/SemanticMoney library and the existing Superfluid protocol and therefore the end-user. It is the contract that is responsible for sanitizing input data as TokenMonad/SemanticMoney offloads this to the inheriting contract. It includes the following:

  • implementation of the virtual functions in TokenMonad.sol
  • the SuperfluidPool creation function
  • callAgreement wrapper functions for the core logic functions in TokenMonad.sol and some SuperfluidPool.sol functions
  • encoding/decoding of arbitrary data to/from SuperfluidToken storage similar to the CFA and IDA

SuperfluidPool.sol: The helper contract for GeneralDistributionAgreementV1 representing pools. To this contract, GDA is an "pool operator" (controlled by modifier onlyGDA). It uses beacon proxy for upgradability. There are also concepts such as pool admin and pool members.

Major Design Choices

Related to Superfluid Pool

The Superfluid Pool is a contract that is created via the GDA contract and enables the distribution of funds to N pool members, proportional to the pool units assigned to them. The admin of the pool can update the units of the pool members at any time, and distribute via the pool.

Happy Path Distribution

A happy path would look like:

  • Alice creates a new pool via the GDA and sets herself as the admin
  • Alice updates pool units for Bob (100 for Bob) and Carol (200 for Carol)
  • Bob decides to connect to this pool (in the IDA, the corresponding concept would be approve subscription)
  • Dan instantly distributes 300 POOLx tokens to the pool
  • Bob now has 100 POOLx tokens
  • Carol has 200 claimable POOLx tokens, she claims and now has 200 POOLx tokens

NOTE: This example showed an instant distribution. A flow distribution would look the same, the only difference being that instead of defining an amount to be distributed (here: 300 POOLx), Dan would define a flowrate to be distributed (e.g. 300 POOLx/day). The recipients (here: Bob and Carol) would then receive proportions of that flow, with the flow rate being proportional to the units assigned to them

Separation of Superfluid Pool

In the IDA, every index is embedded in the storage of the SuperfluidToken it's created for via createIndex.
In the GDA, every index is contained in a dedicated SuperfluidPool contract which is created by invoking createPool.
In the IDA, the index creator aka published is the only one who can distribute tokens via that index.
In the GDA, anybody can distribute tokens via a pool (if allowed by the pool admin).
Since the index data structure in SuperfluidPool is a mapping from addresses to uints, it's suited to implement the ERC20 interface. The SuperfluidPool contains a function for the pool admin to update member units (essentially mint and burn in one, if viewed through the lens of a token interface) and for disconnected pool members to claim any tokens which have been distributed and are unclaimed.

Many-to-many Distribution Support

A SuperfluidPool can be configured to only allow the admin of the pool to distribute (1-to-N), see the PoolConfig struct in IGeneralDistributionAgreementV1.sol.
If permission to distribute isn't restricted to the admin only, the GDA essentially allows many-to-many instant and flowing distributions, something not supported by the IDA.

Superfluid Pool is Token-Specific

Similar to how Indexes work in the IDA, the SuperfluidPool in the GDA is token-specific. That is, a SuperfluidPool can only distribute tokens specified at creation time: createPool(ISuperfluidToken token, address admin, PoolConfig memory config).

Lack-of Cascading Superfluid Pool Support

Edge case:

  • Generally, there exist a nanny-rule that one cannot update units of pool A for another existing pool. However, one can still create some units of pool A for pool B before the pool B is created.

Solvency Mechanism

Limits of 3P Support

The patrician period is defined as a proportion of the cumulated deposit of an account being consumed.
With that deposit now potentially being split between 2 agreements (CFA and GDA), the calculation made in the liquidation case in order to assign rewards, gives a result specific for that agreement.

Misc

Adjustment Flow

(miao)

Lack-of Callback Support

(miao)

References

Clone this wiki locally