Skip to content

Application Binary Interface

The Application Binary Interface (ABI) is a data encoding scheme for working with smart contracts. The types defined in the ABI are the same as those you encounter when writing smart contracts with Solidity.

Using ABI in Trident

The abi package in Trident includes libraries to encode/decode ABIs. Take calling function totalSupply() public view returns (uint256) function as an example to illustrate how to interact with a contract using ABI

// 1. Define function parameters (empty for totalSupply)
List<Type> inputParameters = Collections.emptyList();

// 2. Create function and encode
Function function = new Function(
    "totalSupply",     // Function name
    inputParameters,   // Function input parameters
    Arrays.asList(new TypeReference<Uint256>() {})  // Function output parameters
);
String encodedHex = FunctionEncoder.encode(function);

// 3. Call the contract
TransactionExtention txnExt = client.triggerConstantContract(
    ownerAddress,      // Caller address
    contractAddress,   // Contract address
    encodedHex        // Encoded function call
);

// 4. Decode the result
String result = Numeric.toHexString(txnExt.getConstantResult(0).toByteArray());
BigInteger totalSupply = (BigInteger) FunctionReturnDecoder.decode(
    result, 
    function.getOutputParameters()
).get(0).getValue();

// For tokens with 18 decimals (like JST), the result might be:
// 9900000000000000000000000000

Type Matching

The parameter types in your code must exactly match the function definition in the smart contract. For example:

// In smart contract
function transfer(address _to, uint _value) public returns (bool)  // uint is alias for uint256
// In Java code - Correct ✓
List<Type> params = Arrays.asList(
    new Address("TRxxxxxxxxxxxxxxxxxxxxxxxxxxx"),  // address type
    new Uint256(1000000)                         // uint256 type
);

// In Java code - Wrong ✗
List<Type> params = Arrays.asList(
    new Utf8String("TRxxxxxxxxxxxxxxxxxxxxxxxxxxx"),  // wrong type for address
    new Int256(1000000)                             // wrong type for uint
);

For TRC10 token, use Uint256 even if the contract parameter is defined as trcToken:

// In smart contract
function transferToken(address _to, trcToken _id, uint256 _amount) external;
// In Java code
List<Type> params = Arrays.asList(
    new Address("TRxxxxxxxxxxxxxxxxxxxxxxxxxxx"),  // address _to
    new Uint256(1000016),                        // trcToken _id
    new Uint256(1000000)                         // uint256 _amount
);

Using incorrect types will result in transaction failure or unexpected behavior.

Struct Support (ABI v2)

Trident supports ABI v2: structs (Solidity tuple types), nested structs, arrays of structs and nested arrays can all be encoded and decoded.

Map a Solidity struct to a Java class by extending StaticStruct (all fields are fixed-size types) or DynamicStruct (contains at least one dynamic field such as string, bytes or a dynamic array), and pass the fields to the super constructor in declaration order:

// In smart contract
struct MarketParams {
    address loanToken;
    address collateralToken;
    address oracle;
    address irm;
    uint256 lltv;
}
import org.tron.trident.abi.datatypes.Address;
import org.tron.trident.abi.datatypes.StaticStruct;
import org.tron.trident.abi.datatypes.generated.Uint256;

public class MarketParams extends StaticStruct {
    public MarketParams(Address loanToken, Address collateralToken,
        Address oracle, Address irm, Uint256 lltv) {
      super(loanToken, collateralToken, oracle, irm, lltv);
    }
}

A struct class works like any other Type:

  • Encode: pass an instance as a function parameter to FunctionEncoder.encode, or encode it standalone with TypeEncoder.encode(struct) — for example to compute keccak256(abi.encode(struct)) identifiers.
  • Decode: reference the class with new TypeReference<MarketParams>() {} in FunctionReturnDecoder.decode, and the decoder instantiates it through the constructor above.

Structs nest naturally: a DynamicStruct can contain a StaticStruct field, and DynamicArray<SomeStruct> handles arrays of structs.

For complete, runnable walkthroughs decoding and re-encoding real mainnet transactions of JustLend V2 and SunSwap V4 with structs, see Complex ABI Examples.

Packed Encoding

TypeEncoder.encodePacked(type) implements Solidity's abi.encodePacked — values are concatenated without padding, as commonly used for hash-based signatures and commitments.