This article mainly introduces how to encode and decode parameters when triggering a smart contract in the Tron network. The encoding and decoding of parameters follows the Solidity ABI encoding rules.

# ABI Encoding Specification

This chapter mainly introduces the ABI coding rules through examples. For detailed ABI coding rules, please refer to the [ABI Specification](🔗) in Solidity documentation.

## Function Selector

The first four bytes of the `data` field of a contract function call are the function selector, specifying the function to be called.

The function selector is the first (left, high-order in big-endian) four bytes of the Keccak-256 hash of the function signature. The function signature contains only the function name and parameter types, without parameter names and spaces. Take tranfer(address _to, uint256 _value) as an example, its function signature is transfer(address, uint256).

You can get the Keccak-256 hash value of the function signature by calling the [tronweb.sha3](🔗) interface.

## Argument Encoding

Starting from the fifth byte, the encoded arguments follow. This encoding is also used in other places, e.g. the return values and also event arguments are encoded in the same way, without the four bytes specifying the function.

### Types

We distinguish static and dynamic types. Static types are encoded in-place and dynamic types are encoded at a separately allocated location after the current block.

  • Static Types:Fixed-length parameters, such as uint256, bytes32, bool (the boolean type is uint8, which can only be 0 or 1). Taking uint256 as an example, for a parameter whose type is uint256, even if the value is 1, it needs to be padded with 0 to make it 256 bits, that is, 32 bytes, so the length of the static parameter is fixed and has nothing to do with the value.

  • Dynamic Types:The length of dynamic parameters is indeterminate. Dynamic parameter types include: bytes, string, T[] for any T, T[k] for any dynamic T and any k >= 0, (T1,...,Tk) if Ti is dynamic for some 1 <= i <= k.

### Static Argument Encoding

**Example 1**



The function signature is `baz(uint32,bool)`, Keccak-256 value of function signature is `0xcdcd77c0992ec5bbfc459984220f8c45084cc24d9b6efed1fae540db8de801d2`, Its function selector is 0xcdcd77c0.

The parameter encoding is expressed in hexadecimal, and every two hexadecimal digits occupies one byte. Since the maximum length of static parameters is 256 bits, during encoding, the length of each static parameter is 256 bits, that is, 32 bytes, with a total of 64 hexadecimal digits. When the parameter is less than 256 bits, the left side is filled with 0s.

Pass a set of parameters (69, true) to the baz method, the encoding result is as follows:

  • Convert the decimal number 69 to hexadecimal 45, and add 0 to the left to make it occupy 32 bytes, the result is: 0x0000000000000000000000000000000000000000000000000000000000000045

  • Boolean true is 1 of uint8, its hexadecimal value is also 1, and add 0 to the left to make it occupy 32 bytes, and the result is: 0x0000000000000000000000000000000000000000000000000000000000000001

In total:



**Example 2**

Similarly, for static type data of `bytes` type, it needs to be padded to 32 bytes when encoding. The difference is that bytes type data needs to be padded on the right. Take the following function as an example



Function signature is `bar(bytes3[2])`, function selector is: `0xfce353f6`.

Pass a set of parameters `(abc, def)` to this function, the encoding result is as follows:

  • The ASCII value of a b c are 97, 98, 99 in decimal, and 61, 62, 63 in hexadecimal. If parameter is less than 32 bytes,it's need to fill with 0 on the right, the result is: 0x6162630000000000000000000000000000000000000000000000000000000000

  • The ASCII value of d e f are 100, 101, 102 in decimal, and 64, 65, 66 in hexadecimal. If parameter is less than 32 bytes,it's need to fill with 0 on the right, the result is: 0x6465660000000000000000000000000000000000000000000000000000000000

In total:



### Dynamic Argument Encoding

For dynamic parameters, due to their indeterminate lengths, it is necessary to use a fixed-length offset to occupy the space first, and record the number of offset bytes of the actual position of the dynamic parameters, and then encode the data.

Take the function `f(uint,uint32[],bytes10,bytes)` as an example, when passing the parameters (0x123, [0x456, 0x789], "1234567890", "Hello, world!") to it, the encoding The result is as follows:

  • The first static parameter encoding: uints with unmarked lengths are regarded as uint256, and the encoding result of 0x123 is:

    
  • The offset of the second dynamic parameter: For uint32[], since the array length is unknown,first use the offset to occupy the place, and the offset records the number of bytes at the starting position of this parameter. Before the formal encoding of this uint32 parameter, there are: the encoding of the first parameter uint (32 bytes), the offset of the second parameter uint32[] (32 bytes), and the encoding of the third parameter bytes10 (32 words) section), the offset of the fourth parameter bytes (32 bytes), therefore, the start bytes of the value encoding should be 128, which is 0x80, and the encoding result is:

    
  • The value encoding of second dynamic parameter : an array [0x456, 0x789] is passed to uint32[]. For dynamic parameters, first record its length, which is 0x2, and then encode the value. The encoding result of this parameter is:

    
  • The third static parameter encoding: "1234567890" is a static bytes10 parameter, convert it to hex format and pad with 0, the result is:

    
  • The offset of the fourth dynamic parameter: This parameter type is `bytes`, it is a dynamic type, so first use the offset to occupy the place. The content before the actual content of the parameter is: 1. the encoding of the first parameter uint (32 bytes), 2. the offset of the second parameter uint32[] (32 bytes), 3. the encoding of the third parameter bytes10 (32 bytes) ), 4. the offset of the fourth parameter bytes (32 bytes), 5. the encoding of the second parameter uint32[] (96 bytes). So the offset should be 224 which is 0xe0.

    
  • The value encoding of fourth dynamic parameter : For the parameter value of`bytes` type :"Hello, world!", first record its length 13, which is 0xd. Then convert the string to hexadecimal characters, that is : 0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000. The encoding result of this parameter is:

    

    All parameters are encoded, and the final data is

    

# Parameter's Encoding and Decoding

After understanding the ABI encoding rules, you can use the ABI rules to encode and decode parameters in the code. The TRON community provides many SDKs or libraries for developers to use. Some SDKs have already encapsulated the encoding and decoding of parameters. You can call it directly, such as [trident-java](🔗). The following will use trident-java SDK and JavaScript libraries to illustrate how to encode and decode parameters in code.

## Parameter Encoding

We take the transfer function in USDT contract as an example:



Suppose you transfer 50000 USDT to the address 412ed5dd8a98aea00ae32517742ea5289761b2710e, and call the triggersmartcontract interface as follows:



In the above command, the parameter's encoding needs to be in accordance with the [ABI rules](🔗).

### Example of Parameter Encoding Using Javascript

For JavaScript, users can use the `ethers` library, here is the sample code:



Output:



### Example of Parameter Encoding Using trident-java

The process of parameter encoding has been encapsulated in trident, just select the parameter type and pass in the parameter value. The type of the parameter is in the `org.tron.trident.abi.datatypes` package, please select the appropriate java class according to the parameter type. The following sample code shows how to use trident to generate `data` information of contract. The main steps are as follows:

  1. To construct a `Function` object, three parameters are required: function name, input parameters and output parameters. See [Function code](🔗) for details.

  2. Call the `FunctionEncoder.encode` function to encode the `Function` object and generate the `data` of the contract transaction.



## Parameter decoding

In the above section of the parameter encoding , the invoked triggersmartcontract generates a transaction object, and then signs and broadcasts it. After the transaction is successfully on chain, the transaction information on the chain can be obtained through gettransactionbyid:



The results are as follows:



The `raw_data.contract[0].parameter.value.data` field in the return value is the called transfer(address to, uint256 value) function and its parameters. The first four bytes `a9059cbb` of the data field are function selectors, which come from the first 4 bytes after Keccak-256 operation of `transfer(address, uint256)` in ASCII format, which is used for the virtual machine to address the function. The latter part is the parameter, which is the same as the parameter in the `wallet/triggersmartcontract` interface in the parameter encoding chapter.

Function selector,the first four bytes of data, obtained by Keccak-256, cannot be reversed. The function signature can be obtained in two ways:

  • If the contract ABI can be obtained, the selector of each contract function can be calculated and compared with the first four bytes of data to judge the function

  • The contract generated by the contract may not have ABI on the chain. The contract deployer can also clear the ABI on the chain through the `clearAbi` interface. When the ABI cannot be obtained, you can try to query the functions in the database through `Ethereum Signature Database`.

For parameters decode please refer to below content.

### Example of Parameter Decoding using javascript

#### Decode data

The following JavaScript code decodes the `data` field and obtains the parameters passed by the transfer function:



Sample code output:



#### Decode the return value of a contract query operation

We take the query function in USDT contract as an example:



Suppose you query the balance of `410583A68A3BCD86C25AB1BEE482BAC04A216B0261` and call the `triggerconstantcontract` interface as follows:



The results are as follows:



The `constant_result` is the return value of balanceOf. Here is the sample code for decoding constant_result:



Sample code output:



### Example of Parameter Decoding using trident-java

#### Decode data

The following Java code decodes the `data` field using trident and obtains the parameters passed by the transfer function:



#### Decode the return value of a contract query operation

The constant function call will return a `TransactionExtention` object, in which the `constantResult` field is the query result, which is a List<ByteString>. After converting it to a hex string, you can use the `TypeDecoder` class in the above sample code to decode the return value of the contract query operation. Or you can also use the `decode` method of `org.tron.trident.abi.FunctionReturnDecoder`:

Specify the type of the return value in the `org.tron.trident.abi.FunctionReturnDecoder: decode` method, and it can convert the result to an object of this type.