Skip to main content

Distribution Pools

In this page we will explain Distribution Pools and show you the most relevant ways to interact with them through the Super Token interface. To do this, we will go through some key concepts, and show you how to leverage Superfluid's SuperTokenV1Library.sol for your Distribution Pools smart contracts.

About SuperTokenV1Library.sol

The SuperTokenV1Library.sol is a comprehensive library that enables interactions with all of the Superfluid components (including Pools) through the SuperToken interface.

About the General Distributions Agreement - GDA

At times, we use "Distribution Pools" or the "General Distributions Agreement (GDA)" interchangeably due to "GDA" being the name of the implementation in our codebase.

What is a Pool?

A pool is a smart contract that facilitates the distribution of tokens to multiple members, managed by a pool admin. Members hold units within the pool that determine their proportion of the distribution.

A visualization of units in a pool

note

The Superfluid pool implements basic ERC20 functionality, allowing it to interact seamlessly with ERC20 standards. This allows you to interact with the pool units as if they were ERC20 tokens, including transferring them to other addresses, if it is allowed by the pool configuration. Check the next section for more information on pool configurations.

About Member Units

How is a member's share of the pool determined?

A pool member's units determine their share of the pool's distributions. In the background, the calculation of each member's share is calculated following these two steps:

  1. Calculating the flow rate per unit: We calculate the flow rate or amount of tokens to be distributed per unit like so:
Superfluid with people

  1. Calculating the flow rate for each member: We multiply the flow rate per unit by the number of units each member has to get the flow rate for each member, as follows:
Superfluid with people

One of the limitations of Solidity is its incapacity to handle floating point numbers. This makes it so that the flow rate per unit is calculated as an integer. If the result of the division is not an integer, the result is rounded down.

Examples

The examples below show how the flow rate per unit is calculated in different scenarios where Distributions reach their limitations

  1. Example 1: Let's take a pool that has 100 wei/second as total flow rate and 3 members, each member has 1 unit.
    • The flow rate per unit is 100 / 3 = 33.33
    • However, since Solidity can't handle floating point numbers, the flow rate per unit is 33
    • The pool distributes 33 tokens to each unit
    • 1 token is left undistributed
  2. Example 2: Let's take a pool that has 100 wei/second as total flow rate and 200 members, each member has 1 units.
    • The flow rate per unit is 100 / 200 = 0.5
    • However, since Solidity can't handle floating point numbers, the flow rate per unit is 0
    • The pool distributes 0 tokens to each unit
    • 200 tokens are left undistributed

These examples are extreme and almost never happen in practice. However, it is important to be aware of these limitations when designing your pools.

How to design your pools?

The best way to design your pools is to make sure that the total flow rate or the tokens distributed are always orders of magnitude higher than the number of total units in the pool. This way, you can be sure that the flow rate per unit will always be significantly higher than 0 and that all members will receive a share of the distribution.

Important Functions

Here are some of the most important functions provided by SuperTokenV1Library.sol for interacting with Superfluid pools:

Reminder

These functions are meant to be called from contracts that import SuperTokenV1Library.sol and are not directly accessible as external calls on the blockchain.

createPool

function createPool(ISuperToken token, address admin, PoolConfig memory poolConfig)

Creates a new pool with the specified admin, configuration and poolConfig.

The PoolConfig struct is defined as follows:

struct PoolConfig {
bool transferabilityForUnitsOwner;
bool distributionFromAnyAddress;
}
  • transferabilityForUnitsOwner: If true, the pool members can transfer their owned units, else, only the pool admin can manipulate the units for pool members
  • distributionFromAnyAddress: If true, anyone can execute distributions via the pool, else, only the pool admin can execute distributions via the pool

updateMemberUnits

function updateMemberUnits(ISuperToken token, ISuperfluidPool pool, address memberAddress, uint128 newUnits)

Updates the number of units a member has within a pool, effectively changing their share of future distributions.

Important

Keep in mind that the total amount of units in the pool needs to be significantly lower than the total flow rate or the total tokens distributed of the pool. To understand more why this is the case, please refer to the Member Units section.

claimAll

function claimAll(ISuperToken token, ISuperfluidPool pool, address memberAddress)

Allows a member to claim their share of the tokens from all previous distributions.

connectPool

function connectPool(ISuperToken token, ISuperfluidPool pool)

Connects a pool member to a pool.

About pool connections

The pool member needs to connect to a pool before the distribution balance is reflected in their net balance. If the distribution starts before the user is connected to the pool, the user will still receive the tokens when they connect to the pool eventually.

disconnectPool

function disconnectPool(ISuperToken token, ISuperfluidPool pool)

Disconnects a pool member from a pool.

distributeToPool

function distributeToPool(ISuperToken token, address from, ISuperfluidPool pool, uint256 requestedAmount)

Distributes a specified amount of tokens to the pool, to be shared among members according to their units.

Example Usage

Here's how you might use these functions within a smart contract to set up and manage a pool:

// Assume ISuperToken and SuperfluidPool interfaces are imported and available.

contract MyPool {
Using SuperTokenV1Library for ISuperToken;
ISuperToken private superToken;
ISuperfluidPool private pool;
PoolConfig private poolConfig = PoolConfig({
transferabilityForUnitsOwner: true,
distributionFromAnyAddress: true
});

constructor(ISuperToken _superToken) {
superToken = _superToken;
pool = superToken.createPool(address(this), poolConfig);
}

// Use updateMemberUnits to assign units to a member
function updateMemberUnits(address member, uint128 units) public {
superToken.updateMemberUnits(pool, member, units);
}

function distribute(uint256 amount) public {
superToken.distributeToPool(address(this), pool, amount);
}

function distributeFlow(int96 flowRate) public {
superToken.distributeFlow(address(this), pool, flowRate);
}
}

In this example, MyPool creates a pool, adds a member, and makes an Instant Distribution (discreet transfer - through distribute) and a Streaming Distribution (continuous flow - through distributeFlow) using the functions from SuperTokenV1Library.sol.

Learn more about the SuperTokenV1Library

For more detailed information on the implementation and usage of SuperTokenV1Library.sol, refer to the Technical Reference.