First, we’ll need to create a folder for our project. Navigate to your and type
mkdir hello-world
cd hello-world
Now that we’re inside our project folder, we’ll use npm init to initialize the project.
npm init # (or npm init --yes)
It doesn’t matter how you answer the installation questions.
Approve the package.json, and we’re good to go!
Step 2: Install Hardhat
Hardhat is a development environment to compile, deploy, test, and debug your Ethereum software. It helps developers build smart contracts and dApps locally before deploying to the live chain.
Inside our hello-world project run:
npm install --save-dev hardhat
Check out this page for more details on .
Inside our hello-world project folder, run:
npx hardhat
You should then see a welcome message and the option to select what you want to do. Select “create an empty hardhat.config.js”:
This command will generate a hardhat.config.js file, where we’ll specify all the configurations for our project (in step 13).
You can choose to create the project in JavaScript or TypeScript, but remember that the deployment and interaction files will have to be changed accordingly!
Create a folder to keep our smart contract code file. In the command line, type:
mkdir contracts
cd contracts
Open the hello-world project in your favourite editor (e.g., VSCode, IntelliJ IDEA). Smart contracts are written in a language called Solidity, which we will use to write our smart contract.
Below, there are three sample smart contracts that we can choose for this tutorial.
Navigate to the “contracts” folder and create a new file with the name of the smart contract you choose (e.g., Greeter.sol).
Copy and paste the contents below into your file, and be sure to read the comments to understand what this contract does:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/**
* @title Storage
* @dev Store & retrieve value in a variable
* @custom:dev-run-script ./scripts/deploy_with_ethers.ts
*/
contract Storage {
uint256 number;
/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;
contract Payable {
// Payable address can receive Ether
address payable public owner;
address User;
// Payable constructor can receive Ether
constructor() payable {
owner = payable(msg.sender);
}
// Function to deposit Ether into this contract.
// Call this function along with some Ether.
// The balance of this contract will be automatically updated.
function deposit(address u) public payable {
User=u;
}
// Call this function along with some Ether.
// The function will throw an error since this function is not payable.
function notPayable() public {}
function retrieveAdd() public view returns (address){ return User; }
function GetBalance() public view returns (uint256){
return address(this).balance;
}
receive() external payable {}
// Function to withdraw all Ether from this contract.
function withdraw() public {
// get the amount of Ether stored in this contract
uint amount = address(this).balance;
// send all Ether to owner
// Owner can receive Ether since the address of owner is payable
(bool success, ) = owner.call{value: amount}("");
require(success, "Failed to send Ether");
}
// Function to transfer Ether from this contract to address from input
function transfer(address payable _to, uint _amount) public {
// Note that "to" is declared as payable
(bool success, ) = _to.call{value: _amount}("");
require(success, "Failed to send Ether");
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
// Import this file to use console.log
import "hardhat/console.sol";
contract Lock {
uint public unlockTime;
address payable public owner;
event Withdrawal(uint amount, uint when);
constructor(uint _unlockTime) payable {
require(
block.timestamp < _unlockTime,
"Unlock time should be in the future"
);
unlockTime = _unlockTime;
owner = payable(msg.sender);
}
function withdraw() public {
// Uncomment this line to print a log in your terminal
// console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp);
require(block.timestamp >= unlockTime, "You can't withdraw yet");
require(msg.sender == owner, "You aren't the owner");
emit Withdrawal(address(this).balance, block.timestamp);
owner.transfer(address(this).balance);
}
}
Step 4: Connect Metamask
Step 5: Update hardhat.config.js
We need to update hardhat.config.js so that our project knows the details about the 1DLT node.
Add the 1DLT node information into the network list in hardhat.config.js
Calling deploy() on a ContractFactory will start the deployment and return a Promise that resolves to a Contract object. This object has a method for each of our smart contract functions.
Step 7: Deploy the contract
Let's compile our contract to make sure everything is working so far. The compile task is one of the built-in Hardhat tasks.
From the command line, run:
npx hardhat compile
You might be warned about the SPDX license identifier not provided in the source file, but there is no need to worry about that.
We're finally ready to deploy our smart contract! Navigate to the command line and run:
npx hardhat run scripts/deploy.js --network node_1DLT
You should then see something like:
Contract deployed to address: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570
If the installation does not require you to install the plugin , which has everything you need to develop smart contracts, install it with the following command:
See .
Hardhat does an amazing job explaining each of these lines of code in their . We’ve adopted their explanations here.
A ContractFactory in ethers.js is an abstraction used to deploy new smart contracts, so Greeter here is a for instances of our hello world contract. When using the hardhat-ethers plugin ContractFactory andContract, instances are connected to the first signer (owner) by default.