DEV Community

Cover image for How To Deploy Cost Effective Smart Contracts
Waylon Jepsen
Waylon Jepsen

Posted on • Updated on

How To Deploy Cost Effective Smart Contracts

When people think about smart contracts, they tend to think about Ehereum. However, many ecosystems are building or have built support for the distributed computing that smart contracts allow for. Hedera recently announced their support for Smart Contracts 2.0 that will allow the contracts to run with all the native costs, security, and speeds of the Hedera network, which are pretty impressive.

This post will show you how to deploy a smart contract to the Hedera network with the JavaScrip SDK. We will first compile our smart contract into byte code. Then we will store the byte-code to the Hedera File Service, deploy our contact, and modify the state variable of our contract.

Compiling Your Smart Contract

You will first need to compile your smart contract into byte-code. There are a few different ways you can do this, recommend using remix. Remix will output a file usually called simple_storage.json. If you copy this file into your IDE, you will be able to initialize it in JavaScript like this: let json = require('./compiledSmartContract.json').

Storing the byte-code on the Hedera File Service

We need the fileID of its byte code stored on the Hedera file service to deploy our contract. We can get this by using the FileCreateTransaction API from the hedera JS SDK and passing it the byte-code.

    const compiled = json['data']['bytecode']['object'];
    // Store Contact in file service. Different from eth. Transaction size is smaller on hedera for security 
    const mycontract = await new FileCreateTransaction()
        .setContents(compiled)
        .setKeys([PrivateKey.fromString(myPrivateKey)])
        // The default max fee of 1 HBAR is not enough to make a file ( starts around 1.1 HBAR )
        .setMaxTransactionFee(new Hbar(2)) // 2 HBAR
        .execute(client);

    const TransactionReceipt  = await mycontract.getReceipt(client);
    const fileid =  new FileId(TransactionReceipt.fileId);
    console.log("file ID: " + fileid);
Enter fullscreen mode Exit fullscreen mode

Afterward, we can get the FileID from the FileCreateTransaction receipt, as shown in the example above.

Deploying

Once you have a fileId of the byte-code from your contract, you can pass the fileId from the previous step to the ContractCreateTransaction() API call.

    // Deploy Contract
    const deploy = await new ContractCreateTransaction()
        .setGas(300)
        .setBytecodeFileId(fileid)
        .execute(client);

    const receipt = await deploy.getReceipt(client); //Get the new contract 
    const newContractId = receipt.contractId;        
    console.log("The contract ID is " + newContractId);
Enter fullscreen mode Exit fullscreen mode

After deploying the contract you can await the receipt to get the contract ID.

Calling the Smart Contract Functions

When calling the smart contract functions, you have to know whether or not the function you want to call is modifying the state variables of the contract. If you are changing state variables, you will use the ContractExecuteTransaction() endpoint. Otherwise, you will use the ContractCallQuery() endpoint. You can think of this a doing reads vs doing writes.

Modifying State (writes)

For example, I am calling the set function in the contract outlined in the solidity documentation, I am modifying the storedData state variable.

Using the Hedera API to call this function would look something like this.

    const setter = await new ContractExecuteTransaction()
        .setContractId(newContractId)
        .setGas(400000)
        .setFunction("set", new ContractFunctionParameters().addUint256(7))
        .setMaxTransactionFee(new Hbar(3))


    const contractCallResult = await setter.execute(client);
    const testing = await contractCallResult.getRecord(client);
    console.log("Status Code:", testing.status)
Enter fullscreen mode Exit fullscreen mode

Not Modifying State (reads)

The call to the corresponding getter would look something like this

    const getter = await new ContractCallQuery() // 
        .setContractId(newContractId)
        .setFunction("get")
        .setGas(300000)
        .setMaxQueryPayment(new Hbar(1)) // defaults to 1, if requires more than one need change
    // set should be around at least 3-5k gas
    const contractGetter = await getter.execute(client);
    const message = await contractGetter.getUint256(0);
    console.log("contract message: " + message);
Enter fullscreen mode Exit fullscreen mode

Discussion (0)