Deploy your own Bitcoin dapp

Extend your Bitcoin app with more dapps

If you’ve built dapps on Ethereum, you can easily build on Bitcoin. Your Bitcoin chain is EVM-equivalent, allowing you to write Solidity smart contracts on Bitcoin without learning a new toolkit. All your existing code and tools work seamlessly out of the box.

What you'll learn

  • How to compile smart contracts

  • How to deploy a contract to Supersonic on both testnet and mainnet

Prerequisites

  • A Node.js installation running at minimum Node.js version 14.

  • Initialized Hardhat TypeScript project

  • A wallet with sufficient BVM on Supersonic to pay for deploying smart contracts.

    • For testnet, you can get BVM from the faucet.

    • For mainnet, you can buy BVM from Uniswap and use Naka bridge to bridge funds to Supersonic.

This how-to guide explains how to deploy a smart contract on Supersonic using hardhat-zksync-deploy (note: Supersonic is deployed on Bitcoin using ZK Stack so we could reuse ZKSync's developer suite for deploying contracts)

Installation

To install the hardhat-zksync-deploy plugin and additional necessary packages, execute the following command:

npm install -D @matterlabs/hardhat-zksync-deploy hardhat zksync-ethers ethers

Once installed, add the plugin at the top of the hardhat.config.ts file.

import "@matterlabs/hardhat-zksync-deploy";

Create a new smart contract

Here are the steps to create new smart contract:

  1. Navigate to the root of your project.

  2. Create a folder named contracts.

  3. Inside the contracts folder, create a file named SimpleStorage.sol.

Now we should add some code to the new SimpleStorage.sol file:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract SimpleStorage {
    uint private number;

    // Function to set the number
    function setNumber(uint _number) public {
        number = _number;
    }

    // Function to get the number
    function getNumber() public view returns (uint) {
        return number;
    }
}

Configuration

Before we continue with the deployment, we must include hardhat-zksync-solc plugin in order to compile our contracts.

npm install -D @matterlabs/hardhat-zksync-solc

Add the plugin at the top of the hardhat.config.ts file:

import "@matterlabs/hardhat-zksync-solc";

To enable deployment across various networks within the hardhat.config.ts file, it's essential to configure the networks section. For this example, we will be deploying on Supersonic Testnet & Mainnet, so we need to adjust network accordingly. Furthermore, it's also important to configure the compilers settings.

import "@matterlabs/hardhat-zksync-solc";
import "@matterlabs/hardhat-zksync-deploy";
import { HardhatUserConfig } from "hardhat/config";

const config: HardhatUserConfig = {
  zksolc: {
    // By not specifying any options, we are using the default settings of zksolc.
  },
  solidity: {
    version: "0.8.17",
  },
  defaultNetwork: "supersonicTestnet",
  networks: {
    supersonicTestnet: {
      url: "https://rpc.testnet.supersonic2.bvm.network",
      ethNetwork: "",
      zksync: true
    },
    supersonicMainnet: {
      url: "https://rpc.supersonic.bvm.network",
      ethNetwork: "",
      zksync: true
    },
  },
};
export default config;

Compilation

Execute the following command in your terminal to run the compilation:

npx hardhat compile

After successful compilation, you should see the output similar to this:

Compiling 1 Solidity file
Successfully compiled 1 Solidity file
Done in 0.69s.

In the root of your project you will see two new folders that represent zksolc compilation result:

  • artifacts-zk

  • cache-zk

Deploy script

Here are the steps to create deploy script with hardhat-zksync-deploy plugin.

  1. Navigate to your project's root directory.

  2. Create a new folder named deploy.

  3. Inside the deploy folder, create a file named deploy-simple-storage.ts.

Now we should add some code to the new deploy-simple-storage.ts file:

import { Wallet } from "zksync-ethers";
import * as ethers from "ethers";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { Deployer } from "@matterlabs/hardhat-zksync-deploy";
import dotenv from "dotenv";

dotenv.config();

const PRIVATE_KEY = process.env.PRIVATE_KEY || "";

if (!PRIVATE_KEY) {
  throw new Error("Wallet private key is not configured in .env file!");
}

// An example of a deploy script
export default async function (hre: HardhatRuntimeEnvironment) {
  console.log(`Running deploy script for the SimpleStorage contract`);

  // Initialize the wallet.
  const wallet = new Wallet(PRIVATE_KEY);

  // Create deployer object and load the artifact of the contract you want to deploy.
  const deployer = new Deployer(hre, wallet);
  const artifact = await deployer.loadArtifact("SimpleStorage");

  // Estimate contract deployment fee
  const deploymentFee = await deployer.estimateDeployFee(artifact, []);

  const parsedFee = ethers.formatEther(deploymentFee);
  console.log(`The deployment is estimated to cost ${parsedFee} ETH`);

  // Deploy contract
  const simpleStorageContract = await deployer.deploy(artifact, []);

  // Show the contract info.
  const contractAddress = await simpleStorageContract.getAddress();
  console.log(`${artifact.contractName} was deployed to ${contractAddress}`);
}

To deploy contract on Supersonic Testnet, run the following command:

npx hardhat deploy-zksync --network supersonicTestnet 

To deploy contract on Supersonic Mainnet, run the command:

npx hardhat deploy-zksync --network supersonicMainnet 

After successful deployment, your console output should look something like this:

Running deploy script for the SimpleStorage contract
SimpleStorage was deployed to 0xCE5e67aF41C194aB05fCC3860ef66790A147Adf9
Done in 4.2s.

Check your deployed contract on this block explorer for Supersonic Testnet or on this block explorer for Supersonic Mainnet using deployed address of the contract.

Last updated