HSCS: Smart Contract

Hello World sequence: Write a smart contract in Solidity, compile it, then use Hedera Smart Contract Service (HSCS) to deploy it and interact with it.

What you will accomplish


Prerequisites

Before you begin, you should have completed the following HW sequence:


Get started: Set up project

To follow along, start with the main branch, which is the default branch of the repo. This gives you the initial state from which you can follow along with the steps as described in the tutorial.

In the terminal, from the hello-future-world directory, enter the subdirectory for this sequence.

cd 03-hscs-smart-contract-ethersjs/

Reuse the .env file by copying the one that you have previously created into the directory for this sequence.

cp ../00-create-fund-account/.env ./
Check that you have copied the `.env` file correctly

To do so, use the pwd command to check that you are indeed in the right subdirectory within the repo.

pwd

This should output a path that ends with /hello-future-world/03-hscs-smart-contract-ethersjs. If not, you will need to start over.

/some/path/hello-future-world/03-hscs-smart-contract-ethersjs

Next, use the ls command to check that the .env file has been copied into this subdirectory.

ls -a

The first few line of the output should look display .env. If not, you'll need to start over.

.
..
.env

Next, install the dependencies using npm.

npm install

You will also need to install a Solidity compiler. This time use the --global flag.

npm install --global [email protected]

Solidity is a programming language that was designed specifically for writing smart contracts in. The Solidity compiler outputs bytecode that can be run by an Ethereum Virtual Machine (EVM) implementation.

Note that although the npm package is named solc, the executable exposed on your command line is named solcjs.

Then, open both these files in a code editor, such as VS Code.

  • my_contract.sol

  • script-hscs-smart-contract-ethersjs.js


Write the smart contract

An almost-complete smart contract has already been prepared for you, my_contract.sol. You will only need to make one modification (outlined below) for it to compile successfully.

Step 1: Get the name stored in mapping

Within the greet() function, we would like to access the names mapping and retrieve the name of the account that is invoking this function. The account is identified by its EVM account alias, which is available as msg.sender within the Solidity code.

        string memory name = names[msg.sender];

Note: This smart contract has two functions, introduce and greet. You will invoke both of them later on.


Compile the smart contract

Once you have completed writing the smart contract in Solidity, you will need to compile it using the Solidity compiler installed earlier.

Invoke the compiler on your Solidity file. Then, list files in the current directory.

solcjs --bin --abi ./my_contract.sol
ls

You should see an output similar to the following:

my_contract.sol
my_contract_sol_MyContract.abi
my_contract_sol_MyContract.bin
  • The .abi file contains JSON and describes the interface used to interact with the smart contract.

  • The .bin file contains EVM bytecode, and this is used in the deployment of the smart contract.

Note that while the .abi file is human-readable, the .bin file is not intended to be human-readable.


Configure RPC Connection

  1. Sign up for an account at auth.arkhia.io/signup. If prompted, click on the link in your confirmation email.

  2. Click on the +CREATE PROJECT button in the top-right corner of the Arkhia dashboard.

  1. Fill in whatever you like in the modal dialog that pops up.

  1. Click on the "Manage" button on the right side of your newly created project.

Now, you should see the project details.

  • Under "Network", select "Hedera Testnet".

  • Copy the "JSON-RPC" field.

  • In the "Security" section, copy the "API Key" field.

In the .env file, edit the property with the key RPC_URL, replacing YOUR_JSON_RPC_URL with the "JSON-RPC" value, followed by /, and finally, the "API key" value that you have just copied.

For example, if the API key field is ABC123, and the JSON-RPC field is https://pool.arkhia.io/hedera/testnet/json-rpc/v1, the line in your .env file should look like this:

RPC_URL=https://pool.arkhia.io/hedera/testnet/json-rpc/v1/ABC123
Alternative RPC configuration

Arkhia is one of several different options for JSON-RPC connections. This tutorial covers all of the different options: How to Connect to Hedera Networks Over RPC.


Write the script

An almost complete script has already been prepared for you, script-hscs-smart-contract-ethersjs.js. You will only need to make a few modifications (outlined below) for it to run successfully.

Step 2: Prepare smart contract for deployment

Initialize an instance of ContractFactory from EthersJs.

    const myContractFactory = new ContractFactory(
        abi, evmBytecode, accountWallet);

Note: The ContractFactory class is used to prepare a smart contract for deployment. To do so, pass in the ABI and bytecode output by the Solidity compiler earlier. Also, pass in the accountWallet object, which is used to authorize transactions and is needed for the deployment transaction.

Upon preparation, it sends a deployment transaction to the network, and an instance of a Contract object is created based on the result of the deployment transaction. This is stored in a variable, myContract, which will be used in the next steps. This has already been done for you in the script.

Step 3: Invoke a smart contract transaction

The introduce function requires a single parameter of type string, and changes the state of the smart contract to store this value. Enter your name (or nickname) as the parameter. For example, if you wish to use "bguiz", the invocation should look like this:

    const myContractWriteTxRequest = await myContract.functions.introduce('bguiz');

Step 4: Invoke a smart contract query

In the previous step, you changed some state of the smart contract, which involved submitting a transaction to the network. This time, you are going to read some state of the smart contract. This is much simpler to do as no transaction is needed.

Invoke the greet function and save its response to a variable, myContractQueryResult. This function does not take any parameters.

    const [myContractQueryResult] = await myContract.functions.greet();

When invoking functions in a smart contract, you may do so in two different ways:

  • With a transaction Smart contract state may be changed.

  • Without a transaction Smart contract state may be queried but may not be changed.


Run the script

In the terminal, run the script using the following command:

node script-hscs-smart-contract-ethersjs.js

You should see output similar to the following:

accountId: 0.0.1201
accountAddress: 0x7394111093687e9710b7a7aEBa3BA0f417C54474
accountExplorerUrl: https://hashscan.io/testnet/address/0x7394111093687e9710b7a7aEBa3BA0f417C54474
myContractAddress: 0x9A6856897a72E790Ae765bFF997396199BDf1B72
myContractExplorerUrl: https://hashscan.io/testnet/address/0x9A6856897a72E790Ae765bFF997396199BDf1B72
myContractWriteTxHash: 0x32684e8d8e60126e171db968a4b20153ba96a40920a036dbebb48e19fb74664d
myContractWriteTxExplorerUrl: https://hashscan.io/testnet/transaction/0x32684e8d8e60126e171db968a4b20153ba96a40920a036dbebb48e19fb74664d
myContractQueryResult: Hello future - bguiz

Open myContractExplorerUrl in your browser and check that:

  1. The contract exists

  2. Under the "Contract Bytecode" section, its "Compiler Version" field matches the version of the Solidity compiler that you used (0.8.17)

  3. Under the "Recent Contract Calls" section, There should be two transactions:

    • (3A) The transaction with the earlier timestamp (bottom) should be the deployment transaction.

      • Navigate to this transaction by clicking on the timestamp.

      • Under the "Contract Result" section, the "Input - Function & Args" field should be a relatively long set of hexadecimal values.

      • This is the EVM bytecode output by the Solidity compiler.

      • Navigate back to the Contract page (browser button).

    • (3B) The transaction with the later timestamp (top) should be the transaction in which the introduce function was invoked.

      • Navigate to this transaction by clicking on the timestamp.

      • Under the "Contract Result" section, the "Input - Function & Args" field should be a relatively short set of hexadecimal values.

      • This is the representation of

        • the function identifier as the first eight characters (e.g. 0xc63193f6 for the introduce function), and

        • the input string value (e.g. 0x5626775697a0 for bguiz).

      • Navigate back to the Contract page (browser button).

Drawing
HSCS contract in Hashscan, with annotated items to check.
Additional checks

The steps above are sufficient to check that you have deployed and interacted with the same contract successfully. You may optionally wish to perform these additional checks as well.

Open myContractWriteTxExplorerUrl in your browser. This should be the same page as "the transaction with the later timestamp" in 3B from the previous checks. Check that:

  • The transaction exists

  • Its "Type" field is "ETHEREUM TRANSACTION"

  • Under the "Contract Result" section, its "From" field matches the value of accountId

  • Under the "Contract Result" section, its "To" field matches the value of myContractAddress


Complete

Congratulations, you have completed the Hedera Smart Contract Service Hello World sequence! 🎉🎉🎉

You have learned how to:


Next Steps

Now that you have completed this Hello World sequence, you have interacted with Hedera Smart Contract Service (HSCS). There are other Hello World sequences for Hedera File Service (HFS), and Hedera Token Service (HTS), which you may wish to check out next.

You may also wish to check out the more detailed HSCS workshop, which goes into much more depth.


Cheat sheet

Skip to final state

The repo, github.com/hedera-dev/hello-future-world, is intended to be used alongside this tutorial.

To skip ahead to the final state, use the completed branch. This gives you the final state with which you can compare your implementation to the completed steps of the tutorial.

git fetch origin completed:completed
git checkout completed

To see the full set of differences between the initial and final states of the repo, you can use diff.

cd 03-hscs-smart-contract-ethersjs/
git diff main..completed -- ./

Alternatively, you may view the diff rendered on Github: hedera-dev/hello-future-world/compare/main..completed (This will show the diff for all sequences.)

Note that the branch names are delimited by .., and not by ..., as the latter finds the diff with the latest common ancestor commit, which is not what we want in this case.


Writer: Brendan Editors: Abi, Michiel, Ryan, Krystal

Last updated

Was this helpful?

#2416: #441 #524 #553 update docs with portal faucet + API key features

Change request updated