# Local testing using a mock subscription contract
Source: https://docs.chain.link/vrf/v2-5/subscription/test-locally

> For the complete documentation index, see [llms.txt](/llms.txt).

This guide explains how to test Chainlink VRF v2.5 on a [Remix IDE](https://remix-ide.readthedocs.io/en/latest/run.html#environment) sandbox blockchain environment. **Note**: You can reuse the same logic on another development environment, such as Hardhat or Foundry. For example, read the Hardhat Starter Kit [RandomNumberConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberConsumer.spec.js).

> **CAUTION: Test on public testnets thoroughly**
>
> Even though local testing has several benefits, testing with a VRF mock covers the bare minimum of use cases. Make
> sure to test your consumer contract thoroughly on public testnets.

## Benefits of local testing

## Testing logic

Complete the following tasks to test your VRF v2.5 consumer locally:

1. Deploy the [VRFCoordinatorV2\_5Mock](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol). This contract is a mock of the [VRFCoordinatorV2\_5](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol) contract.
2. Call the [createSubscription function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol#L56) (which `VRFCoordinatorV2_5Mock` inherits) to create a new subscription.
3. Call the VRFCoordinatorV2\_5Mock [`fundSubscription` function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol#L174) to fund your newly created subscription. **Note**: You can fund with an arbitrary amount.
4. Deploy your VRF consumer contract.
5. Call the [addConsumer function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol#L12) (which `VRFCoordinatorV2_5Mock` inherits) to add your consumer contract to your subscription.
6. Request random words from your consumer contract.
7. Call the VRFCoordinatorV2\_5Mock [fulfillRandomWords function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol#L101) to fulfill your consumer contract request.

## Testing

### Open the contracts on Remix IDE

For local testing, use the default "Remix VM" environment.

Open *VRFv2\_5Consumer* and compile in Remix:

```sol
// SPDX-License-Identifier: MIT
// An example of a consumer contract that relies on a subscription for funding.
pragma solidity ^0.8.20;

import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */

/**
 * @title The RandomNumberConsumerV2_5 contract
 * @notice A contract that gets random values from Chainlink VRF V2_5
 */
contract RandomNumberConsumerV2_5 is VRFConsumerBaseV2Plus {
  // Your subscription ID.
  uint256 immutable s_subscriptionId;

  // The gas lane to use, which specifies the maximum gas price to bump to.
  // For a list of available gas lanes on each network,
  // see https://docs.chain.link/docs/vrf-contracts/#configurations
  bytes32 immutable s_keyHash;

  // Depends on the number of requested values that you want sent to the
  // fulfillRandomWords() function. Storing each word costs about 20,000 gas,
  // so 100,000 is a safe default for this example contract. Test and adjust
  // this limit based on the network that you select, the size of the request,
  // and the processing of the callback request in the fulfillRandomWords()
  // function.
  uint32 constant CALLBACK_GAS_LIMIT = 100_000;

  // The default is 3, but you can set this higher.
  uint16 constant REQUEST_CONFIRMATIONS = 3;

  // For this example, retrieve 2 random values in one request.
  // Cannot exceed VRFCoordinatorV2_5.MAX_NUM_WORDS.
  uint32 constant NUM_WORDS = 2;

  uint256[] public s_randomWords;
  uint256 public s_requestId;

  event ReturnedRandomness(uint256[] randomWords);

  /**
   * @notice Constructor inherits VRFConsumerBaseV2Plus
   *
   * @param subscriptionId - the subscription ID that this contract uses for funding requests
   * @param vrfCoordinator - coordinator, check https://docs.chain.link/vrf/v2-5/supported-networks
   * @param keyHash - the gas lane to use, which specifies the maximum gas price to bump to
   */
  constructor(
    uint256 subscriptionId,
    address vrfCoordinator,
    bytes32 keyHash
  ) VRFConsumerBaseV2Plus(vrfCoordinator) {
    s_keyHash = keyHash;
    s_subscriptionId = subscriptionId;
  }

  /**
   * @notice Requests randomness
   * Assumes the subscription is funded sufficiently; "Words" refers to unit of data in Computer Science
   */
  function requestRandomWords() external onlyOwner {
    // Will revert if subscription is not set and funded.
    s_requestId = s_vrfCoordinator.requestRandomWords(
      VRFV2PlusClient.RandomWordsRequest({
        keyHash: s_keyHash,
        subId: s_subscriptionId,
        requestConfirmations: REQUEST_CONFIRMATIONS,
        callbackGasLimit: CALLBACK_GAS_LIMIT,
        numWords: NUM_WORDS,
        extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false}))
      })
    );
  }

  /**
   * @notice Callback function used by VRF Coordinator
   *
   * @param  - id of the request
   * @param randomWords - array of random results from VRF Coordinator
   */
  function fulfillRandomWords(
    uint256,
    /* requestId */
    uint256[] calldata randomWords
  ) internal override {
    s_randomWords = randomWords;
    emit ReturnedRandomness(randomWords);
  }
}
```

Open *VRFCoordinatorV2\_5Mock* in Remix:

```sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol";
```

On the *Solidity Compiler* tab, expand the *Advanced Configurations* section and check the *Enable optimization* box before you compile the *VRFCoordinatorV2\_5Mock* contract:

(Image: Image)

Your Remix IDE file explorer should display *VRFCoordinatorV2\_5Mock.sol* and *VRFv2\_5Consumer.sol*:

(Image: Image)

### Deploy VRFCoordinatorV2\_5Mock

1. Open *VRFCoordinatorV2\_5Mock.sol*.

2. Under *DEPLOY & RUN TRANSACTIONS*, select *VRFCoordinatorV2\_5Mock*.

   (Image: Image)

3. Under *DEPLOY*, fill in the `_BASEFEE`, `_GASPRICELINK` and `_WEIPERUNITLINK`. These variables are used in the *VRFCoordinatorV2\_5Mock* contract to represent the base fee, the gas price (in LINK tokens), and the current LINK/ETH price for the VRF requests.

   (Image: Image)

   You can set:

   - `_BASEFEE` to 100000000000000000
   - `_GASPRICELINK` to 1000000000
   - `_WEIPERUNITLINK` to the current LINK/ETH price. Click the "Latest Price" button to view it:
     {" "}

4. Click *transact* to deploy the *VRFCoordinatorV2\_5Mock* contract.

5. Once deployed, you should see the *VRFCoordinatorV2\_5Mock* contract under *Deployed Contracts*.

   (Image: Image)

6. Note the address of the deployed contract.

### Create and fund a subscription

1. Click `createSubscription` to create a new subscription.

2. In the Remix IDE console, read your transaction decoded output to find the subscription ID. Note the subscription ID, which is required for multiple steps in this tutorial.

   (Image: Image)

3. Click on `fundSubscription` to fund your subscription. Fill in your subscription ID for `_subid` and set the `_amount` to 100000000000000000000. This mocks funding your subscription with 100 LINK.

### Deploy the VRF consumer contract

1. In the file explorer, open *VRFv2\_5Consumer.sol*.

2. Under *DEPLOY & RUN TRANSACTIONS*, select *RandomNumberConsumerV2\_5*.

   (Image: Image)

3. Under *DEPLOY*, fill in the following parameters:
   - `SUBSCRIPTIONID` with your subscription ID
   - `VRFCOORDINATOR` with the deployed *VRFCoordinatorV2\_5Mock* address
   - `_KEYHASH_` with an arbitrary `bytes32` (In this example, you can set the *KEYHASH* to 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae).

4. Click *transact* to deploy the *RandomNumberConsumerV2\_5* contract.

5. After the consumer contract is deployed, you should see the *RandomNumberConsumerV2\_5* contract under *Deployed Contracts*. Note the address of the deployed contract.

### Add the consumer contract to your subscription

1. Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2\_5Mock* contract.

2. Click *addConsumer* and fill in the `_subid` with your subscription ID and `_consumer` with your deployed consumer contract address.

   (Image: Image)

3. Click *transact*.

### Request random words

1. Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberConsumerV2\_5* contract.

2. Click `requestRandomWords`.

   (Image: Image)

3. Click `s_requestId` to display the last request ID. In this example, the output is *1*.

   (Image: Image)

4. Note your request ID.

### Fulfill the VRF request

Because you are testing on a local blockchain environment, you must fulfill the VRF request yourself.

1. Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2\_5Mock* contract.

2. Click `fulfillRandomWords` and fill in `_requestId` with your VRF request ID and `_consumer` with your consumer contract address.

   (Image: Image)

3. Click `transact`.

### Check the results

1. Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberConsumerV2\_5* contract.

2. For each VRF request, your consumer contract requests two random words. After a request is fulfilled, the two random words are stored in the `s_randomWords` array. You can check the stored random words by reading the two first indexes of the `s_randomWords` array. To do so, click the *s\_randomWords* function and:
   1. Fill in the index with *0* then click *call* to read the first random word.

      {" "}

      (Image: Image)

   2. You can read the second random word in a similar way: fill in the index with *1* then click *call* to display the second random word.

## Next steps

This guide demonstrated how to test a VRF v2.5 consumer contract on your local blockchain. The guide uses the Remix IDE for learning purposes, but you can reuse the same [testing logic](#testing-logic) in another development environment, such as Hardhat. For example, see the Hardhat Starter Kit [RandomNumberConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberConsumer.spec.js).