Repository: LFDT-web3j/web3j (Java)

Issue:
Can not generate java class of static struct in some case.
The generated code does not contain the struct that is defined in static array

**Solidity**
```    
struct Player {
       address addr; 
       uint256 timeLeft; 
}
struct Config{ 
        uint64 index; 
        Player[2] players; 
    }
```
**Generated warpper**
```
public static class Config extends StaticStruct {
        public BigInteger index;
        public List<Player> players;
}
```
I can not find the Class of _Player_ . 
But it successfully generates when I modity the static array to dynamic, like this:
```
struct Config{ 
        uint64 index; 
        Player[] players; 
    }
```

- Is it unimplemented feature or bug? 
- Should I avoid to use struct in static array when i try to generate wrapper?

> web3j version: 4.11.1





Discussion:

Patch:
diff --git a/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java b/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java
index b29dd6c18..0559fca03 100644
--- a/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java
+++ b/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java
@@ -129,7 +129,7 @@ public class SolidityFunctionWrapper extends Generator {
     private final boolean abiFuncs;
     private final int addressLength;
 
-    private final HashMap<Integer, ClassName> structClassNameMap = new HashMap<>();
+    private final HashMap<String, ClassName> structClassNameMap = new HashMap<>();
 
     private final List<NamedType> structsNamedTypeList = new ArrayList<>();
 
@@ -587,10 +587,6 @@ private List<TypeSpec> buildStructTypes(final List<AbiDefinition> functionDefini
     private static String getStructName(String internalType) {
         final String fullStructName = internalType.substring(internalType.lastIndexOf(" ") + 1);
         String tempStructName = fullStructName.substring(fullStructName.lastIndexOf(".") + 1);
-        int arrayPos = tempStructName.indexOf("[");
-        if (arrayPos > -1) {
-          tempStructName = tempStructName.substring(0, arrayPos);
-        }
         final String structName =
                 SourceVersion.isName(tempStructName) ? tempStructName : "_" + tempStructName;
         return structName;
@@ -611,6 +607,7 @@ private String adjustToNativeTypeIfNecessary(NamedType component) {
     }
 
     private NamedType normalizeNamedType(NamedType namedType) {
+        // dynamic array
         if (namedType.getType().endsWith("[]") && namedType.getInternalType().endsWith("[]")) {
             return new NamedType(
                     namedType.getName(),
@@ -620,6 +617,18 @@ private NamedType normalizeNamedType(NamedType namedType) {
                             .getInternalType()
                             .substring(0, namedType.getInternalType().length() - 2),
                     namedType.isIndexed());
+        } else if (namedType.getType().startsWith("tuple[")
+                && namedType.getInternalType().contains("[")
+                && namedType.getInternalType().endsWith("]")) { // static array
+
+            return new NamedType(
+                    namedType.getName(),
+                    namedType.getType().substring(0, namedType.getType().indexOf("[")),
+                    namedType.getComponents(),
+                    namedType
+                            .getInternalType()
+                            .substring(0, namedType.getInternalType().indexOf("[")),
+                    namedType.isIndexed());
         } else {
             return namedType;
         }
@@ -628,7 +637,7 @@ private NamedType normalizeNamedType(NamedType namedType) {
     @NotNull
     private List<AbiDefinition.NamedType> extractStructs(
             final List<AbiDefinition> functionDefinitions) {
-        final HashMap<Integer, AbiDefinition.NamedType> structMap = new LinkedHashMap<>();
+        final HashMap<String, AbiDefinition.NamedType> structMap = new LinkedHashMap<>();
         functionDefinitions.stream()
                 .flatMap(
                         definition -> {
@@ -637,7 +646,7 @@ private List<AbiDefinition.NamedType> extractStructs(
                             parameters.addAll(definition.getOutputs());
                             return parameters.stream()
                                     .map(this::normalizeNamedType)
-                                    .filter(namedType -> namedType.getType().startsWith("tuple"));
+                                    .filter(namedType -> namedType.getType().equals("tuple"));
                         })
                 .forEach(
                         namedType -> {
@@ -646,7 +655,7 @@ private List<AbiDefinition.NamedType> extractStructs(
                                     .map(this::normalizeNamedType)
                                     .filter(
                                             nestedNamedStruct ->
-                                                    nestedNamedStruct.getType().startsWith("tuple"))
+                                                    nestedNamedStruct.getType().equals("tuple"))
                                     .forEach(
                                             nestedNamedType ->
                                                     structMap.put(
@@ -2288,7 +2297,7 @@ public boolean isIndexed() {
             return namedType.isIndexed();
         }
 
-        public int structIdentifier() {
+        public String structIdentifier() {
             return namedType.structIdentifier();
         }
     }
diff --git a/core/src/main/java/org/web3j/protocol/core/methods/response/AbiDefinition.java b/core/src/main/java/org/web3j/protocol/core/methods/response/AbiDefinition.java
index d08b1ad8c..e13d61295 100644
--- a/core/src/main/java/org/web3j/protocol/core/methods/response/AbiDefinition.java
+++ b/core/src/main/java/org/web3j/protocol/core/methods/response/AbiDefinition.java
@@ -275,12 +275,11 @@ public void setComponents(final List<NamedType> components) {
             this.components = components;
         }
 
-        public int structIdentifier() {
+        public String structIdentifier() {
             return ((internalType == null ? type : internalType.isEmpty() ? type : internalType)
                             + components.stream()
-                                    .map(namedType -> String.valueOf(namedType.structIdentifier()))
-                                    .collect(Collectors.joining()))
-                    .hashCode();
+                                    .map(NamedType::structIdentifier)
+                                    .collect(Collectors.joining()));
         }
 
         public int nestedness() {


Test patch:
diff --git a/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperGeneratorTest.java b/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperGeneratorTest.java
index 8c3e924d5..ddbefe684 100644
--- a/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperGeneratorTest.java
+++ b/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperGeneratorTest.java
@@ -232,6 +232,28 @@ public void testArrayOfStructClassGenerationCompareJavaFile() throws Exception {
         compareJavaFile("ArrayOfStructClassGeneration", true);
     }
 
+    @Test
+    public void testArrayOfStructAndStructGeneration() throws Exception {
+        testCodeGeneration(
+                "arrayofstructandstruct", "ArrayOfStructAndStruct", JAVA_TYPES_ARG, false);
+    }
+
+    @Test
+    public void testArrayOfStructAndStructCompareJavaFile() throws Exception {
+        compareJavaFile("ArrayOfStructAndStruct", true);
+    }
+
+    @Test
+    public void testStaticArrayOfStructsInStructGeneration() throws Exception {
+        testCodeGeneration(
+                "staticarrayofstructsinstruct", "StaticArrayOfStructsInStruct", JAVA_TYPES_ARG, false);
+    }
+
+    @Test
+    public void testStaticArrayOfStructsInStructGenerationCompareJavaFile() throws Exception {
+        compareJavaFile("StaticArrayOfStructsInStruct", true);
+    }
+
     private void compareJavaFile(String inputFileName, boolean useBin) throws Exception {
         String contract = inputFileName.toLowerCase();
         String packagePath =
diff --git a/codegen/src/test/resources/solidity/arrayofstructandstruct/ArrayOfStructAndStruct.sol b/codegen/src/test/resources/solidity/arrayofstructandstruct/ArrayOfStructAndStruct.sol
new file mode 100644
index 000000000..7f754db09
--- /dev/null
+++ b/codegen/src/test/resources/solidity/arrayofstructandstruct/ArrayOfStructAndStruct.sol
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.20;
+
+
+contract ArrayOfStructAndStruct {
+
+    struct Foo {
+        bool dummy;
+    }
+
+    constructor() {
+
+    }
+    function test(Foo[2] calldata foos) external {
+        revert();
+    }
+
+    function testSingle(Foo calldata foo) external {
+        revert();
+    }
+}
diff --git a/codegen/src/test/resources/solidity/arrayofstructandstruct/build/ArrayOfStructAndStruct.abi b/codegen/src/test/resources/solidity/arrayofstructandstruct/build/ArrayOfStructAndStruct.abi
new file mode 100644
index 000000000..0da5ecba7
--- /dev/null
+++ b/codegen/src/test/resources/solidity/arrayofstructandstruct/build/ArrayOfStructAndStruct.abi
@@ -0,0 +1,1 @@
+[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"components":[{"internalType":"bool","name":"dummy","type":"bool"}],"internalType":"struct ArrayOfStructAndStruct.Foo[2]","name":"foos","type":"tuple[2]"}],"name":"test","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"dummy","type":"bool"}],"internalType":"struct ArrayOfStructAndStruct.Foo","name":"foo","type":"tuple"}],"name":"testSingle","outputs":[],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
diff --git a/codegen/src/test/resources/solidity/arrayofstructandstruct/build/ArrayOfStructAndStruct.bin b/codegen/src/test/resources/solidity/arrayofstructandstruct/build/ArrayOfStructAndStruct.bin
new file mode 100644
index 000000000..43f374cac
--- /dev/null
+++ b/codegen/src/test/resources/solidity/arrayofstructandstruct/build/ArrayOfStructAndStruct.bin
@@ -0,0 +1,1 @@
+608060405234801561000f575f80fd5b5061014f8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80631ae18a6414610038578063f0cd1e3b14610054575b5f80fd5b610052600480360381019061004d91906100a1565b610070565b005b61006e600480360381019061006991906100ee565b610074565b005b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f8190508260206002028201111561009b5761009a61007c565b5b92915050565b5f604082840312156100b6576100b5610078565b5b5f6100c384828501610080565b91505092915050565b5f80fd5b5f602082840312156100e5576100e46100cc565b5b81905092915050565b5f6020828403121561010357610102610078565b5b5f610110848285016100d0565b9150509291505056fea2646970667358221220deb8c438006301a2bb5f5ed22ad6516a4f075c63a360dad46a6571057187273164736f6c63430008140033
\ No newline at end of file
diff --git a/codegen/src/test/resources/solidity/arrayofstructandstruct/build/java/ArrayOfStructAndStruct.java b/codegen/src/test/resources/solidity/arrayofstructandstruct/build/java/ArrayOfStructAndStruct.java
new file mode 100644
index 000000000..93e170c46
--- /dev/null
+++ b/codegen/src/test/resources/solidity/arrayofstructandstruct/build/java/ArrayOfStructAndStruct.java
@@ -0,0 +1,148 @@
+package org.web3j.unittests.java;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.web3j.abi.TypeReference;
+import org.web3j.abi.datatypes.Bool;
+import org.web3j.abi.datatypes.Function;
+import org.web3j.abi.datatypes.StaticStruct;
+import org.web3j.abi.datatypes.Type;
+import org.web3j.crypto.Credentials;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.RemoteCall;
+import org.web3j.protocol.core.RemoteFunctionCall;
+import org.web3j.protocol.core.methods.response.TransactionReceipt;
+import org.web3j.tx.Contract;
+import org.web3j.tx.TransactionManager;
+import org.web3j.tx.gas.ContractGasProvider;
+
+/**
+ * <p>Auto generated code.
+ * <p><strong>Do not modify!</strong>
+ * <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>,
+ * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the 
+ * <a href="https://github.com/web3j/web3j/tree/main/codegen">codegen module</a> to update.
+ *
+ * <p>Generated with web3j version none.
+ */
+@SuppressWarnings("rawtypes")
+public class ArrayOfStructAndStruct extends Contract {
+    public static final String BINARY = "608060405234801561000f575f80fd5b5061014f8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80631ae18a6414610038578063f0cd1e3b14610054575b5f80fd5b610052600480360381019061004d91906100a1565b610070565b005b61006e600480360381019061006991906100ee565b610074565b005b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f8190508260206002028201111561009b5761009a61007c565b5b92915050565b5f604082840312156100b6576100b5610078565b5b5f6100c384828501610080565b91505092915050565b5f80fd5b5f602082840312156100e5576100e46100cc565b5b81905092915050565b5f6020828403121561010357610102610078565b5b5f610110848285016100d0565b9150509291505056fea2646970667358221220deb8c438006301a2bb5f5ed22ad6516a4f075c63a360dad46a6571057187273164736f6c63430008140033";
+
+    private static String librariesLinkedBinary;
+
+    public static final String FUNC_TEST = "test";
+
+    public static final String FUNC_TESTSINGLE = "testSingle";
+
+    @Deprecated
+    protected ArrayOfStructAndStruct(String contractAddress, Web3j web3j, Credentials credentials,
+            BigInteger gasPrice, BigInteger gasLimit) {
+        super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
+    }
+
+    protected ArrayOfStructAndStruct(String contractAddress, Web3j web3j, Credentials credentials,
+            ContractGasProvider contractGasProvider) {
+        super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
+    }
+
+    @Deprecated
+    protected ArrayOfStructAndStruct(String contractAddress, Web3j web3j,
+            TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+        super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
+    }
+
+    protected ArrayOfStructAndStruct(String contractAddress, Web3j web3j,
+            TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
+        super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
+    }
+
+    public RemoteFunctionCall<TransactionReceipt> test(List<Foo> foos) {
+        final Function function = new Function(
+                FUNC_TEST, 
+                Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.StaticArray2<Foo>(Foo.class, foos)), 
+                Collections.<TypeReference<?>>emptyList());
+        return executeRemoteCallTransaction(function);
+    }
+
+    public RemoteFunctionCall<TransactionReceipt> testSingle(Foo foo) {
+        final Function function = new Function(
+                FUNC_TESTSINGLE, 
+                Arrays.<Type>asList(foo), 
+                Collections.<TypeReference<?>>emptyList());
+        return executeRemoteCallTransaction(function);
+    }
+
+    @Deprecated
+    public static ArrayOfStructAndStruct load(String contractAddress, Web3j web3j,
+            Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
+        return new ArrayOfStructAndStruct(contractAddress, web3j, credentials, gasPrice, gasLimit);
+    }
+
+    @Deprecated
+    public static ArrayOfStructAndStruct load(String contractAddress, Web3j web3j,
+            TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+        return new ArrayOfStructAndStruct(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
+    }
+
+    public static ArrayOfStructAndStruct load(String contractAddress, Web3j web3j,
+            Credentials credentials, ContractGasProvider contractGasProvider) {
+        return new ArrayOfStructAndStruct(contractAddress, web3j, credentials, contractGasProvider);
+    }
+
+    public static ArrayOfStructAndStruct load(String contractAddress, Web3j web3j,
+            TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
+        return new ArrayOfStructAndStruct(contractAddress, web3j, transactionManager, contractGasProvider);
+    }
+
+    public static RemoteCall<ArrayOfStructAndStruct> deploy(Web3j web3j, Credentials credentials,
+            ContractGasProvider contractGasProvider) {
+        return deployRemoteCall(ArrayOfStructAndStruct.class, web3j, credentials, contractGasProvider, getDeploymentBinary(), "");
+    }
+
+    public static RemoteCall<ArrayOfStructAndStruct> deploy(Web3j web3j,
+            TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
+        return deployRemoteCall(ArrayOfStructAndStruct.class, web3j, transactionManager, contractGasProvider, getDeploymentBinary(), "");
+    }
+
+    @Deprecated
+    public static RemoteCall<ArrayOfStructAndStruct> deploy(Web3j web3j, Credentials credentials,
+            BigInteger gasPrice, BigInteger gasLimit) {
+        return deployRemoteCall(ArrayOfStructAndStruct.class, web3j, credentials, gasPrice, gasLimit, getDeploymentBinary(), "");
+    }
+
+    @Deprecated
+    public static RemoteCall<ArrayOfStructAndStruct> deploy(Web3j web3j,
+            TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+        return deployRemoteCall(ArrayOfStructAndStruct.class, web3j, transactionManager, gasPrice, gasLimit, getDeploymentBinary(), "");
+    }
+
+    public static void linkLibraries(List<Contract.LinkReference> references) {
+        librariesLinkedBinary = linkBinaryWithReferences(BINARY, references);
+    }
+
+    private static String getDeploymentBinary() {
+        if (librariesLinkedBinary != null) {
+            return librariesLinkedBinary;
+        } else {
+            return BINARY;
+        }
+    }
+
+    public static class Foo extends StaticStruct {
+        public Boolean dummy;
+
+        public Foo(Boolean dummy) {
+            super(new org.web3j.abi.datatypes.Bool(dummy));
+            this.dummy = dummy;
+        }
+
+        public Foo(Bool dummy) {
+            super(dummy);
+            this.dummy = dummy.getValue();
+        }
+    }
+}
+
diff --git a/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/StaticArrayOfStructsInStruct.sol b/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/StaticArrayOfStructsInStruct.sol
new file mode 100644
index 000000000..439f2f9e4
--- /dev/null
+++ b/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/StaticArrayOfStructsInStruct.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.20;
+
+
+contract StaticArrayOfStructsInStruct {
+
+    struct Player {
+        address addr;
+        uint256 timeLeft;
+    }
+    struct Config{
+        uint64 index;
+        Player[2] players;
+    }
+
+    function test(Config calldata config) external {
+        revert();
+    }
+}
diff --git a/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/build/StaticArrayOfStructsInStruct.abi b/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/build/StaticArrayOfStructsInStruct.abi
new file mode 100644
index 000000000..7df02f132
--- /dev/null
+++ b/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/build/StaticArrayOfStructsInStruct.abi
@@ -0,0 +1,1 @@
+[{"inputs":[{"components":[{"internalType":"uint64","name":"index","type":"uint64"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"timeLeft","type":"uint256"}],"internalType":"struct StaticArrayOfStructsInStruct.Player[2]","name":"players","type":"tuple[2]"}],"internalType":"struct StaticArrayOfStructsInStruct.Config","name":"config","type":"tuple"}],"name":"test","outputs":[],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
diff --git a/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/build/StaticArrayOfStructsInStruct.bin b/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/build/StaticArrayOfStructsInStruct.bin
new file mode 100644
index 000000000..465f012b8
--- /dev/null
+++ b/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/build/StaticArrayOfStructsInStruct.bin
@@ -0,0 +1,1 @@
+608060405234801561000f575f80fd5b5060c58061001c5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80639acc3bf114602a575b5f80fd5b60406004803603810190603c91906069565b6042565b005b5f80fd5b5f80fd5b5f80fd5b5f60a08284031215606057605f604a565b5b81905092915050565b5f60a08284031215607b57607a6046565b5b5f608684828501604e565b9150509291505056fea2646970667358221220a67d48af17079065cb181167be61364e31cd9d588c89b4a1ca7ceb1a9bf640a864736f6c63430008140033
\ No newline at end of file
diff --git a/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/build/java/StaticArrayOfStructsInStruct.java b/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/build/java/StaticArrayOfStructsInStruct.java
new file mode 100644
index 000000000..416052448
--- /dev/null
+++ b/codegen/src/test/resources/solidity/staticarrayofstructsinstruct/build/java/StaticArrayOfStructsInStruct.java
@@ -0,0 +1,167 @@
+package org.web3j.unittests.java;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.web3j.abi.TypeReference;
+import org.web3j.abi.datatypes.Address;
+import org.web3j.abi.datatypes.Function;
+import org.web3j.abi.datatypes.StaticStruct;
+import org.web3j.abi.datatypes.Type;
+import org.web3j.abi.datatypes.generated.StaticArray2;
+import org.web3j.abi.datatypes.generated.Uint256;
+import org.web3j.abi.datatypes.generated.Uint64;
+import org.web3j.abi.datatypes.reflection.Parameterized;
+import org.web3j.crypto.Credentials;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.RemoteCall;
+import org.web3j.protocol.core.RemoteFunctionCall;
+import org.web3j.protocol.core.methods.response.TransactionReceipt;
+import org.web3j.tx.Contract;
+import org.web3j.tx.TransactionManager;
+import org.web3j.tx.gas.ContractGasProvider;
+
+/**
+ * <p>Auto generated code.
+ * <p><strong>Do not modify!</strong>
+ * <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>,
+ * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the 
+ * <a href="https://github.com/web3j/web3j/tree/main/codegen">codegen module</a> to update.
+ *
+ * <p>Generated with web3j version none.
+ */
+@SuppressWarnings("rawtypes")
+public class StaticArrayOfStructsInStruct extends Contract {
+    public static final String BINARY = "608060405234801561000f575f80fd5b5060c58061001c5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80639acc3bf114602a575b5f80fd5b60406004803603810190603c91906069565b6042565b005b5f80fd5b5f80fd5b5f80fd5b5f60a08284031215606057605f604a565b5b81905092915050565b5f60a08284031215607b57607a6046565b5b5f608684828501604e565b9150509291505056fea2646970667358221220a67d48af17079065cb181167be61364e31cd9d588c89b4a1ca7ceb1a9bf640a864736f6c63430008140033";
+
+    private static String librariesLinkedBinary;
+
+    public static final String FUNC_TEST = "test";
+
+    @Deprecated
+    protected StaticArrayOfStructsInStruct(String contractAddress, Web3j web3j,
+            Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
+        super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
+    }
+
+    protected StaticArrayOfStructsInStruct(String contractAddress, Web3j web3j,
+            Credentials credentials, ContractGasProvider contractGasProvider) {
+        super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
+    }
+
+    @Deprecated
+    protected StaticArrayOfStructsInStruct(String contractAddress, Web3j web3j,
+            TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+        super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
+    }
+
+    protected StaticArrayOfStructsInStruct(String contractAddress, Web3j web3j,
+            TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
+        super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
+    }
+
+    public RemoteFunctionCall<TransactionReceipt> test(Config config) {
+        final Function function = new Function(
+                FUNC_TEST, 
+                Arrays.<Type>asList(config), 
+                Collections.<TypeReference<?>>emptyList());
+        return executeRemoteCallTransaction(function);
+    }
+
+    @Deprecated
+    public static StaticArrayOfStructsInStruct load(String contractAddress, Web3j web3j,
+            Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
+        return new StaticArrayOfStructsInStruct(contractAddress, web3j, credentials, gasPrice, gasLimit);
+    }
+
+    @Deprecated
+    public static StaticArrayOfStructsInStruct load(String contractAddress, Web3j web3j,
+            TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+        return new StaticArrayOfStructsInStruct(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
+    }
+
+    public static StaticArrayOfStructsInStruct load(String contractAddress, Web3j web3j,
+            Credentials credentials, ContractGasProvider contractGasProvider) {
+        return new StaticArrayOfStructsInStruct(contractAddress, web3j, credentials, contractGasProvider);
+    }
+
+    public static StaticArrayOfStructsInStruct load(String contractAddress, Web3j web3j,
+            TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
+        return new StaticArrayOfStructsInStruct(contractAddress, web3j, transactionManager, contractGasProvider);
+    }
+
+    public static RemoteCall<StaticArrayOfStructsInStruct> deploy(Web3j web3j,
+            Credentials credentials, ContractGasProvider contractGasProvider) {
+        return deployRemoteCall(StaticArrayOfStructsInStruct.class, web3j, credentials, contractGasProvider, getDeploymentBinary(), "");
+    }
+
+    @Deprecated
+    public static RemoteCall<StaticArrayOfStructsInStruct> deploy(Web3j web3j,
+            Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
+        return deployRemoteCall(StaticArrayOfStructsInStruct.class, web3j, credentials, gasPrice, gasLimit, getDeploymentBinary(), "");
+    }
+
+    public static RemoteCall<StaticArrayOfStructsInStruct> deploy(Web3j web3j,
+            TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
+        return deployRemoteCall(StaticArrayOfStructsInStruct.class, web3j, transactionManager, contractGasProvider, getDeploymentBinary(), "");
+    }
+
+    @Deprecated
+    public static RemoteCall<StaticArrayOfStructsInStruct> deploy(Web3j web3j,
+            TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+        return deployRemoteCall(StaticArrayOfStructsInStruct.class, web3j, transactionManager, gasPrice, gasLimit, getDeploymentBinary(), "");
+    }
+
+    public static void linkLibraries(List<Contract.LinkReference> references) {
+        librariesLinkedBinary = linkBinaryWithReferences(BINARY, references);
+    }
+
+    private static String getDeploymentBinary() {
+        if (librariesLinkedBinary != null) {
+            return librariesLinkedBinary;
+        } else {
+            return BINARY;
+        }
+    }
+
+    public static class Player extends StaticStruct {
+        public String addr;
+
+        public BigInteger timeLeft;
+
+        public Player(String addr, BigInteger timeLeft) {
+            super(new org.web3j.abi.datatypes.Address(160, addr), 
+                    new org.web3j.abi.datatypes.generated.Uint256(timeLeft));
+            this.addr = addr;
+            this.timeLeft = timeLeft;
+        }
+
+        public Player(Address addr, Uint256 timeLeft) {
+            super(addr, timeLeft);
+            this.addr = addr.getValue();
+            this.timeLeft = timeLeft.getValue();
+        }
+    }
+
+    public static class Config extends StaticStruct {
+        public BigInteger index;
+
+        public List<Player> players;
+
+        public Config(BigInteger index, List<Player> players) {
+            super(new org.web3j.abi.datatypes.generated.Uint64(index), 
+                    new org.web3j.abi.datatypes.generated.StaticArray2<Player>(Player.class, players));
+            this.index = index;
+            this.players = players;
+        }
+
+        public Config(Uint64 index,
+                @Parameterized(type = Player.class) StaticArray2<Player> players) {
+            super(index, players);
+            this.index = index.getValue();
+            this.players = players.getValue();
+        }
+    }
+}
+