2

I am trying to deploy a contract on Hedera; the file is 9766 bytes, so I created a file and appended the contract to it, but now I get the error "exceptional receipt status: ERROR_DECODING_BYTESTRING: error retrieving contract creation record". I believe I did something wrong in my code. Any help will be appreciated.

package blockchain

import (
    "encoding/json"
    "fmt"
    "io/ioutil"

    "github.com/.../scanner/env"
    "github.com/hashgraph/hedera-sdk-go/v2"
)

type contract struct {
    Abi string `json:"abi"`
    Bin string `json:"bin"`
}

type contracts struct {
    Contracts map[string]contract `json:"contracts"`
    Version   string              `json:"version"`
}

func DeployContract() {
    var client *hedera.Client
    var err error

    // Retrieving network type from environment variable HEDERA_NETWORK
    client, err = hedera.ClientForName(env.GetEnv["HEDERA_NETWORK"])
    if err != nil {
        println(err.Error(), ": error creating client")
        return
    }

    // Retrieving operator ID from environment variable OPERATOR_ID
    operatorAccountID, err := hedera.AccountIDFromString(env.GetEnv["OPERATOR_ID"])
    if err != nil {
        println(err.Error(), ": error converting string to AccountID")
        return
    }

    // Retrieving operator key from environment variable OPERATOR_KEY
    operatorKey, err := hedera.PrivateKeyFromString(env.GetEnv["OPERATOR_KEY"])
    if err != nil {
        println(err.Error(), ": error converting string to PrivateKey")
        return
    }

    // Setting the client operator ID and key
    client.SetOperator(operatorAccountID, operatorKey)

    // Make sure to close client after running
    defer func() {
        err = client.Close()
        if err != nil {
            println(err.Error(), ": error closing client")
            return
        }
    }()

    // Read in the compiled contract from contract.json
    rawSmartContract, err := ioutil.ReadFile("./contract/contract.json")
    if err != nil {
        println(err.Error(), ": error reading contract.json")
        return
    }

    // Initialize contracts
    var smartContract contracts = contracts{}

    // Parse the rawSmartContract into smartContract
    err = json.Unmarshal([]byte(rawSmartContract), &smartContract)
    if err != nil {
        println(err.Error(), ": error unmarshaling")
        return
    }

    // Retrieve the bytecode from the parsed smart contract
    smartContractByteCode := smartContract.Contracts["contract.sol:ScanInput"].Bin

    //output contract bytecode size
    fmt.Printf("Contract bytecode size: %v bytes\n", len(smartContractByteCode))

    // Create a new file
    newFileResponse, err := hedera.NewFileCreateTransaction().
        // Accepts both Key and []Key
        // All keys at the top level of a key list must sign to create or modify the file. Any one of
        // the keys at the top level key list can sign to delete the file.
        SetKeys(client.GetOperatorPublicKey()).
        // Basic starting file content
        SetContents([]byte("Initializing file.")).
        SetMemo("go file append test").
        // Set max fee if we don't want to get overcharged
        SetMaxTransactionFee(hedera.NewHbar(2)).
        Execute(client)
    if err != nil {
        println(err.Error(), ": error creating file")
        return
    }

    // Get receipt to make sure the transaction worked
    receipt, err := newFileResponse.GetReceipt(client)
    if err != nil {
        println(err.Error(), ": error retrieving file creation receipt")
        return
    }

    // Retrieve file ID from the receipt
    fileID := *receipt.FileID

    // File append
    fileResponse, err := hedera.NewFileAppendTransaction().
        // Make sure the node is the same as the new file, as we don't have to wait for propagation
        SetNodeAccountIDs([]hedera.AccountID{newFileResponse.NodeID}).
        // File ID to append to
        SetFileID(fileID).
        // Contents that will be appended to the end of the file
        SetContents([]byte(smartContractByteCode)).
        // Set max transaction when you are not sure how much it will cost.
        SetMaxTransactionFee(hedera.NewHbar(5)).
        Execute(client)
    if err != nil {
        println(err.Error(), ": error executing file append transaction")
        return
    }

    // Checking if transaction went through
    receipt, err = fileResponse.GetReceipt(client)
    if err != nil {
        println(err.Error(), ": error retrieving file append transaction receipt")
        return
    }

    // Checking if append succeeded
    println(receipt.Status.String())
    info, err := hedera.NewFileInfoQuery().
        // Once again same node account ID
        SetNodeAccountIDs([]hedera.AccountID{fileResponse.NodeID}).
        // Only the file ID is required for this
        SetFileID(fileID).
        Execute(client)

    if err != nil {
        println(err.Error(), ": error executing file info query")
        return
    }

    println("File size according to `FileInfoQuery`:", info.Size)
    println("File memo according to `FileInfoQuery`:", info.FileMemo)

    // Retrieve the receipt to make sure the transaction went through and to get bytecode file ID
    byteCodeTransactionReceipt, err := newFileResponse.GetReceipt(client)
    if err != nil {
        println(err.Error(), ": error getting file create transaction receipt")
        return
    }

    // Retrieve bytecode file ID from the receipt
    byteCodeFileID := *byteCodeTransactionReceipt.FileID

    fmt.Printf("contract bytecode file: %v\n", byteCodeFileID)

    // Instantiate the contract instance
    contractTransactionID, err := hedera.NewContractCreateTransaction().
        // Set gas to create the contract
        // Failing to set this to a sufficient amount will result in "INSUFFICIENT_GAS" status
        SetGas(100000).
        // The contract bytecode must be set to the file ID containing the contract bytecode
        SetBytecodeFileID(byteCodeFileID).
        // Set the admin key on the contract in case the contract should be deleted or
        // updated in the future
        SetAdminKey(client.GetOperatorPublicKey()).
        Execute(client)

    if err != nil {
        println(err.Error(), ": error creating contract")
        return
    }

    // Get the new contract record to make sure the transaction ran successfully
    contractRecord, err := contractTransactionID.GetRecord(client)
    if err != nil {
        println(err.Error(), ": error retrieving contract creation record")
        return
    }

    // Get the contract create result from the record
    contractCreateResult, err := contractRecord.GetContractCreateResult()
    if err != nil {
        println(err.Error(), ": error retrieving contract creation result")
        return
    }

    // Get the new contract ID from the receipt contained in the record
    newContractID := *contractRecord.Receipt.ContractID

    fmt.Printf("Contract create gas used: %v\n", contractCreateResult.GasUsed)
    fmt.Printf("Contract create transaction fee: %v\n", contractRecord.TransactionFee)
    fmt.Printf("contract: %v\n", newContractID)

}

Solidity Contract: https://drive.google.com/file/d/1YQ5B9Z2CL4i3R_4eSS3OQSEAbzSooehr/view?usp=sharing

mev
  • 177
  • 5

1 Answers1

0

I think I responded to this in Discord, but here goes for completion. I think the issue is that your code looks for Bin in the Json when it's bin.

Switch smartContractByteCode := smartContract.Contracts["contract.sol:ScanInput"].Bin

for

smartContractByteCode := smartContract.Contracts["contract.sol:ScanInput"].bin

Greg Scullard
  • 241
  • 1
  • 10