Deploy Your First Smart Contract

In this tutorial, you will learn how to create a simple smart contract on Hedera using Solidity.


Prerequisites

We recommend you complete the following introduction to get a basic understanding of Hedera transactions. This example does not build upon the previous examples.

  1. Set up your environment here.


1. Create a "Hello Hedera" Smart Contract

Create a smart contract in solidity using the remix IDE. The "Hello Hedera" contract Solidity file is sampled below along with the "Hello Hedera" JSON file that is produced after the contract has been compiled. You can use remix to create and compile the contract yourself or you can copy the files below into your project. If you are not familiar with Solidity you can check out the docs here. Hedera supports the latest version of Solidity (v0.8.9) on previewnet and testnet.

The contract stores two variables the owner and message. The constructor passes in the message parameter. The set_message function allows the owner to update the message variable and the get_message function allows you to return the message.

The HelloHedera.sol will serve as a reference to the contract that was compiled. The HelloHedera.json file contains the data.bytecode.object field that will be used to store the contract bytecode in a file on the Hedera network.

pragma solidity >=0.7.0 <0.8.9;

contract HelloHedera {
    // the contract's owner, set in the constructor
    address owner;

    // the message we're storing
    string message;

    constructor(string memory message_) {
        // set the owner of the contract for `kill()`
        owner = msg.sender;
        message = message_;
    }

    function set_message(string memory message_) public {
        // only allow the owner to update the message
        if (msg.sender != owner) return;
        message = message_;
    }

    // return a string
    function get_message() public view returns (string memory) {
        return message;
    }

    // recover the funds of the contract
    function kill() public { if (msg.sender == owner) selfdestruct(payable(msg.sender)); }
}

2. Store the Smart Contract Bytecode on Hedera

Create a file using the FileCreateTransaction() API to store the hex-encoded byte code of the "Hello Hedera" contract. Once the file is created, you can obtain the file ID from the receipt of the transaction.

You can alternatively use the CreateContractFlow() API that creates the bytecode file for you and subsequently creates the contract on Hedera in a single API.

Note: The bytecode is required to be hex-encoded. It should not be the actual data the hex represents.

//Import the compiled contract from the HelloHedera.json file
Gson gson = new Gson();
JsonObject jsonObject;

InputStream jsonStream = HelloHederaSmartContract.class.getClassLoader().getResourceAsStream("HelloHedera.json");
jsonObject = gson.fromJson(new InputStreamReader(jsonStream, StandardCharsets.UTF_8), JsonObject.class);

//Store the "object" field from the HelloHedera.json file as hex-encoded bytecode
String object = jsonObject.getAsJsonObject("data").getAsJsonObject("bytecode").get("object").getAsString();
byte[] bytecode = object.getBytes(StandardCharsets.UTF_8);

//Create a file on Hedera and store the hex-encoded bytecode
FileCreateTransaction fileCreateTx = new FileCreateTransaction()
        //Set the bytecode of the contract
        .setContents(bytecode);

//Submit the file to the Hedera test network signing with the transaction fee payer key specified with the client
TransactionResponse submitTx = fileCreateTx.execute(client);

//Get the receipt of the file create transaction
TransactionReceipt fileReceipt = submitTx.getReceipt(client);

//Get the file ID from the receipt
FileId bytecodeFileId = fileReceipt.fileId;

//Log the file ID
System.out.println("The smart contract bytecode file ID is " +bytecodeFileId)

//v2 Hedera Java SDK

3. Deploy a Hedera Smart Contract

Create the contract and set the file ID to the file ID that stores the hex-encoded byte code from the previous step. You will also need to set gas the value that will create the contract and pass the constructor parameters using ContractFunctionParameters() API. In this example, "hello from Hedera!" was passed to the constructor. After the transaction is successfully executed, you can get the contract ID from the receipt.

Note: You will need to set the gas value high enough to deploy the contract. If you don't have enough gas, you will receive an INSUFFICIENT_GAS response.

// Instantiate the contract instance
 ContractCreateTransaction contractTx = new ContractCreateTransaction()
      //Set the file ID of the Hedera file storing the bytecode
      .setBytecodeFileId(newFileId)
      //Set the gas to instantiate the contract
      .setGas(100_000)
      //Provide the constructor parameters for the contract
      .setConstructorParameters(new ContractFunctionParameters().addString("Hello from Hedera!"));

//Submit the transaction to the Hedera test network
TransactionResponse contractResponse = contractTx.execute(client);

//Get the receipt of the file create transaction
TransactionReceipt contractReceipt = contractResponse.getReceipt(client);

//Get the smart contract ID
ContractId newContractId = contractReceipt.contractId;

//Log the smart contract ID
System.out.println("The smart contract ID is " + newContractId);

//v2 Hedera Java SDK

4. Call Contract Functions

Call the get_message contract function

In the previous step, the contract message variable was set to "hello from Hedera!." You can return this message from the contract by submitting a query that will return the stored message string. The ContractCallQuery() similarly does not modify the state of the contract like other Hedera queries. It only reads stored values.

// Calls a function of the smart contract
ContractCallQuery contractQuery = new ContractCallQuery()
     //Set the gas for the query
     .setGas(100000) 
     //Set the contract ID to return the request for
     .setContractId(newContractId)
     //Set the function of the contract to call 
     .setFunction("get_message" )
     //Set the query payment for the node returning the request
     //This value must cover the cost of the request otherwise will fail 
     .setQueryPayment(new Hbar(2)); 

//Submit to a Hedera network
ContractFunctionResult getMessage = contractQuery.execute(client);
//Get the message
String message = getMessage.getString(0); 

//Log the message
System.out.println("The contract message: " + message);

//v2 Hedera Java SDK

Call the set_message contract function

Call the set_message function of the contract. To do this you will need to use the ContractExecuteTransaction() API. This transaction will update the contract message. Once the transaction is successfully submitted you can verify the message was updated by requesting ContractCallQuery(). The message returned from the contract should now log "Hello from Hedera again!"

 //Create the transaction to update the contract message
 ContractExecuteTransaction contractExecTx = new ContractExecuteTransaction()
        //Set the ID of the contract
        .setContractId(newContractId)
        //Set the gas for the call
        .setGas(100_000)
        //Set the function of the contract to call
        .setFunction("set_message", new ContractFunctionParameters().addString("Hello from Hedera again!"));

//Submit the transaction to a Hedera network and store the response
TransactionResponse submitExecTx = contractExecTx.execute(client);

//Get the receipt of the transaction
TransactionReceipt receipt2 = submitExecTx.getReceipt(client);

//Confirm the transaction was executed successfully 
System.out.println("The transaction status is" +receipt2.status);

//Query the contract for the contract message
 ContractCallQuery contractCallQuery = new ContractCallQuery()
        //Set ID of the contract to query
        .setContractId(newContractId)
        //Set the gas to execute the contract call
        .setGas(100_000)
        //Set the contract function
        .setFunction("get_message")
        //Set the query payment for the node returning the request
        //This value must cover the cost of the request otherwise will fail 
        .setQueryPayment(new Hbar(2));
 
 //Submit the query to a Hedera network
ContractFunctionResult contractUpdateResult = contractCallQuery.execute(client);

//Get the updated message
String message2 = contractUpdateResult.getString(0);

//Log the updated message
System.out.println("The contract updated message: " + message2);
  • Created a simple smart contract on Hedera

  • Interacted with contract functions


Additional Resources

➡ Have a question? Ask on StackOverflow

Last updated