👷Create Your First dAPP using Hardhat
Prerequisites
Hardhat projects are Node.js projects with the hardhat package installed and a hardhat.config.js file.
Create a new Hardhat Project
Download hardhat
npm install --save-dev hardhatAfter the installation is successful, next, create a simple Hardhat project. Run the following commands:
mkdir my_contract
cd my_contact
npx hardhat initLet’s choose create a JavaScript or TypeScript project. We recommend choosing TypeScript, but if you’re not familiar with it, simply select JavaScript.

Select Create a JavaScript project, a simple project creation wizard will ask you some questions. After that, the wizard will create some directories and files and install the necessary dependencies. The most important of these dependencies is the Hardhat Toolbox, a plugin that bundles all the things you need to start working with Hardhat.

The initialized project has the following structure:
contracts/
ignition/modules/
test/
hardhat.config.jsThese are the default paths for a Hardhat project.
contracts/is where the source files for your contracts should be.ignition/modules/is where the Ignition modules that handle contract deployments should be.test/is where your tests should go.hardhat.config.jsis used for project configuration, such as blockchain network settings, contract compilation version settings, and more.
Install Sight Oracle and openzeppelin dependency.
npm install --save-dev @sight-oracle/contracts @openzeppelin/contractsWriting Contract
In the src directory, create a new file named Example.sol, and copy the example contract code below into contracts/Example.sol.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@sight-oracle/contracts/Oracle/Types.sol";
import "@sight-oracle/contracts/Oracle/Oracle.sol";
import "@sight-oracle/contracts/Oracle/RequestBuilder.sol";
import "@sight-oracle/contracts/Oracle/ResponseResolver.sol";
contract Example {
// Use Sight Oracle's RequestBuilder and ResponseResolver to interact with Sight Oracle
using RequestBuilder for Request;
using ResponseResolver for CapsulatedValue;
event OracleCallback(bytes32 indexed reqId);
bytes32 latestReqId;
Oracle public oracle;
CapsulatedValue private _target;
constructor(address oracle_) payable {
oracle = Oracle(payable(oracle_));
}
function makeRequest() public payable {
// Initialize new FHE computation request of a single step.
Request memory r = RequestBuilder.newRequest(
msg.sender,
1,
address(this),
this.callback.selector, // specify the callback for Oracle
""
);
// Generate a random encrypted value and store in Sight Network
r.rand();
// Send the request via Sight FHE Oracle
latestReqId = oracle.send(r);
}
// only Oracle can call this
function callback(
bytes32 reqId,
CapsulatedValue[] memory values
) public onlyOracle {
// Decode value from Oracle callback
CapsulatedValue memory result = values[0];
// Keep this encrypted target value
_target = result;
emit OracleCallback(reqId);
}
function getLatestReqId() public view returns (bytes32) {
return latestReqId;
}
function getTarget() public view returns (CapsulatedValue memory) {
return _target;
}
modifier onlyOracle() {
require(msg.sender == address(oracle), "Only Oracle Can Do This");
_;
}
}Explanation
Contract Initialization:
The
Examplecontract imports the necessary modules from the Sight Oracle package.The contract uses the
RequestBuilderlibrary to construct requests and theResponseResolverlibrary to interpret the responses.
Constructor:
The constructor initializes the contract with the address of the Sight Oracle. This address is used to send requests and handle callbacks.
makeRequest Function:
This function initiates a new request to the Sight Oracle.
A new request is created using
RequestBuilder.newRequest, specifying the sender, the number of steps in the computation, the address to which the callback should be sent, and the callback function.The
randfunction is called to generate a random encrypted value and store it in the Sight Network.The
sendfunction sends the request to the Sight Oracle.
callback Function:
This function is called by the Sight Oracle once the computation is complete.
It decodes the returned value using the
ResponseResolverand stores the encrypted target value in the_targetvariable.
Modifiers:
onlyOracle: Ensures that only the Sight Oracle can call thecallbackfunction.
View Function:
getLatestReqId: Retrieves the request ID of the most recent request sent to theOracle.getTarget: Retrieves the target value of the most recent request.
Compile Contract
To compile Example contracts in your Hardhat project, use the built-in compile task:
npx hardhat compileAfter a successful compilation, some new files will be generated in our project directory. The cache/ directory contains cache files. The artifacts/ directory’s build-info folder stores information about the build process. The artifacts/contracts folder contains the ABI interface information for each compiled contract.

Deploy Contract with Script
Dependencies needed for installation when deployment.
npm i hardhat-deploy dotenv --save-devSet environment variables.
Create a .env file in the root directory and set the following environment variables:
PRIVATE_KEY=<YOUR_PRIVATE_KEY>
SEPOLIA_RPC_URL=<SEPOLIA_RPC_URL>
SEPOLIA_ORACLE_CONTRACT_ADDRESS=0xC5ac65f17Ce781E9F325634b6218Dc75a5CF9abFSEPOLIA_ORACLE_CONTRACT_ADDRESS is the Oracle address we have deployed on the Sepolia test network.
If you don’t have a Sepolia RPC yet, you can click here to require one.
Note: You can get the
private keythrough MetaMask by going to Account Details => Export Private Key (Please use a test wallet, as leaking the private key poses a risk of account theft!).
network configuration
Add the following code to the hardhat.config.js file:
require("@nomicfoundation/hardhat-toolbox");
require("dotenv/config");
require("hardhat-deploy");
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: {
version: "0.8.27",
},
defaultNetwork: "hardhat",
networks: {
hardhat: {},
sepolia: {
url: process.env.SEPOLIA_RPC_URL,
accounts: [process.env.PRIVATE_KEY],
chainId: 11155111,
},
},
namedAccounts: {
deployer: {
default: 0,
},
},
};Explanation:
The first three lines import the necessary dependencies:
@nomicfoundation/hardhat-toolboxis the toolkit recommended by Hardhat officially.To use
.envenvironment variables, you must first install thedotenvdependency and then import it usingrequire("dotenv").config()inhardhat.config.js.hardhat-deployis a powerful deployment plugin for Hardhat that provides a more structured and repeatable way to deploy smart contracts. Click here to learn more.
defaultNetwork: "hardhat",
networks: {
hardhat: {},
sepolia: {
url: process.env.SEPOLIA_RPC_URL,
accounts: [process.env.PRIVATE_KEY],
chainId: 11155111,
},
},This code sets the default network to the hardhat local simulation network, and we also additionally configure the sepolia network:
accountscan be an array of multiple private keys, used for blockchain access and interaction.chainIdis a unique ID for the Sepolia test network, used to identify the network.
namedAccounts: {
deployer: {
default: 0,
},
},This section defines an account named deployer, which by default uses the first account (index 0) from the account list.
Write a deployment script.
Create a file named deploy/deploy-example.js in the root directory.
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy, log } = deployments;
const { deployer } = await getNamedAccounts();
log("------------------- deploying ------------------");
const example = await deploy("Example", {
from: deployer,
args: [process.env.SEPOLIA_ORACLE_CONTRACT_ADDRESS],
log: true,
waitConfirmations: 1,
});
log("Example deployed, address is: ", example.address);
};
module.exports.tags = ["all", "example"];getNamedAccountsis a function used to retrieve named accounts (such as deployer), which are typically specified in the Hardhat configuration file.deploymentsprovides various deployment-related functionalities (like thedeployfunction), which can be used to deploy contracts and record deployment information.
const example = await deploy("Example", {
from: deployer,
args: [process.env.SEPOLIA_ORACLE_CONTRACT_ADDRESS],
log: true,
waitConfirmations: 1,
});This code use the address of the Oracle contract as a parameter for the Example contract. deploy() function is used to deploy contracts, where the first parameter is the name of the contract, which must already exist in the project. The second parameter is an object, and its properties are as follows:
from: Specifies which account to use for deploying the contract.
args: []: The constructor arguments for the contract.
log: Indicates whether to print deployment logs.
waitConfirmations: Waits for 1 block confirmation to ensure the deployment is on-chain.
Then execute hardhat deploy to carry out the deployment.
npx hardhat deploy --network sepoliaWait for about a minute, and you should see the printed information as below. Congratulations! You have successfully deployed a Example contracts on the Sepolia test network in Hardhat!

Deploy Contract with Ignition
In this section, we’ll using Hardhat Ignition to deploy a smart contract. Ignition is a deployment manager provided by Hardhat that simplifies contract deployment and configuration.
You can copy this code in /ignition/modules/Example.js.
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");
const hre = require("hardhat");
const ExampleModule = buildModule("ExampleModule", (m) => {
const networkName = hre.network.name;
console.log(`Deploying to network: ${networkName}`);
const oracleContractAddress = process.env.SEPOLIA_ORACLE_CONTRACT_ADDRESS;
const Example = m.contract("Example", [oracleContractAddress]);
m.call(Example, "makeRequest");
return { Example };
});
module.exports = ExampleModule;Explanation
buildModule: The first aspect to note is that modules are created by calling the
buildModulefunction, which requires a module ID and a callback function. Our module will be identified as"ExampleModule".m: The
mparameter being passed into the callback is an instance of aModuleBuilder, which is an object with methods to define and configure your smart contract instances.m.contract("Example", [oracleContractAddress]): Deploys the
Examplecontract and passes the Oracle address as a constructor parameter.m.call(Example, "makeRequest"): It will invoke the
makeRequestfunction within the Example contract.
Run the deployment script
npx hardhat ignition deploy ignition/modules/Example.js --network sepoliaThen you will see the following output information.

Congratulations, you have successfully deployed the contract and sent a request to the Oracle.
Last updated