Hardhat¶
-
Test and Deploy with Hardhat
Master Solidity smart contract development with Hardhat. Learn testing, deployment, and network interaction in one comprehensive tutorial.
Contracts Code Blob Size Disclaimer
The maximum contract code blob size on Polkadot Hub networks is 100 kilobytes, significantly larger than Ethereum’s EVM limit of 24 kilobytes.
For detailed comparisons and migration guidelines, see the EVM vs. PolkaVM documentation page.
Overview¶
Hardhat is a robust development environment for Ethereum-compatible chains that makes smart contract development more efficient. This guide walks you through the essentials of using Hardhat to create, compile, test, and deploy smart contracts on Polkadot Hub.
Prerequisites¶
Before getting started, ensure you have:
- Node.js (v16.0.0 or later) and npm installed
- Basic understanding of Solidity programming
- Some PAS test tokens to cover transaction fees (easily obtainable from the Polkadot faucet). To learn how to get test tokens, check out the Test Tokens section
Set Up Hardhat¶
-
Create a new directory for your project and navigate into it:
-
Initialize a new npm project:
-
To interact with Polkadot, Hardhat requires the following plugin to compile contracts to PolkaVM bytecode and to spawn a local node compatible with PolkaVM:
-
Create a Hardhat project:
Select Create a JavaScript project when prompted and follow the instructions. After that, your project will be created with three main folders:
contracts
- where your Solidity smart contracts livetest
- contains your test files that validate contract functionalityignition
- deployment modules for safely deploying your contracts to various networks
-
Add the following folders to the
.gitignore
file if they are not already there: -
Finish the setup by installing all the dependencies:
Note
This last step is needed to set up the
hardhat-polkadot
plugin. It will install the@parity/hardhat-polkadot
package and all its dependencies. In the future, the plugin will handle this automatically.
Compile Your Contract¶
The plugin will compile your Solidity contracts for Solidity versions 0.8.0
and higher to be PolkaVM compatible. When compiling your contract, there are two ways to configure your compilation process:
- npm compiler - uses library @parity/resolc for simplicity and ease of use
- Binary compiler - uses your local
resolc
binary directly for more control and configuration options
To compile your project, follow these instructions:
-
Modify your Hardhat configuration file to specify which compilation process you will be using and activate the
polkavm
flag in the Hardhat network:hardhat.config.jsrequire('@nomicfoundation/hardhat-toolbox'); require('@parity/hardhat-polkadot'); /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { solidity: '0.8.28', resolc: { compilerSource: 'binary', settings: { compilerPath: 'INSERT_PATH_TO_RESOLC_COMPILER', }, }, networks: { hardhat: { polkavm: true, }, }, };
For the binary configuration, replace
INSERT_PATH_TO_RESOLC_COMPILER
with the proper path to the binary. To obtain the binary, check the releases section of theresolc
compiler, and download the latest version.The default settings used can be found in the
constants.ts
file of thehardhat-polkadot
source code. You can change them according to your project needs. Generally, the recommended settings for optimized outputs are the following:hardhat.config.jsresolc: { ... settings: { optimizer: { enabled: true, parameters: 'z', fallbackOz: true, runs: 200, }, standardJson: true, }, ... }
You can check the
ResolcConfig
for more information about compilation settings. -
Compile the contract with Hardhat:
-
After successful compilation, you'll see the artifacts generated in the
artifacts-pvm
directory:You should see JSON files containing the contract ABI and bytecode of the contracts you compiled.
Set Up a Testing Environment¶
Hardhat allows you to spin up a local testing environment to test and validate your smart contract functionalities before deploying to live networks. The hardhat-polkadot
plugin provides the possibility to spin up a local node with an ETH-RPC adapter for running local tests.
For complete isolation and control over the testing environment, you can configure Hardhat to work with a fresh local Substrate node. This approach is ideal when you want to test in a clean environment without any existing state or when you need specific node configurations.
Configure a local node setup by adding the node binary path along with the ETH-RPC adapter path:
require('@nomicfoundation/hardhat-toolbox');
require('@parity/hardhat-polkadot');
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
...
networks: {
hardhat: {
polkavm: true,
nodeConfig: {
nodeBinaryPath: 'INSERT_PATH_TO_SUBSTRATE_NODE',
rpcPort: 8000,
dev: true,
},
adapterConfig: {
adapterBinaryPath: 'INSERT_PATH_TO_ETH_RPC_ADAPTER',
dev: true,
},
},
},
};
Replace INSERT_PATH_TO_SUBSTRATE_NODE
and INSERT_PATH_TO_ETH_RPC_ADAPTER
with the actual paths to your compiled binaries. The dev: true
flag configures both the node and adapter for development mode. To obtain these binaries, check the Installation section on the Local Development Node page.
Once configured, start your chosen testing environment with:
This command will launch either the forked network or local node (depending on your configuration) along with the ETH-RPC adapter, providing you with a complete testing environment ready for contract deployment and interaction. By default, the Substrate node will be running on localhost:8000
and the ETH-RPC adapter on localhost:8545
.
The output will be something like this:
Starting server at 127.0.0.1:8000 ../bin/substrate-node --rpc-port=8000 --dev Starting the Eth RPC Adapter at 127.0.0.1:8545 ../bin/eth-rpc --node-rpc-url=ws://localhost:8000 --dev 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. 2025-05-29 13:00:32 🌐 Connecting to node at: ws://localhost:8000 ... 2025-05-29 13:00:32 Substrate Node 2025-05-29 13:00:32 ✌️ version 3.0.0-dev-f73c228b7a1 2025-05-29 13:00:32 ❤️ by Parity Technologies <admin@parity.io>, 2017-2025 2025-05-29 13:00:32 📋 Chain specification: Development 2025-05-29 13:00:32 🏷 Node name: electric-activity-4221 2025-05-29 13:00:32 👤 Role: AUTHORITY 2025-05-29 13:00:32 💾 Database: RocksDb at /var/folders/f4/7rdt2m9d7j361dm453cpggbm0000gn/T/substrateOaoecu/chains/dev/db/full 2025-05-29 13:00:36 [0] 💸 generated 1 npos voters, 1 from validators and 0 nominators ...
Test Your Contract¶
When testing your contract, be aware that @nomicfoundation/hardhat-toolbox/network-helpers
is not fully compatible with Polkadot Hub's available RPCs. Specifically, Hardhat-only helpers like time
and loadFixture
may not work due to missing RPC calls in the node. For more details, refer to the Compatibility section in the hardhat-revive
docs. You should avoid using helpers like time
and loadFixture
when writing tests.
To run your test:
-
Update the
hardhat.config.js
file accordingly to the Set Up a Testing Environment section -
Execute the following command to run your tests:
Deploy to a Local Node¶
Before deploying to a live network, you can deploy your contract to a local node using Ignition modules:
-
Update the Hardhat configuration file to add the local network as a target for local deployment:
-
Start a local node:
This command will spawn a local Substrate node along with the ETH-RPC adapter.
-
In a new terminal window, deploy the contract using Ignition:
Deploying to a Live Network¶
After testing your contract locally, you can deploy it to a live network. This guide will use the Polkadot Hub TestNet as the target network. Here's how to configure and deploy:
-
Fund your deployment account with enough tokens to cover gas fees. In this case, the needed tokens are PAS (on Polkadot Hub TestNet). You can use the Polkadot faucet to obtain testing tokens.
-
Export your private key and save it in a
.env
file:Replace
INSERT_PRIVATE_KEY
with your actual private key. For further details on private key exportation, refer to the article How to export an account's private key.Warning
Never reveal your private key. Be sure you add the
.env
file to your.gitignore
file. -
Install the
dotenv
package to load the private key into your Hardhat configuration: -
Update your config to load it:
-
Update your Hardhat configuration file with network settings for the Polkadot network you want to target:
hardhat.config.jsrequire('@nomicfoundation/hardhat-toolbox'); require('@parity/hardhat-polkadot'); require('dotenv').config(); /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { ... networks: { hardhat: { ... }, localNode: { ... }, polkadotHubTestnet: { polkavm: true, url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', accounts: [process.env.PRIVATE_KEY], }, }, }, };
-
Deploy your contract using Ignition:
Interacting with Your Contract¶
Once deployed, you can create a script to interact with your contract. To do so, create a file called scripts/interact.js
and add some logic to interact with the contract.
For example, for the default MyToken.sol
contract, you can use the following file that connects to the contract at its address and retrieves the unlockTime
, which represents when funds can be withdrawn. The script converts this timestamp into a readable date and logs it. It then checks the contract's balance and displays it. Finally, it attempts to call the withdrawal function on the contract, but it catches and logs the error message if the withdrawal is not yet allowed (e.g., before unlockTime
).
const hre = require('hardhat');
async function main() {
// Get the contract factory
const MyToken = await hre.ethers.getContractFactory('MyToken');
// Replace with your deployed contract address
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
// Attach to existing contract
const token = await MyToken.attach(contractAddress);
// Get signers
const [deployer] = await hre.ethers.getSigners();
// Read contract state
const name = await token.name();
const symbol = await token.symbol();
const totalSupply = await token.totalSupply();
const balance = await token.balanceOf(deployer.address);
console.log(`Token: ${name} (${symbol})`);
console.log(
`Total Supply: ${hre.ethers.formatUnits(totalSupply, 18)} tokens`,
);
console.log(
`Deployer Balance: ${hre.ethers.formatUnits(balance, 18)} tokens`,
);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Run your interaction script:
Where to Go Next¶
Hardhat provides a powerful environment for developing, testing, and deploying smart contracts on Polkadot Hub. Its plugin architecture allows seamless integration with PolkaVM through the hardhat-resolc
and hardhat-revive-node
plugins.
Explore more about smart contracts through these resources:
-
Guide Smart Contracts on Polkadot
Dive into advanced smart contract concepts.
-
External Hardhat Documentation
Learn more about Hardhat's advanced features and best practices.
-
External OpenZeppelin Contracts
Test your skills by deploying contracts with prebuilt templates.
| Created: June 6, 2025