-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Big fix for codegen when Array of struct and struct used together #2068
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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[") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Main change is to add handling for static array in |
||
&& 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")); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was added in my previous PR merged https://github.com/hyperledger/web3j/pull/2061/files#diff-11944d4d901c6c86e0bb4f4bb1af18f9b3644a325a39e7cc7437878613330294R590 However, after fixing |
||
.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(); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +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"}] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
608060405234801561000f575f80fd5b5061014f8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80631ae18a6414610038578063f0cd1e3b14610054575b5f80fd5b610052600480360381019061004d91906100a1565b610070565b005b61006e600480360381019061006991906100ee565b610074565b005b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f8190508260206002028201111561009b5761009a61007c565b5b92915050565b5f604082840312156100b6576100b5610078565b5b5f6100c384828501610080565b91505092915050565b5f80fd5b5f602082840312156100e5576100e46100cc565b5b81905092915050565b5f6020828403121561010357610102610078565b5b5f610110848285016100d0565b9150509291505056fea2646970667358221220deb8c438006301a2bb5f5ed22ad6516a4f075c63a360dad46a6571057187273164736f6c63430008140033 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +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"}] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
608060405234801561000f575f80fd5b5060c58061001c5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80639acc3bf114602a575b5f80fd5b60406004803603810190603c91906069565b6042565b005b5f80fd5b5f80fd5b5f80fd5b5f60a08284031215606057605f604a565b5b81905092915050565b5f60a08284031215607b57607a6046565b5b5f608684828501604e565b9150509291505056fea2646970667358221220a67d48af17079065cb181167be61364e31cd9d588c89b4a1ca7ceb1a9bf640a864736f6c63430008140033 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was added in my previous PR merged https://github.com/hyperledger/web3j/pull/2061/files#diff-11944d4d901c6c86e0bb4f4bb1af18f9b3644a325a39e7cc7437878613330294R590
However, after fixing
normalizeNamedType
to handle static array, this is no longer needed, although there is no harm to leave it there