FunctionEncoder.buildMethodSignature generates incorrect signature
FunctionEncoder.buildMethodSignature generates incorrect signature
When building a signature for a method that accepts dynamic arrays, buildMethodSignature includes the string literal dynamicarray in the signature instead of the correct parameter type, such as bytes[].
Steps To Reproduce
Consider the following Solidity struct:
struct Offer {
bool isCreated;
bool isTaken;
address maker;
bytes interfaceId;
address stablecoin;
uint256 amountLowerBound;
uint256 amountUpperBound;
uint256 securityDepositAmount;
SwapDirection direction;
bytes price;
bytes[] settlementMethods;
uint256 protocolVersion;
bytes32 extraData;
}
and consider the following Solidity function:
function openOffer(bytes16 offerID, Offer memory newOffer) public {
//Actual function implementation not relevant
}
Create a basic contract containing this struct and function, and use Web3J to generate a wrapper for it. Deploy the contract on a test blockchain, and then try to call the openOffer method of the generated contract wrapper.
Expected behavior
The function call is successful.
Actual behavior
The function call reverts without giving a reason string.
Environment
- Web3j version: Recent clone from master branch
- Java Version (not Android): Temurin 11 LTS (jdk-11.0.13+8 for macOS x64 Intel)
- Operating System: macOS 12.0.1 Monterey
Additional context
In the process of calling openOffer, buildMethodSignature generates the following string to be hashed in order to obtain the method signature:
openOffer(bytes16(bool,bool,address,bytes,address,uint256,uint256,uint256,uint8,bytes,dynamicarray,uint256,bytes32))
which produces the following method signature: 5c3952db. This is obviously wrong, as Solidity has no type named dynamicarray, and thus the function call will revert. The correct method signature is 23cd78c0, and this can be obtained by replacing dynamicarray in the previous string with bytes[] to produce the string:
openOffer(bytes16,(bool,bool,address,bytes,address,uint256,uint256,uint256,uint8,bytes,bytes[],uint256,bytes32))
When buildMethodSignature is replaced with the following:
protected static String buildMethodSignature(
final String methodName, final List<Type> parameters) {
if (methodName == "openOffer") {
return "openOffer(bytes16,(bool,bool,address,bytes,address,uint256,uint256,uint256,uint8,bytes,bytes[],uint256,bytes32))";
}
final StringBuilder result = new StringBuilder();
result.append(methodName);
result.append("(");
final String params =
parameters.stream().map(Type::getTypeAsString).collect(Collectors.joining(","));
result.append(params);
result.append(")");
return result.toString();
}
the function call succeeds.
Hi everyone.I encountered the same problem with version 4.8.6. I rewrote part of the code to make sure it works properly, I put the modified code below, hope it can help someone who needs it.
public class MyDynamicStruct extends DynamicStruct {
public MyDynamicStruct(List<Type> values) {
super(values);
}
public MyDynamicStruct(Type... values) {
super(values);
}
public MyDynamicStruct(Class<Type> type, Type... values) {
super(type, values);
}
@Override
@SneakyThrows
public String getTypeAsString() {
final StringBuilder type = new StringBuilder("(");
Field itemTypesField = DynamicStruct.class.getDeclaredField("itemTypes");
itemTypesField.setAccessible(true);
List<Class<Type>> itemTypes = (List<Class<Type>>) itemTypesField.get(this);
for (int i = 0; i < itemTypes.size(); ++i) {
final Class<Type> cls = itemTypes.get(i);
if (StructType.class.isAssignableFrom(cls)) {
type.append(getValue().get(i).getTypeAsString());
} else if (Array.class.isAssignableFrom(cls)) {
type.append(getValue().get(i).getTypeAsString());
} else {
type.append(AbiTypes.getTypeAString(cls));
}
if (i < itemTypes.size() - 1) {
type.append(",");
}
}
type.append(")");
return type.toString();
}
}
Finally, replace the "DynamicStruct" in the swapper class and you're good to go. Maybe you also need to modify the DynamicArray link
I faced this issue too,when will offical fix and publish a new version?
Solved after merging #1526.