> For the complete documentation index, see [llms.txt](https://docs-v4.nftx.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-v4.nftx.io/contracts/gacha-vault.md).

# NFTXGachaVault

NFTXGachaVault — the vault half of the gacha: the machine registry, bucketed NFT custody, the withdrawal state machine, and the depositor reward accumulator.

`NFTXGachaVault` is the **vault half** of a gacha machine. It owns the machine registry, custodies deposited NFTs in per-collection buckets, runs the request → mature → execute → expire withdrawal state machine, and streams spin revenue to depositors through a unit-based reward accumulator. The spin half — [NFTXGacha](/contracts/gacha.md) — draws inventory and distributes revenue through this contract's gated seam. Concepts are covered in the [Gacha](/gacha/gacha.md) section; this page is the function reference.

Function signatures below come from the `IGachaVault` / `IGachaRewards` interfaces. The contract is `Ownable`, `Pausable`, `ReentrancyGuard`, and inherits `TokenEscrow` for pull-payment reward withdrawals.

{% hint style="warning" %}
Gacha is **pre-mainnet**. `NFTXGachaVault` is deployed only on **Ethereum Sepolia** (`11155111`) at `0x4cDF1a772B8E076E10d112d1F72bbA7980925f5d`, as a rehearsal. There is no mainnet deployment. Always confirm against the on-chain record before integrating.
{% endhint %}

## Depositor surface

### `deposit`

Deposits NFTs of a whitelisted collection into a machine. Units are drawable immediately (they enter the next spin snapshot) but enter the reward denominator only after the activation delay (1h) — the anti-snipe guard.

```solidity
function deposit(uint _machineId, address _collection, uint[] calldata _tokenIds) external;
```

**Access:** `nonReentrant`, `whenNotPaused`. Reverts on an inactive or unknown machine, a collection the machine doesn't whitelist (`CollectionNotInMachine`), an empty token list (`NothingToDeposit`), or a deposit past the unit cap (`UnitCapExceeded`).

| Parameter     | Type      | Description                                          |
| ------------- | --------- | ---------------------------------------------------- |
| `_machineId`  | `uint`    | The machine to deposit into                          |
| `_collection` | `address` | The collection being deposited (must be whitelisted) |
| `_tokenIds`   | `uint[]`  | The token IDs to deposit                             |

**Returns:** None.

### `requestWithdrawal`

Opens a withdrawal request for whole units of a bucket. Rewards on those units stop immediately, and the units are excluded from new spin snapshots — but they stay in custody and remain winnable until the request executes.

```solidity
function requestWithdrawal(uint _machineId, address _collection, uint32 _units) external returns (uint withdrawalId_);
```

**Access:** `nonReentrant`. Reverts on zero units (`NothingToWithdraw`) or a request beyond the caller's withdrawable units net of other pending requests (`InsufficientWithdrawableUnits`).

| Parameter     | Type      | Description                  |
| ------------- | --------- | ---------------------------- |
| `_machineId`  | `uint`    | The machine to withdraw from |
| `_collection` | `address` | The bucket being withdrawn   |
| `_units`      | `uint32`  | Whole units to request       |

| Return          | Type   | Description                          |
| --------------- | ------ | ------------------------------------ |
| `withdrawalId_` | `uint` | The id of the new withdrawal request |

### `executeWithdrawal`

Completes a matured withdrawal. Transfers out `min(requested, currently withdrawable)` whole NFTs, chosen by contract order (never caller-named). Any shortfall — units the machine consumed during the delay — is re-credited to the owner as residual reward units.

```solidity
function executeWithdrawal(uint _withdrawalId) external;
```

**Access:** `nonReentrant`. Reverts if the request doesn't exist (`WithdrawalRequestDoesNotExist`) or hasn't matured (`WithdrawalNotMatured`); a matured request expires after its 48-hour execution window and must be re-requested.

| Parameter       | Type   | Description                       |
| --------------- | ------ | --------------------------------- |
| `_withdrawalId` | `uint` | The matured withdrawal to execute |

**Returns:** None. Assets always transfer to the request's owner, whoever calls.

## Rewards

### `harvest`

Settles an account's pending rewards for a machine into its `TokenEscrow` balance; the account then calls `withdraw` to receive the ETH (the standard two-step every NFTX revenue path uses).

```solidity
function harvest(uint _machineId, address _account) external;
```

**Access:** `nonReentrant`.

| Parameter    | Type      | Description                           |
| ------------ | --------- | ------------------------------------- |
| `_machineId` | `uint`    | The machine to harvest                |
| `_account`   | `address` | The account whose rewards are settled |

**Returns:** None.

### `pendingRewards` / `rewardUnits`

Views into the reward accumulator. `pendingRewards` is the ETH an account could harvest right now; `rewardUnits` is an account's reward stake in a bucket (live plus residual units).

```solidity
function pendingRewards(uint _machineId, address _account) external view returns (uint amount_);
function rewardUnits(uint _machineId, address _collection, address _account) external view returns (uint units_);
```

| Parameter     | Type      | Description                     |
| ------------- | --------- | ------------------------------- |
| `_machineId`  | `uint`    | The machine                     |
| `_collection` | `address` | The bucket (`rewardUnits` only) |
| `_account`    | `address` | The account                     |

## Machine management

All `onlyOwner`.

### `createMachine`

Creates a machine with a curated collection whitelist and a per-collection unit cap, and returns its id. Pricing is configured separately on [NFTXGacha](/contracts/gacha.md#setmachinepricing) before the machine can be spun.

```solidity
function createMachine(address[] calldata _collections, uint32 _unitCap) external returns (uint machineId_);
```

**Access:** `onlyOwner`. Reverts on an empty list or more than `MAX_COLLECTIONS` (30) (`InvalidCollectionCount`), or a repeated address (`DuplicateCollection`).

| Parameter      | Type        | Description                                |
| -------------- | ----------- | ------------------------------------------ |
| `_collections` | `address[]` | The collections the machine accepts (1–30) |
| `_unitCap`     | `uint32`    | Max units any one bucket may hold          |

| Return       | Type   | Description          |
| ------------ | ------ | -------------------- |
| `machineId_` | `uint` | The new machine's id |

### `setMachineUnitCap` / `setMachineActive`

Adjust a machine's per-bucket unit cap, or activate / deactivate it. Deactivating blocks new spins and deposits only; pending spins, withdrawals, and harvests are never blocked.

```solidity
function setMachineUnitCap(uint _machineId, uint32 _unitCap) external;
function setMachineActive(uint _machineId, bool _active) external;
```

| Parameter    | Type     | Description                                       |
| ------------ | -------- | ------------------------------------------------- |
| `_machineId` | `uint`   | The machine to configure                          |
| `_unitCap`   | `uint32` | The new per-bucket unit cap (`setMachineUnitCap`) |
| `_active`    | `bool`   | Activate (`true`) or deactivate (`false`)         |

**Returns:** None.

### `setGacha` / `setProtocolFeeReceiver`

Re-point the gacha allowed to consume this vault's inventory, and the receiver of distributions that find no active reward stake.

```solidity
function setGacha(address _gacha) external;
function setProtocolFeeReceiver(address _protocolFeeReceiver) external;
```

**Returns:** None.

## The gacha seam

These are callable only by the configured [NFTXGacha](/contracts/gacha.md) (`CallerIsNotGacha`). They are the interface the spin half uses to draw a prize, hand it over, and distribute revenue — documented for completeness; integrators read through the views, not these.

```solidity
function consume(uint _machineId, address _collection, uint _idRand, address _winner) external returns (uint tokenId_);
function deliver(address _collection, uint _tokenId) external;
function distribute(uint _machineId, uint[] calldata _prices) external payable;
```

## Deferred delivery

A prize whose transfer reverts (a paused token, a transfer-policy registry that hasn't whitelisted the vault) parks in custody with its winner pinned, so a claim is never wedged by one collection's transfer rules. Anyone retries it later.

### `redeliver` / `pendingDeliveryCount`

```solidity
function redeliver(address _collection, uint _tokenId) external;
function pendingDeliveryCount() external view returns (uint count_);
```

`redeliver` is permissionless and never pausable; it reverts if there's no parked prize for the token (`NothingToDeliver`). `pendingDeliveryCount` is the number of parked prizes — physical custody equals live units plus parked prizes.

## Views

### `machineCount` / `machineCollections` / `machineActive`

```solidity
function machineCount() external view returns (uint count_);
function machineCollections(uint _machineId) external view returns (address[] memory collections_);
function machineActive(uint _machineId) external view returns (bool active_);
```

`machineCount` is the number of machines ever created; the other two return a machine's collection whitelist and active flag.

### `drawableUnits` / `liveUnitsBatch` / `snapshotInputs`

Inventory views. `drawableUnits` is a single bucket's units eligible for the next draw (`liveUnits − pendingWithdrawals`); `liveUnitsBatch` reads several buckets at once; `snapshotInputs` returns the machine's collections and their drawable units together — the inputs a spin snapshot is built from.

```solidity
function drawableUnits(uint _machineId, address _collection) external view returns (uint32 units_);
function liveUnitsBatch(uint _machineId, address[] calldata _collections) external view returns (uint32[] memory liveUnits_);
function snapshotInputs(uint _machineId) external view returns (address[] memory collections_, uint32[] memory drawableUnits_);
```

### `withdrawableUnits` / `bucketTokenIds`

`withdrawableUnits` is the whole NFTs an account could currently withdraw from a bucket (its fractional share floored to whole units). `bucketTokenIds` lists the token IDs a bucket currently holds.

```solidity
function withdrawableUnits(uint _machineId, address _collection, address _account) external view returns (uint units_);
function bucketTokenIds(uint _machineId, address _collection) external view returns (uint[] memory tokenIds_);
```

| Parameter     | Type      | Description                              |
| ------------- | --------- | ---------------------------------------- |
| `_machineId`  | `uint`    | The machine                              |
| `_collection` | `address` | The bucket                               |
| `_account`    | `address` | The depositor (`withdrawableUnits` only) |
