# ZivoeYDL.sol

## Introduction

This contract manages the accounting for distributing yield across multiple contracts.

This contract has the following responsibilities:

* Escrows yield in between distribution periods.
* Manages accounting for yield distribution.
* Supports modification of certain state variables for governance purposes.
* Tracks historical values using EMA (exponential moving average) on 30-day basis.

{% embed url="<https://www.figma.com/board/qjuQ0uGQl9QD7KeBwyf73d/Zivoe-Visualization?node-id=207-547&t=qclDyOdCku2fPByD-4>" %}

#### State Variables

<table><thead><tr><th width="194.33333333333331">Type</th><th width="179">Name</th><th>Description</th></tr></thead><tbody><tr><td><a data-mention href="#recipients">#recipients</a></td><td>protocolRecipients</td><td>Tracks the distributions for protocol earnings.</td></tr><tr><td><a data-mention href="#recipients">#recipients</a></td><td>residualRecipients</td><td>Tracks the distributions for residual earnings.</td></tr><tr><td>address</td><td>GBL</td><td>The ZivoeGlobals contract.</td></tr><tr><td>address</td><td>distributedAsset</td><td>The "stablecoin" that will be distributed via YDL.</td></tr><tr><td>uint256</td><td>emaSTT</td><td>Weighted moving average for senior tranche size, a.k.a. zSTT.totalSupply().</td></tr><tr><td>uint256</td><td>emaJTT</td><td>Weighted moving average for junior tranche size, a.k.a. zJTT.totalSupply().</td></tr><tr><td>uint256</td><td>distributionCounter</td><td>Number of calls to distributeYield().</td></tr><tr><td>uint256</td><td>lastDistribution</td><td>Used for timelock constraint to call distributeYield().</td></tr><tr><td>uint256</td><td>targetAPYBIPS</td><td>The target annualized yield for senior tranche.</td></tr><tr><td>uint256</td><td>targetRatioBIPS</td><td>The target ratio of junior to senior tranche.</td></tr><tr><td>uint256</td><td>protocolEarningsRateBIPS</td><td>The protocol earnings rate.</td></tr><tr><td>uint256</td><td>daysBetweenDistributions</td><td>Number of days between yield distributions.</td></tr><tr><td>uint256</td><td>retrospectiveDistributions</td><td>Retrospective moving average period.</td></tr><tr><td>bool</td><td>unlocked</td><td>Prevents contract from supporting functionality until unlocked.</td></tr><tr><td>uint256</td><td>BIPS</td><td>Private constant, <code>10000</code></td></tr><tr><td>uint256</td><td>RAY</td><td>Private constant, <code>10**27</code></td></tr><tr><td><a data-mention href="zivoemath.sol">zivoemath.sol</a></td><td>MATH</td><td>Refers to the ZivoeMath contract,</td></tr></tbody></table>

#### `Recipients`

This struct stores information for distributions of yield (used for earnings and residual).

<table><thead><tr><th width="145.33333333333331">Type</th><th width="168">Name</th><th>Description</th></tr></thead><tbody><tr><td>address[]</td><td>recipients</td><td>An array of addresses that will benefit from protocol earnings.</td></tr><tr><td>uint256[]</td><td>proportion</td><td>An array of weights in BIPS for each specific recipient above.</td></tr></tbody></table>

## **Sections**

[#read-functions](#read-functions "mention")

* [#earningstrancheuse](#earningstrancheuse "mention") - Calculates the distribution of yield ("earnings") for the four primary groups.
* [#viewdistributions](#viewdistributions "mention") - View distribution information for protocol and residual earnings recipients.

[#write-functions](#write-functions "mention")

* [#distributeyield](#distributeyield "mention") - Distributes available yield within this contract to appropriate entities.
* [#returnasset](#returnasset "mention") - Returns an asset to DAO if not `distributedAsset()`.
* [#unlock](#unlock "mention") - Unlocks this contract for distributions, initializes values.
* [#updatedistributedasset](#updatedistributedasset "mention") - Updates the distributed asset for this particular contract.
* [#updateprotocolearningsratebips](#updateprotocolearningsratebips "mention") - Updates the state variable "protocolEarningsRateBIPS".
* [#updaterecipients](#updaterecipients "mention") - Updates the protocolRecipients or residualRecipients.
* [#updatetargetapybips](#updatetargetapybips "mention") - Updates the state variable "targetAPYBIPS".
* [#updatetargetratiobips](#updatetargetratiobips "mention") - Updates the state variable "targetRatioBIPS".

[#events](#events "mention")

* [#assetreturned](#assetreturned "mention")
* [#updateddistributedasset](#updateddistributedasset "mention")
* [#updatedprotocolearningsratebips](#updatedprotocolearningsratebips "mention")
* [#updatedprotocolrecipients](#updatedprotocolrecipients "mention")
* [#updatedresidualrecipients](#updatedresidualrecipients "mention")
* [#updatedtargetapybips](#updatedtargetapybips "mention")
* [#updatedtargetratiobips](#updatedtargetratiobips "mention")
* [#yielddistributed](#yielddistributed "mention")
* [#yielddistributedsingle](#yielddistributedsingle "mention")

## Read Functions

#### `earningsTrancheuse()`

Calculates the distribution of yield ("earnings") for the four primary groups.

```solidity
function earningsTrancheuse(
    uint256 yP, 
    uint256 yD
) public view returns (
    uint256[] memory protocol, 
    uint256 senior, 
    uint256 junior, 
    uint256[] memory residual
);
```

<table><thead><tr><th width="156.33333333333331">Type</th><th width="176">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>yP</td><td>Yield for the protocol.</td></tr><tr><td>uint256</td><td>yD</td><td>Yield for the remaining three groups.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="160.33333333333331">Type</th><th width="181">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256[]</td><td>protocol</td><td>Protocol earnings.</td></tr><tr><td>uint256</td><td>senior</td><td>Senior tranche earnings.</td></tr><tr><td>uint256</td><td>junior</td><td>Junior tranche earnings.</td></tr><tr><td>uint256[]</td><td>residual</td><td>Residual earnings.</td></tr></tbody></table>

#### `viewDistributions()`

View distribution information for protocol and residual earnings recipients.

```solidity
function viewDistributions() external view returns (
    address[] memory protocolEarningsRecipients, 
    uint256[] memory protocolEarningsProportion, 
    address[] memory residualEarningsRecipients, 
    uint256[] memory residualEarningsProportion
);
```

*Returns*

<table><thead><tr><th width="160.33333333333331">Type</th><th width="181">Name</th><th>Description</th></tr></thead><tbody><tr><td>address[]</td><td>protocolEarningsRecipients</td><td>The destinations for protocol earnings distributions.</td></tr><tr><td>uint256[]</td><td>protocolEarningsProportion</td><td>The proportions for protocol earnings distributions.</td></tr><tr><td>address[]</td><td>residualEarningsRecipients</td><td>The destinations for residual earnings distributions.</td></tr><tr><td>uint256[]</td><td>residualEarningsProportion</td><td>The proportions for residual earnings distributions.</td></tr></tbody></table>

## Write Functions

#### `distributeYield()`

Distributes available yield within this contract to appropriate entities.

```solidity
function distributeYield() external;
```

Emits the [#yielddistributed](#yielddistributed "mention") and [#yielddistributedsingle](#yielddistributedsingle "mention") event(s)

#### `returnAsset()`

Returns an asset to DAO if not `distributedAsset()`.

```solidity
function returnAsset(address asset) external;
```

<table><thead><tr><th width="156.33333333333331">Type</th><th width="176">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>asset</td><td>The asset to return.</td></tr></tbody></table>

Emits the [#assetreturned](#assetreturned "mention") event

#### `unlock()`

Unlocks this contract for distributions, initializes values.

```solidity
function unlock() external;
```

#### `updateDistributedAsset()`

Updates the distributed asset for this particular contract.

```solidity
function updateDistributedAsset(address _distributedAsset) external nonReentrant;
```

<table><thead><tr><th width="156.33333333333331">Type</th><th width="176">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>_distributedAsset</td><td>The new value for distributed asset.</td></tr></tbody></table>

Emits the [#updateddistributedasset](#updateddistributedasset "mention") event

#### `updateProtocolEarningsRateBIPS()`

Updates the state variable "protocolEarningsRateBIPS".

```solidity
function updateProtocolEarningsRateBIPS(uint256 _protocolEarningsRateBIPS) external;
```

<table><thead><tr><th width="156.33333333333331">Type</th><th width="176">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>_protocolEarningsRateBIPS</td><td>The new value for protocolEarningsRateBIPS.</td></tr></tbody></table>

Emits the [#updatedprotocolearningsratebips](#updatedprotocolearningsratebips "mention") event

#### `updateRecipients()`

Updates the protocolRecipients or residualRecipients.

```solidity
function updateRecipients(
    address[] memory recipients, 
    uint256[] memory proportions, 
    bool protocol
) external;
```

<table><thead><tr><th width="156.33333333333331">Type</th><th width="176">Name</th><th>Description</th></tr></thead><tbody><tr><td>address[]</td><td>recipients</td><td>An array of addresses to which protocol earnings will be distributed.</td></tr><tr><td>uint256[]</td><td>proportions</td><td>An array of ratios relative to the recipients - in BIPS. Sum should equal to 10000.</td></tr><tr><td>bool</td><td>protocol</td><td>Specifiy "true" to update protocol earnings, or "false" to update residual earnings.</td></tr></tbody></table>

Emits the [#updatedprotocolrecipients](#updatedprotocolrecipients "mention") and [#updatedresidualrecipients](#updatedresidualrecipients "mention") event(s)

#### `updateTargetAPYBIPS()`

Updates the state variable "targetAPYBIPS".

```solidity
function updateTargetAPYBIPS(uint256 _targetAPYBIPS) external;
```

<table><thead><tr><th width="156.33333333333331">Type</th><th width="176">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>_targetAPYBIPS</td><td>The new value for targetAPYBIPS.</td></tr></tbody></table>

Emits the [#updatedtargetapybips](#updatedtargetapybips "mention") event

#### `updateTargetRatioBIPS()`

Updates the state variable "targetRatioBIPS".

```solidity
function updateTargetRatioBIPS(uint256 _targetRatioBIPS) external;
```

<table><thead><tr><th width="156.33333333333331">Type</th><th width="176">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>_targetRatioBIPS</td><td>The new value for targetRatioBIPS.</td></tr></tbody></table>

Emits the [#updatedtargetratiobips](#updatedtargetratiobips "mention") event

## Events

#### **`AssetReturned()`**

Emitted during [#returnasset](#returnasset "mention")

```solidity
event AssetReturned(address indexed asset, uint256 amount);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="132">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>True</td><td>asset</td><td>The asset returned.</td></tr><tr><td>uint256</td><td>False</td><td>amount</td><td>The amount of "asset" returned to DAO.</td></tr></tbody></table>

#### **`UpdatedDistributedAsset()`**

Emitted during [#updatedistributedasset](#updatedistributedasset "mention")

```solidity
event UpdatedDistributedAsset(address indexed oldAsset, address indexed newAsset);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="132">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>True</td><td>oldAsset</td><td>The old value of distributedAsset.</td></tr><tr><td>address</td><td>True</td><td>newAsset</td><td>The new value of distributedAsset.</td></tr></tbody></table>

#### **`UpdatedProtocolEarningsRateBIPS()`**

Emitted during [#updateprotocolearningsratebips](#updateprotocolearningsratebips "mention")

```solidity
event UpdatedProtocolEarningsRateBIPS(uint256 oldValue, uint256 newValue);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="132">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>False</td><td>oldValue</td><td>The old value of protocolEarningsRateBIPS.</td></tr><tr><td>uint256</td><td>False</td><td>newValue</td><td>The new value of protocolEarningsRateBIPS.</td></tr></tbody></table>

#### **`UpdatedProtocolRecipients()`**

Emitted during [#updaterecipients](#updaterecipients "mention")

```solidity
event UpdatedProtocolRecipients(address[] recipients, uint256[] proportion);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="132">Name</th><th>Description</th></tr></thead><tbody><tr><td>address[]</td><td>False</td><td>recipients</td><td>The new recipients to receive protocol earnings.</td></tr><tr><td>uint256[]</td><td>False</td><td>proportion</td><td>The proportion distributed across recipients.</td></tr></tbody></table>

#### **`UpdatedResidualRecipients()`**

Emitted during [#updaterecipients](#updaterecipients "mention")

```solidity
event UpdatedResidualRecipients(address[] recipients, uint256[] proportion);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="132">Name</th><th>Description</th></tr></thead><tbody><tr><td>address[]</td><td>False</td><td>recipients</td><td>The new recipients to receive residual earnings.</td></tr><tr><td>uint256[]</td><td>False</td><td>proportion</td><td>The proportion distributed across recipients.</td></tr></tbody></table>

#### **`UpdatedTargetAPYBIPS()`**

Emitted during [#updatetargetapybips](#updatetargetapybips "mention")

```solidity
event UpdatedTargetAPYBIPS(uint256 oldValue, uint256 newValue);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="132">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>False</td><td>oldValue</td><td>The old value of targetAPYBIPS.</td></tr><tr><td>uint256</td><td>False</td><td>newValue</td><td>The new value of targetAPYBIPS.</td></tr></tbody></table>

#### **`UpdatedTargetRatioBIPS()`**

Emitted during [#updatedtargetratiobips](#updatedtargetratiobips "mention")

```solidity
event UpdatedTargetRatioBIPS(uint256 oldValue, uint256 newValue);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="132">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>False</td><td>oldValue</td><td>The old value of targetRatioBIPS.</td></tr><tr><td>uint256</td><td>False</td><td>newValue</td><td>The new value of targetRatioBIPS.</td></tr></tbody></table>

#### **`YieldDistributed()`**

Emitted during [#distributeyield](#distributeyield "mention")

```solidity
event YieldDistributed(
    uint256[] protocol, 
    uint256 senior, 
    uint256 junior, 
    uint256[] residual
);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="132">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256[]</td><td>False</td><td>protocol</td><td>The amount of earnings distributed to protocol earnings recipients.</td></tr><tr><td>uint256</td><td>False</td><td>senior</td><td>The amount of earnings distributed to the senior tranche.</td></tr><tr><td>uint256</td><td>False</td><td>junior</td><td>The amount of earnings distributed to the junior tranche.</td></tr><tr><td>uint256[]</td><td>False</td><td>residual</td><td>The amount of earnings distributed to residual earnings recipients.</td></tr></tbody></table>

#### **`YieldDistributedSingle()`**

Emitted during [#distributeyield](#distributeyield "mention")

```solidity
event YieldDistributedSingle(
    address indexed asset, 
    address indexed recipient, 
    uint256 amount
);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="132">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>True</td><td>asset</td><td>The "asset" being distributed.</td></tr><tr><td>address</td><td>True</td><td>recipient</td><td>The recipient of the distribution.</td></tr><tr><td>uint256</td><td>False</td><td>amount</td><td>The amount distributed</td></tr></tbody></table>
