Using Hardhat to Deploy To Moonbeam¶
Introduction¶
Hardhat is an Ethereum development environment that helps developers manage and automate the recurring tasks inherent to building smart contracts and DApps. Hardhat can directly interact with Moonbeam's Ethereum API so it can also be used to deploy smart contracts into Moonbeam.
This guide will cover how to use Hardhat to compile, deploy, and debug Ethereum smart contracts on the Moonbase Alpha TestNet. This guide can also be adapted for Moonbeam, Moonriver, or Moonbeam development node.
Checking Prerequisites¶
To get started, you will need the following:
- Have MetaMask installed and connected to Moonbase Alpha
- Have an account with funds, which you can get from Mission Control
- To test out the examples in this guide on Moonbeam or Moonriver, you will need to have your own endpoint and API key which you can get from one of the supported Endpoint Providers.
Creating a Hardhat Project¶
You will need to create a Hardhat project if you don't already have one. You can create one by completing the following steps:
- Create a directory for your project
mkdir hardhat && cd hardhat
- Initialize the project which will create a
package.json
filenpm init -y
- Install Hardhat
npm install hardhat
-
Create a project
npx hardhat
Note
npx
is used to run executables installed locally in your project. Although Hardhat can be installed globally, we recommend installing locally in each project so that you can control the version on a project by project basis. -
A menu will appear which will allow you to create a new project or use a sample project. For this example, you can choose Create an empty hardhat.config.js
This will create a Hardhat config file (hardhat.config.js
) in your project directory.
Once you have your Hardhat project, you can also install the ethers plugin. This provides a convenient way to use the ethers.js library to interact with the network. To install it, run the following command:
npm install @nomiclabs/hardhat-ethers ethers
The Contract File¶
With your empty project created, next you are going to create a contracts
directory. You can do so by running the following command:
mkdir contracts && cd contracts
The smart contract that you'll deploy as an example will be called Box
, it will let you store a value that can be retrieved later. In the contracts
directory, you can create the Box.sol
file:
touch Box.sol
Open the file and add the following contract to it:
// contracts/Box.sol
pragma solidity ^0.8.1;
contract Box {
uint256 private value;
// Emitted when the stored value changes
event ValueChanged(uint256 newValue);
// Stores a new value in the contract
function store(uint256 newValue) public {
value = newValue;
emit ValueChanged(newValue);
}
// Reads the last stored value
function retrieve() public view returns (uint256) {
return value;
}
}
Hardhat Configuration File¶
Before you can deploy the contract to Moonbase Alpha, you'll need to modify the Hardhat configuration file and create a secure file to store your private key in.
You can create a secrets.json
file to store your private key by running:
touch secrets.json
Then add your private key to it:
{
"privateKey": "YOUR-PRIVATE-KEY-HERE"
}
Make sure to add the file to your project's .gitignore
, and to never reveal your private key.
Note
Please always manage your private keys with a designated secret manager or similar service. Never save or commit your private keys inside your repositories.
Next you can take the following steps to modify the hardhat.config.js
file and add Moonbase Alpha as a network:
- Import the Ethers plugin
- Import the
secrets.json
file - Inside the
module.exports
, you need to provide the Solidity version (0.8.1
according to our contract file) - Add the Moonbase Alpha network configuration
// 1. Import the ethers plugin required to interact with the contract
require('@nomiclabs/hardhat-ethers');
// 2. Import your private key from your pre-funded Moonbase Alpha testing account
const { privateKey } = require('./secrets.json');
module.exports = {
// 3. Specify the Solidity version
solidity: "0.8.1",
networks: {
// 4. Add the Moonbase Alpha network specification
moonbase: {
url: 'https://rpc.api.moonbase.moonbeam.network',
chainId: 1287, // 0x507 in hex,
accounts: [privateKey]
}
}
};
You can modify the hardhat.config.js
file to use any of the Moonbeam networks:
moonbeam: {
url: 'RPC-API-ENDPOINT-HERE', // Insert your RPC URL here
chainId: 1284, // (hex: 0x504),
accounts: [privateKey]
},
moonriver: {
url: 'RPC-API-ENDPOINT-HERE', // Insert your RPC URL here
chainId: 1285, // (hex: 0x505),
accounts: [privateKey]
},
moonbase: {
url: 'https://rpc.api.moonbase.moonbeam.network',
chainId: 1287, // (hex: 0x507),
accounts: [privateKey]
},
dev: {
url: 'http://127.0.0.1:9933',
chainId: 1281, // (hex: 0x501),
accounts: [privateKey]
},
Congratulations! You are now ready for deployment!
Compiling Solidity¶
To compile the contract you can simply run:
npx hardhat compile
After compilation, an artifacts
directory is created: it holds the bytecode and metadata of the contract, which are .json
files. It’s a good idea to add this directory to your .gitignore
.
Deploying the Contract¶
In order to deploy the Box.sol
smart contract, you will need to write a simple deployment script. You can create a new directory for the script and name it scripts
and add a new file to it called deploy.js
:
mkdir scripts && cd scripts
touch deploy.js
Next, you need to write your deployment script which can be done using ethers
. Because you'll be running it with Hardhat, you don't need to import any libraries.
To get started start, take the following steps:
- Create a local instance of the contract with the
getContractFactory
method - Use the
deploy
method that exists within this instance to instantiate the smart contract - Wait for the deployment by using
deployed
- Once deployed, you can fetch the address of the contract using the contract instance.
// scripts/deploy.js
async function main() {
// 1. Get the contract to deploy
const Box = await ethers.getContractFactory('Box');
console.log('Deploying Box...');
// 2. Instantiating a new Box smart contract
const box = await Box.deploy();
// 3. Waiting for the deployment to resolve
await box.deployed();
// 4. Use the contract instance to get the contract address
console.log('Box deployed to:', box.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
You can now deploy the Box.sol
contract using the run
command and specifying moonbase
as the network:
npx hardhat run --network moonbase scripts/deploy.js
If you're using another Moonbeam network, make sure that you specify the correct network. The network name needs to match how it's defined in the hardhat.config.js
.
After a few seconds, the contract is deployed, and you should see the address in the terminal.
Congratulations, your contract is live! Save the address, as you will use it to interact with this contract instance in the next step.
Interacting with the Contract¶
To interact with your newly deployed contract on Moonbase Alpha, you can launch the Hardhat console
by running:
npx hardhat console --network moonbase
Next you can take the following steps, entering in one line at a time:
- Create a local instance of the
Box.sol
contractconst Box = await ethers.getContractFactory('Box');
- Connect the local instance to the deployed contract, using the address of the contract
const box = await Box.attach('0x425668350bD782D80D457d5F9bc7782A24B8c2ef');
- Interact with the attached contract. For this example, you can call the
store
method and store a simple valueawait box.store(5)
The transaction will be signed by your Moonbase account and broadcast to the network. The output should look similar to:
Notice your address labeled from
, the address of the contract, and the data
that is being passed. Now, you can retrieve the value by running:
(await box.retrieve()).toNumber()
You should see 5
or the value you have stored initially.
Congratulations, you have successfully deployed and interacted with a contract using Hardhat!