# 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. |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sperax.io/sperax-farms-protocol/technical-documents/smart-contracts/base-contracts/farm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
