web3j icon indicating copy to clipboard operation
web3j copied to clipboard

Issue when decoding StaticStruct3 field on generated static class

Open theonekeyg opened this issue 2 years ago • 0 comments

I'm having issues with decoding data with generated bindings from the contract. java.lang.UnsupportedOperationException: Array types must be wrapped in a TypeReference

Issue_description

One of methods of my contract returns static struct as response. Here is declaration of this struct

    public static class RelayInfo extends StaticStruct {
        public BigInteger lastSeenBlockNumber;

        public BigInteger lastSeenTimestamp;

        public BigInteger firstSeenBlockNumber;

        public BigInteger firstSeenTimestamp;

        public List<byte[]> urlParts;

        public String relayManager;

        public RelayInfo(BigInteger lastSeenBlockNumber, BigInteger lastSeenTimestamp, BigInteger firstSeenBlockNumber, BigInteger firstSeenTimestamp, List<byte[]> urlParts, String relayManager) {
            super(new org.web3j.abi.datatypes.generated.Uint32(lastSeenBlockNumber), 
                    new org.web3j.abi.datatypes.generated.Uint40(lastSeenTimestamp), 
                    new org.web3j.abi.datatypes.generated.Uint32(firstSeenBlockNumber), 
                    new org.web3j.abi.datatypes.generated.Uint40(firstSeenTimestamp), 
                    new org.web3j.abi.datatypes.generated.StaticArray3<org.web3j.abi.datatypes.generated.Bytes32>(
                            org.web3j.abi.datatypes.generated.Bytes32.class,
                            org.web3j.abi.Utils.typeMap(urlParts, org.web3j.abi.datatypes.generated.Bytes32.class)), 
                    new org.web3j.abi.datatypes.Address(160, relayManager));
            this.lastSeenBlockNumber = lastSeenBlockNumber;
            this.lastSeenTimestamp = lastSeenTimestamp;
            this.firstSeenBlockNumber = firstSeenBlockNumber;
            this.firstSeenTimestamp = firstSeenTimestamp;
            this.urlParts = urlParts;
            this.relayManager = relayManager;
        }

        public RelayInfo(Uint32 lastSeenBlockNumber, Uint40 lastSeenTimestamp, Uint32 firstSeenBlockNumber, Uint40 firstSeenTimestamp, StaticArray3<Bytes32> urlParts, Address relayManager) {
            super(lastSeenBlockNumber, lastSeenTimestamp, firstSeenBlockNumber, firstSeenTimestamp, urlParts, relayManager);
            this.lastSeenBlockNumber = lastSeenBlockNumber.getValue();
            this.lastSeenTimestamp = lastSeenTimestamp.getValue();
            this.firstSeenBlockNumber = firstSeenBlockNumber.getValue();
            this.firstSeenTimestamp = firstSeenTimestamp.getValue();
            this.urlParts = urlParts.getValue().stream().map(v -> v.getValue()).collect(Collectors.toList());
            this.relayManager = relayManager.getValue();
        }
    }

The error is thrown when the decoder is trying to decode StaticStruct3 field, because the StaticStruct3 is inherits from org.web3j.abi.datatypes.Array (the urlParts field is bytes32[3] in solidity source), here is the full backtrace:

Exception in thread "main" java.lang.UnsupportedOperationException: Array types must be wrapped in a TypeReference
	at org.web3j.abi.TypeDecoder.decode(TypeDecoder.java:119)
	at org.web3j.abi.TypeDecoder.decodeStaticStructElement(TypeDecoder.java:400)
	at org.web3j.abi.TypeDecoder.decodeStaticStruct(TypeDecoder.java:365)
	at org.web3j.abi.DefaultFunctionReturnDecoder.build(DefaultFunctionReturnDecoder.java:113)
	at org.web3j.abi.DefaultFunctionReturnDecoder.decodeFunctionResult(DefaultFunctionReturnDecoder.java:52)
	at org.web3j.abi.FunctionReturnDecoder.decode(FunctionReturnDecoder.java:57)
	at org.web3j.tx.Contract.executeCall(Contract.java:313)
	at org.web3j.tx.Contract.executeCallSingleValueReturn(Contract.java:324)
	at org.web3j.tx.Contract.executeCallSingleValueReturn(Contract.java:335)
	at org.web3j.tx.Contract.lambda$executeRemoteCallSingleValueReturn$1(Contract.java:457)
	at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
	at org.sample.ContractInteractor.getRelayInfo(ContractInteractor.java:74)
	at org.sample.KnownRelaysManager.getRelayInfo(KnownRelaysManager.java:42)
	at org.sample.RelaySelectionManager.getRelays(RelaySelectionManager.java:40)
	at org.sample.RelayClient.relayTransaction(RelayClient.java:104)
	at org.sample.App.main(App.java:44)

I wish I could provide code samples to replicate the issue, but the contract is deployed to private network, hope provided info is good enough. Is this a bug? I did not make any changes to the generated contract bindings.

Issue_context

I'm using web3j bindings generated with web3j-cli 1.4.2 with web3j 4.9.7.

theonekeyg avatar Mar 22 '23 14:03 theonekeyg