While Hardhat itself does not provide a deployment feature, plugins like hardhat-deploy can be used to easily create deployment tasks. Here, we will explain actual deployment scripts. We will look at the script for deploying the Funding contract implemented on day17.
Deployment Script
Let’s start by looking at an example of an actual deployment script.
// deploy/01-deploy-funding.ts
import { HardhatRuntimeEnvironment } from "hardhat/types"
import { DeployFunction } from "hardhat-deploy/types"
import { developmentChains } from "../helpder-hardhat-config"
import { networkConfig } from "../helpder-hardhat-config"
import verify from "../scripts/verify"
const deployFunding: DeployFunction = async function (
hre: HardhatRuntimeEnvironment,
) {
const { getNamedAccounts, deployments, network } = hre
const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()
log("-----------------------------------------------------")
log("Deploying Funding and waiting for confirmations...")
const funding = await deploy("Funding", {
from: deployer,
args: [],
log: true,
waitConfirmations: networkConfig[network.name].blockConfirmations || 0,
})
log(`Funding deployed at ${funding.address}`)
if (
!developmentChains.includes(network.name) &&
process.env.ETHERSCAN_API_KEY
) {
await verify(funding.address, [])
}
}
export default deployFunding
deployFunding.tags = ["all", "funding"]
This script is deploying a contract named Funding
. For the deployment, the deploy
function is being used.
hre, getNamedAccounts, deployments, network
The code on line 11, hre
(HardhatRuntimeEnvironment
), is exported from hardhat/types
and represents the execution environment of Hardhat. This variable hre
allows access to the functionalities provided by Hardhat’s execution environment. For example, the three variables defined on the left side represent properties (functionalities) defined in hre.
// deploy/01-deploy-funding.ts (excerpt)
const { getNamedAccounts, deployments, network } = hre
getNamedAccounts
: A function provided by thehardhat-deploy
plugin, it retrieves a list of named accounts from the configuration file (hardhat.config.ts
). You can set named accounts for each network, and by using this, you can easily refer to accounts in the script. For example, if you have set an account for deployment asdeployer
, you can retrieve the account usinggetNamedAccounts
in the form of{ deployer }
.deployments
: An object provided by thehardhat-deploy
plugin, it offers methods for deployment-related operations. Specifically, it allows for the deployment of smart contracts (deploy
method), retrieval of deployed smart contracts (get
method), and retrieval of all deployed smart contracts (all
method), among others. It also includes a function,log
, for console output during deployment.network
: Provides information and functionalities related to the currently selected network and its settings. It includes the network name, config (network settings: RPC URL, chain id, etc. For more details, refer to day21).
With the above in mind, referring to lines 11 and 12, you can see that deploy and deployer are obtained from getNamedAccounts
and deployments
, respectively. deploy
is the function that executes the process for actual deployment, and deployer
is the user who executes the deploy (and this account is defined in the configuration file, see the section namedAccounts
from line 51 onwards in day 21).
// deploy/01-deploy-funding.ts (excerpt)
const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()
deploy function
The actual deployment is carried out in line 16. This is where the previously loaded deploy function is executed.
// deploy/01-deploy-funding.ts (excerpt)
const funding = await deploy("Funding", {
from: deployer,
args: [],
log: true,
waitConfirmations: networkConfig[network.name].blockConfirmations || 0,
})
The deploy function takes arguments as described below.
name
: The name of the contract to be deployed. This must be unique and is used to refer to a specific contract deployment.from
: The address of the account sending the transaction. This account will pay the gas required for the contract deployment.args
: An array of arguments to be passed to the contract constructor. In other words, you define arguments according to the specifications of the constructor of the smart contract you developed.log
: If set to true, details of the deployment will be logged to the console.waitConfirmations
: In blockchain, when a transaction is included in a block and verified by the network, it is considered ‘confirmed’. This setting specifies the number of confirmations (the more confirmations, the less likely the transaction is to be tampered with. However, waiting for many confirmations prolongs the time it takes for the deployment to complete).
verify
The following source is the section where verification is requested on Etherscan. The actual request for verification is done in the verify function, which is used as a separate file placed under scripts named verify.ts.
// deploy/01-deploy-funding.ts (excerpt)
if (
!developmentChains.includes(network.name) &&
process.env.ETHERSCAN_API_KEY
) {
await verify(funding.address, [])
}
// scripts/verify.ts
import { run } from "hardhat"
const verify = async (contractAddress: string, args: any[]) => {
console.log("Verifying contract...")
try {
await run("verify:verify", {
address: contractAddress,
constructorArguments: args,
})
} catch (e: any) {
if (e.message.toLowerCase().includes("already verified")) {
console.log("Already verified!")
} else {
console.log(e)
}
}
}
export default verify
The run
function on line 7 is provided by hardhat
and can execute Hardhat’s tasks. It is a function for programmatically executing Hardhat tasks. Hardhat includes several standard tasks for compilation, testing, deployment, etc., which can be manually executed using the hardhat
command-line tool. However, these tasks can also be called directly from within a script, and that’s the role of the run
function.
The basic usage format is as follows. In the example above, the verify (verify:verify
) task is being executed. The arguments include the address of the deployed contract and the arguments of the contract constructor (the deployed contract is obtained as funding
from the deployment result on line 17, and using funding.address
, you can obtain the address of the deployed contract).
await hre.run('taskName', taskArguments)
The part where the run function is executed is surrounded by a try-catch
block. If the execution of the run
function inside the try
block does not go well, the error is captured in the catch
block, and the error output is made to the console.
export
// deploy/01-deploy-funding.ts (excerpt)
export default deployFunding
deployFunding.tags = ["all", "funding"]
The TypeScript export
statement is used to export functions, objects, values, types, etc., from a module. This allows other modules to use the exported entities using the import
statement. In the example above, the previously defined deployFunding function is made public and available for use.
Continuing, the next part defines options for executing the deployment. If you specify the option as --tags all
, functions tagged with all are executed. If you specify --tags funding
, functions tagged with funding are executed (for instance, if the deployment consists of multiple deployment scripts, you can specify whether to execute all or only specific deployment scripts).
Executing the Deployment Script
Next, let’s actually execute a deployment locally.
# console
% yarn hardhat deploy --network hardhat --tags all
yarn run v1.22.19
$ /Users/username/code/token-village/funding/node_modules/.bin/hardhat deploy --tags all
Generating typings for: 1 artifacts in dir: typechain-types for target: ethers-v6
Successfully generated 6 typings!
Compiled 1 Solidity file successfully
-----------------------------------------------------
Deploying Funding and waiting for confirmations...
deploying "Funding" (tx: 0xbc444ca6c542123b21a0f1a3515a8d8f2f43b980f8e747417596779369851eda)...: deployed at 0x5FbDB2315678afecb367f032d93F642f64180aa3 with 538126 gas
Funding deployed at 0x5FbDB2315678afecb367f032d93F642f64180aa3
✨ Done in 6.67s.
%
Deployment can be executed in the following format.
% yarn hardhat deploy --network Network-Name [--tags Tag-Name]
For the network option, specify the network (local (hardhat), testnet (such as sepolia), or mainnet (mainnet)). For networks other than mainnet, they must be defined in hardhat.config.ts (see day 21 for configuration details).
コメント