> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/reserve-protocol/reserve-index-dtf/llms.txt
> Use this file to discover all available pages before exploring further.

# StakingVault Contract

> ERC4626 vault with voting power, multi-token rewards, and configurable unstaking delays

## Overview

The **StakingVault** contract is a transferrable ERC4626 vault that enables staking of an underlying token to earn voting power and multi-token rewards. It implements the full ERC20Votes interface for governance participation and supports configurable unstaking delays for security.

### Key Features

* **ERC4626 Standard**: Full compatibility with vault standards
* **ERC20Votes**: Voting power delegation for governance
* **Multi-Token Rewards**: Support for unlimited reward tokens with drip distribution
* **Unstaking Delay**: Configurable delay for withdrawals
* **Exponential Reward Decay**: Smooth reward distribution using half-life model
* **Slashing Mechanism**: Ability to burn shares for punitive actions

### Architecture

StakingVault extends:

* ERC4626Upgradeable (vault functionality)
* ERC20PermitUpgradeable (gasless approvals)
* ERC20VotesUpgradeable (governance)
* OwnableUpgradeable (access control)
* UUPSUpgradeable (upgradeability)

## Staking Functions

### Deposit and Delegate

Deposit tokens and automatically self-delegate voting power.

<ParamField path="assets" type="uint256">
  Amount of underlying tokens to deposit
</ParamField>

```solidity StakingVault.sol theme={null}
function depositAndDelegate(uint256 assets) external returns (uint256 shares)
```

<Info>
  This convenience function combines `deposit()` and `delegate()` into a single transaction, automatically delegating voting power to yourself.
</Info>

### Burn (Slashing)

Burn shares and redistribute underlying tokens to remaining holders.

<ParamField path="_shares" type="uint256">
  Amount of shares to burn
</ParamField>

```solidity StakingVault.sol theme={null}
function burn(uint256 _shares) external
```

<Warning>
  This is a slashing function. Burned shares reduce the caller's balance and automatically distribute the underlying assets to all remaining stakers as native rewards.
</Warning>

## Unstaking Configuration

### Set Unstaking Delay

Configure the delay before withdrawn tokens become claimable.

<ParamField path="_delay" type="uint256">
  New unstaking delay in seconds (max 4 weeks)
</ParamField>

```solidity StakingVault.sol theme={null}
function setUnstakingDelay(uint256 _delay) external onlyOwner
```

<ParamField path="MAX_UNSTAKING_DELAY" type="uint256" default="4 weeks">
  Maximum allowed unstaking delay
</ParamField>

## Reward Management

### Add Reward Token

Add a new reward token to the vault.

<ParamField path="_rewardToken" type="address">
  Address of the reward token to add
</ParamField>

```solidity StakingVault.sol theme={null}
function addRewardToken(address _rewardToken) external onlyOwner
```

<Info>
  Reward tokens cannot be the vault's share token or underlying asset. The contract tracks the token's balance and distributes new tokens using an exponential decay curve.
</Info>

### Remove Reward Token

Remove a reward token from future distributions.

<ParamField path="_rewardToken" type="address">
  Address of the reward token to remove
</ParamField>

```solidity StakingVault.sol theme={null}
function removeRewardToken(address _rewardToken) external onlyOwner
```

<Warning>
  Users can still claim accrued rewards for removed tokens. This only stops new rewards from accumulating.
</Warning>

### Claim Rewards

Claim accumulated rewards for specified tokens.

<ParamField path="_rewardTokens" type="address[]">
  Array of reward token addresses to claim
</ParamField>

```solidity StakingVault.sol theme={null}
function claimRewards(
    address[] calldata _rewardTokens
) external returns (uint256[] memory claimableRewards)
```

### Set Reward Ratio

Configure the reward distribution rate via half-life.

<ParamField path="rewardHalfLife" type="uint256">
  Half-life for reward handout in seconds (1 day to 2 weeks)
</ParamField>

```solidity StakingVault.sol theme={null}
function setRewardRatio(uint256 rewardHalfLife) external onlyOwner
```

<ParamField path="MAX_REWARD_HALF_LIFE" type="uint256" default="2 weeks">
  Maximum reward half-life
</ParamField>

<ParamField path="MIN_REWARD_HALF_LIFE" type="uint256" default="1 day">
  Minimum reward half-life
</ParamField>

## View Functions

### Get All Reward Tokens

Retrieve all currently registered reward tokens.

```solidity StakingVault.sol theme={null}
function getAllRewardTokens() external view returns (address[] memory)
```

### Total Assets

Get total underlying assets including accrued native rewards.

```solidity StakingVault.sol theme={null}
function totalAssets() public view override returns (uint256)
```

### Poke

Manually trigger reward accrual for the caller.

```solidity StakingVault.sol theme={null}
function poke() external
```

<Info>
  This function is useful for updating your reward balances without performing a deposit or withdrawal.
</Info>

## Reward Tracking Structures

### RewardInfo

<ParamField path="payoutLastPaid" type="uint256">
  Timestamp of last reward calculation
</ParamField>

<ParamField path="rewardIndex" type="uint256">
  Cumulative reward per share (D18+decimals)
</ParamField>

<ParamField path="balanceAccounted" type="uint256">
  Amount of rewards already distributed to index
</ParamField>

<ParamField path="balanceLastKnown" type="uint256">
  Last known total balance of reward token
</ParamField>

<ParamField path="totalClaimed" type="uint256">
  Total amount claimed by all users
</ParamField>

### UserRewardInfo

<ParamField path="lastRewardIndex" type="uint256">
  User's last checkpoint reward index
</ParamField>

<ParamField path="accruedRewards" type="uint256">
  Unclaimed rewards for this user
</ParamField>

## Events

<ResponseField name="UnstakingDelaySet" type="event">
  Emitted when unstaking delay is updated

  **Parameters:**

  * `delay` - New unstaking delay in seconds
</ResponseField>

<ResponseField name="RewardTokenAdded" type="event">
  Emitted when a reward token is registered

  **Parameters:**

  * `rewardToken` - Address of the added reward token
</ResponseField>

<ResponseField name="RewardTokenRemoved" type="event">
  Emitted when a reward token is removed

  **Parameters:**

  * `rewardToken` - Address of the removed reward token
</ResponseField>

<ResponseField name="RewardsClaimed" type="event">
  Emitted when a user claims rewards

  **Parameters:**

  * `user` - Address claiming rewards
  * `rewardToken` - Token being claimed
  * `amount` - Amount claimed
</ResponseField>

<ResponseField name="RewardRatioSet" type="event">
  Emitted when reward distribution rate changes

  **Parameters:**

  * `rewardRatio` - New reward ratio (per-second rate)
  * `halfLife` - Corresponding half-life in seconds
</ResponseField>

## Unstaking Manager

When unstaking delay is non-zero, withdrawals are managed by a separate UnstakingManager contract:

<ParamField path="unstakingManager" type="UnstakingManager">
  Automatically deployed contract that holds tokens during unstaking period
</ParamField>

<Info>
  Users receive a lock ID when unstaking and must wait for the delay period before calling `claimLock()` on the UnstakingManager.
</Info>

## Usage Example

```solidity theme={null}
// Deposit and start earning rewards
uint256 shares = vault.depositAndDelegate(1000e18);

// Wait for rewards to accumulate
// ...

// Claim rewards
address[] memory tokens = vault.getAllRewardTokens();
uint256[] memory claimed = vault.claimRewards(tokens);

// Initiate withdrawal (creates lock if delay > 0)
vault.withdraw(shares, receiver, owner);

// After delay, claim from UnstakingManager
vault.unstakingManager().claimLock(lockId);
```

## Constants

<ParamField path="SCALAR" type="uint256" default="1e18">
  Scaling factor for reward calculations
</ParamField>

<ParamField path="LN_2" type="uint256" default="0.693147180559945309e18">
  Natural logarithm of 2 (for exponential decay)
</ParamField>
