How to port a dApp to Reef - Part 1: Deploy Smart Contract to Reef

How to port a dApp to Reef - Part 1: Deploy Smart Contract to Reef


Briefing - What is this tutorial all about?

If you're new to developing solutions on Reef, you will definitely come across Reefs EVM compatibility, which offers you easy deployment, interaction, and porting of your legacy Ethereum Solidity smart contracts. We will explain the process of porting an existing Solidity smart contract to Reef's affordable & efficient layer1 blockchain.

EVM-model-machine-state-world-state
https://ethereum.org/en/developers/docs/evm/
EVM-model-compile-deploy
https://hackernoon.com/ethernaut-lvl-0-walkthrough-abis-web3-and-how-to-abuse-them-d92a8842d71b

Relevance - Why do I need this tutorial?

We will explain the most important steps to port an existing smart contract from Ethereum to Reef. This will offer you an economical alternative and new home for your decentral applications. At the same time, you will enjoy full Reef community benefits, low fees, and fast transactions.

See our blockchain comparison chart below:

Prerequisites - What do I need to get started?

  1. Existing smart contract
  2. Metamask account
  3. Sepolia added to Metamask (you can use https://chainlist.org/ )
  4. ETH on Sepolia (get them here: https://sepolia.dev/)
  5. Reef chain extension
  6. Reef extension account
  7. How to get REEF tokens
  • Join Reef’s Discord server
  • Verify
  • Select the Builder role in #start-here
  • Go to the #faucet channel
  • Type /faucet [wallet address] and hit Enter

The bot will help you with auto-complete!



🚀 Getting started - we are ready to go!

Step0: Visit https://github.com/reef-defi and then visit the repository hardhat-reef-examples

The contract we are going to deploy is the following called Flipper.sol :

// Specifies the version of Solidity, using semantic versioning.
// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
pragma solidity ^0.8.4;

contract Flipper {
	bool private value;

	/// Constructor that initializes the `bool` value to the given `init_value`.
	constructor(bool initvalue) public {
		value = initvalue;
	}

	/// A message that can be called on instantiated contracts.
	/// This one flips the value of the stored `bool` from `true`
	/// to `false` and vice versa.
	function flip() public {
		value = !value;
	}

	/// Simply returns the current value of our `bool`.
	function get() public view returns (bool) {
		return value;
	}
}

Step1: Setup an empty folder

Now on the IDE, I am adding a folder to the project called Sepolia-Reef-Project and start with following command. This will create a simple hardhat project (inspired by https://hardhat.org/tutorial/)

npm install --save-dev hardhat

Now that we have all the packages installed, let us run hardhat with following command:

npx hardhat

Next step will be installing ethers, as it is the Ethereum library with the following command:

npm install --save-dev @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chain

Step2: Create a folder called “contracts” and a folder called “scripts”

Let us copy the contract called Flipper.sol to our contract folder.

// Specifies the version of Solidity, using semantic versioning.
// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
pragma solidity ^0.8.4;

contract Flipper {
	bool private value;

	/// Constructor that initializes the `bool` value to the given `init_value`.
	constructor(bool initvalue) public {
		value = initvalue;
	}

	/// A message that can be called on instantiated contracts.
	/// This one flips the value of the stored `bool` from `true`
	/// to `false` and vice versa.
	function flip() public {
		value = !value;
	}

	/// Simply returns the current value of our `bool`.
	function get() public view returns (bool) {
		return value;
	}
}

Step3: Add javascript file deploy.js to your “scripts” folder and save it

async function main() {

  const Flipper = await ethers.getContractFactory("Flipper");
 
  // Start deployment, returning a promise that resolves to a contract object
  
  const flipper = await Flipper.deploy("Hello Flipper!");

  console.log("Deploy done");
  console.log("Hello World!");
  console.log({
    flipper_contract_address: flipper.address,
    deploy_hash: flipper.deployTransaction,
  });

}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

Step4: Provide all necessary information to the hardhat.config.js file

require("@nomiclabs/hardhat-waffle");

const SEPOLIA_PRIVATE_KEY = "27ff5174ee7d69f3e05f0fbab104d2b969855f17010d6af16546252971b18cc7";

// https://linkpool.io/resources/release-of-public-ethereum-rpcs/

module.exports = {
  solidity: "0.8.4",
  networks: {
    sepolia: {
      url: `https://rpc.sepolia.org/`,
      accounts: [`${SEPOLIA_PRIVATE_KEY}`]
    }
  }
};

Click the three dots top right corner, then Account details to get your Private Key.

Now you just need to enter your password, then you can copy your private key.

Step5: Compile your contract for the first time

npx hardhat compile

Step6: Now let us deploy our contract to Sepolia

npx hardhat run scripts/deploy.js --network sepolia

Running the command gives us following output:

Now copy your flipper_contract_address.

Step7: Check https://sepolia.etherscan.io/ and paste your contracts address

Paste the address into the search field and let's review the deployed contract on Etherscan.

Step8: Use the exact same folder structure for the deployment to Reef

Good thing is: We do not have to change the directory or set up a new project. We can stay right here to add some Reef specifics and deploy this project to Reef chain.

Step9: Add Reef hardhat to the project folder

yarn add @reef-defi/hardhat-reef

Step10: Add hardhat-ethers dependency

yarn add @nomiclabs/hardhat-ethers

Step11: Install Reef hardhat

yarn add hardhat

Step12: Adjust your deploy.js script to meet Reef-specific settings

const hre = require("hardhat");

async function main() {
  // define your testnet_account in hardhat.config.js
  const alice = await hre.reef.getSignerByName("testnet_account");
  await alice.claimDefaultAccount();

  const HelloWorld = await hre.reef.getContractFactory("HelloWorld", alice);

  // Start deployment, returning a promise that resolves to a contract object
  
  const helloworld = await HelloWorld.deploy("Hello World!");

  console.log("Deploy done");
  console.log("Hello World!");
  console.log({
    helloworld_contract_address: helloworld.address,
    deploy_hash: helloworld.deployTransaction,
  });

}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

Step13: Add hardhat.config.js specifics for Reef

require("@reef-defi/hardhat-reef");

module.exports = {
  solidity: "0.8.4",
  defaultNetwork: "reef",
  networks: {
    reef: {
      url: "ws://substrate-node:9944",
      scanUrl: "<http://api:8000>",
    },
    reef_testnet: {
      url: "wss://rpc-testnet.reefscan.info/ws",
      scanUrl: "https://api-testnet.reefscan.info", 
      seeds: {
        testnet_account: "", // SEED GOES HERE
      },
    },
    reef_mainnet: {
      url: "wss://rpc.reefscan.info/ws",
      scanUrl: "wss://api.reefscan.info",
      seeds: {
        mainnet_account: "", // SEED GOES HERE
      },
    },
  },
};

Step14: Deploy your smart contract to Reef testnet

yarn hardhat run scripts/deploy.js --network reef_testnet

Now lets save the contract address!

Found it! Now we can click on it and get some more information about the contract and its status.

See some information about the contract here. In the next videos we are looking at how to verify a contract!

Step15: Now finally let us interact with the contract using the flip.js script

const hre = require("hardhat");

async function main() {
  // Get a Flipper contract on already deployed address
  //  (process.env.FLIPPER_ADDRESS) ? process.env.FLIPPER_ADDRESS :  
  const flipperAddress = "0x4EFfeB2FEA4450107437bf81c10306bA7906eEFe";
  
  const alice = await hre.reef.getSignerByName("testnet_account")
  const flipper = await hre.reef.getContractAt("Flipper", flipperAddress, alice);

  // Call flip()
  console.log("Current value:", await flipper.get());
  await flipper.flip();
  console.log("New value after flip():", await flipper.get());
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

We now basically interact with the existing contract using this script here. We are then printing out the statements and see if our contract worked as expected.

Use following command:

yarn hardhat run scripts/flip.js --network reef_testnet

Debriefing - What are the most important takeaways from this tutorial?


What's next?

Check out more tutorials about the Reef ecosystem here on this blog. Learn how to claim your EVM address or code a simple smart contract from scratch. In the next videos, we are going to look into smart contract verification, wallet integration & UI-examples.