# ZivoeRewardsVesting.sol

## Introduction

This contract facilitates staking and yield distribution, as well as vesting tokens.

This contract has the following responsibilities:

* Allows creation of vesting schedules (and revocation) for "vestingToken".&#x20;
* Allows unstaking of vested tokens.
* Allows claiming yield distributed / "deposited" to this contract.
* Allows multiple assets to be added as "rewardToken" for distributions (except for "vestingToken").
* Vests rewardTokens linearly overtime to stakers.

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

#### State Variables

<table><thead><tr><th width="212.33333333333331">Type</th><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>GBL</td><td>The ZivoeGlobals contract.</td></tr><tr><td>address</td><td>vestingToken</td><td>The token vesting, in this case Zivoe ($ZVE).</td></tr><tr><td>address[]</td><td>rewardTokens</td><td>Array of ERC20 tokens distributed as rewards (if present).</td></tr><tr><td>uint256</td><td>vestingTokenAllocated</td><td>The amount of vestingToken currently allocated.</td></tr><tr><td>uint256</td><td>_totalSupply</td><td>Total supply of (non-transferrable) LP tokens for reards contract.</td></tr><tr><td>mapping(address => <a data-mention href="#reward">#reward</a>)</td><td>rewardData</td><td>Contains rewards information for each rewardToken.</td></tr><tr><td>mapping(address => bool)</td><td>vestingScheduleSet</td><td>Tracks if a wallet has been assigned a schedule.</td></tr><tr><td>mapping(address => <a data-mention href="#vestingschedule">#vestingschedule</a>)</td><td>vestingScheduleOf</td><td>Tracks the vesting schedule of accounts.</td></tr><tr><td>mapping(address => mapping(address => (uint256))</td><td>accountRewardPerTokenPaid</td><td>The order is account -> rewardAsset -> amount.</td></tr><tr><td>mapping(address => mapping(address => (uint256))</td><td>rewards</td><td>The order is account -> rewardAsset -> amount.</td></tr><tr><td>mapping(address => uint256)</td><td>_balances</td><td>Contains LP token balance of each account (is 1:1 ratio with amount deposited).</td></tr><tr><td>IERC20</td><td>stakingToken</td><td>IERC20 wrapper for the stakingToken (deposited to receive LP tokens).</td></tr></tbody></table>

#### `Reward`

This struct stores information for reward tokens.

<table><thead><tr><th width="137.33333333333331">Type</th><th width="254">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>rewardsDuration</td><td>How long rewards take to vest, e.g. 30 days.</td></tr><tr><td>uint256</td><td>periodFinish</td><td>When current rewards will finish vesting.</td></tr><tr><td>uint256</td><td>rewardRate</td><td>Rewards emitted per second.</td></tr><tr><td>uint256</td><td>lastUpdateTime</td><td>Last time this data struct was updated.</td></tr><tr><td>uint256</td><td>rewardPerTokenStored</td><td>Last snapshot of rewardPerToken taken.</td></tr></tbody></table>

#### `VestingSchedule`

This struct stores information for vesting schedules.

<table><thead><tr><th width="144.33333333333331">Type</th><th width="205">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>start</td><td>The block.timestamp at which tokens will start vesting.</td></tr><tr><td>uint256</td><td>cliff</td><td>The block.timestamp at which tokens are first claimable.</td></tr><tr><td>uint256</td><td>end</td><td>The block.timestamp at which tokens will stop vesting (finished).</td></tr><tr><td>uint256</td><td>totalVesting</td><td>The total amount to vest.</td></tr><tr><td>uint256</td><td>totalWithdrawn</td><td>The total amount withdrawn so far.</td></tr><tr><td>uint256</td><td>vestingPerSecond</td><td>The amount of vestingToken that vests per second.</td></tr><tr><td>bool</td><td>revokable</td><td>Whether or not this vesting schedule can be revoked.</td></tr></tbody></table>

## **Sections**

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

* [#balanceof](#balanceof "mention") - Returns the amount of tokens owned by "account", received when depositing via `stake()`.
* [#getrewardforduration](#getrewardforduration "mention") - Returns the total amount of rewards being distributed to everyone for current rewardsDuration.
* [#totalsupply](#totalsupply "mention") - Returns the amount of tokens in existence; these are minted and burned when depositing or withdrawing.
* [#viewaccountrewardpertokenpaid](#viewaccountrewardpertokenpaid "mention") - Returns the last snapshot of rewardPerTokenStored taken for a reward asset.
* [#viewrewards](#viewrewards "mention") - Returns the rewards earned of a specific rewardToken for an address.
* [#viewschedule](#viewschedule "mention") - Provides information for a vesting schedule. See [#vestingschedule](#vestingschedule "mention")
* [#amountwithdrawable](#amountwithdrawable "mention") - Returns the amount of $ZVE tokens a user can withdraw.
* [#earned](#earned "mention") - Provides information on the rewards available for claim.
* [#lasttimerewardapplicable](#lasttimerewardapplicable "mention") - Helper function for assessing distribution timelines.
* [#rewardpertoken](#rewardpertoken "mention") - Cumulative amount of rewards distributed per LP token.

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

* [#addreward](#addreward "mention") - Adds a new asset as a reward to this contract.
* [#depositreward](#depositreward "mention") - Deposits a reward to this contract for distribution.
* [#fullwithdraw](#fullwithdraw "mention") - Simultaneously calls `withdraw()` and `getRewards()` for convenience.
* [#createvestingschedule](#createvestingschedule "mention") - Sets the vestingSchedule for an account.
* [#revokevestingschedule](#revokevestingschedule "mention") - Ends vesting schedule for a given account (if revokable).
* [#getrewards](#getrewards "mention") - Claim rewards for all possible \_rewardTokens.
* [#withdraw](#withdraw "mention") - Withdraws the specified amount of stakingToken from this contract.

[#events](#events "mention")

* [#rewardadded](#rewardadded "mention")
* [#rewarddeposited](#rewarddeposited "mention")
* [#rewarddistributed](#rewarddistributed "mention")
* [#staked](#staked "mention")
* [#vestingschedulecreated](#vestingschedulecreated "mention")
* [#vestingschedulerevoked](#vestingschedulerevoked "mention")
* [#withdrawn](#withdrawn "mention")

## Read Functions

#### `balanceOf()`

Returns the amount of tokens owned by "account", received when depositing via `stake()`.

```solidity
function balanceOf(
    address account
) external view returns (uint256 amount);
```

<table><thead><tr><th width="143.33333333333331">Type</th><th width="120">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The account to view information of.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="121">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The amount of tokens owned by "account".</td></tr></tbody></table>

#### `getRewardForDuration()`

Returns the total amount of rewards being distributed to everyone for current rewardsDuration.

```solidity
function getRewardForDuration(
    address _rewardsToken
) external view returns (uint256 amount);
```

<table><thead><tr><th width="143.33333333333331">Type</th><th width="151">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>_rewardsToken</td><td>The asset that's being distributed.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="121">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The amount of rewards being distributed.</td></tr></tbody></table>

#### `totalSupply()`

Returns the amount of tokens in existence; these are minted and burned when depositing or withdrawing.

```solidity
function totalSupply() external view returns (uint256 amount);
```

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="121">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The amount of tokens in existence.</td></tr></tbody></table>

#### `viewAccountRewardPerTokenPaid()`

Returns the last snapshot of rewardPerTokenStored taken for a reward asset.

```solidity
function viewAccountRewardPerTokenPaid(
    address account, 
    address rewardAsset
) external view returns (uint256 amount);
```

<table><thead><tr><th width="143.33333333333331">Type</th><th width="157">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The account to view information of.</td></tr><tr><td>address</td><td>rewardAsset</td><td>The reward token for which we want to return the rewardPerTokenstored.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="121">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The latest up-to-date value of rewardPerTokenStored.</td></tr></tbody></table>

#### `viewRewards()`

Returns the rewards earned of a specific rewardToken for an address.

```solidity
function viewRewards(
    address account,
    address rewardAsset
) external view returns (uint256 amount);
```

<table><thead><tr><th width="143.33333333333331">Type</th><th width="144">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The account to view information of.</td></tr><tr><td>address</td><td>rewardAsset</td><td>The asset earned as a reward.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="121">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The amount of rewards earned.</td></tr></tbody></table>

#### `viewSchedule()`

Provides information for a vesting schedule. See [#vestingschedule](#vestingschedule "mention")

```solidity
function viewSchedule(address account) external view returns (
    uint256 start, 
    uint256 cliff, 
    uint256 end, 
    uint256 totalVesting, 
    uint256 totalWithdrawn, 
    uint256 vestingPerSecond, 
    bool revokable
);
```

<table><thead><tr><th width="143.33333333333331">Type</th><th width="144">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The account to view information of.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="178">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>start</td><td>The block.timestamp at which tokens will start vesting.</td></tr><tr><td>uint256</td><td>cliff</td><td>The block.timestamp at which tokens are first claimable.</td></tr><tr><td>uint256</td><td>end</td><td>The block.timestamp at which tokens will stop vesting (finished).</td></tr><tr><td>uint256</td><td>totalVesting</td><td>The total amount to vest.</td></tr><tr><td>uint256</td><td>totalWithdrawn</td><td>The total amount withdrawn so far.</td></tr><tr><td>uint256</td><td>vestingPerSecond</td><td>The amount of vestingToken that vests per second.</td></tr><tr><td>bool</td><td>revokable</td><td>Whether or not this vesting schedule can be revoked.</td></tr></tbody></table>

#### `amountWithdrawable()`

Returns the amount of $ZVE tokens a user can withdraw.

```solidity
function amountWithdrawable(
    address account
) public view returns (uint256 amount);
```

<table><thead><tr><th width="143.33333333333331">Type</th><th width="144">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The account to be withdrawn from.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="121">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>Withdrawable amount of $ZVE tokens.</td></tr></tbody></table>

#### `earned()`

Provides information on the rewards available for claim.

```solidity
function earned(
    address account, 
    address _rewardsToken
) public view returns (uint256 amount);
```

<table><thead><tr><th width="143.33333333333331">Type</th><th width="156">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The account to view information of.</td></tr><tr><td>address</td><td>_rewardsToken</td><td>The asset that's being distributed.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="121">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The amount of rewards earned.</td></tr></tbody></table>

#### `lastTimeRewardApplicable()`

Helper function for assessing distribution timelines.

```solidity
function lastTimeRewardApplicable(
    address _rewardsToken
) public view returns (uint256 timestamp); 
```

<table><thead><tr><th width="143.33333333333331">Type</th><th width="155">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>_rewardsToken</td><td>The asset that's being distributed.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="121">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>timestamp</td><td>The most recent time (in UNIX format) at which rewards are available for distribution.</td></tr></tbody></table>

#### `rewardPerToken()`

Cumulative amount of rewards distributed per LP token.

```solidity
function rewardPerToken(
    address _rewardsToken
) public view returns (uint256 amount);
```

<table><thead><tr><th width="143.33333333333331">Type</th><th width="168">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>_rewardsToken</td><td>The asset that's being distributed.</td></tr></tbody></table>

*Returns*

<table><thead><tr><th width="148.33333333333331">Type</th><th width="121">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The cumulative amount of rewards distributed per LP token.</td></tr></tbody></table>

## Write Functions

#### `addReward()`

Adds a new asset as a reward to this contract.

```solidity
function addReward(
    address _rewardsToken, 
    uint256 _rewardsDuration
) external;
```

<table><thead><tr><th width="160">Type</th><th width="201.33333333333331">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>_rewardsToken</td><td>The asset that's being distributed</td></tr><tr><td>uint256</td><td>_rewardsDuration</td><td>How long rewards take to vest, e.g. 30 days (denoted in seconds).</td></tr></tbody></table>

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

#### `depositReward()`

Deposits a reward to this contract for distribution.

```solidity
function depositReward(
    address _rewardsToken, 
    uint256 reward
) external updateReward(address(0)) nonReentrant;
```

<table><thead><tr><th width="149.33333333333331">Type</th><th width="179">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>_rewardsToken</td><td>The asset that's being distributed.</td></tr><tr><td>uint256</td><td>reward</td><td>The amount of the _rewardsToken to deposit.</td></tr></tbody></table>

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

#### `fullWithdraw()`

Simultaneously calls `withdraw()` and `getRewards()` for convenience.

```solidity
function fullWithdraw() external;
```

Emits the [#withdrawn](#withdrawn "mention") and [#rewarddistributed](#rewarddistributed "mention") event(s)

#### `createVestingSchedule()`

Sets the vestingSchedule for an account.

```solidity
function createVestingSchedule(
    address account,
    uint256 daysToCliff, 
    uint256 daysToVest, 
    uint256 amountToVest, 
    bool revokable
) external onlyZVLorITO;
```

<table><thead><tr><th width="95">Type</th><th width="158.33333333333331">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The account vesting $ZVE</td></tr><tr><td>uint256</td><td>daysToCliff</td><td>The number of days before vesting is claimable (a.k.a. cliff period).</td></tr><tr><td>uint256</td><td>daysToVest</td><td>The number of days for the entire vesting period, from beginning to end.</td></tr><tr><td>uint256</td><td>amountToVest</td><td>The amount of tokens being vested.</td></tr><tr><td>bool</td><td>revokable</td><td>If the vested amount can be revoked.</td></tr></tbody></table>

Emits the [#vestingschedulecreated](#vestingschedulecreated "mention") and [#staked](#staked "mention") event

#### `revokeVestingSchedule()`

Ends vesting schedule for a given account (if revokable).

```solidity
function revokeVestingSchedule(
    address account
) external updateReward(account) onlyZVLOrITO nonReentrant;
```

<table><thead><tr><th width="130.33333333333331">Type</th><th width="134">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The acount to revoke a vesting schedule for.</td></tr></tbody></table>

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

#### `getRewards()`

Claim rewards for all possible \_rewardTokens.

```solidity
function getRewards() public updateReward(_msgSender());
```

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

#### `withdraw()`

Withdraws the specified amount of stakingToken from this contract.

```solidity
function withdraw(uint256 amount) public nonReentrant updateReward(_msgSender());
```

<table><thead><tr><th width="149.33333333333331">Type</th><th width="179">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The amount of the _rewardsToken to withdraw.</td></tr></tbody></table>

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

## Events

#### **`RewardAdded()`**

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

```solidity
event RewardAdded(address indexed reward);
```

<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>reward</td><td>The asset that's being distributed.</td></tr></tbody></table>

#### **`RewardDeposited()`**

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

```solidity
event RewardDeposited(
    address indexed reward, 
    uint256 amount, 
    address indexed depositor
);
```

<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>reward</td><td>The asset that's being deposited.</td></tr><tr><td>uint256</td><td>False</td><td>amount</td><td>The amount deposited.</td></tr><tr><td>address</td><td>True</td><td>depositor</td><td>The _msgSender() who deposited said reward.</td></tr></tbody></table>

#### **`RewardDistributed()`**

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

```solidity
event RewardDistributed(
    address indexed account, 
    address indexed rewardsToken, 
    uint256 reward
);
```

<table><thead><tr><th width="127.33333333333331">Type</th><th width="98">Indexed</th><th width="142">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>True</td><td>account</td><td>The account receiving a reward.</td></tr><tr><td>address</td><td>True</td><td>rewardsToken</td><td>The ERC20 asset distributed as a reward.</td></tr><tr><td>uint256</td><td>False</td><td>reward</td><td>The amount of "rewardsToken" distributed.</td></tr></tbody></table>

#### **`Staked()`**

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

```solidity
event Staked(address indexed account, 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>account</td><td>The account staking "stakingToken".</td></tr><tr><td>uint256</td><td>False</td><td>amount</td><td>The amount of "stakingToken" staked.</td></tr></tbody></table>

#### **`VestingScheduleCreated()`**

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

```solidity
event VestingScheduleCreated(
    address indexed account, 
    uint256 start, 
    uint256 cliff, 
    uint256 end, 
    uint256 totalVesting, 
    uint256 vestingPerSecond, 
    bool revokable
);
```

<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>account</td><td>The account that was given a vesting schedule.</td></tr><tr><td>uint256</td><td>False</td><td>start</td><td>The block.timestamp at which tokens will start vesting.</td></tr><tr><td>uint256</td><td>False</td><td>cliff</td><td>The block.timestamp at which tokens are first claimable.</td></tr><tr><td>uint256</td><td>False</td><td>end</td><td>The block.timestamp at which tokens will stop vesting (finished).</td></tr><tr><td>uint256</td><td>False</td><td>totalVesting</td><td>The total amount to vest.</td></tr><tr><td>uint256</td><td>False</td><td>vestingPerSecond</td><td>The amount of vestingToken that vests per second.</td></tr><tr><td>bool</td><td>False</td><td>revokable</td><td>Whether or not this vesting schedule can be revoked.</td></tr></tbody></table>

#### **`VestingScheduleRevoked()`**

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

```solidity
event VestingScheduleRevoked(
    address indexed account, 
    uint256 amountRevoked, 
    uint256 cliff, 
    uint256 end, 
    uint256 totalVesting, 
    bool revokable
);
```

<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>account</td><td>The account that was revoked a vesting schedule.</td></tr><tr><td>uint256</td><td>False</td><td>amountRevoked</td><td>The amount of tokens revoked.</td></tr><tr><td>uint256</td><td>False</td><td>cliff</td><td>The updated value for cliff.</td></tr><tr><td>uint256</td><td>False</td><td>end</td><td>The updated value for end.</td></tr><tr><td>uint256</td><td>False</td><td>totalVesting</td><td>The total amount to vested (claimable).</td></tr><tr><td>bool</td><td>False</td><td>revokable</td><td>The final revokable status of schedule (always false after revocation).</td></tr></tbody></table>

#### **`Withdrawn()`**

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

```solidity
event Withdrawn(address indexed account, 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>account</td><td>The account withdrawing "stakingToken".</td></tr><tr><td>uint256</td><td>False</td><td>amount</td><td>The amount of "stakingToken" to withdraw.</td></tr></tbody></table>
