> For the complete documentation index, see [llms.txt](https://docs.sperax.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sperax.io/sperax-farms-protocol/technical-documents/smart-contracts/base-contracts/farm.md).

# Farm

[Git Source](https://github.com/Sperax/Demeter-Protocol/blob/cc93b9106874316d6dd016cdace652e2ca4ef8e1/contracts/Farm.sol)

**Inherits:** FarmStorage, OwnableUpgradeable, ReentrancyGuardUpgradeable, MulticallUpgradeable

**Author:** Sperax Foundation.

This contract contains the core logic for the Sperax farms.

## Functions

### constructor

```solidity
constructor();
```

### withdraw

Function to be called to withdraw deposit.

```solidity
function withdraw(uint256 _depositId) external virtual;
```

**Parameters**

| Name         | Type      | Description            |
| ------------ | --------- | ---------------------- |
| `_depositId` | `uint256` | The id of the deposit. |

### claimRewards

A function to be called by the depositor to claim rewards.

```solidity
function claimRewards(uint256 _depositId) external;
```

**Parameters**

| Name         | Type      | Description            |
| ------------ | --------- | ---------------------- |
| `_depositId` | `uint256` | The id of the deposit. |

### initiateCooldown

Function to be called to initiate cooldown for a staked deposit.

*\_depositId is corresponding to the user's deposit.*

```solidity
function initiateCooldown(uint256 _depositId) external nonReentrant;
```

**Parameters**

| Name         | Type      | Description                         |
| ------------ | --------- | ----------------------------------- |
| `_depositId` | `uint256` | The id of the deposit to be locked. |

### addRewards

Add rewards to the farm.

```solidity
function addRewards(address _rwdToken, uint256 _amount) external nonReentrant;
```

**Parameters**

| Name        | Type      | Description                         |
| ----------- | --------- | ----------------------------------- |
| `_rwdToken` | `address` | The reward token's address.         |
| `_amount`   | `uint256` | The amount of reward tokens to add. |

### updateCooldownPeriod

Update the cooldown period.

```solidity
function updateCooldownPeriod(uint256 _newCooldownPeriod) external onlyOwner;
```

**Parameters**

| Name                 | Type      | Description                                             |
| -------------------- | --------- | ------------------------------------------------------- |
| `_newCooldownPeriod` | `uint256` | The new cooldown period (in days). E.g: 7 means 7 days. |

### farmPauseSwitch

Pause / UnPause the farm.

```solidity
function farmPauseSwitch(bool _isPaused) external onlyOwner;
```

**Parameters**

| Name        | Type   | Description                                         |
| ----------- | ------ | --------------------------------------------------- |
| `_isPaused` | `bool` | Desired state of the farm (true to pause the farm). |

### closeFarm

A function to explicitly close the farm.

*Recovers remaining non accrued rewards.*

```solidity
function closeFarm() external onlyOwner nonReentrant;
```

### recoverERC20

Recover erc20 tokens other than the reward tokens.

```solidity
function recoverERC20(address _token) external onlyOwner nonReentrant;
```

**Parameters**

| Name     | Type      | Description                       |
| -------- | --------- | --------------------------------- |
| `_token` | `address` | Address of token to be recovered. |

### recoverRewardFunds

Get the remaining reward balance out of the farm.

*Function recovers minOf(\_amount, rewardsLeft).*

```solidity
function recoverRewardFunds(address _rwdToken, uint256 _amount) external nonReentrant;
```

**Parameters**

| Name        | Type      | Description                                      |
| ----------- | --------- | ------------------------------------------------ |
| `_rwdToken` | `address` | The reward token's address.                      |
| `_amount`   | `uint256` | The amount of the reward tokens to be withdrawn. |

### setRewardRate

Function to update reward params for a fund.

```solidity
function setRewardRate(address _rwdToken, uint128[] memory _newRewardRates) external;
```

**Parameters**

| Name              | Type        | Description                                                |
| ----------------- | ----------- | ---------------------------------------------------------- |
| `_rwdToken`       | `address`   | The reward token's address.                                |
| `_newRewardRates` | `uint128[]` | The new reward rate for the fund (includes the precision). |

### updateRewardData

Transfer the tokenManagerRole to other user.

*Only the existing tokenManager for a reward can call this function.*

```solidity
function updateRewardData(address _rwdToken, address _newTknManager) external;
```

**Parameters**

| Name             | Type      | Description                       |
| ---------------- | --------- | --------------------------------- |
| `_rwdToken`      | `address` | The reward token's address.       |
| `_newTknManager` | `address` | Address of the new token manager. |

### computeRewards

Function to compute the total accrued rewards for a deposit for each subscription.

```solidity
function computeRewards(address _account, uint256 _depositId)
    external
    view
    virtual
    returns (uint256[][] memory rewards);
```

**Parameters**

| Name         | Type      | Description            |
| ------------ | --------- | ---------------------- |
| `_account`   | `address` | The user's address.    |
| `_depositId` | `uint256` | The id of the deposit. |

**Returns**

| Name      | Type          | Description                                                                      |
| --------- | ------------- | -------------------------------------------------------------------------------- |
| `rewards` | `uint256[][]` | The total accrued rewards for the deposit for each subscription (uint256\[]\[]). |

### getRewardFunds

Get the reward fund details.

```solidity
function getRewardFunds() external view returns (RewardFund[] memory);
```

**Returns**

| Name     | Type           | Description                                                   |
| -------- | -------------- | ------------------------------------------------------------- |
| `<none>` | `RewardFund[]` | The available reward funds' details for all the reward funds. |

### getRewardData

Get the reward details for specified reward token.

```solidity
function getRewardData(address _rwdToken) external view returns (RewardData memory);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `_rwdToken` | `address` | The address of the reward token. |

**Returns**

| Name     | Type         | Description                                                  |
| -------- | ------------ | ------------------------------------------------------------ |
| `<none>` | `RewardData` | The available reward details for the specified reward token. |

### getDepositInfo

Get deposit info for a deposit id.

```solidity
function getDepositInfo(uint256 _depositId) external view returns (Deposit memory);
```

**Parameters**

| Name         | Type      | Description            |
| ------------ | --------- | ---------------------- |
| `_depositId` | `uint256` | The id of the deposit. |

**Returns**

| Name     | Type      | Description                 |
| -------- | --------- | --------------------------- |
| `<none>` | `Deposit` | The deposit info (Deposit). |

### getNumSubscriptions

Get number of subscriptions for an account.

```solidity
function getNumSubscriptions(uint256 _depositId) external view returns (uint256);
```

**Parameters**

| Name         | Type      | Description     |
| ------------ | --------- | --------------- |
| `_depositId` | `uint256` | The deposit id. |

**Returns**

| Name     | Type      | Description                                  |
| -------- | --------- | -------------------------------------------- |
| `<none>` | `uint256` | The number of subscriptions for the deposit. |

### getSubscriptionInfo

Get subscription stats for a deposit.

```solidity
function getSubscriptionInfo(uint256 _depositId, uint256 _subscriptionId) external view returns (Subscription memory);
```

**Parameters**

| Name              | Type      | Description            |
| ----------------- | --------- | ---------------------- |
| `_depositId`      | `uint256` | The deposit id.        |
| `_subscriptionId` | `uint256` | The subscription's id. |

**Returns**

| Name     | Type           | Description                           |
| -------- | -------------- | ------------------------------------- |
| `<none>` | `Subscription` | The subscription info (Subscription). |

### getRewardRates

Get reward rates for a rewardToken.

```solidity
function getRewardRates(address _rwdToken) external view returns (uint256[] memory);
```

**Parameters**

| Name        | Type      | Description                 |
| ----------- | --------- | --------------------------- |
| `_rwdToken` | `address` | The reward token's address. |

**Returns**

| Name     | Type        | Description                                         |
| -------- | ----------- | --------------------------------------------------- |
| `<none>` | `uint256[]` | The reward rates for the reward token (uint256\[]). |

### getRewardFundInfo

Get farm reward fund info.

```solidity
function getRewardFundInfo(uint8 _fundId) external view returns (RewardFund memory);
```

**Parameters**

| Name      | Type    | Description    |
| --------- | ------- | -------------- |
| `_fundId` | `uint8` | The fund's id. |

**Returns**

| Name     | Type         | Description                        |
| -------- | ------------ | ---------------------------------- |
| `<none>` | `RewardFund` | The reward fund info (RewardFund). |

### getRewardTokens

Function to get the reward tokens added in the farm.

```solidity
function getRewardTokens() external view returns (address[] memory);
```

**Returns**

| Name     | Type        | Description                          |
| -------- | ----------- | ------------------------------------ |
| `<none>` | `address[]` | The reward tokens added in the farm. |

### getTokenAmounts

Function to be called by Rewarder to get tokens and amounts associated with the farm's liquidity.

*This function should be overridden to add the respective logic.*

```solidity
function getTokenAmounts() external view virtual returns (address[] memory, uint256[] memory);
```

**Returns**

| Name     | Type        | Description                                   |
| -------- | ----------- | --------------------------------------------- |
| `<none>` | `address[]` | Tokens associated with the farm's pool.       |
| `<none>` | `uint256[]` | Amounts associated with the farm's liquidity. |

### updateFarmRewardData

Function to update the FarmRewardData for all funds.

```solidity
function updateFarmRewardData() public virtual;
```

### claimRewardsTo

Claim rewards and send it to another account.

*Only the depositor can call this function.*

```solidity
function claimRewardsTo(address _account, uint256 _depositId) public nonReentrant;
```

**Parameters**

| Name         | Type      | Description             |
| ------------ | --------- | ----------------------- |
| `_account`   | `address` | To receive the rewards. |
| `_depositId` | `uint256` | The id of the deposit.  |

### updateFarmStartTime

Update the farm start time.

*Can be updated only before the farm start. New start time should be in future.*

```solidity
function updateFarmStartTime(uint256 _newStartTime) public virtual onlyOwner;
```

**Parameters**

| Name            | Type      | Description              |
| --------------- | --------- | ------------------------ |
| `_newStartTime` | `uint256` | The new farm start time. |

### isFarmOpen

Returns if farm is open. Farm is open if it is not closed.

*This function can be overridden to add any new/additional logic.*

```solidity
function isFarmOpen() public view virtual returns (bool);
```

**Returns**

| Name     | Type   | Description                |
| -------- | ------ | -------------------------- |
| `<none>` | `bool` | bool True if farm is open. |

### isFarmActive

Returns if farm is active. Farm is active if it is not paused and not closed.

*This function can be overridden to add any new/additional logic.*

```solidity
function isFarmActive() public view virtual returns (bool);
```

**Returns**

| Name     | Type   | Description                  |
| -------- | ------ | ---------------------------- |
| `<none>` | `bool` | bool True if farm is active. |

### getRewardBalance

Get the reward balance for specified reward token.

*This function calculates the available reward balance by considering the accrued rewards and the token supply.*

```solidity
function getRewardBalance(address _rwdToken) public view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `_rwdToken` | `address` | The address of the reward token. |

**Returns**

| Name     | Type      | Description                                                  |
| -------- | --------- | ------------------------------------------------------------ |
| `<none>` | `uint256` | The available reward balance for the specified reward token. |

### \_recoverERC20

```solidity
function _recoverERC20(address _token) internal virtual;
```

### \_deposit

Common logic for deposit in the farm.

```solidity
function _deposit(address _account, bool _lockup, uint256 _liquidity) internal returns (uint256);
```

**Parameters**

| Name         | Type      | Description                               |
| ------------ | --------- | ----------------------------------------- |
| `_account`   | `address` | Address of the depositor.                 |
| `_lockup`    | `bool`    | Lockup option for the deposit.            |
| `_liquidity` | `uint256` | Liquidity amount to be added to the pool. |

**Returns**

| Name     | Type      | Description     |
| -------- | --------- | --------------- |
| `<none>` | `uint256` | The deposit id. |

### \_initiateCooldown

Common logic for initiating cooldown.

```solidity
function _initiateCooldown(uint256 _depositId) internal;
```

**Parameters**

| Name         | Type      | Description        |
| ------------ | --------- | ------------------ |
| `_depositId` | `uint256` | User's deposit Id. |

### \_withdraw

Common logic for withdraw.

```solidity
function _withdraw(uint256 _depositId) internal;
```

**Parameters**

| Name         | Type      | Description        |
| ------------ | --------- | ------------------ |
| `_depositId` | `uint256` | User's deposit id. |

### \_updateAndClaimFarmRewards

Claim rewards for the user.

*NOTE: any function calling this private function should be marked as non-reentrant.*

```solidity
function _updateAndClaimFarmRewards(uint256 _depositId) internal;
```

**Parameters**

| Name         | Type      | Description            |
| ------------ | --------- | ---------------------- |
| `_depositId` | `uint256` | The id of the deposit. |

### \_updateAndClaimFarmRewardsTo

Claim rewards for the user and send it to another account.

*NOTE: any function calling this private function should be marked as non-reentrant.*

```solidity
function _updateAndClaimFarmRewardsTo(uint256 _depositId, address _receiver) internal;
```

**Parameters**

| Name         | Type      | Description                                                     |
| ------------ | --------- | --------------------------------------------------------------- |
| `_depositId` | `uint256` | The id of the deposit.                                          |
| `_receiver`  | `address` | The receiver of the rewards (Could be different from depositor) |

### \_recoverRewardFunds

Get the remaining reward balance out of the farm.

*Function recovers minOf(\_amount, rewardsLeft).*

*In case of partial withdraw of funds, the reward rate has to be set manually again.*

```solidity
function _recoverRewardFunds(address _rwdToken, uint256 _amount) internal;
```

**Parameters**

| Name        | Type      | Description                                     |
| ----------- | --------- | ----------------------------------------------- |
| `_rwdToken` | `address` | The reward token's address.                     |
| `_amount`   | `uint256` | The amount of the reward token to be withdrawn. |

### \_setRewardRate

Function to update reward params for a fund.

```solidity
function _setRewardRate(address _rwdToken, uint128[] memory _newRewardRates) internal;
```

**Parameters**

| Name              | Type        | Description                                                |
| ----------------- | ----------- | ---------------------------------------------------------- |
| `_rwdToken`       | `address`   | The reward token's address.                                |
| `_newRewardRates` | `uint128[]` | The new reward rate for the fund (includes the precision). |

### \_setupFarm

Function to setup the reward funds and initialize the farm global params during construction.

```solidity
function _setupFarm(
    string calldata _farmId,
    uint256 _farmStartTime,
    uint256 _cooldownPeriod,
    RewardTokenData[] memory _rwdTokenData
) internal initializer;
```

**Parameters**

| Name              | Type                | Description                                                         |
| ----------------- | ------------------- | ------------------------------------------------------------------- |
| `_farmId`         | `string`            | ID of the farm. E.g: `Demeter_Camelot_V2`.                          |
| `_farmStartTime`  | `uint256`           | - Farm start time.                                                  |
| `_cooldownPeriod` | `uint256`           | - Cooldown period in days for locked deposits. E.g: 7 means 7 days. |
| `_rwdTokenData`   | `RewardTokenData[]` | - Reward data for each reward token.                                |

### \_addRewardData

Adds new reward token to the farm.

```solidity
function _addRewardData(address _token, address _tknManager) internal;
```

**Parameters**

| Name          | Type      | Description                              |
| ------------- | --------- | ---------------------------------------- |
| `_token`      | `address` | Address of the reward token to be added. |
| `_tknManager` | `address` | Address of the reward token Manager.     |

### \_updateLastRewardAccrualTime

Update the last reward accrual time.

```solidity
function _updateLastRewardAccrualTime() internal virtual;
```

### \_getAccRewards

Computes the accrued reward for a given fund id and time interval.

*`_alreadyAccRewardBal` is useful when this function called from `computeRewards` function. As `computeReward` is a view function and it doesn't update the `accRewardBal` in the `rewardData`.*

```solidity
function _getAccRewards(uint8 _rwdId, uint8 _fundId, uint256 _time, uint256 _alreadyAccRewardBal)
    internal
    view
    returns (uint256);
```

**Parameters**

| Name                   | Type      | Description                               |
| ---------------------- | --------- | ----------------------------------------- |
| `_rwdId`               | `uint8`   | Id of the reward token.                   |
| `_fundId`              | `uint8`   | Id of the reward fund.                    |
| `_time`                | `uint256` | Time interval for the reward computation. |
| `_alreadyAccRewardBal` | `uint256` | Already accrued reward balance.           |

**Returns**

| Name     | Type      | Description                                                               |
| -------- | --------- | ------------------------------------------------------------------------- |
| `<none>` | `uint256` | accRewards Accrued rewards for the given `_rwdId`, `_fundId` and `_time`. |

### \_validateDeposit

Validate the deposit for account.

```solidity
function _validateDeposit(address _account, uint256 _depositId) internal view;
```

**Parameters**

| Name         | Type      | Description                                            |
| ------------ | --------- | ------------------------------------------------------ |
| `_account`   | `address` | Address of the caller to be checked against depositor. |
| `_depositId` | `uint256` | Id of the deposit.                                     |

### \_validateNotRecentDeposit

A function to validate deposit ts to prevent flash loan vulnerabilities

*Reverts when deposit made in the same transaction.*

```solidity
function _validateNotRecentDeposit(uint256 _depositTs) internal view;
```

**Parameters**

| Name         | Type      | Description                                                                   |
| ------------ | --------- | ----------------------------------------------------------------------------- |
| `_depositTs` | `uint256` | depositTs of user's deposit. (It represents deposit ts or increaseDeposit ts) |

### \_validateFarmOpen

Validate if farm is open. Revert otherwise.

*This function can be overridden to add any new/additional logic.*

```solidity
function _validateFarmOpen() internal view;
```

### \_validateFarmActive

Validate if farm is active. Revert otherwise. Farm is active if it is not paused and not closed.

*This function can be overridden to add any new/additional logic.*

```solidity
function _validateFarmActive() internal view;
```

### \_validateTokenManager

Validate the caller is the token Manager. Revert otherwise.

```solidity
function _validateTokenManager(address _rwdToken) internal view;
```

**Parameters**

| Name        | Type      | Description              |
| ----------- | --------- | ------------------------ |
| `_rwdToken` | `address` | Address of reward token. |

### \_validateRewardToken

Validate the reward token is valid.

```solidity
function _validateRewardToken(address _rwdToken) internal view;
```

**Parameters**

| Name        | Type      | Description              |
| ----------- | --------- | ------------------------ |
| `_rwdToken` | `address` | Address of reward token. |

### \_getRewardAccrualTimeElapsed

Get the time elapsed since the last reward accrual.

```solidity
function _getRewardAccrualTimeElapsed() internal view virtual returns (uint256);
```

**Returns**

| Name     | Type      | Description                                          |
| -------- | --------- | ---------------------------------------------------- |
| `<none>` | `uint256` | time The time elapsed since the last reward accrual. |

### \_validateCooldownPeriod

An internal function to validate cooldown period.

```solidity
function _validateCooldownPeriod(uint256 _cooldownPeriod) internal pure;
```

**Parameters**

| Name              | Type      | Description             |
| ----------------- | --------- | ----------------------- |
| `_cooldownPeriod` | `uint256` | Period to be validated. |

### \_validateNonZeroAddr

Validate address.

```solidity
function _validateNonZeroAddr(address _addr) internal pure;
```

**Parameters**

| Name    | Type      | Description              |
| ------- | --------- | ------------------------ |
| `_addr` | `address` | Address to be validated. |

### \_subscribeRewardFund

Add subscription to the reward fund for a deposit.

```solidity
function _subscribeRewardFund(uint8 _fundId, uint256 _depositId, uint256 _liquidity) private;
```

**Parameters**

| Name         | Type      | Description                   |
| ------------ | --------- | ----------------------------- |
| `_fundId`    | `uint8`   | The reward fund id.           |
| `_depositId` | `uint256` | The unique ID of the deposit. |
| `_liquidity` | `uint256` | The liquidity of the deposit. |

### \_unsubscribeRewardFund

Unsubscribe a reward fund from a deposit.

*The rewards claimed from the reward fund is persisted in the event.*

```solidity
function _unsubscribeRewardFund(uint8 _fundId, uint256 _depositId) private;
```

**Parameters**

| Name         | Type      | Description                               |
| ------------ | --------- | ----------------------------------------- |
| `_fundId`    | `uint8`   | The reward fund id.                       |
| `_depositId` | `uint256` | The deposit id corresponding to the user. |
