hashgraph / hashgraph/hedera-sdk-reference

ABI support in SDKs

Open
#140 0 comments 0 reactions 1 assignee Claimed by @ochikov View on GitHub
enhancement
Dominant language
HTML
Stars
7
Forks
3
PR merge metrics
No merged PRs in 30d

Description

### Problem

Across SDKs, we've got the following functionalities:
- ContractCallQuery - returning a result of executing a function
- ContractCreateFlow - which is returning only receipt
- ContractCreateTransaction - which is returning only the receipt
- ContractExecuteTransaction - which returns only receipt, but not a result of the call (if we call a function)

All those flows use `ContractFunctionParameters()`.
In the `ContractFunctionParameters()` we’ve got the following methods:
- addString
- addStringArray
- addBytes
- addBytes32
- addBytesArray
- addBytes32Array
- addBool
- addInt8
- addUint8
- addInt16
- addUint16

and so on…. [a file with `1700`](https://github.com/hashgraph/hedera-sdk-js/blob/develop/src/contract/ContractFunctionParameters.js) lines and a lot of methods, switch cases, and IFs.

### **The workflow is as follows:**

- We are calling some of the “add methods” of `ContractFunctionParameters`
- Then, we call `_addParam`
- Then we call `argumentToBytes` and convert the passing params to the function to bytes (`Uint8Array`)

Then we got `ContractFunctionSelector` [file with `1400`](https://github.com/hashgraph/hedera-sdk-js/blob/develop/src/contract/ContractFunctionSelector.js) lines of code.

We are using that file with all the helper methods inside to create the signature of the function.

### **For example:**

- We’ve got `ArgumentType` to integers
- We’ve got different methods such as `addString` which returns the signature of the function
- We’ve got `solidityTypeToString` where we are transpile solidity types to string, for example:

```
case ArgumentType.uint8:
s = "uint8";
```

This all is created because we are not requiring the ABI of a contract when we are doing:

- ContractCallQuery
- ContractCreateFlow
- ContractCreateTransaction
- ContractExecuteTransaction
- ….etc

**The above workflow assumes that the user will know the exact parameters that a function is accepting when performing the above calls. According to my opinion, this could lead to errors and unpredicted behavior because of the missing or wrong passed params.**

We can use the **ABI** of the contract and then pass params. We can leave the transforming of the contract function params to bytes to the SDK and then decode them back to the SDK.

For example, when we are retrieving results from:

- ContractFunctionResult

we need to decode manually the response again using similar functions as in `ContractFunctionParameters` :

- `getUint40` and to pass the index of the returned param of the contract function

As you can see, this is not convenient, because the users must know the signature of the functions (what is accepting and what is returning).

### Solution

### **Encoding and passing data to contract**

- We can add the following setter and function params:
```
setAbi()
```

```
callFunction
```

- setAbi will receive the ABI of the compiled contract, for example:

```
.setAbi(setDataContract.abi)
```

- callFunction will receive the signature of the function together with the passed params, for example:
```
callFunction("setMultipleMessages", [
"New Message",
"Second New Message",
]);
```

### **Decoding and retrieving data from the contract**

I’ve implemented a method called:

`const result = txResponse.getResult(["uint32", "uint64", "string"]);`

Where you can pass the signature of the function (from the ABI) and use it to decode and return the result.

The method `getResult` is tested in production (actually it is released because a lof of people had problems decoding data from contract calls).

### Alternatives

## **Notes from the last meeting:**

For passing the input:

- Maybe the whole ABI is too much information
- We can use a similar approach to the `getResult` function with something like:
- setValue (with passing the signature)
- setABIFunction (not sure the “ABI” terminology is used correctly here)
- setFunctionSignature

For getting the output:

- we can keep the method `getResult` passing the function signature

For different SDKs:

- We need to consider using the ready-to-be-used solutions for ABI encode/decode or write our own (this will be quite big enough because the SDKs are trying now to do it on their own and the result is that only the main cases (straightforward) are supported.
- SDKs potential libraries that we can use:
- GO SDK Quick example: https://go.dev/play/p/VSmWHUavjMZ (checked ✅)
- JAVA:
- for ABI encode/decode they are using headlong (checked ✅)
- for RLP operations they are using web3j (checked ✅)
- C++: 1. за `C++` - [[Silkworm](https://github.com/torquem-ch/silkworm)](https://github.com/torquem-ch/silkworm) (still WIP). Requires `C++20` compiler, which does not work at the moment because `Hedera C++ SDK` uses `C++17` (to be checked)
- Rust: https://github.com/gakonst/ethers-rs (to be checked)
- Swift: https://github.com/gnosis/Web3.swift or https://github.com/Boilertalk/Web3.swift (to be checked)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.