# VotingEscrow

**Inherits:** [HistoricalBalance](https://docs.mav.xyz/technical-reference/maverick-v2/v2-contracts/maverick-v2-reward-contracts/votingescrowbase/historicalbalance),[ IMaverickV2VotingEscrowBase](https://docs.mav.xyz/technical-reference/maverick-v2/v2-contracts/maverick-v2-reward-contracts/interfaces/imaverickv2votingescrowbase), ReentrancyGuard, [Multicall](https://docs.mav.xyz/technical-reference/maverick-v2/v2-contracts/maverick-v2-common-contracts/base/multicall)

Provides staking, vote power history, vote delegation. The balance received for staking (and thus the voting power) goes up exponentially by the end of the staked period.

### State Variables <a href="#state-variables" id="state-variables"></a>

#### YEAR\_BASE <a href="#year_base" id="year_base"></a>

```solidity
uint256 public constant YEAR_BASE = 1.5e18;
```

#### startTimestamp <a href="#starttimestamp" id="starttimestamp"></a>

This function retrieves the starting timestamp. This may be used for reward calculations or other time-based logic.

```solidity
uint256 public immutable startTimestamp;
```

#### MIN\_STAKE\_DURATION <a href="#min_stake_duration" id="min_stake_duration"></a>

```solidity
uint256 public constant MIN_STAKE_DURATION = 4 weeks;
```

#### MAX\_STAKE\_DURATION <a href="#max_stake_duration" id="max_stake_duration"></a>

```solidity
uint256 public constant MAX_STAKE_DURATION = 4 * (365 days);
```

#### \_lockups <a href="#lockups" id="lockups"></a>

```solidity
mapping(address => Lockup[]) internal _lockups;
```

#### \_extenders <a href="#extenders" id="extenders"></a>

```solidity
mapping(address => mapping(address => mapping(uint256 => bool))) internal _extenders;
```

#### baseToken <a href="#basetoken" id="basetoken"></a>

This function retrieves the address of the ERC20 token used as the base token for staking and rewards.

```solidity
IERC20 public immutable baseToken;
```

### Functions <a href="#functions" id="functions"></a>

#### constructor <a href="#constructor" id="constructor"></a>

```solidity
constructor(string memory __name, string memory __symbol) ERC20(__name, __symbol) EIP712(__name, "1");
```

#### \_stake <a href="#stake" id="stake"></a>

Internal function that stakes an amount for a duration to an address.

This function validates that `to` is not the zero address and that the duration is within bounds.

Function also does a transferFrom for the base token amount. This requires that the sender approve this ve contract to be able to transfer tokens for the sender.

```solidity
function _stake(uint128 amount, uint256 duration, address to, uint256 lockupId)
    internal
    nonReentrant
    returns (Lockup memory lockup);
```

#### \_unstake <a href="#unstake" id="unstake"></a>

Internal function that unstakes an account's lockup.

This function validates that the lockup has not already been claimed and does burn the account's voting votes.

But the function does not transfer the baseTokens to the staker. That transfer operation must be executed seperately as appropiate.

This function also does not validate that the lockup end time has passed nor does it validate that `account` has permissions to unstake this lockupId.

```solidity
function _unstake(address account, uint256 lockupId) internal returns (Lockup memory lockup);
```

#### \_extend <a href="#extend" id="extend"></a>

Internal function that extends an account's lockup.

This function validates that the lockup has not already been claimed.

This function also does not validate that the `account` has permissions to unstake this lockupId.

```solidity
function _extend(address account, uint256 lockupId, uint256 duration, uint128 amount)
    internal
    returns (Lockup memory newLockup);
```

#### stake <a href="#stake" id="stake"></a>

This function stakes a specified amount of tokens for a defined duration, allowing the caller (msg.sender) to specify an optional recipient for the staked tokens.

```solidity
function stake(uint128 amount, uint256 duration, address to) public returns (Lockup memory lockup);
```

**Parameters**

| Name       | Type      | Description                                                                                 |
| ---------- | --------- | ------------------------------------------------------------------------------------------- |
| `amount`   | `uint128` | The amount of tokens to be staked.                                                          |
| `duration` | `uint256` | The duration of the lockup period.                                                          |
| `to`       | `address` | The address to which the staked tokens will be credited (optional, defaults to msg.sender). |

**Returns**

| Name     | Type     | Description                                                                                            |
| -------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `lockup` | `Lockup` | A Lockup struct containing details about the newly created lockup (see struct definition for details). |

#### stakeToSender <a href="#staketosender" id="staketosender"></a>

This function stakes a specified amount of tokens for the caller (msg.sender) for a defined duration.

```solidity
function stakeToSender(uint128 amount, uint256 duration) public virtual returns (Lockup memory lockup);
```

**Parameters**

| Name       | Type      | Description                        |
| ---------- | --------- | ---------------------------------- |
| `amount`   | `uint128` | The amount of tokens to be staked. |
| `duration` | `uint256` | The duration of the lockup period. |

**Returns**

| Name     | Type     | Description                                                                                            |
| -------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `lockup` | `Lockup` | A Lockup struct containing details about the newly created lockup (see struct definition for details). |

#### unstake <a href="#unstake" id="unstake"></a>

This function unstakes the specified lockup ID for the caller (msg.sender), returning the details of the unstaked lockup.

```solidity
function unstake(uint256 lockupId, address to) public nonReentrant returns (Lockup memory lockup);
```

**Parameters**

| Name       | Type      | Description                                                                                 |
| ---------- | --------- | ------------------------------------------------------------------------------------------- |
| `lockupId` | `uint256` | The ID of the lockup to be unstaked.                                                        |
| `to`       | `address` | The address to which the unstaked tokens should be sent (optional, defaults to msg.sender). |

**Returns**

| Name     | Type     | Description                                                                                       |
| -------- | -------- | ------------------------------------------------------------------------------------------------- |
| `lockup` | `Lockup` | A Lockup struct containing details about the unstaked lockup (see struct definition for details). |

#### unstakeToSender <a href="#unstaketosender" id="unstaketosender"></a>

This function is a simplified version of `unstake` that automatically sends the unstaked tokens to the caller (msg.sender).

```solidity
function unstakeToSender(uint256 lockupId) public returns (Lockup memory lockup);
```

**Parameters**

| Name       | Type      | Description                          |
| ---------- | --------- | ------------------------------------ |
| `lockupId` | `uint256` | The ID of the lockup to be unstaked. |

**Returns**

| Name     | Type     | Description                                                                                       |
| -------- | -------- | ------------------------------------------------------------------------------------------------- |
| `lockup` | `Lockup` | A Lockup struct containing details about the unstaked lockup (see struct definition for details). |

#### merge <a href="#merge" id="merge"></a>

This function merges multiple lockups associated with the caller (msg.sender) into a single new lockup.

```solidity
function merge(uint256[] memory lockupIds) public returns (Lockup memory newLockup);
```

**Parameters**

| Name        | Type        | Description                                              |
| ----------- | ----------- | -------------------------------------------------------- |
| `lockupIds` | `uint256[]` | An array containing the IDs of the lockups to be merged. |

**Returns**

| Name        | Type     | Description                                                                                           |
| ----------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `newLockup` | `Lockup` | A Lockup struct containing details about the newly merged lockup (see struct definition for details). |

#### extendForSender <a href="#extendforsender" id="extendforsender"></a>

This function extends the lockup period for the caller (msg.sender) for a specified lockup ID, adding a new duration and amount.

```solidity
function extendForSender(uint256 lockupId, uint256 duration, uint128 amount)
    public
    virtual
    returns (Lockup memory newLockup);
```

**Parameters**

| Name       | Type      | Description                                      |
| ---------- | --------- | ------------------------------------------------ |
| `lockupId` | `uint256` | The ID of the lockup to be extended.             |
| `duration` | `uint256` | The additional duration to extend the lockup by. |
| `amount`   | `uint128` | The additional amount of tokens to be locked.    |

**Returns**

| Name        | Type     | Description                                                                                             |
| ----------- | -------- | ------------------------------------------------------------------------------------------------------- |
| `newLockup` | `Lockup` | A Lockup struct containing details about the newly extended lockup (see struct definition for details). |

#### extendForAccount <a href="#extendforaccount" id="extendforaccount"></a>

This function extends the lockup period for a specified account, adding a new duration and amount. The caller (msg.sender) must be authorized to manage the lockup through an extender contract.

```solidity
function extendForAccount(address account, uint256 lockupId, uint256 duration, uint128 amount)
    public
    returns (Lockup memory newLockup);
```

**Parameters**

| Name       | Type      | Description                                                |
| ---------- | --------- | ---------------------------------------------------------- |
| `account`  | `address` | The address of the account whose lockup is being extended. |
| `lockupId` | `uint256` | The ID of the lockup to be extended.                       |
| `duration` | `uint256` | The additional duration to extend the lockup by.           |
| `amount`   | `uint128` | The additional amount of tokens to be locked.              |

**Returns**

| Name        | Type     | Description                                                                                             |
| ----------- | -------- | ------------------------------------------------------------------------------------------------------- |
| `newLockup` | `Lockup` | A Lockup struct containing details about the newly extended lockup (see struct definition for details). |

#### approveExtender <a href="#approveextender" id="approveextender"></a>

This function grants approval for a designated extender contract to manage a specific lockup on behalf of the staker.

```solidity
function approveExtender(address extender, uint256 lockupId) public;
```

**Parameters**

| Name       | Type      | Description                                          |
| ---------- | --------- | ---------------------------------------------------- |
| `extender` | `address` | The address of the extender contract to be approved. |
| `lockupId` | `uint256` | The ID of the lockup for which to grant approval.    |

#### revokeExtender <a href="#revokeextender" id="revokeextender"></a>

This function revokes approval previously granted to an extender contract for managing a specific lockup.

```solidity
function revokeExtender(address extender, uint256 lockupId) public;
```

**Parameters**

| Name       | Type      | Description                                                           |
| ---------- | --------- | --------------------------------------------------------------------- |
| `extender` | `address` | The address of the extender contract whose approval is being revoked. |
| `lockupId` | `uint256` | The ID of the lockup for which to revoke approval.                    |

#### isApprovedExtender <a href="#isapprovedextender" id="isapprovedextender"></a>

This function checks whether a specific account has been approved by a staker to manage a particular lockup through an extender contract.

```solidity
function isApprovedExtender(address account, address extender, uint256 lockupId) public view returns (bool);
```

**Parameters**

| Name       | Type      | Description                                                                                |
| ---------- | --------- | ------------------------------------------------------------------------------------------ |
| `account`  | `address` | The address of the account to check for approval (may be the extender or another account). |
| `extender` | `address` | The address of the extender contract for which to check approval.                          |
| `lockupId` | `uint256` | The ID of the lockup to verify approval for.                                               |

**Returns**

| Name     | Type   | Description                                                                        |
| -------- | ------ | ---------------------------------------------------------------------------------- |
| `<none>` | `bool` | isApproved True if the account is approved for the lockup, False otherwise (bool). |

#### \_checkApprovedExtender <a href="#checkapprovedextender" id="checkapprovedextender"></a>

```solidity
function _checkApprovedExtender(address account, uint256 lockupId) internal view;
```

#### \_checkDuration <a href="#checkduration" id="checkduration"></a>

```solidity
function _checkDuration(uint256 duration) internal pure;
```

#### previewVotes <a href="#previewvotes" id="previewvotes"></a>

This function simulates a lockup scenario, providing details about the resulting lockup structure for a specified amount and duration.

```solidity
function previewVotes(uint128 amount, uint256 duration) public view returns (Lockup memory lockup);
```

**Parameters**

| Name       | Type      | Description                        |
| ---------- | --------- | ---------------------------------- |
| `amount`   | `uint128` | The amount of tokens to be locked. |
| `duration` | `uint256` | The duration of the lockup period. |

**Returns**

| Name     | Type     | Description                                                                                        |
| -------- | -------- | -------------------------------------------------------------------------------------------------- |
| `lockup` | `Lockup` | A Lockup struct containing details about the simulated lockup (see struct definition for details). |

#### getLockup <a href="#getlockup" id="getlockup"></a>

This function retrieves the details of a specific lockup for a given staker and lockup index.

```solidity
function getLockup(address staker, uint256 index) public view returns (Lockup memory lockup);
```

**Parameters**

| Name     | Type      | Description                                                         |
| -------- | --------- | ------------------------------------------------------------------- |
| `staker` | `address` | The address of the staker for which to retrieve the lockup details. |
| `index`  | `uint256` | The index of the lockup within the staker's lockup history.         |

**Returns**

| Name     | Type     | Description                                                                              |
| -------- | -------- | ---------------------------------------------------------------------------------------- |
| `lockup` | `Lockup` | A Lockup struct containing details about the lockup (see struct definition for details). |

#### lockupCount <a href="#lockupcount" id="lockupcount"></a>

This function retrieves the total number of lockups associated with a specific staker.

```solidity
function lockupCount(address staker) public view returns (uint256 count);
```

**Parameters**

| Name     | Type      | Description                                                       |
| -------- | --------- | ----------------------------------------------------------------- |
| `staker` | `address` | The address of the staker for which to retrieve the lockup count. |

**Returns**

| Name    | Type      | Description                                 |
| ------- | --------- | ------------------------------------------- |
| `count` | `uint256` | The total number of lockups for the staker. |

#### transfer <a href="#transfer" id="transfer"></a>

Transfers of voting balances are not allowed. This function will revert.

```solidity
function transfer(address, uint256) public pure override returns (bool);
```

#### transferFrom <a href="#transferfrom" id="transferfrom"></a>

Transfers of voting balances are not allowed. This function will revert.

```solidity
function transferFrom(address, address, uint256) public pure override returns (bool);
```

<br>


---

# 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.mav.xyz/technical-reference/maverick-v2/v2-contracts/maverick-v2-reward-contracts/votingescrowbase/votingescrow.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.
