Skip to content

Commit

Permalink
Merge pull request #13 from pappas999/feat/deploy-and-fund
Browse files Browse the repository at this point in the history
Feat/deploy and fund
  • Loading branch information
PatrickAlphaC authored Jun 30, 2021
2 parents 7f8fcd9 + 2fd4052 commit 5db05ab
Show file tree
Hide file tree
Showing 29 changed files with 420 additions and 140 deletions.
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export KOVAN_RPC_URL='NOOOOOO GARY'
export PRIVATE_KEY='abcdef'
export KOVAN_RPC_URL='www.infura.io/asdfadsfafdadf'
export PRIVATE_KEY='0xabcdef'
export ALCHEMY_MAINNET_RPC_URL="https://eth-mainnet.alchemyapi.io/v2/your-api-key"
52 changes: 41 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@
- [Request & Receive data](https://docs.chain.link/docs/request-and-receive-data)
- [Chainlink Price Feeds](https://docs.chain.link/docs/using-chainlink-reference-contracts)
- [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf)

## Requirements

- [NPM](https://www.npmjs.com/) or [YARN](https://yarnpkg.com/)

## Installation

Set your `KOVAN_RPC_URL` [environment variable.](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html). You can get one for free at [Infura's site.](https://infura.io/). You'll also need to set the variable `PRIVATE_KEY` which is your private key from you wallet, ie metamask.
Set your `KOVAN_RPC_URL` [environment variable.](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html). You can get one for free at [Infura's site.](https://infura.io/) You'll also need to set the variable `PRIVATE_KEY` which is your private key from you wallet, ie MetaMask. This is needed for deploying contracts to public networks.

You can set these in your `.env` file if you're unfamiliar with how setting environment variables work. Check out our [.env example](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/.env.example). If you wish to use this method to set these variables, update the values in the .env.example file, and then rename it to '.env'

![WARNING](https://via.placeholder.com/15/f03c15/000000?text=+) **WARNING** ![WARNING](https://via.placeholder.com/15/f03c15/000000?text=+)

You can set this in your `.env` file if you're unfamiliar with how setting environment variables work.
Don't commit and push any changes to .env files that may contain sensitive information, such as a private key! If this information reaches a public GitHub repository, someone can use it to check if you have any Mainnet funds in that wallet address, and steal them!

`.env` example:
```
Expand All @@ -35,15 +39,15 @@ export MNEMONIC='cat dog frog...'
export MAINNET_RPC_URL="https://eth-mainnet.alchemyapi.io/v2/your-api-key"
```

If you plan on deploying to a local [Hardhat network](https://hardhat.org/hardhat-network/) that's a fork of the Ethereum mainnet instead of a public test network like Kovan, you'll also need to set your `MAINNET_RPC_URL` [environment variable.](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html) and uncomment the `forking` section in `hardhat.config.js`. You can get one for free at [Alchemy's site.](https://alchemyapi.io/).
If you plan on deploying to a local [Hardhat network](https://hardhat.org/hardhat-network/) that's a fork of the Ethereum mainnet instead of a public test network like Kovan, you'll also need to set your `MAINNET_RPC_URL` [environment variable.](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html) and uncomment the `forking` section in `hardhat.config.js`. You can get one for free at [Alchemy's site.](https://alchemyapi.io/).

You can also use a `PRIVATE_KEY` instead of a `MNEMONIC` environment variable by uncommenting the section in the `hardhat.config.js`, and commenting out the `MNEMONIC` line.
You can also use a `PRIVATE_KEY` instead of a `MNEMONIC` environment variable by uncommenting the section in the `hardhat.config.js`, and commenting out the `MNEMONIC` line.

Then you can install all the dependencies

```bash
git clone https://github.com/smartcontractkit/chainlink-hardhat-box
cd chainlink-hardhat-box
git clone https://github.com/smartcontractkit/hardhat-starter-kit/
cd hardhat-starter-kit
```
then

Expand All @@ -57,14 +61,32 @@ Or
yarn
```


## Auto-Funding

This Starter Kit is configured by default to attempt to auto-fund any newly deployed contract that uses Any-API or Chainlink VRF, to save having to manually fund them after each deployment. The amount in LINK to send as part of this process can be modified in the [Starter Kit Config](https://github.com/smartcontractkit/chainlink-hardhat-box/blob/main/helper-hardhat-config.js), and are configurable per network.

| Parameter | Description | Default Value |
| -----------|:-----------------------------------------------------------------| :-------------|
| fundAmount | Amount of LINK to transfer when funding contracts | 1 LINK |

If you wish to deploy the smart contracts without performing the auto-funding, run the following command when doing your deployment:

```bash
npx hardhat deploy --tags main
```


## Deploy

Deployment scripts are in the [deploy](https://github.com/pappas999/chainlink-hardhat-box/tree/main/deploy) directory. If required, edit the desired environment specific variables or constructor parameters in each script, then run the hardhat deployment plugin as follows. If no network is specified, it will default to the Kovan network.
Deployment scripts are in the [deploy](https://github.com/smartcontractkit/hardhat-starter-kit/tree/main/deploy) directory. If required, edit the desired environment specific variables or constructor parameters in each script, then run the hardhat deployment plugin as follows. If no network is specified, it will default to the Kovan network.

This will deploy to a local hardhat network

This will deploy to a local hardhat network

```bash
npx hardhat deploy
npx hardhat deploy
```

To deploy to testnet:
Expand All @@ -73,10 +95,18 @@ npx hardhat deploy --network kovan
```

## Test
Tests are located in the [test](https://github.com/pappas999/chainlink-hardhat-box/tree/main/test) directory and can be modified as required. To run them:
Tests are located in the [test](https://github.com/smartcontractkit/hardhat-starter-kit/tree/main/test) directory, and are split between unit tests and integration tests. Unit tests should only be run on local environments, and integration tests should only run on live environments.

To run unit tests:

```bash
yarn test
```

To run integration tests:

```bash
npx hardhat test
yarn test-integration
```

## Run
Expand Down
34 changes: 22 additions & 12 deletions contracts/APIConsumer.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
pragma solidity ^0.6.6;

import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol";
import "@chainlink/contracts/src/v0.6/vendor/Ownable.sol";

contract APIConsumer is ChainlinkClient, Ownable {

contract APIConsumer is ChainlinkClient {

uint256 public volume;

address private oracle;
bytes32 private jobId;
uint256 private fee;

/**
* Network: Kovan
* Oracle: 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e
Expand All @@ -29,18 +30,18 @@ contract APIConsumer is ChainlinkClient {
jobId = stringToBytes32(_jobId);
fee = _fee;
}

/**
* Create a Chainlink request to retrieve API response, find the target
* data, then multiply by 1000000000000000000 (to remove decimal places from data).
*/
function requestVolumeData() public returns (bytes32 requestId)
function requestVolumeData() public returns (bytes32 requestId)
{
Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);

// Set the URL to perform the GET request on
request.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");

// Set the path to find the desired data in the API response, where the response format is:
// {"RAW":
// {"ETH":
Expand All @@ -52,23 +53,32 @@ contract APIConsumer is ChainlinkClient {
// }
// }
request.add("path", "RAW.ETH.USD.VOLUME24HOUR");

// Multiply the result by 1000000000000000000 to remove decimals
int timesAmount = 10**18;
request.addInt("times", timesAmount);

// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}

/**
* Receive the response in the form of uint256
*/
*/
function fulfill(bytes32 _requestId, uint256 _volume) public recordChainlinkFulfillment(_requestId)
{
volume = _volume;
}

/**
* Withdraw LINK from this contract
*
*/
function withdrawLink() external onlyOwner {
LinkTokenInterface linkToken = LinkTokenInterface(chainlinkTokenAddress());
require(linkToken.transfer(msg.sender, linkToken.balanceOf(address(this))), "Unable to transfer");
}

function stringToBytes32(string memory source) public pure returns (bytes32 result) {
bytes memory tempEmptyStringTest = bytes(source);
if (tempEmptyStringTest.length == 0) {
Expand Down
19 changes: 9 additions & 10 deletions contracts/RandomNumberConsumer.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@

pragma solidity 0.6.6;

import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
contract RandomNumberConsumer is VRFConsumerBase {

bytes32 internal keyHash;
uint256 internal fee;
uint256 public randomResult;
event RequestedRandomness(bytes32 requestId);

/**
* Constructor inherits VRFConsumerBase
*
*
* Network: Kovan
* Chainlink VRF Coordinator address: 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9
* LINK token address: 0xa36085F69e2889c224210F603D836748e7dC0088
Expand All @@ -20,17 +19,17 @@ contract RandomNumberConsumer is VRFConsumerBase {
constructor(address _vrfCoordinator,
address _link,
bytes32 _keyHash,
uint _fee)
uint _fee)
VRFConsumerBase(
_vrfCoordinator, // VRF Coordinator
_link // LINK Token
) public
{
keyHash = _keyHash;
fee = _fee;
fee = _fee;
}
/**

/**
* Requests randomness
*/
function getRandomNumber() public returns (bytes32 requestId) {
Expand All @@ -44,10 +43,10 @@ contract RandomNumberConsumer is VRFConsumerBase {
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
randomResult = randomness;
}

/**
* Withdraw LINK from this contract
*
*
* DO NOT USE THIS IN PRODUCTION AS IT CAN BE CALLED BY ANY ADDRESS.
* THIS IS PURELY FOR EXAMPLE PURPOSES.
*/
Expand Down
2 changes: 1 addition & 1 deletion contracts/test/MockOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ contract MockOracle is ChainlinkRequestInterface, LinkTokenReceiver {

uint256 constant public EXPIRY_TIME = 5 minutes;
uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000;

struct Request {
address callbackAddr;
bytes4 callbackFunctionId;
Expand Down
2 changes: 1 addition & 1 deletion deploy/00_Deploy_Mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ module.exports = async ({
log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
}
}
module.exports.tags = ['all', 'mocks']
module.exports.tags = ['all', 'mocks', 'main']
5 changes: 4 additions & 1 deletion deploy/01_Deploy_PriceConsumerV3.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = async ({
deployments,
getChainId
}) => {

const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()
const chainId = await getChainId()
Expand All @@ -17,6 +18,7 @@ module.exports = async ({
}
// Price Feed Address, values can be obtained at https://docs.chain.link/docs/reference-contracts
// Default one below is ETH/USD contract on Kovan
log("----------------------------------------------------")
const priceConsumerV3 = await deploy('PriceConsumerV3', {
from: deployer,
args: [ethUsdPriceFeedAddress],
Expand All @@ -25,6 +27,7 @@ module.exports = async ({
log("Run Price Feed contract with command:")
log("npx hardhat read-price-feed --contract " + priceConsumerV3.address + " --network " + networkConfig[chainId]['name'])
log("----------------------------------------------------")

}

module.exports.tags = ['all', 'feed']
module.exports.tags = ['all', 'feed', 'main']
14 changes: 7 additions & 7 deletions deploy/02_Deploy_APIConsumer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let { networkConfig } = require('../helper-hardhat-config')
let { networkConfig} = require('../helper-hardhat-config')

module.exports = async ({
getNamedAccounts,
Expand All @@ -10,6 +10,8 @@ module.exports = async ({
let linkTokenAddress
let oracle
let additionalMessage = ""
//set log level to ignore non errors
ethers.utils.Logger.setLogLevel(ethers.utils.Logger.levels.ERROR)

if (chainId == 31337) {
linkToken = await get('LinkToken')
Expand All @@ -23,18 +25,16 @@ module.exports = async ({
}
const jobId = networkConfig[chainId]['jobId']
const fee = networkConfig[chainId]['fee']
const networkName = networkConfig[chainId]['name']

const apiConsumer = await deploy('APIConsumer', {
from: deployer,
args: [oracle, jobId, fee, linkTokenAddress],
log: true
})

log("Run the following command to fund contract with LINK:")
log("npx hardhat fund-link --contract " + apiConsumer.address + " --network " + networkConfig[chainId]['name'] + additionalMessage)
log("Then run API Consumer contract with following command:")
log("npx hardhat request-data --contract " + apiConsumer.address + " --network " + networkConfig[chainId]['name'])
log("Run API Consumer contract with following command:")
log("npx hardhat request-data --contract " + apiConsumer.address + " --network " + networkName)
log("----------------------------------------------------")
}

module.exports.tags = ['all', 'api']
module.exports.tags = ['all', 'api', 'main']
6 changes: 3 additions & 3 deletions deploy/03_Deploy_RandomNumberConsumer.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
let { networkConfig } = require('../helper-hardhat-config')

let { networkConfig} = require('../helper-hardhat-config')

module.exports = async ({
getNamedAccounts,
deployments,
getChainId
}) => {

const { deploy, get, log } = deployments
const { deployer } = await getNamedAccounts()
const chainId = await getChainId()
Expand Down Expand Up @@ -39,4 +39,4 @@ module.exports = async ({
log("----------------------------------------------------")
}

module.exports.tags = ['all', 'vrf']
module.exports.tags = ['all', 'vrf']
54 changes: 54 additions & 0 deletions deploy/04_Setup_Contracts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const { networkConfig, autoFundCheck } = require('../helper-hardhat-config')
const { ethers, getNamedAccounts } = require('hardhat')

module.exports = async ({
getNamedAccounts,
deployments
}) => {
const { deploy, log, get } = deployments
const chainId = await getChainId()
let linkTokenAddress
let additionalMessage = ""
//set log level to ignore non errors
ethers.utils.Logger.setLogLevel(ethers.utils.Logger.levels.ERROR)
const networkName = networkConfig[chainId]['name']

if (chainId == 31337) {
linkToken = await get('LinkToken')
MockOracle = await get('MockOracle')
linkTokenAddress = linkToken.address
oracle = MockOracle.address
additionalMessage = " --linkaddress " + linkTokenAddress
} else {
linkTokenAddress = networkConfig[chainId]['linkToken']
oracle = networkConfig[chainId]['oracle']
}

//Try Auto-fund APIConsumer contract with LINK
const APIConsumer = await deployments.get('APIConsumer')
const apiConsumer = await ethers.getContractAt('APIConsumer', APIConsumer.address)

if (await autoFundCheck(apiConsumer.address, networkName, linkTokenAddress, additionalMessage)) {
await hre.run("fund-link", { contract: apiConsumer.address, linkaddress: linkTokenAddress })
} else {
log("Then run API Consumer contract with following command:")
log("npx hardhat request-data --contract " + apiConsumer.address + " --network " + networkName)
}
log("----------------------------------------------------")


//Now try Auto-fund VRFConsumer contract

const RandomNumberConsumer = await deployments.get('RandomNumberConsumer')
const randomNumberConsumer = await ethers.getContractAt('RandomNumberConsumer', RandomNumberConsumer.address)

if (await autoFundCheck(apiConsumer.address, networkName, linkTokenAddress, additionalMessage)) {
await hre.run("fund-link", { contract: randomNumberConsumer.address, linkaddress: linkTokenAddress })
} else {
log("Then run RandomNumberConsumer contract with the following command:")
log("npx hardhat request-random-number --contract " + randomNumberConsumer.address + " --network " + networkName)
}
log("----------------------------------------------------")

}
module.exports.tags = ['all']
Loading

0 comments on commit 5db05ab

Please sign in to comment.