Skip to content

Commit

Permalink
Init repo
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelkaplan13 committed Feb 12, 2024
0 parents commit 37dd3f8
Show file tree
Hide file tree
Showing 26 changed files with 1,985 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
c_chain_url="https://api.avax-test.network/ext/bc/C/rpc"
c_chain_blockchain_id="7fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5"
c_chain_teleporter_registry_address="0xb35f163b70AbABeE69cDF40bCDA94df2c37d9df8"
c_chain_vrf_coordinator_address="0x2eD832Ba664535e5886b75D64C46EB9a228C2610"
c_chain_vrf_subscription_id="1"
c_chain_vrf_key_hash="354d2f95da55398f44b7cff77da56283d9c6c829a4bdf1bbcaf2ad6a4d081f61"

subnet_url="https://subnets.avax.network/dispatch/testnet/rpc"
subnet_blockchain_id="9f3be606497285d0ffbb5ac9ba24aa60346a9b1812479ed66cb329f394a4b1c7"
subnet_teleporter_registry_address="0xb35f163b70AbABeE69cDF40bCDA94df2c37d9df8"

user_private_key=""
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Compiler files
cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/

# Docs
docs/

# Dotenv file
.env
13 changes: 13 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[submodule "contracts/lib/forge-std"]
path = contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "contracts/lib/openzeppelin-contracts"]
path = contracts/lib/openzeppelin-contracts
url = https://github.com/openzeppelin/openzeppelin-contracts
branch = v4.8.1
[submodule "contracts/lib/chainlink"]
path = contracts/lib/chainlink
url = https://github.com/smartcontractkit/chainlink
[submodule "contracts/lib/teleporter"]
path = contracts/lib/teleporter
url = https://github.com/ava-labs/teleporter
66 changes: 66 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
Copyright (C) 2024, Ava Labs, Inc. All rights reserved.

Ecosystem License
Version: 1.1

Subject to the terms herein, Ava Labs, Inc. (**“Ava Labs”**) hereby grants you
a limited, royalty-free, worldwide, non-sublicensable, non-transferable,
non-exclusive license to use, copy, modify, create derivative works based on,
and redistribute the Software, in source code, binary, or any other form,
including any modifications or derivative works of the Software (collectively,
**“Licensed Software”**), in each case subject to this Ecosystem License
(**“License”**).

This License applies to all copies, modifications, derivative works, and any
other form or usage of the Licensed Software. You will include and display
this License, without modification, with all uses of the Licensed Software,
regardless of form.

You will use the Licensed Software solely (i) in connection with the Avalanche
Public Blockchain platform, having a NetworkID of 1 (Mainnet) or 5 (Fuji), and
associated blockchains, comprised exclusively of the Avalanche X-Chain,
C-Chain, P-Chain and any subnets linked to the P-Chain (“Avalanche Authorized
Platform”) or (ii) for non-production, testing or research purposes within the
Avalanche ecosystem, in each case, without any commercial application
(“Non-Commercial Use”); provided that this License does not permit use of the
Licensed Software in connection with (a) any forks of the Avalanche Authorized
Platform or (b) in any manner not operationally connected to the Avalanche
Authorized Platform other than, for the avoidance of doubt, the limited
exception for Non-Commercial Use. Ava Labs may publicly announce changes or
additions to the Avalanche Authorized Platform, which may expand or modify
usage of the Licensed Software. Upon such announcement, the Avalanche
Authorized Platform will be deemed to be the then-current iteration of such
platform.

You hereby acknowledge and agree to the terms set forth at
www.avalabs.org/important-notice.

If you use the Licensed Software in violation of this License, this License
will automatically terminate and Ava Labs reserves all rights to seek any
remedy for such violation.

Except for uses explicitly permitted in this License, Ava Labs retains all
rights in the Licensed Software, including without limitation the ability to
modify it.

Except as required or explicitly permitted by this License, you will not use
any Ava Labs names, logos, or trademarks without Ava Labs’ prior written
consent.

You may use this License for software other than the “Licensed Software”
specified above, as long as the only change to this License is the definition
of the term “Licensed Software.”

The Licensed Software may reference third party components. You acknowledge
and agree that these third party components may be governed by a separate
license or terms and that you will comply with them.

**TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE LICENSED SOFTWARE IS PROVIDED
ON AN “AS IS” BASIS, AND AVA LABS EXPRESSLY DISCLAIMS AND EXCLUDES ALL
REPRESENTATIONS, WARRANTIES AND OTHER TERMS AND CONDITIONS, WHETHER EXPRESS OR
IMPLIED, INCLUDING WITHOUT LIMITATION BY OPERATION OF LAW OR BY CUSTOM,
STATUTE OR OTHERWISE, AND INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTY,
TERM, OR CONDITION OF NON-INFRINGEMENT, MERCHANTABILITY, TITLE, OR FITNESS FOR
PARTICULAR PURPOSE. YOU USE THE LICENSED SOFTWARE AT YOUR OWN RISK. AVA LABS
EXPRESSLY DISCLAIMS ALL LIABILITY (INCLUDING FOR ALL DIRECT, CONSEQUENTIAL OR
OTHER DAMAGES OR LOSSES) RELATED TO ANY USE OF THE LICENSED SOFTWARE.**
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Subnet VRF Contracts

This repository provides **example** contracts for how an Avalanche Subnet could leverage [Chainlink VRF](https://docs.chain.link/vrf) functionality (available on the C-chain) using [Teleporter](https://github.com/ava-labs/teleporter). This allows newly launched Subnets to immediately utilize VRF without any trusted intermediaries or third-party integration requirements.

**The contracts in this repository are not audited and are not suitable for production use.**

## Contracts

### VRFProvider
The `VRFProvider` contract is intended to be deployed on the same chain that Chainlink VRF is available on (i.e. the C-chain). It is configured to receive randomness requests from a specific `VRFProxy`, and passes those requests on to the Chainlink VRF coordinator. When the random values are provided by the Chainlink VRF coordinator, the `VRFProvider` in turn sends those values back to the `VRFProxy` that requested them via Teleporter.

In order be able to successfully request random values from the configured Chainlink VRF coordinator, the `VRFProvider` must be added to a [VRF subscription as an allowed consumer](https://docs.chain.link/vrf/v2/subscription/ui). The specific subsciption ID to be used is set by each randomness request.

### VRFProxy
The `VRFProxy` contract is intended to be deployed on any Subnet chain that would like to leverage Chainlink VRF but does not have a direct VRF integration. It is configured to request values from a specific `VRFProvider` that is deployed on another chain via Teleporter. It provides the same `requestRandomWords` interface as Chainlink VRF coordinators, and returns random values to fulfill requests via the same `fulfillRandomWords` method used by Chainlink VRF consumers.

In order to be able to request random values from a `VRFProxy`, accounts must be added as allowed consumers via `addConsumer`.

### SimpleBettingGame
A sample contract demostrating the use of VRF. Implements a simple betting game that leverages a `VRFProxy` to fulfill random values.

## Dependencies
In order to build and deploy the contracts using the scripts in this repository, [Foundry](https://book.getfoundry.sh/getting-started/installation) is required.

## Building and Testing
The contracts in this repository can be built and tested using the following scripts.
```bash
./scripts/build.sh
./scripts/test.sh
```
Included in the unit test script is a test coverage report.
```
| File | % Lines | % Statements | % Branches | % Funcs |
|---------------------------|-----------------|-----------------|-----------------|-----------------|
| src/GasUtils.sol | 100.00% (7/7) | 100.00% (4/4) | 100.00% (3/3) | 100.00% (1/1) |
| src/SimpleBettingGame.sol | 100.00% (38/38) | 100.00% (42/42) | 100.00% (22/22) | 100.00% (6/6) |
| src/VRFProvider.sol | 100.00% (12/12) | 100.00% (15/15) | 100.00% (8/8) | 100.00% (2/2) |
| src/VRFProxy.sol | 100.00% (25/25) | 100.00% (29/29) | 100.00% (14/14) | 100.00% (4/4) |
| Total | 100.00% (82/82) | 100.00% (90/90) | 100.00% (47/47) | 100.00% (13/13) |
```

## Deploying
The example contracts can be deployed by setting proper environment variable values as follows.
```bash
cp .env.example .env
```
The `user_private_key` value then must be set in the `.env` file. The full list of configurable environment variables includes:
| Environment Variable | Description |
|--------|--------|
| c_chain_url | RPC endpoint for the C-chain (where Chainlink VRF is available) |
| c_chain_blockchain_id | Blockchain ID of the C-chain (hexadecimal encoded) |
| c_chain_teleporter_registry_address | Teleporter registry contract used by the `VRFProvider` on the C-chain |
| c_chain_vrf_coordinator_address | Address of the Chainlink VRF Coordinator to be used by the `VRFProvider` |
| c_chain_vrf_subscription_id | The Chainlink VRF subscription ID to be used by the `VRFProxy` |
| c_chain_vrf_key_hash | The Chainlink VRF key hash to be used by the `VRFProxy` |
| subnet_url | RPC endpoint for the Subnet chain to be used|
| subnet_blockchain_id | Blockchain ID of the Subnet chain to be used (hexadecimal encoded) |
| subnet_teleporter_registry_address | Teleporter registry contract used by the `VRFProvider` on the Subnet chain |
| user_private_key | Private key for a funded account on both the C-chain and Subnet chain. Used to deploy contracts |
6 changes: 6 additions & 0 deletions contracts/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[profile.default]
src = "src"
out = "out"
libs = ["lib"]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
1 change: 1 addition & 0 deletions contracts/lib/chainlink
Submodule chainlink added at 3cf93c
1 change: 1 addition & 0 deletions contracts/lib/forge-std
Submodule forge-std added at 36c303
1 change: 1 addition & 0 deletions contracts/lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at 045704
1 change: 1 addition & 0 deletions contracts/lib/teleporter
Submodule teleporter added at bedf79
4 changes: 4 additions & 0 deletions contracts/remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@chainlink/=lib/chainlink/
@openzeppelin/=lib/openzeppelin-contracts/
@teleporter/=lib/teleporter/
@subnet-evm-contracts/=lib/teleporter/contracts/lib/subnet-evm/contracts/contracts/
35 changes: 35 additions & 0 deletions contracts/src/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"extends": "solhint:recommended",
"rules": {
"compiler-version": ["error", "0.8.18"],
"no-unused-vars": "error",
"func-visibility": [
"error",
{
"ignoreConstructors": true
}
],
"private-vars-leading-underscore": [
"warn",
{
"strict": true
}
],
"reason-string": [
"warn",
{
"maxLength": 75
}
],
"custom-errors": "off",
"ordering": "error",
"immutable-vars-naming": [
"warn",
{
"immutablesAsConstants": false
}
],
"func-named-parameters": ["error", 5],
"one-contract-per-file": "off"
}
}
Empty file added contracts/src/.solhintignore
Empty file.
44 changes: 44 additions & 0 deletions contracts/src/GasUtils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// (c) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// SPDX-License-Identifier: Ecosystem
pragma solidity 0.8.18;

library GasUtils {
/**
* @dev Amount of gas needed as a buffer for delivering random values to the requesters and handling the result.
* The amount of gas used by the requester itself when receiving the values is specified per request by
* callbackGasLimit.
*/
uint256 public constant GAS_FOR_CALL_EXACT_CHECK = 5_000;

/**
* Implementation taken from VRFCoordinatorV2.sol.
* @dev calls target address with exactly gasAmount gas and data as calldata
* or reverts if at least gasAmount gas is not available.
*/
function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) internal returns (bool) {
bool success;
// solhint-disable-next-line
assembly {
let g := gas()
// Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow
// The gas actually passed to the callee is min(gasAmount, 63//64*gas available).
// We want to ensure that we revert if gasAmount > 63//64*gas available
// as we do not want to provide them with less, however that check itself costs
// gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able
// to revert if gasAmount > 63//64*gas available.
if lt(g, GAS_FOR_CALL_EXACT_CHECK) { revert(0, 0) }
g := sub(g, GAS_FOR_CALL_EXACT_CHECK)
// if g - g//64 <= gasAmount, revert
// (we subtract g//64 because of EIP-150)
if iszero(gt(sub(g, div(g, 64)), gasAmount)) { revert(0, 0) }
// solidity calls check that a contract actually exists at the destination, so we do the same
if iszero(extcodesize(target)) { revert(0, 0) }
// call and return whether we succeeded. ignore return data
// call(gas,addr,value,argsOffset,argsLength,retOffset,retLength)
success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0)
}
return success;
}
}
80 changes: 80 additions & 0 deletions contracts/src/IVRFProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// (c) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// SPDX-License-Identifier: Ecosystem
pragma solidity 0.8.18;

/**
* THIS IS AN EXAMPLE CONTRACT INTERFACE THAT USES UNAUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/

/**
* @notice Represents all of the relevant information for a given
* VRF request message to the VRF partner on a partner chain. This
* struct is ABI encoded/decoded in the Teleporter message passing.
*/
struct VRFRequestInfo {
uint256 requestID;
bytes32 keyHash;
uint64 subID;
uint16 minimumRequestConfirmations;
uint32 callbackGasLimit;
uint32 numWords;
}

/**
* @notice Represents all of the relevant information for a given VRF
* response message received back from the VRF provided on a partner chain.
* This struct is ABI encoded/decoded in the Teleporter message passing.
*/
struct VRFResponseInfo {
uint256 requestID;
uint256[] randomWords;
uint32 callbackGasLimit;
}

/**
* @dev IVRFProxy defines the interface for a contract deployed on a subnet that is meant to act as a proxy to a
* VRFCoordinator deployed on another chain. Approved dApps deployed on the same chain as the VRFProxy can request values
* from it in the same way that dApps could request random values from a VRFCoordinator contract.
*/
interface IVRFProxy {
/**
* @notice Adds the provided consumer to be allowed to request random values
* via this contract. Allowed consumers can use any VRF subscriptions that
* the corresponding VRFProvider contract instance has access to on the VRF
* provider chain.
* @param consumer the address that should be allowed to call requestRandomWords
*/
function addConsumer(address consumer) external;

/**
* @notice Removes the provided consumer such that it is no longer allowed to
* request random values via this contract.
* @param consumer the address that should no longer be allowed to call requestRandomWords
*/
function removeConsumer(address consumer) external;

/**
* @notice Request a set of random words.
* The request is passed on to the partner chain where the VRFProvider is deployed via Teleporter message.
* See https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol#L13
* for further documentation of how each value is used within Chainlink VRF reuests.
* @param keyHash - Corresponds to the VRF keyHash to be used on the partner chain that provides the VRF functionality.
* @param subId - The ID of the VRF subscription to be used by the VRF provider on the partner chain.
* @param minimumRequestConfirmations - How many blocks you'd like the VRF service on the partner chain to wait prior
* to fulfilling the request once the VRF provider submits the request on the partner chain.
* @param callbackGasLimit - How much gas needs to be provided to the fulfillRandomWords call to complete this randomness request.
* @param numWords - The number of uint256 values requested.
* @return requestID - A unique identifier of the request. Can be used to match a request to a reponse in fulfillRandomWords. This
* request ID is separate from any VRF request ID assigned on the partner chain by the VRFProdiver.
*/
function requestRandomWords(
bytes32 keyHash,
uint64 subId,
uint16 minimumRequestConfirmations,
uint32 callbackGasLimit,
uint32 numWords
) external returns (uint256 requestID);
}
Loading

0 comments on commit 37dd3f8

Please sign in to comment.