Skip to content

Commit 5db05ab

Browse files
Merge pull request #13 from pappas999/feat/deploy-and-fund
Feat/deploy and fund
2 parents 7f8fcd9 + 2fd4052 commit 5db05ab

29 files changed

+420
-140
lines changed

.env

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
export KOVAN_RPC_URL='NOOOOOO GARY'
2-
export PRIVATE_KEY='abcdef'
1+
export KOVAN_RPC_URL='www.infura.io/asdfadsfafdadf'
2+
export PRIVATE_KEY='0xabcdef'
33
export ALCHEMY_MAINNET_RPC_URL="https://eth-mainnet.alchemyapi.io/v2/your-api-key"

README.md

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,20 @@
1111
- [Request & Receive data](https://docs.chain.link/docs/request-and-receive-data)
1212
- [Chainlink Price Feeds](https://docs.chain.link/docs/using-chainlink-reference-contracts)
1313
- [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf)
14-
14+
1515
## Requirements
1616

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

1919
## Installation
2020

21-
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.
21+
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.
22+
23+
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'
24+
25+
![WARNING](https://via.placeholder.com/15/f03c15/000000?text=+) **WARNING** ![WARNING](https://via.placeholder.com/15/f03c15/000000?text=+)
2226

23-
You can set this in your `.env` file if you're unfamiliar with how setting environment variables work.
27+
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!
2428

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

38-
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/).
42+
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/).
3943

40-
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.
44+
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.
4145

4246
Then you can install all the dependencies
4347

4448
```bash
45-
git clone https://github.com/smartcontractkit/chainlink-hardhat-box
46-
cd chainlink-hardhat-box
49+
git clone https://github.com/smartcontractkit/hardhat-starter-kit/
50+
cd hardhat-starter-kit
4751
```
4852
then
4953

@@ -57,14 +61,32 @@ Or
5761
yarn
5862
```
5963

64+
65+
## Auto-Funding
66+
67+
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.
68+
69+
| Parameter | Description | Default Value |
70+
| -----------|:-----------------------------------------------------------------| :-------------|
71+
| fundAmount | Amount of LINK to transfer when funding contracts | 1 LINK |
72+
73+
If you wish to deploy the smart contracts without performing the auto-funding, run the following command when doing your deployment:
74+
75+
```bash
76+
npx hardhat deploy --tags main
77+
```
78+
79+
6080
## Deploy
6181

62-
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.
82+
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.
83+
84+
This will deploy to a local hardhat network
6385

6486
This will deploy to a local hardhat network
6587

6688
```bash
67-
npx hardhat deploy
89+
npx hardhat deploy
6890
```
6991

7092
To deploy to testnet:
@@ -73,10 +95,18 @@ npx hardhat deploy --network kovan
7395
```
7496

7597
## Test
76-
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:
98+
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.
99+
100+
To run unit tests:
101+
102+
```bash
103+
yarn test
104+
```
105+
106+
To run integration tests:
77107

78108
```bash
79-
npx hardhat test
109+
yarn test-integration
80110
```
81111

82112
## Run

contracts/APIConsumer.sol

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
pragma solidity ^0.6.6;
22

33
import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol";
4+
import "@chainlink/contracts/src/v0.6/vendor/Ownable.sol";
5+
6+
contract APIConsumer is ChainlinkClient, Ownable {
47

5-
contract APIConsumer is ChainlinkClient {
6-
78
uint256 public volume;
8-
9+
910
address private oracle;
1011
bytes32 private jobId;
1112
uint256 private fee;
12-
13+
1314
/**
1415
* Network: Kovan
1516
* Oracle: 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e
@@ -29,18 +30,18 @@ contract APIConsumer is ChainlinkClient {
2930
jobId = stringToBytes32(_jobId);
3031
fee = _fee;
3132
}
32-
33+
3334
/**
3435
* Create a Chainlink request to retrieve API response, find the target
3536
* data, then multiply by 1000000000000000000 (to remove decimal places from data).
3637
*/
37-
function requestVolumeData() public returns (bytes32 requestId)
38+
function requestVolumeData() public returns (bytes32 requestId)
3839
{
3940
Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
40-
41+
4142
// Set the URL to perform the GET request on
4243
request.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");
43-
44+
4445
// Set the path to find the desired data in the API response, where the response format is:
4546
// {"RAW":
4647
// {"ETH":
@@ -52,23 +53,32 @@ contract APIConsumer is ChainlinkClient {
5253
// }
5354
// }
5455
request.add("path", "RAW.ETH.USD.VOLUME24HOUR");
55-
56+
5657
// Multiply the result by 1000000000000000000 to remove decimals
5758
int timesAmount = 10**18;
5859
request.addInt("times", timesAmount);
59-
60+
6061
// Sends the request
6162
return sendChainlinkRequestTo(oracle, request, fee);
6263
}
63-
64+
6465
/**
6566
* Receive the response in the form of uint256
66-
*/
67+
*/
6768
function fulfill(bytes32 _requestId, uint256 _volume) public recordChainlinkFulfillment(_requestId)
6869
{
6970
volume = _volume;
7071
}
7172

73+
/**
74+
* Withdraw LINK from this contract
75+
*
76+
*/
77+
function withdrawLink() external onlyOwner {
78+
LinkTokenInterface linkToken = LinkTokenInterface(chainlinkTokenAddress());
79+
require(linkToken.transfer(msg.sender, linkToken.balanceOf(address(this))), "Unable to transfer");
80+
}
81+
7282
function stringToBytes32(string memory source) public pure returns (bytes32 result) {
7383
bytes memory tempEmptyStringTest = bytes(source);
7484
if (tempEmptyStringTest.length == 0) {

contracts/RandomNumberConsumer.sol

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
21
pragma solidity 0.6.6;
32

43
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
54
contract RandomNumberConsumer is VRFConsumerBase {
6-
5+
76
bytes32 internal keyHash;
87
uint256 internal fee;
98
uint256 public randomResult;
109
event RequestedRandomness(bytes32 requestId);
11-
10+
1211
/**
1312
* Constructor inherits VRFConsumerBase
14-
*
13+
*
1514
* Network: Kovan
1615
* Chainlink VRF Coordinator address: 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9
1716
* LINK token address: 0xa36085F69e2889c224210F603D836748e7dC0088
@@ -20,17 +19,17 @@ contract RandomNumberConsumer is VRFConsumerBase {
2019
constructor(address _vrfCoordinator,
2120
address _link,
2221
bytes32 _keyHash,
23-
uint _fee)
22+
uint _fee)
2423
VRFConsumerBase(
2524
_vrfCoordinator, // VRF Coordinator
2625
_link // LINK Token
2726
) public
2827
{
2928
keyHash = _keyHash;
30-
fee = _fee;
29+
fee = _fee;
3130
}
32-
33-
/**
31+
32+
/**
3433
* Requests randomness
3534
*/
3635
function getRandomNumber() public returns (bytes32 requestId) {
@@ -44,10 +43,10 @@ contract RandomNumberConsumer is VRFConsumerBase {
4443
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
4544
randomResult = randomness;
4645
}
47-
46+
4847
/**
4948
* Withdraw LINK from this contract
50-
*
49+
*
5150
* DO NOT USE THIS IN PRODUCTION AS IT CAN BE CALLED BY ANY ADDRESS.
5251
* THIS IS PURELY FOR EXAMPLE PURPOSES.
5352
*/

contracts/test/MockOracle.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ contract MockOracle is ChainlinkRequestInterface, LinkTokenReceiver {
1515

1616
uint256 constant public EXPIRY_TIME = 5 minutes;
1717
uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000;
18-
18+
1919
struct Request {
2020
address callbackAddr;
2121
bytes4 callbackFunctionId;

deploy/00_Deploy_Mocks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ module.exports = async ({
3535
log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
3636
}
3737
}
38-
module.exports.tags = ['all', 'mocks']
38+
module.exports.tags = ['all', 'mocks', 'main']

deploy/01_Deploy_PriceConsumerV3.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module.exports = async ({
55
deployments,
66
getChainId
77
}) => {
8+
89
const { deploy, log } = deployments
910
const { deployer } = await getNamedAccounts()
1011
const chainId = await getChainId()
@@ -17,6 +18,7 @@ module.exports = async ({
1718
}
1819
// Price Feed Address, values can be obtained at https://docs.chain.link/docs/reference-contracts
1920
// Default one below is ETH/USD contract on Kovan
21+
log("----------------------------------------------------")
2022
const priceConsumerV3 = await deploy('PriceConsumerV3', {
2123
from: deployer,
2224
args: [ethUsdPriceFeedAddress],
@@ -25,6 +27,7 @@ module.exports = async ({
2527
log("Run Price Feed contract with command:")
2628
log("npx hardhat read-price-feed --contract " + priceConsumerV3.address + " --network " + networkConfig[chainId]['name'])
2729
log("----------------------------------------------------")
30+
2831
}
2932

30-
module.exports.tags = ['all', 'feed']
33+
module.exports.tags = ['all', 'feed', 'main']

deploy/02_Deploy_APIConsumer.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
let { networkConfig } = require('../helper-hardhat-config')
1+
let { networkConfig} = require('../helper-hardhat-config')
22

33
module.exports = async ({
44
getNamedAccounts,
@@ -10,6 +10,8 @@ module.exports = async ({
1010
let linkTokenAddress
1111
let oracle
1212
let additionalMessage = ""
13+
//set log level to ignore non errors
14+
ethers.utils.Logger.setLogLevel(ethers.utils.Logger.levels.ERROR)
1315

1416
if (chainId == 31337) {
1517
linkToken = await get('LinkToken')
@@ -23,18 +25,16 @@ module.exports = async ({
2325
}
2426
const jobId = networkConfig[chainId]['jobId']
2527
const fee = networkConfig[chainId]['fee']
28+
const networkName = networkConfig[chainId]['name']
2629

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

33-
log("Run the following command to fund contract with LINK:")
34-
log("npx hardhat fund-link --contract " + apiConsumer.address + " --network " + networkConfig[chainId]['name'] + additionalMessage)
35-
log("Then run API Consumer contract with following command:")
36-
log("npx hardhat request-data --contract " + apiConsumer.address + " --network " + networkConfig[chainId]['name'])
36+
log("Run API Consumer contract with following command:")
37+
log("npx hardhat request-data --contract " + apiConsumer.address + " --network " + networkName)
3738
log("----------------------------------------------------")
3839
}
39-
40-
module.exports.tags = ['all', 'api']
40+
module.exports.tags = ['all', 'api', 'main']

deploy/03_Deploy_RandomNumberConsumer.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
let { networkConfig } = require('../helper-hardhat-config')
2-
1+
let { networkConfig} = require('../helper-hardhat-config')
32

43
module.exports = async ({
54
getNamedAccounts,
65
deployments,
76
getChainId
87
}) => {
8+
99
const { deploy, get, log } = deployments
1010
const { deployer } = await getNamedAccounts()
1111
const chainId = await getChainId()
@@ -39,4 +39,4 @@ module.exports = async ({
3939
log("----------------------------------------------------")
4040
}
4141

42-
module.exports.tags = ['all', 'vrf']
42+
module.exports.tags = ['all', 'vrf']

deploy/04_Setup_Contracts.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const { networkConfig, autoFundCheck } = require('../helper-hardhat-config')
2+
const { ethers, getNamedAccounts } = require('hardhat')
3+
4+
module.exports = async ({
5+
getNamedAccounts,
6+
deployments
7+
}) => {
8+
const { deploy, log, get } = deployments
9+
const chainId = await getChainId()
10+
let linkTokenAddress
11+
let additionalMessage = ""
12+
//set log level to ignore non errors
13+
ethers.utils.Logger.setLogLevel(ethers.utils.Logger.levels.ERROR)
14+
const networkName = networkConfig[chainId]['name']
15+
16+
if (chainId == 31337) {
17+
linkToken = await get('LinkToken')
18+
MockOracle = await get('MockOracle')
19+
linkTokenAddress = linkToken.address
20+
oracle = MockOracle.address
21+
additionalMessage = " --linkaddress " + linkTokenAddress
22+
} else {
23+
linkTokenAddress = networkConfig[chainId]['linkToken']
24+
oracle = networkConfig[chainId]['oracle']
25+
}
26+
27+
//Try Auto-fund APIConsumer contract with LINK
28+
const APIConsumer = await deployments.get('APIConsumer')
29+
const apiConsumer = await ethers.getContractAt('APIConsumer', APIConsumer.address)
30+
31+
if (await autoFundCheck(apiConsumer.address, networkName, linkTokenAddress, additionalMessage)) {
32+
await hre.run("fund-link", { contract: apiConsumer.address, linkaddress: linkTokenAddress })
33+
} else {
34+
log("Then run API Consumer contract with following command:")
35+
log("npx hardhat request-data --contract " + apiConsumer.address + " --network " + networkName)
36+
}
37+
log("----------------------------------------------------")
38+
39+
40+
//Now try Auto-fund VRFConsumer contract
41+
42+
const RandomNumberConsumer = await deployments.get('RandomNumberConsumer')
43+
const randomNumberConsumer = await ethers.getContractAt('RandomNumberConsumer', RandomNumberConsumer.address)
44+
45+
if (await autoFundCheck(apiConsumer.address, networkName, linkTokenAddress, additionalMessage)) {
46+
await hre.run("fund-link", { contract: randomNumberConsumer.address, linkaddress: linkTokenAddress })
47+
} else {
48+
log("Then run RandomNumberConsumer contract with the following command:")
49+
log("npx hardhat request-random-number --contract " + randomNumberConsumer.address + " --network " + networkName)
50+
}
51+
log("----------------------------------------------------")
52+
53+
}
54+
module.exports.tags = ['all']

0 commit comments

Comments
 (0)