This template sets up a combination of Solidity smart contracts and a React front-end app that interacts with these
smart contracts.
This template includes:
- OpenZeppelin smart contract library.
- hardhat smart contract development tooling.
- wagmi for smart contract interaction.
- Tailwind CSS + Tailwind UI.
- Vite for dev tooling.
The project is configured to deploy on "Passet Hub" network
First, set up Metamask wallet for Passet Hub network, and get some PAS there. (docs)
In contracts directory, set up private key for hardhat:
npx hardhat vars set PRIVATE_KEY "INSERT_PRIVATE_KEY"
How to export private key from Metamask wallet
Contracts are written in contracts/contracts. Each smart contract has a Hardhat Ignition module counterpart in contracts/igniton/modules. More on that in Hardhat Ignition docs.
- Edit smart contracts in
contracts/contracts - Edit ignition module in
contracts/igniton/modules - Run
npx hardhat compileto compile smart contracts - Run
npx hardhat ignition deploy ./ignition/modules/<ModuleName>.ts --network polkadotHubTestnetto deploy them
This is a directory that contains build and deployment artifacts from hardhat.
They aren't ignored, becuase they are used for types generation for frontend: if there's a smart contract already deployed, you may want to keep it in git, so a fresh clone would give you a working frontend.
However, several issues with hardhat are resolved by removing ignition/deployments directory, to start fresh deployment. These issues include:
An unexpected error occurred:
Error: Could not parse row {...
[ MyTokenModule ] reconciliation failed ⛔
The module contains changes to executed futures:
...
In such cases, do rm -rf ignition/deployments, deploy the new contract, and commit the artifacts anew :)
- Generate types from deployed smart contracts by running
npm run generateinfrontenddirectory - Run
npm run devto startviteenvironment - You can import contract ABI and deployed addresses from
src/generated.ts:
import {
myTokenModuleMyTokenAddress,
myTokenModuleMyTokenAbi,
} from "./generated";
const contractAddress = myTokenModuleMyTokenAddress[420420422];
// ...
writeContract({
address: contractAddress,
abi: myTokenModuleMyTokenAbi,
functionName: "mint",
args: [address, BigInt(amount) * 10n ** BigInt(params.decimals)],
});More info at: