Frank Zhang
·6 min readTechnology

Smart Contract Hello World

Translated from the original Chinese post. Read the original (中文) →

Ethereum has been around for quite a few years now. Back in 2017, as a classic crypto “leek” (Chinese slang for a naive retail investor who gets harvested over and over), I actually bought a bunch of different Ethereum-based tokens (including an air coin issued by a senior schoolmate of mine who started his own crypto exchange 🤣), without really understanding how any of it worked. Recently I happened to get a chance to dig into Ethereum smart contracts, so here’s a quick record of how to build a smart contract Hello World.

Ethereum is a distributed blockchain application framework that Vitalik developed in 2013–2014 after being inspired by Bitcoin. Its official website introduces itself like this: “Ethereum is a technology for sending cryptocurrency to anyone for a small fee. It also powers applications that never go down and that anyone can use. It’s the world’s programmable blockchain.”

The Toolchain

Just like many programming languages (Java, C#, etc.) and frameworks (Spring, ASP.NET, Android, iOS), Ethereum has grown a rich toolchain over the years: a programming language (Solidity), an IDE (Remix), local environment tooling (HardHat), and so on. Any engineer can use these tools to get started with smart contract development pretty easily. My setup is fairly minimal: just VS Code (+ the Solidity extension, mainly for syntax highlighting and code formatting), npm (I’ll skip the installation steps here), and HardHat (more on what it does in a moment).

Step by Step

  1. [Initialize the project folder] Create a new folder named after your project, then open it in VS Code.
  2. [Install HardHat] Open a terminal in VS Code and run the following command to install HardHat.
npm install --save-dev hardhat
  1. [Initialize the HardHat local dev environment] Next, run the following command and choose “Create an empty hardhat.config.js”. At this point we have the most basic local development environment.
npx hardhat
  1. [Start coding] Create your first smart contract source file, Greeter.sol, under the ./contracts/ directory:
pragma solidity ^0.8.0;

contract Greeter {
    string private greeting;

    constructor(string memory _greeting) {
        greeting = _greeting;
    }

    function greet() public view returns (string memory) {
        return greeting;
    }

    function setGreeting(string memory _greeting) public {
        greeting = _greeting;
    }
}
  1. [Compile] Compiling with HardHat is dead simple. Just run this in the terminal:
npx hardhat compile
  1. [Deploy] Here I’ll show how to deploy to a testnet (BSC testnet). Following Binance’s official docs, configure hardhat.config.js like this:
require('@nomiclabs/hardhat-ethers');
require("@nomiclabs/hardhat-etherscan");
require("@nomiclabs/hardhat-waffle");

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
  const accounts = await hre.ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
});

module.exports = {
  solidity: {
    version: "0.8.10",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200
      }
    }
  },

  networks: {
    hardhat: {
    },
    bsctest: {
      url: "https://data-seed-prebsc-1-s1.binance.org:8545",
      chainId: 97,
      accounts: ["0x1111111111111111111111111111111111111111111111111111111111111111"]
    },
    bscmain: {
      url: "https://bsc-dataseed.binance.org/",
      chainId: 56,
      accounts: ["0x1111111111111111111111111111111111111111111111111111111111111111"]
    }
  },

  // Config for Etherscan contract verification service.
  // https://hardhat.org/plugins/nomiclabs-hardhat-etherscan.html#usage
  // https://docs.binance.org/smart-chain/developer/deploy/hardhat-verify.html
  etherscan: {
    apiKey: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  },

};

Next, prepare the deployment script scripts/deploy.js

// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
const hre = require("hardhat");

// This is a script for deploying your contracts. You can adapt it to deploy
// yours, or create new ones.
async function main() {
  // This is just a convenience check
  if (network.name === "hardhat") {
    console.warn(
      "You are trying to deploy a contract to the Hardhat Network, which" +
      "gets automatically created and destroyed every time. Use the Hardhat" +
      " option '--network localhost'"
    );
  }

  const [deployer] = await hre.ethers.getSigners();
  console.log(
    "Deploying the contracts with the account:",
    await deployer.getAddress()
  );

  console.log("Account balance: ", (await deployer.getBalance()).toString());

  const greeterContractFactory = await hre.ethers.getContractFactory("Greeter");
  const greeterContract = await greeterContractFactory.deploy("Hello world!");
  await greeterContract.deployed();

  console.log("Greeter contract address: ", greeterContract.address);
}

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

Finally, run the following command:

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

And you’ll see the result:

Deploying the contracts with the account: 0x19E7E376E7C213B7E7e7e46cc70A5dD086DAff2A
Account balance:  3440891252400000000
Greeter contract address:  0xf2bf1f1E7B3f8d1554fEeb88B11B69830eDAc7fa
  1. [Verify the contract] After the previous step, we can already see our freshly deployed contract in the explorer (BSC Testnet Explorer). However, since the contract is only there in compiled form and doesn’t expose its ABI, we can’t interact with it directly through the explorer. To make testing easier, we can verify the contract, after which anyone can interact with it directly via the explorer. To verify it, we need to register a BscScan account and get an API key (link), put it into hardhat.config.js as well, and finally run the following command to complete verification:
npx hardhat verify --network bsctest --contract contracts/Greeter.sol:Greeter 0xf2bf1f1E7B3f8d1554fEeb88B11B69830eDAc7fa "Hello world!"

Here’s the result. Click the last link to open the explorer, connect MetaMask, and start interacting with the contract!

Nothing to compile
Compiling 1 file with 0.8.10

Successfully submitted source code for contract
contracts/Greeter.sol:Greeter at 0xf2bf1f1E7B3f8d1554fEeb88B11B69830eDAc7fa
for verification on the block explorer. Waiting for verification result...

Successfully verified contract Greeter on Etherscan.
https://testnet.bscscan.com/address/0xf2bf1f1E7B3f8d1554fEeb88B11B69830eDAc7fa#code

Wrapping Up

I’ve been playing with smart contracts for over half a year now, and after three or four projects I still find myself walking through the hello world process from scratch every time. So I’m taking this opportunity to write it all down here for future reference.

Honestly, Ethereum smart contracts are a lot like writing APIs with Spring MVC or ASP.NET. Ethereum has a built-in user identity / principal, namely an address on the blockchain, and every smart contract call originates from a signer, which can be either a user’s wallet address or another contract’s address. Smart contracts don’t have a database, so to keep things simple you can think of one as an in-memory program whose memory is never wiped. It’s way easier to pick up than writing backend services.

If I have the time and energy later, I may write about some advanced contract development techniques (like upgradeable contracts, microservice-style contracts, etc.) and explain them using their counterpart concepts from backend development. Beyond the technical side, the red-hot DeFi space (which has actually been around for several years already) can also be understood by analogy with concepts from traditional finance, such as market makers and leveraged yield farming. It’s really fascinating stuff.

The way I see it, entrepreneurs in the blockchain world are currently trying to rebuild a decentralized financial world on-chain, which is a challenge to the traditional, centralized financial world. In terms of efficiency, decentralized finance bypasses centralized financial institutions and drastically lowers transaction costs; after all, those institutions make a fortune on the spread just by shuffling money from one hand to the other. If a whole new financial world really can be built, the prospect is undeniably tempting. As for me, I just hope that, as a humble “leek”, I don’t get harvested by both financial worlds in turn. If I could get a slice of the pie, even better… 🤣🤣🤣

Comments

No comments yet — be the first to leave one.

    Leave a comment

    Comments appear after review. Your email is never shown publicly and is only used to reach you if needed.