Wrapper Generation with Array of Structs Parameter
Wrapper Generation with Array of Structs Parameter
web3j generates a broken contract wrapper when a function contains a parameter which is an array of structs
Steps To Reproduce
pragma solidity ^0.8.6;
pragma experimental ABIEncoderV2;
contract Test {
struct Pair {
uint256 a;
uint256 b;
}
function add(Pair[] calldata pairs) external pure returns (uint256){
return pairs[0].a + pairs[0].b;
}
}
Expected behavior
The wrapper should be generated correctly
Actual behavior
The wrapper does not generate the Pair class as expected. The wrapper also uses org.web3j.abi.Utils.typeMap(pairs, Pair.class) instead of pairs.
public RemoteFunctionCall<BigInteger> add(List<Pair> pairs) {
final Function function = new Function(FUNC_ADD,
Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicArray<Pair>(
Pair.class,
org.web3j.abi.Utils.typeMap(pairs, Pair.class))),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
return executeRemoteCallSingleValueReturn(function, BigInteger.class);
}
Environment
Describe the environment in which the issue occurs
- Web3j version 1.4.1
Additional context
Add any other context about the problem here.
I can confirm this.
I'm facing this error too.
I have same error
With latest web3j version 4.10.3 - I tried generating java wrapper for the code you provided -
pragma solidity ^0.8.6;
pragma experimental ABIEncoderV2;
contract Test {
struct Pair {
uint256 a;
uint256 b;
}
function add(Pair[] calldata pairs) external pure returns (uint256){
return pairs[0].a + pairs[0].b;
}
}
The Pair class generated -
public static class Pair extends StaticStruct {
public BigInteger a;
public BigInteger b;
public Pair(BigInteger a, BigInteger b) {
super(new org.web3j.abi.datatypes.generated.Uint256(a),
new org.web3j.abi.datatypes.generated.Uint256(b));
this.a = a;
this.b = b;
}
public Pair(Uint256 a, Uint256 b) {
super(a, b);
this.a = a.getValue();
this.b = b.getValue();
}
}
The add function generated -
public RemoteFunctionCall<BigInteger> add(List<Pair> pairs) {
final Function function = new Function(FUNC_ADD,
Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicArray<Pair>(Pair.class, pairs)),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
return executeRemoteCallSingleValueReturn(function, BigInteger.class);
}
These seems correct to me.
I am able to deploy the contract and call the add function too using web3j and Besu private QBFT network. Code for reference -
Credentials credentials = Credentials.create(privKey);
Web3j web3j = Web3j.build(new HttpService(nodeUrl));
System.out.println("\nDeploying ArrayOfStructs contract ...");
ArrayOfStructs arrayOfStructs = ArrayOfStructs.deploy(web3j, credentials, new StaticGasProvider(BigInteger.valueOf(4_100_000_000L),BigInteger.valueOf(9_000_000L))).send();
System.out.println("Contract address: " + arrayOfStructs.getContractAddress());
System.out.println("ArrayOfStructs addition method result: " + arrayOfStructs.add(List.of(new ArrayOfStructs.Pair(BigInteger.ONE, BigInteger.TWO))).send());
Closing this ticket, in case someone still faces a issue with Array of Structs plz reopen the ticket.