Step 3: Deploy Blended Contracts
3.1 Create the Deployment Script
This deployment script is responsible for deploying both the Rust smart contract (compiled to Wasm) and the Solidity smart contract (GreetingWithWorld).
deploy/01_deploy_contracts.ts
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
import { ethers } from "ethers";
import fs from "fs";
import crypto from "crypto";
import path from "path";
require("dotenv").config();
const DEPLOYER_PRIVATE_KEY = process.env.DEPLOYER_PRIVATE_KEY || "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts, ethers, config, network } = hre;
const { deploy, save, getOrNull } = deployments;
const { deployer: deployerAddress } = await getNamedAccounts();
console.log("deployerAddress", deployerAddress);
// Deploy WASM Contract
console.log("Deploying WASM contract...");
const wasmBinaryPath = "./greeting/lib.wasm";
// @ts-ignore
const provider = new ethers.JsonRpcProvider(network.config.url);
const deployer = new ethers.Wallet(DEPLOYER_PRIVATE_KEY, provider);
const checkmateValidatorAddress = await deployWasmContract(wasmBinaryPath, deployer, provider, getOrNull, save);
//Deploy Solidity Contract
console.log("Deploying GreetingWithWorld contract...");
const fluentGreetingContractAddress = checkmateValidatorAddress;
const greetingWithWorld = await deploy("GreetingWithWorld", {
from: deployerAddress,
args: [fluentGreetingContractAddress],
log: true,
});
console.log(`GreetingWithWorld contract deployed at: ${greetingWithWorld.address}`);
};
async function deployWasmContract(
wasmBinaryPath: string,
deployer: ethers.Wallet,
provider: ethers.JsonRpcProvider,
getOrNull: any,
save: any
) {
const wasmBinary = fs.readFileSync(wasmBinaryPath);
const wasmBinaryHash = crypto.createHash("sha256").update(wasmBinary).digest("hex");
const artifactName = path.basename(wasmBinaryPath, ".wasm");
const existingDeployment = await getOrNull(artifactName);
if (existingDeployment && existingDeployment.metadata === wasmBinaryHash) {
console.log(`WASM contract bytecode has not changed. Skipping deployment.`);
console.log(`Existing contract address: ${existingDeployment.address}`);
return existingDeployment.address;
}
const gasPrice = (await provider.getFeeData()).gasPrice;
const transaction = {
data: "0x" + wasmBinary.toString("hex"),
gasLimit: 300_000_000,
gasPrice: gasPrice,
};
const tx = await deployer.sendTransaction(transaction);
const receipt = await tx.wait();
if (receipt && receipt.contractAddress) {
console.log(`WASM contract deployed at: ${receipt.contractAddress}`);
const artifact = {
abi: [],
bytecode: "0x" + wasmBinary.toString("hex"),
deployedBytecode: "0x" + wasmBinary.toString("hex"),
metadata: wasmBinaryHash,
};
const deploymentData = {
address: receipt.contractAddress,
...artifact,
};
await save(artifactName, deploymentData);
} else {
throw new Error("Failed to deploy WASM contract");
}
return receipt.contractAddress;
}
export default func;
func.tags = ["all"];
3.2 Create the Hardhat Task
tasks/get-greeting.ts
import { task } from "hardhat/config";
task("get-greeting", "Fetches the greeting from the deployed GreetingWithWorld contract")
.addParam("contract", "The address of the deployed GreetingWithWorld contract")
.setAction(async ({ contract }, hre) => {
const { ethers } = hre;
const GreetingWithWorld = await ethers.getContractAt("GreetingWithWorld", contract);
const greeting = await GreetingWithWorld.getGreeting();
console.log("Greeting:", greeting);
});
3.3 Compile and Deploy the Contracts
Run the following commands to compile and deploy your contracts:
pnpm hardhat compile
pnpm hardhat deploy
pnpm hardhat get-greeting --contract <CONTRACT_ADDRESS>