# NFTXInventoryStakingV3Upgradeable

This contract allows users to stake vTokens to earn fees. Inventory staking positions are minted as xNFTs.&#x20;

## Table of Contents

<details>

<summary>Constants</summary>

[#minimum\_liquidity](#minimum_liquidity "mention")\
[#vtoken\_timelock](#vtoken_timelock "mention")\
[#weth](#weth "mention")\
[#permit2](#permit2 "mention")\
[#nftxvaultfactory](#nftxvaultfactory "mention")\
[#timelockexcludelist](#timelockexcludelist "mention")\
[#max\_timelock](#max_timelock "mention")\
[#max\_early\_withdraw\_penalty](#max_early_withdraw_penalty "mention")\
[#base](#base "mention")

</details>

<details>

<summary>Variables</summary>

[#timelock](#timelock "mention")\
[#earlywithdrawpenaltyinwei](#earlywithdrawpenaltyinwei "mention")\
[#positions](#positions "mention")\
[#vaultglobal](#vaultglobal "mention")\
[#descriptor](#descriptor "mention")

</details>

<details>

<summary>Events</summary>

[#deposit](#deposit "mention")\
[#depositwithnft](#depositwithnft "mention")\
[#combinepositions](#combinepositions "mention")\
[#collectwethfees](#collectwethfees "mention")\
[#withdraw](#withdraw "mention")\
[#updatetimelock](#updatetimelock "mention")\
[#updateearlywithdrawpenalty](#updateearlywithdrawpenalty "mention")

</details>

<details>

<summary>Public Write Functions</summary>

[#deposit-1](#deposit-1 "mention")\
[#depositwithnft-1](#depositwithnft-1 "mention")\
[#increaseposition](#increaseposition "mention")\
[#withdraw-1](#withdraw-1 "mention")\
[#combinepositions-1](#combinepositions-1 "mention")\
[#collectwethfees-1](#collectwethfees-1 "mention")\
[#receivewethrewards](#receivewethrewards "mention")

</details>

<details>

<summary>Owner Write Functions</summary>

[#settimelock](#settimelock "mention")\
[#setearlywithdrawpenalty](#setearlywithdrawpenalty "mention")

</details>

<details>

<summary>Read Functions</summary>

[#pricepersharevtoken](#pricepersharevtoken "mention")

</details>

## Constants

#### MINIMUM\_LIQUIDITY

```solidity
uint256 public constant override MINIMUM_LIQUIDITY = 1_000
```

The minimum amount of vToken required to be staked if the total vToken shares are 0 for that vault.

#### VTOKEN\_TIMELOCK

```solidity
uint256 private constant VTOKEN_TIMELOCK = 1 hours
```

The timelock applied to all xNFTs made by depositing vToken, even if `forceTimelock` is false.

#### WETH

```solidity
function WETH() external view returns (address)
```

Address of `WETH` contract.

#### PERMIT2

```solidity
function PERMIT2() external returns (address)
```

Address of PERMIT2 contract.&#x20;

#### nftxVaultFactory

```solidity
function nftxVaultFactory() external view returns (address)
```

Address of NFTX Vault Factory.

#### timelockExcludeListYeah&#x20;

```solidity
function timelockExcludeList() external view returns (address)
```

List of addresses excluded from having timelocks enforced.

#### MAX\_TIMELOCK

```solidity
uint256 constant MAX_TIMELOCK = 14 days
```

Max timelock duration possible to have set.

#### MAX\_EARLY\_WITHDRAW\_PENALTY

```solidity
uint256 constant MAX_EARLY_WITHDRAW_PENALTY = 1 ether
```

Max early withdrawal penalty, 10e16 = 1%.&#x20;

#### BASE

```solidity
uint256 constant BASE = 1 ether
```

Equal to 10e18.

## Variables

#### timelock

```solidity
function timelock() external view returns (uint256)
```

The timelock duration applied to a position (when minted with NFTs or with forceTimelock).

#### earlyWithdrawPenaltyInWei

```solidity
function earlyWithdrawPenaltyInWei() external view returns (uint256)
```

Early withdrawal penalty. 1e16 = 1%.

#### positions

```solidity
function positions(
    uint256 positionId
)
    external
    view
    returns (
        uint256 nonce,
        uint256 vaultId,
        uint256 timelockedUntil,
        uint256 timelock,
        uint256 vTokenTimelockedUntil,
        uint256 vTokenShareBalance,
        uint256 wethFeesPerVTokenShareSnapshotX128,
        uint256 wethOwed
    )
```

Inventory staking data related to each positionId.&#x20;

#### vaultGlobal

```solidity
function vaultGlobal(
    uint256 vaultId
)
    external
    view
    returns (
        uint256 totalVTokenShares,
        uint256 globalWethFeesPerVTokenShareX128
    )
```

Inventory staking data related to each vaultId. &#x20;

#### descriptor

```solidity
function descriptor() external view returns (address)
```

Contract responsible for generating tokenURI for xNFT positions.

## Events

#### Deposit

```solidity
event Deposit(
    uint256 indexed vaultId,
    uint256 indexed positionId,
    uint256 amount,
    bool forceTimelock
)
```

Emitted by `deposit()`.&#x20;

<table><thead><tr><th width="182.33333333333331">Parameters</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>vaultId</td><td><code>uint256</code></td><td>ID of vault.</td></tr><tr><td>positionId</td><td><code>uint256</code></td><td>ID of staking position.</td></tr><tr><td>amount</td><td><code>uint256</code></td><td>Amount of vToken being deposited.</td></tr><tr><td>forceTimelock</td><td><code>bool</code></td><td>Whether to force a full timelock. Forcing a full timelock allows vToken inventory stakers to off-ramp to NFTs (without paying redeem fees) when they are done staking.</td></tr></tbody></table>

#### DepositWithNFT

```solidity
event DepositWithNFT(
    uint256 indexed vaultId,
    uint256 indexed positionId,
    uint256[] tokenIds,
    uint256[] amounts
)
```

Emitted by `depositWithNFF()`.

<table><thead><tr><th width="182.33333333333331">Parameters</th><th width="131">Type</th><th>Description</th></tr></thead><tbody><tr><td>vaultId</td><td><code>uint256</code></td><td>ID of vault. </td></tr><tr><td>positionId</td><td><code>uint256</code></td><td>ID of staking position.</td></tr><tr><td>tokenIds</td><td><code>uint256[]</code></td><td>Token IDs of NFTs being deposited.</td></tr><tr><td>amounts</td><td><code>uint256[]</code></td><td>Amounts of NFTs (for ERC1155).</td></tr></tbody></table>

#### CombinePositions

```solidity
event CombinePositions(
    uint256 parentPositionId,
    uint256[] childPositionIds
)
```

Emitted by `combinePosition()`.

<table><thead><tr><th width="182.33333333333331">Parameters</th><th width="131">Type</th><th>Description</th></tr></thead><tbody><tr><td>parentPositionId</td><td><code>uint256</code></td><td>ID number of parent position.</td></tr><tr><td>childPositionIds</td><td><code>uint256[]</code></td><td>ID numbers of child positions being merged into parent.</td></tr></tbody></table>

#### CollectWethFees

```solidity
event CollectWethFees(uint256 indexed positionId, uint256 wethAmount)
```

Emitted by `collectWethFees()`.

<table><thead><tr><th width="182.33333333333331">Parameters</th><th width="131">Type</th><th>Description</th></tr></thead><tbody><tr><td>positionId</td><td><code>uint256</code></td><td>ID of staking position.</td></tr><tr><td>wethAmount</td><td><code>uint256</code></td><td>Amount of WETH.</td></tr></tbody></table>

#### Withdraw

```solidity
event Withdraw(
    uint256 indexed positionId,
    uint256 vTokenShares,
    uint256 vTokenAmount,
    uint256 wethAmount
)
```

Emitted by `withdraw()`.

<table><thead><tr><th width="182.33333333333331">Parameters</th><th width="131">Type</th><th>Description</th></tr></thead><tbody><tr><td>positionId</td><td><code>uint256</code></td><td>ID of staking position.</td></tr><tr><td>vTokenShares</td><td><code>uint256</code></td><td>Amount of vToken shares subtracted from the position as a result of removing vToken.</td></tr><tr><td>vTokenAmount</td><td><code>uint256</code></td><td>Amount of vToken returned to sender.</td></tr><tr><td>wethAmount</td><td><code>uint256</code></td><td>Amount of WETH (fees) returned to sender.</td></tr></tbody></table>

#### UpdateTimelock

```solidity
event UpdateTimelock(uint256 newTimelock)
```

Emitted by `setTimelock()`.

<table><thead><tr><th width="182.33333333333331">Parameters</th><th width="131">Type</th><th>Description</th></tr></thead><tbody><tr><td>newTimelock</td><td><code>uint256</code></td><td>New timelock duration. In seconds. </td></tr></tbody></table>

#### UpdateEarlyWithdrawPenalty

```solidity
event UpdateEarlyWithdrawPenalty(uint256 newEarlyWithdrawPenaltyInWei)
```

Emitted by `setEarlyWithdrawPenalty()`.

<table><thead><tr><th width="287.3333333333333">Parameters</th><th width="118">Type</th><th>Description</th></tr></thead><tbody><tr><td>newEarlyWithdrawPenaltyInWei</td><td><code>uint256</code></td><td>New early withdrawal penalty. 1e16 = 1%.</td></tr></tbody></table>

## Write Functions

#### deposit

```solidity
function deposit(
    uint256 vaultId,
    uint256 amount,
    address recipient,
    bytes calldata encodedPermit2,
    bool viaPermit2,
    bool forceTimelock
) external returns (uint256 positionId)
```

Pulls vToken from the caller and returns an xNFT inventory staking position. Uses Uniswap's Permit2 contract for vToken approval and transfer, if specified. The xNFT position will have a 1-hour (hard) timelock, during which time the position cannot be withdrawn. &#x20;

If the deposit is the first deposit that the inventory staking pool has ever received, then `MINIMUM_LIQUIDITY` (i.e, 1000 wei) of the vTokenShares are locked up forever to prevent [front-running attacks](https://ethereum-magicians.org/t/address-eip-4626-inflation-attacks-with-virtual-shares-and-assets/12677).

If `forceTimelock` is set to false, then no regular timelock is applied and the position can be increased using `increasePosition()` but the owner of the position can only withdraw/off-ramp back to vToken (not NFTs).&#x20;

If `forceTimelock` is set to true, then a regular 3-day timelock is applied in addition to the hard 1-hour timelock. Unlike the hard 1-hour time-lock, the regular 3-day timelock allows early withdrawals by charging a fee that begins at 10% and goes down linearly to zero over the duration of the timelock. The benefit of setting `forceTimelock` to `true` is that the owner of the position can withdraw/off-ramp to either vToken or NFTs.&#x20;

<table><thead><tr><th width="174.5">Parameters</th><th width="129">Type</th><th>Description</th></tr></thead><tbody><tr><td>vaultId</td><td><code>uint256</code></td><td>The vault ID of the vToken being deposited.</td></tr><tr><td>amount</td><td><code>uint256</code></td><td>The amount of vToken to deposit.</td></tr><tr><td>recipient</td><td><code>address</code></td><td>The address which will receive the xNFT. </td></tr><tr><td>encodedPermit2</td><td><code>bytes</code></td><td><p>Encoded Permit2 data:</p><pre class="language-solidity"><code class="lang-solidity">address owner,
IPermitAllowanceTransfer.PermitSingle,
bytes memory signature
</code></pre></td></tr><tr><td>viaPermit2</td><td><code>bool</code></td><td>Whether to use Permit2.</td></tr><tr><td>forceTimelock</td><td><code>bool</code></td><td>Whether to force a full 3-day timelock. See paragraph above for more details.</td></tr></tbody></table>

<table><thead><tr><th width="172.5">Return values</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>positionId</td><td><code>uint256</code></td><td>ID of the new inventory position.</td></tr></tbody></table>

#### depositWithNFT

```solidity
function depositWithNFT(
    uint256 vaultId,
    uint256[] calldata tokenIds,
    uint256[] calldata amounts,
    address recipient
) external returns (uint256 positionId)
```

Pulls NFTs from sender, mints, and stakes vToken, and returns an xNFT inventory staking position. The xNFT position will have a 3-day timelock, during which time an early withdrawal penalty is charged in vToken if the owner of the position decides to withdraw. The early withdrawal penalty is 10% of the position and goes down linearly to zero over the duration of the timelock.&#x20;

If the deposit is the first deposit that the inventory staking pool has ever received, then `MINIMUM_LIQUIDITY` (i.e, 1000 wei) of the vTokenShares are locked up forever to prevent [front-running attacks](https://ethereum-magicians.org/t/address-eip-4626-inflation-attacks-with-virtual-shares-and-assets/12677).

<table><thead><tr><th width="174.5">Parameters</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>vaultId</td><td><code>uint256</code></td><td>Vault ID of the vToken to be minted and staked.</td></tr><tr><td>tokenIDs</td><td><code>uint256[]</code></td><td>Token IDs of NFTs being deposited.</td></tr><tr><td>amounts</td><td><code>uint256[]</code></td><td>Amounts of NFTs (for ERC1155).</td></tr><tr><td>recipient</td><td><code>address</code></td><td>Address which receives the xNFT. </td></tr></tbody></table>

<table><thead><tr><th width="172.5">Return values</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>positionId</td><td><code>uint256</code></td><td>ID of the newly minted xNFT inventory position.</td></tr></tbody></table>

#### increasePosition

```solidity
function increasePosition(
    uint256 positionId,
    uint256 amount,
    bytes calldata encodedPermit2,
    bool viaPermit2,
    bool forceTimelock
) external
```

Increases the size of an inventory staking position that was created using vToken and did not force a regular 3-day timelock. Positions can be increased more than once as long as `forceTimelock` is `false`. After a position is increased with `forceTimelock` as `true`, then it can no longer be increased. It can, however, still be combined with other positions.

<table><thead><tr><th width="174.5">Parameters</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>positionId</td><td><code>uint256</code></td><td>ID number of staking position.</td></tr><tr><td>amount</td><td><code>uint256</code></td><td>Amount of vToken.</td></tr><tr><td>encodedPermit2</td><td><code>bytes</code></td><td><p>Encoded Permit2 data:</p><pre class="language-solidity"><code class="lang-solidity">address owner,
IPermitAllowanceTransfer.PermitSingle,
bytes memory signature
</code></pre></td></tr><tr><td>viaPermit2</td><td><code>bool</code></td><td>Whether to use Permit2.</td></tr><tr><td>forceTimelock</td><td><code>bool</code></td><td>Whether to force a regular timelock. If a full timelock is enforced, then the position can not be increased again; however, it can still be combined with other positions.</td></tr></tbody></table>

#### withdraw

```solidity
function withdraw(
    uint256 positionId,
    uint256 vTokenShares,
    uint256[] calldata nftIds,
    uint256 vTokenPremiumLimit
) external payable override nonReentrant
```

Reduces a position's `vTokenShares` and returns vToken/NFTs and ETH to the caller. Charges an early withdrawal penalty, paid in vToken, if the position has an active timelock. The penalty begins at 10% and goes down linearly to zero over the 3-day timelock duration. Early withdrawals are not possible for vToken -created positions unless they forced a full 3-day timelock,

<table><thead><tr><th width="205.5">Parameters</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>positionId</td><td><code>uint256</code></td><td>ID of the position.</td></tr><tr><td>vTokenShares</td><td><code>uint256</code></td><td>Number of vTokenShares to withdraw.</td></tr><tr><td>nftIds</td><td><code>uint256[]</code></td><td>NFT IDs to redeem.</td></tr><tr><td>vTokenPremiumLimit</td><td><code>uint256</code></td><td>Max total premium fee (denominated in vToken) to be paid.</td></tr><tr><td><code>msg.value</code></td><td><code>uint256</code></td><td>Amount of ETH to send. </td></tr></tbody></table>

#### combinePositions

```solidity
function combinePositions(
    uint256 parentPositionId,
    uint256[] calldata childPositionIds
) external
```

Merges one or more child positions into a parent position. Requires that there are no timelocks remaining on any of the child positions.&#x20;

<table><thead><tr><th width="174.5">Parameters</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>parentPositionId</td><td><code>uint256</code></td><td>The position that child positions merge into. </td></tr><tr><td>childPositionIds</td><td><code>uint256[]</code></td><td>The positions being merged into a parent position.</td></tr></tbody></table>

#### collectWethFees&#x20;

```solidity
function collectWethFees(uint256[] calldata positionIds) external
```

Claims WETH fees from one or more positions.

<table><thead><tr><th width="201.5">Parameters</th><th width="130">Type</th><th>Description</th></tr></thead><tbody><tr><td>positionIds</td><td><code>uint256[]</code></td><td>IDs of the positions.</td></tr></tbody></table>

#### receiveWethRewards&#x20;

```solidity
function receiveWethRewards(
    uint256 vaultId,
    uint256 wethAmount
) external returns (bool rewardsDistributed)
```

Retrieves WETH rewards. Only callable by fee distributor.&#x20;

<table><thead><tr><th width="201.5">Parameters</th><th width="130">Type</th><th>Description</th></tr></thead><tbody><tr><td>vaultId</td><td><code>uint256</code></td><td>ID number of vault. </td></tr><tr><td>wethAmount</td><td><code>uint256</code></td><td>Amount of WETH.</td></tr></tbody></table>

<table><thead><tr><th width="201.5">Return values</th><th width="130">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardsDistributed</td><td><code>bool</code></td><td>True if function completes successfully.</td></tr></tbody></table>

## Owner Functions

#### setTimelock

```solidity
function setTimelock(uint256 timelock_) external
```

Sets the timelock duration for future deposits.&#x20;

<table><thead><tr><th width="201.5">Parameters</th><th width="130">Type</th><th>Description</th></tr></thead><tbody><tr><td>timelock_</td><td><code>uint256</code></td><td>New timelock duration, in seconds.</td></tr></tbody></table>

#### setEarlyWithdrawPenalty

```solidity
function setEarlyWithdrawPenalty(
    uint256 earlyWithdrawPenaltyInWei_
) external
```

Sets the early withdraw penalty for current and future deposits.&#x20;

<table><thead><tr><th width="263.5">Parameters</th><th width="109">Type</th><th>Description</th></tr></thead><tbody><tr><td>earlyWithdrawPenaltyInWei_</td><td><code>uint256</code></td><td>New early withdraw penalty. 10e16 = 1%.</td></tr></tbody></table>

## Read Functions

#### pricePerShareVToken

```solidity
function pricePerShareVToken(uint256 vaultId) external view returns (uint256)
```

Returns the ratio of vTokens per share. &#x20;

<table><thead><tr><th width="201.5">Parameters</th><th width="130">Type</th><th>Description</th></tr></thead><tbody><tr><td>vaultId</td><td><code>uint256</code></td><td>Vault ID of the vToken.</td></tr></tbody></table>

<table><thead><tr><th width="201.5">Name</th><th width="130">Type</th><th>Description</th></tr></thead><tbody><tr><td><em>unnamed</em></td><td><code>uint256</code></td><td>vTokens per share. </td></tr></tbody></table>

#### wethBalance

```solidity
function wethBalance(uint256 positionId) external view returns (uint256)
```

Returns the amount of WETH that can be claimed by the xNFT with `positionId`.

<table><thead><tr><th width="201.5">Parameters</th><th width="130">Type</th><th>Description</th></tr></thead><tbody><tr><td>positionID</td><td><code>uint256</code></td><td>ID of position.</td></tr></tbody></table>

<table><thead><tr><th width="201.5">Return values</th><th width="130">Type</th><th>Description</th></tr></thead><tbody><tr><td><em>unnamed</em></td><td><code>uint256</code></td><td>WETH balance of position.</td></tr></tbody></table>


---

# 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.nftx.io/core-contracts/nftxinventorystakingv3upgradeable.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.
