Skip to main content

Segments

Definition

A Dynamic stream is composed of multiple segments, which are separate partitions with different streaming amount and rates. The protocol uses these segments to enable custom streaming curves, which power exponential streams, cliff streams, etc.

Technically, a segment is a struct with three fields:

FieldTypeDescription
Amountuint128The amount of tokens to be streamed in this segment, denoted in units of the token's decimals.
ExponentUD2x18The exponent of this segment, denoted as a fixed-point number.
Timestampuint40The Unix timestamp indicating this segment's end.

Each segment has its own streaming function:

f(x)=xexpcsaf(x) = x^{exp} * csa

Therefore, the distribution function of a dynamic stream becomes:

f(x)=xexpcsa+Σ(esa)f(x) = x^{exp} * csa + \Sigma(esa)

Where:

  • xx is the elapsed time divided by the total time in the current segment.
  • expexp is the current segment exponent.
  • csacsa is the current segment amount.
  • Σ(esa)\Sigma(esa) is the sum of all elapsed segments' amounts.
info

Segments can be used to represent any monotonic increasing function.

caution

Because x is a percentage, the payment rate is inversely proportional to the exponent. For example, if the exponent is 0.5, the rate is quadratically faster compared to the baseline when the exponent is 1.

Conversely, if the exponent is 2, the rate is quadratically slower compared to baseline.

Requirements

Examples

A segment can be used to represent any monotonic increasing function. A few popular examples are highlighted below:

Constant Curve (exp = 0)

A constant segment follows the function f(x)=cf(x) = c. This is achieved with an exponent of 0.

LockupDynamic.Segment({
amount: amount, // Total amount in this segment
exponent: ud2x18(0e18), // Exponent = 0 (constant)
timestamp: endTime // End time of the segment
});

A constant curve can be used to unlock amount in tranches where the entire segment amount unlocks at the beginning or the end of the segment.

Linear Curve (exp = 1)

A linear segment follows the function f(x)=cxf(x) = cx. This is achieved with an exponent of 1.

LockupDynamic.Segment({
amount: amount, // Total amount in this segment
exponent: ud2x18(1e18), // Exponent = 1 (linear)
timestamp: endTime // End time of the segment
});

A linear curve unlocks amount linearly over time.

Accelerating Curve (exp > 1)

A function f(x)=cxexpexp>1f(x) = cx^{exp} \mid exp > 1 can be used to create a segment that unlocks slowly at the beginning and then quickly at the end.

For example, an exponent of 2 unlocks 25% of the segment amount in the first 50% of the time and the remaining 75% in the last 50% of the time.

segments[0] = LockupDynamic.Segment({
amount: totalAmount, // Total amount in this segment
exponent: ud2x18(2e18), // Exponent = 2 (Quadratic)
timestamp: endTime // End time of the stream
});

As you may have realized, the higher the exponent, the steeper the curve gets at the end. For example, an exponent of 4 unlocks 6% of the segment amount in the first 50% of the time and the remaining 94% in the last 50% of the time.

Decelerating Curve (exp < 1)

A function f(x)=cxexp0<exp<1f(x) = cx^{exp} \mid 0 < exp < 1 can be used to create a segment that unlocks quickly at the beginning and then slowly at the end.

For example, an exponent of 0.2 unlocks 80% of the segment amount in the first 50% of the time and the remaining 20% in the last 50% of the time.

segments[0] = LockupDynamic.Segment({
amount: totalAmount, // Total amount in this segment
exponent: ud2x18(0.3e18), // Exponent = 0.3
timestamp: endTime // End time of the stream
});