3

I am relatively new to interacting with smart contracts in Java and I am facing a problem while trying to retrieve a tuple[] returned by the smart contract function. Here is the ABI definition of the function I want to call:

{
  "inputs":[{"internalType":"address","name":"account","type":"address"}],
  "name":"claimableRewards",
  "outputs":
    [{"components":
      [
        {"internalType":"address","name":"token","type":"address"},
        {"internalType":"uint256","name":"amount","type":"uint256"}
      ],
      "internalType":"struct MultiFeeDistribution.RewardData[]",
      "name":"rewards",
      "type":"tuple[]"
    }],
  "stateMutability":"view",
  "type":"function"
}

Here is the link to the smart contract code: https://polygonscan.com/address/0x920f22e1e5da04504b765f8110ab96a20e6408bd#code

And here is the Java code that I wrote to call the function (I have removed the errors checking to make the code easier to read):

List<Type> claimableRewardsParams = Arrays.<Type>asList(new Address(credentials.getAddress()));
List<TypeReference<?>> claimableRewardsReturnTypes = Arrays.<TypeReference<?>>asList(new TypeReference<DynamicArray<DynamicStruct>>() {});

final Function claimableRewardsFunction = new Function(
        "claimableRewards",
        claimableRewardsParams,
        claimableRewardsReturnTypes);

String claimableRewardsEncodedFunction = FunctionEncoder
        .encode(claimableRewardsFunction);          

EthCall claimableRewardsResponse = web3.ethCall(
        Transaction.createEthCallTransaction(walletAddress, adamantRewardsContractAddress, claimableRewardsEncodedFunction),
        DefaultBlockParameterName.LATEST)
        .sendAsync().get();

List<Type> claimableRewardsSomeTypes = FunctionReturnDecoder.decode(
        claimableRewardsResponse.getValue(), claimableRewardsFunction.getOutputParameters());

When I run the program I get the following exception:

Exception in thread "main" java.lang.RuntimeException: TypeReferenced struct must contain a constructor with types that extend Type

I have tried several other definitions for claimableRewardsReturnTypes, but I can't get it to work. Can someone please help me?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Coin Lover
  • 31
  • 3

2 Answers2

3

You need to define a class that extends DynamicStruct

public class RewardData extends DynamicStruct {
    public RewardData(Address token, Uint256 amount) {
        super(new Type[]{token, amount});
    }
}

and then replace DynamicStruct with RewardData

List<TypeReference<?>> claimableRewardsReturnTypes = Arrays.<TypeReference<?>>asList(new TypeReference<DynamicArray<RewardData>>() {});
PierreLuo
  • 31
  • 4
1
    {
  "inputs":[{"internalType":"address","name":"account","type":"address"}],
  "name":"claimableRewards",
  "outputs":
    [{"components":
      [
        {"internalType":"address","name":"token","type":"address"},
        {"internalType":"uint256[]","name":"amount","type":"uint256[]"}
      ],
      "internalType":"struct MultiFeeDistribution.RewardData[]",
      "name":"rewards",
      "type":"tuple[]"
    }],
  "stateMutability":"view",
  "type":"function"
}
  • The tuple contains an array. If it is such an abi, how to write it? – user19322569 Jun 12 '22 at 05:23
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 12 '22 at 10:22