-
-
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
Handle ABI V2 nested array case #1726
Comments
The first step to solve this would be to add this ABI definition to the This would add the above to the test cases we can work with. After finishing with this, and having encoding decoding tests working. Move on to the codegen module. And, following the same above way, add the tests and see where the problem is happening. This PR should be your reference for changes #1321 as it is doing almost the same thing to implement support for struct arrays support. |
{
"inputs": [{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}],
"name": "getPlayerWork",
"outputs": [{
"components": [{
"internalType": "address",
"name": "workType",
"type": "address"
}, {
"internalType": "address",
"name": "owner",
"type": "address"
}, {
"internalType": "uint256[]",
"name": "blocks",
"type": "uint256[]"
}],
"internalType": "struct Mining.PlayerWork",
"name": "",
"type": "tuple"
}],
"stateMutability": "view",
"type": "function"
} I still don't understand what you mean, how to write this output parameter? |
If I understand right, you will write your own Foo, call it something I don't know, that has the same ABI definition as the one above and test against it. |
public static class PlayerWork extends DynamicStruct {
public String workType;
public String careerAddr;
public BigInteger startTime;
public BigInteger endTime;
public String owner;
public List<BigInteger> blocks;
public BigInteger beginTime;
public PlayerWork(String workType, String careerAddr, BigInteger startTime, BigInteger endTime, String owner, List<BigInteger> blocks, BigInteger beginTime) {
super(new org.web3j.abi.datatypes.Address(160, workType),
new org.web3j.abi.datatypes.Address(160, careerAddr),
new org.web3j.abi.datatypes.generated.Uint256(startTime),
new org.web3j.abi.datatypes.generated.Uint256(endTime),
new org.web3j.abi.datatypes.Address(160, owner),
new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.generated.Uint256>(
org.web3j.abi.datatypes.generated.Uint256.class,
org.web3j.abi.Utils.typeMap(blocks, org.web3j.abi.datatypes.generated.Uint256.class)),
new org.web3j.abi.datatypes.generated.Uint256(beginTime));
this.workType = workType;
this.careerAddr = careerAddr;
this.startTime = startTime;
this.endTime = endTime;
this.owner = owner;
this.blocks = blocks;
this.beginTime = beginTime;
}
public PlayerWork(Address workType, Address careerAddr, Uint256 startTime, Uint256 endTime, Address owner, DynamicArray<Uint256> blocks, Uint256 beginTime) {
super(workType, careerAddr, startTime, endTime, owner, blocks, beginTime);
this.workType = workType.getValue();
this.careerAddr = careerAddr.getValue();
this.startTime = startTime.getValue();
this.endTime = endTime.getValue();
this.owner = owner.getValue();
this.blocks = blocks.getValue().stream().map(v -> v.getValue()).collect(Collectors.toList());
this.beginTime = beginTime.getValue();
}
} This will throw an exception |
How did you generate this? |
public static void generateClass(String abiFile,String generateFile){
String[] args = Arrays.asList(
"-a",abiFile,
"-p","cn.contract",
"-o",generateFile
).toArray(new String[0]);
Stream.of(args).forEach(System.out::println);
SolidityFunctionWrapperGenerator.main(args);
} |
org.web3j codegen 4.9.2 |
And what do you run to get the exception? |
Thanks, but what are you running here? |
Can you provide a command or some code that throw this exception? |
Also, you can use permalink to share lines of code. And, code blocks for code blocks for a more readable discussion. |
As long as the tuple contains an array of output parameters, an exception will occur. |
[{
"inputs": [{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}],
"name": "getPlayerWork",
"outputs": [{
"components": [{
"internalType": "address",
"name": "workType",
"type": "address"
}, {
"internalType": "address",
"name": "careerAddr",
"type": "address"
}, {
"internalType": "uint256",
"name": "startTime",
"type": "uint256"
}, {
"internalType": "uint256",
"name": "endTime",
"type": "uint256"
}, {
"internalType": "address",
"name": "owner",
"type": "address"
}, {
"internalType": "uint256[]",
"name": "blocks",
"type": "uint256[]"
}, {
"internalType": "uint256",
"name": "beginTime",
"type": "uint256"
}],
"internalType": "struct Mining.PlayerWork",
"name": "",
"type": "tuple"
}],
"stateMutability": "view",
"type": "function"
}] This is the abi file and the generated java file is wrong. |
package cn.contract;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.DynamicStruct;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteFunctionCall;
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/master/codegen">codegen module</a> to update.
*
* <p>Generated with web3j version 4.9.2.
*/
@SuppressWarnings("rawtypes")
public class Market extends Contract {
public static final String BINARY = "Bin file was not provided";
public static final String FUNC_GETPLAYERWORK = "getPlayerWork";
@Deprecated
protected Market(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
}
protected Market(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
}
@Deprecated
protected Market(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}
protected Market(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
}
public RemoteFunctionCall<PlayerWork> getPlayerWork(BigInteger tokenId) {
final Function function = new Function(FUNC_GETPLAYERWORK,
Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(tokenId)),
Arrays.<TypeReference<?>>asList(new TypeReference<PlayerWork>() {}));
return executeRemoteCallSingleValueReturn(function, PlayerWork.class);
}
@Deprecated
public static Market load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
return new Market(contractAddress, web3j, credentials, gasPrice, gasLimit);
}
@Deprecated
public static Market load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
return new Market(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}
public static Market load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
return new Market(contractAddress, web3j, credentials, contractGasProvider);
}
public static Market load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
return new Market(contractAddress, web3j, transactionManager, contractGasProvider);
}
public static class PlayerWork extends DynamicStruct {
public String workType;
public String careerAddr;
public BigInteger startTime;
public BigInteger endTime;
public String owner;
public List<BigInteger> blocks;
public BigInteger beginTime;
public PlayerWork(String workType, String careerAddr, BigInteger startTime, BigInteger endTime, String owner, List<BigInteger> blocks, BigInteger beginTime) {
super(new org.web3j.abi.datatypes.Address(160, workType),
new org.web3j.abi.datatypes.Address(160, careerAddr),
new org.web3j.abi.datatypes.generated.Uint256(startTime),
new org.web3j.abi.datatypes.generated.Uint256(endTime),
new org.web3j.abi.datatypes.Address(160, owner),
new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.generated.Uint256>(
org.web3j.abi.datatypes.generated.Uint256.class,
org.web3j.abi.Utils.typeMap(blocks, org.web3j.abi.datatypes.generated.Uint256.class)),
new org.web3j.abi.datatypes.generated.Uint256(beginTime));
this.workType = workType;
this.careerAddr = careerAddr;
this.startTime = startTime;
this.endTime = endTime;
this.owner = owner;
this.blocks = blocks;
this.beginTime = beginTime;
}
public PlayerWork(Address workType, Address careerAddr, Uint256 startTime, Uint256 endTime, Address owner, DynamicArray<Uint256> blocks, Uint256 beginTime) {
super(workType, careerAddr, startTime, endTime, owner, blocks, beginTime);
this.workType = workType.getValue();
this.careerAddr = careerAddr.getValue();
this.startTime = startTime.getValue();
this.endTime = endTime.getValue();
this.owner = owner.getValue();
this.blocks = blocks.getValue().stream().map(v -> v.getValue()).collect(Collectors.toList());
this.beginTime = beginTime.getValue();
}
}
} |
I agree, but we need to find a way to reproduce this to add tests for it and know what we need to implement. Then, we can work on a fix and decide whether this is a bug or a missing feature. |
Can you guys generate a java file based on the abi file I provided? |
Can you try generating it, please? And let us know the exact steps to see that exception? |
public BigInteger getPlayerWork(BigInteger tokenId) { |
} |
Write these two classes to run. |
使用 web3j1.4.1 生成java文件,支持Tuple类型 |
When the bug can be fixed? |
This complex structure also cannot be parsed |
When the bug can be fixed? |
Is there any fix for this? Hotfix or dirty way around it? |
@874341642 @metaglobal Can you provide the Solidity code for the respective abi provided? |
I tried to create a solidity code in respect to your provided abi - pragma solidity ^0.8.0;
contract Random {
struct PlayerWork {
address workType;
address owner;
uint256[] blocks;
}
function getPlayerWork(uint256 tokenId) public view returns (PlayerWork[] memory) {
PlayerWork[] memory works = new PlayerWork[](1);
works[0].workType = address(0x123);
works[0].owner = address(0x456);
works[0].blocks = new uint256[](3);
works[0].blocks[0] = 1;
works[0].blocks[1] = 2;
works[0].blocks[2] = 3;
return works;
}
} Then using web3j only I compiled and generated java wrappers. The abi generated (look at the difference, instead of tuple this one has tuple[]) - {
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getPlayerWork",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "workType",
"type": "address"
},
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "uint256[]",
"name": "blocks",
"type": "uint256[]"
}
],
"internalType": "struct Random.PlayerWork[]",
"name": "",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
} Seems it is working fine for me, can you please check? |
Closing this ticket as everything seems working fine with latest web3j 4.10.0, if someone faces any issue kindly reopen so we can discuss. |
Thanks @NickSneoI had a similar situation when the result returned with address[]Solidity Code
java code
the error i got
|
Add an annotation on the dynamicArray parameter in the constructor may helps:
@parameterized(type = Address.class) |
As discussed by @874341642 in #1321 (comment), the following ABI:
Returns the following exception:
The text was updated successfully, but these errors were encountered: