web3j
web3j copied to clipboard
`Unsupported type encountered: tuple` when trying to create contract wrapper
Tuple types don't seem to be supported
When trying to create a contract wrapper with web3j generate solidity generate --abiFile=myJson.json --outputDir=src/java/ --package=my.package
, i run into this error:
Unsupported type encountered: tuple
What is the status regarding this, is supporting tuples on the roadmap?
Example snippet from the abi:
...
{"constant":false,"inputs":[{"components":[{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"address","name":"takerAddress","type":"address"},{"internalType":"address","name":"feeRecipientAddress","type":"address"},{"internalType":"address","name":"senderAddress","type":"address"},{"internalType":"uint256","name":"makerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"takerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"makerFee","type":"uint256"},{"internalType":"uint256","name":"takerFee","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"},{"internalType":"bytes","name":"makerFeeAssetData","type":"bytes"},{"internalType":"bytes","name":"takerFeeAssetData","type":"bytes"}],"internalType":"struct LibOrder.Order[]","name":"orders","type":"tuple[]"}],"name":"batchCancelOrders","outputs":[],"payable":true,"stateMutability":"payable","type":"function"}
...
I also have this problem. How can I solve it?
Same here. I read that it was fixed and merged in new versions but even if I'm using v4.8.4 of web3j, it still doesn't support tuples. I don't think that's the case but for your information, I'm trying to generate wrappers via Gradle and my development environment is on WSL. How can we solve this problem?
I tried to simplify the contract I wrote here:
pragma solidity >=0.6.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/math/SafeMath.sol";
contract Wallet {
using SafeMath for uint;
struct Consumer {
string id;
Item[] itemStructs;
}
struct Item {
string itemId;
uint quantity;
}
mapping (address => Consumer) public consumers;
mapping (address => mapping(string => bool)) public containsItem;
function addItemToWallet(address _address, Item memory _item) public {
Consumer storage consumer = consumers[_address];
bool isAdded = false;
for (uint i = 0; i<consumer.itemStructs.length; i++) {
if (keccak256(bytes(consumer.itemStructs[i].itemId)) == keccak256(bytes(_item.itemId))) {
require(containsItem[_address][_item.itemId] = true);
consumer.itemStructs[i].quantity = consumer.itemStructs[i].quantity.add(_item.quantity);
isAdded = true;
}
}
if (isAdded == false) {
consumer.itemStructs.push(_item);
containsItem[_address][_item.itemId] = true;
}
}
}
It also gives this error when I run ./gradlew generateContractWrappers:
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :compileSolidity
Compiler run successful. Artifact(s) can be found in directory build/resources/main/solidity.
The message received from the daemon indicates that the daemon has disappeared.
Build request sent: Build{id=7484af22-3964-481c-874c-272d0ec2aabb, currentDir=/home/kay/ethereum-projects/loyalty-solidity-smart-contracts}
Attempting to read last messages from the daemon log...
Daemon pid: 19295
log file: /home/kay/.gradle/daemon/6.8.2/daemon-19295.out.log
----- Last 20 lines from daemon log file - daemon-19295.out.log -----
2021-02-19T16:01:08.687+0300 [DEBUG] [org.gradle.launcher.daemon.server.DefaultIncomingConnectionHandler] Starting executing command: Build{id=7484af22-3964-481c-874c-272d0ec2aabb, currentDir=/home/kay/ethereum-projects/loyalty-solidity-smart-contracts} with connection: socket connection from /127.0.0.1:41293 to /127.0.0.1:56444.
2021-02-19T16:01:08.691+0300 [ERROR] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] Command execution: started DaemonCommandExecution[command = Build{id=7484af22-3964-481c-874c-272d0ec2aabb, currentDir=/home/kay/ethereum-projects/loyalty-solidity-smart-contracts}, connection = DefaultDaemonConnection: socket connection from /127.0.0.1:41293 to /127.0.0.1:56444] after 0.0 minutes of idle
2021-02-19T16:01:08.691+0300 [INFO] [org.gradle.launcher.daemon.server.DaemonRegistryUpdater] Marking the daemon as busy, address: [3311916f-d332-4e8d-8b27-bbbb224fb970 port:41293, addresses:[localhost/127.0.0.1]]
2021-02-19T16:01:08.692+0300 [DEBUG] [org.gradle.launcher.daemon.registry.PersistentDaemonRegistry] Marking busy by address: [3311916f-d332-4e8d-8b27-bbbb224fb970 port:41293, addresses:[localhost/127.0.0.1]]
2021-02-19T16:01:08.696+0300 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire exclusive lock on daemon addresses registry.
2021-02-19T16:01:08.700+0300 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
2021-02-19T16:01:08.701+0300 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
2021-02-19T16:01:08.702+0300 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] resetting idle timer
2021-02-19T16:01:08.702+0300 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] daemon is running. Sleeping until state changes.
2021-02-19T16:01:08.704+0300 [INFO] [org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy] Daemon is about to start building Build{id=7484af22-3964-481c-874c-272d0ec2aabb, currentDir=/home/kay/ethereum-projects/loyalty-solidity-smart-contracts}. Dispatching build started information...
2021-02-19T16:01:08.705+0300 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 19: dispatching org.gradle.launcher.daemon.protocol.BuildStarted@1870be57
2021-02-19T16:01:08.708+0300 [DEBUG] [org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment] Configuring env variables: [PATH, LESSCLOSE, BROWSER, XDG_DATA_DIRS, TERM, LANG, VSCODE_GIT_IPC_HANDLE, PIPE_LOGGING, VSCODE_GIT_ASKPASS_MAIN, NVM_INC, COLORTERM, VSCODE_IPC_HOOK_CLI, LOGNAME, VSCODE_GIT_ASKPASS_NODE, PWD, TERM_PROGRAM_VERSION, GIT_ASKPASS, USES_VSCODE_SERVER_SPAWN, AMD_ENTRYPOINT, _, NVM_CD_FLAGS, SHELL, NVM_DIR, LESSOPEN, WSL_INTEROP, WSL_DISTRO_NAME, TERM_PROGRAM, HOSTTYPE, GOPATH, OLDPWD, USER, GOROOT, NAME, WSLENV, VERBOSE_LOGGING, LS_COLORS, NVM_BIN, HOME, SHLVL]
2021-02-19T16:01:08.719+0300 [DEBUG] [org.gradle.launcher.daemon.server.exec.LogToClient] About to start relaying all logs to the client via the connection.
2021-02-19T16:01:08.719+0300 [INFO] [org.gradle.launcher.daemon.server.exec.LogToClient] The client will now receive all logging from the daemon (pid: 19295). The daemon log file: /home/kay/.gradle/daemon/6.8.2/daemon-19295.out.log
2021-02-19T16:01:08.721+0300 [INFO] [org.gradle.launcher.daemon.server.exec.LogAndCheckHealth] Starting build in new daemon [memory: 512 MiB]
2021-02-19T16:01:08.734+0300 [DEBUG] [org.gradle.launcher.daemon.server.exec.ExecuteBuild] The daemon has started executing the build.
2021-02-19T16:01:08.734+0300 [DEBUG] [org.gradle.launcher.daemon.server.exec.ExecuteBuild] Executing build with daemon context: DefaultDaemonContext[uid=5dacd15e-f5c8-45a5-a2ea-e83282cbe123,javaHome=/usr/lib/jvm/java-11-openjdk-amd64,daemonRegistryDir=/home/kay/.gradle/daemon,pid=19295,idleTimeout=10800000,priority=NORMAL,daemonOpts=--add-opens,java.base/java.util=ALL-UNNAMED,--add-opens,java.base/java.lang=ALL-UNNAMED,--add-opens,java.base/java.lang.invoke=ALL-UNNAMED,--add-opens,java.prefs/java.util.prefs=ALL-UNNAMED,-XX:MaxMetaspaceSize=256m,-XX:+HeapDumpOnOutOfMemoryError,-Xms256m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country,-Duser.language=en,-Duser.variant]
Compiler run successful. Artifact(s) can be found in directory build/resources/main/solidity.
Unsupported type encountered: tuple
Daemon vm is shutting down... The daemon has exited normally or was terminated in response to a user interrupt.
----- End of the daemon log -----
FAILURE: Build failed with an exception.
* What went wrong:
Gradle build daemon disappeared unexpectedly (it may have been killed or may have crashed)
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
> Task :generateContractWrappers
Unsupported type encountered: tuple
Hope you guys can help us with it, thanks in advance!
@kalekale hi, from the commands you used to generate the wrappers I can see you are using an older version of the CLI. I would recommend you delete the .web3
j directory and download web3j once more the new command is web3j generate solidity ....
.
@kerimay hi, I used the contract that you provided and I was able to generate the wrappers fine I will dig deeper into the Gradle logs you provided to check what exactly the issue might be.
@kalekale hi, from the commands you used to generate the wrappers I can see you are using an older version of the CLI. I would recommend you delete the
.web3
j directory and download web3j once more the new command isweb3j generate solidity ....
.@kerimay hi, I used the contract that you provided and I was able to generate the wrappers fine I will dig deeper into the Gradle logs you provided to check what exactly the issue might be.
I figured out that my general Gradle version on WSL wasn't updated and also, I had a special case with my contract. Except the method I provided here, I also had a function like this:
function getConsumerData(address _address) public view returns (Consumer memory) {
return consumers[_address];
}
It was working on Remix IDE but maybe it was a bad practice I don't know, this caused the main issue on my case. Other functions with tuples worked well. Thank you for your attention @AlexandrouR
@kerimay I do get the same issue when I try to generate the wrappers after adding the function, however, I can't compile this in Remix as I get this Invalid input source specified.
Interesting, because I can compile and deploy it in Remix with no issue. Is it maybe because of compiler version? Mine was 0.7.4
Just encountered the same problem while trying to build a wrapper.
Here is minimal example in solidity that fails.
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
contract Hello {
struct Input {
FooInput[] some;
}
struct FooInput {
address someAddr;
BarInput[] barInputs;
}
struct BarInput {
uint8 xyz;
}
function foo(Input memory output) public pure returns (bool){
return true;
}
}
Then I used solcjs and web3j to build a wrapper:
$ solcjs -V
0.6.0+commit.26b70077.Emscripten.clang
$ web3j -v
...
by Web3Labs
Version: 1.4.1
Build timestamp: 2021-02-16 20:28:33.742 UTC
$ solcjs --bin --abi --optimize hello.sol -o bb
hello.sol:19:14: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
function foo(Input memory output) public pure returns (bool){
^-----------------^
$ web3j generate solidity --abiFile=bb/hello_sol_Hello.abi -o java -p foo.bar
by Web3Labs
Generating foo.bar.Hello_sol_Hello ... Unsupported type encountered: tuple
Please advise how to tackle this problem?
Have the same problem: solc 0.8.2, web3j-cli 1.4.1
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.2;
contract Multicall {
struct Call {
address target;
bytes callData;
}
function aggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes[] memory returnData) {
blockNumber = block.number;
returnData = new bytes[](calls.length);
for(uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
require(success);
returnData[i] = ret;
}
}
}
$ solcjs Multicall.sol --optimize --bin --abi -o ./ $ web3j solidity generate -b Multicall_sol_Multicall.bin -a Multicall_sol_Multicall.abi -p cc -o ./ .. Generating cc.Multicall_sol_Multicall ... Unsupported type encountered: tuple
using maven plugin with web3j 5.0.0
- same issue with tuples when trying to compile an interface with a struct as param.
Whats the solution here? Provider is 3rd party. How can i provide structs manually?
referencing also https://github.com/web3j/web3j/issues/653 i stumbled upon - sadly web3j doesnt support more recent solidity versions like 0.8 - how to use another solc with web3j?
pragma solidity >=0.7.0;
pragma experimental ABIEncoderV2;
interface SomeInterface {
struct SomeStruct {
address addressA;
address addressB;
}
function someFunction(SomeStruct calldata params) external payable returns (uint256 result);
}
Code to produce the error
@BarBozz web3j:5.0.0
was a mistake release. The latest version of web3j currently is 4.8.4
where tuples are supported to some extent.
@MajdT51 and @lukoyanov The current generator still don't support structs containing addresses and list of structs. Will be added in the next release.
Hello @SweeXordious, is this feature still under development or already released?
@kristianstoinov try the latest release please and see. If it's still not working, then nobody picked it up so far.
I tried the latest version and it still has this issue.
@njovy Which version did you try exactly ?
@SweeXordious I used the latest web3j-cli which is 1.4.1 and this version uses 4.8.4
_ _____ _
| | |____ (_)
__ _____| |__ / /_
\ \ /\ / / _ \ '_ \ \ \ |
\ V V / __/ |_) |.___/ / |
\_/\_/ \___|_.__/ \____/| |
_/ |
|__/
by Web3Labs
Version: 1.4.1
Build timestamp: 2021-02-16 20:28:33.742 UTC
The error message says Unsupported type encountered: tuple
. I believe this is misleading because it does generate a simple tuple type. This error occurred because of an array of tuple type, tuple[]
.
I am checking the history of commits. There are multiple commits which touch on tuples. Howverr, we need a new web3j-cli release using latest master to see if this is covered or not. Maybe you can try creating a web3j-cli binary locally targeting latest master manually and see if the problem persists. Thanks.
I just built the latest master branch of the web3j-cli it's not able to generate structs just yet...
@davida5 did you change the following line: https://github.com/web3j/web3j-cli/blob/45c2e095c6fed724b7ab32d97bbd03b6cfea91ae/build.gradle#L22 to:
web3jVersion = '4.9.1'
?
@SweeXordious thanks, after changing the version as suggested it worked, the struct was generated as : MyClass extends StaticStruct
.
Also I had to change the the generated web3j script --- the "lib" in the classpath is now called "libs" ----
Awesome. I will open an issue under web3j-cli to create a new release.
I am checking the history of commits. There are multiple commits which touch on tuples. Howverr, we need a new web3j-cli release using latest master to see if this is covered or not. Maybe you can try creating a web3j-cli binary locally targeting latest master manually and see if the problem persists. Thanks.
Can you write step by step? @SweeXordious
<build>
<plugins>
<plugin>
<groupId>org.web3j</groupId>
<artifactId>web3j-maven-plugin</artifactId>
<version>4.9.4</version>
<configuration>
<soliditySourceFiles/>
</configuration>
</plugin>
</plugins>
</build>
@SweeXordious still cannot deal with turple, need help @conor10 @snazha-blkio @antonydenyer
struct A {
B[] b;
}
struct B {
uint256 b1;
address b2;
}
run with mvn web3j:generate-sources
error show:
Unsupported type encountered: tuple
Just checked, Web3J doesn't currently support structs of array of structs. That's why it's failing
Just checked, Web3J doesn't currently support structs of array of structs. That's why it's failing
sad, bro. if like that, i need try to create bytes with another lib.
Yes. I might work on this by the end of the year. But nothing promised.
Yes. I might work on this by the end of the year. But nothing promised.
I would also like to contribute. Which library do I need to look at regarding this part of the modification?
That would be really awesome if you could work on this.
The concerned modules are:
- abi: contains the encoder/decoder for all types. This is where the encoding logic should be.
- codegen: contains the Java wrapper code generator for the smart contracts.
The implementation should start at the abi
module and have tests for different cases, mainly structs containing array of structs. And, after all of this is working, the codegen
should be updated accordingly.
The abi
part is hardest and might require some refactors.
You can be inspired from the following PRs as they touch on this:
When web3J support structs of array of structs @SweeXordious?
I really need generate wrapper this abi, currently still error on web3j-cli version: 1.4.2
[
{
"inputs": [
{
"internalType": "uint256",
"name": "_expectedState",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_settlePrice",
"type": "uint256"
},
{
"internalType": "address",
"name": "_referralAddr",
"type": "address"
},
{
"internalType": "bytes",
"name": "_signature",
"type": "bytes"
},
{
"components": [
{
"internalType": "address",
"name": "maker",
"type": "address"
},
{
"internalType": "enum MarketOrder.OrderKind",
"name": "kind",
"type": "uint8"
},
{
"components": [
{
"internalType": "enum MarketAsset.TokenStandard",
"name": "erc",
"type": "uint8"
},
{
"internalType": "address",
"name": "addr",
"type": "address"
},
{
"internalType": "uint256",
"name": "id",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "quantity",
"type": "uint256"
}
],
"internalType": "struct MarketAsset.Asset[]",
"name": "assets",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "expiredAt",
"type": "uint256"
},
{
"internalType": "address",
"name": "paymentToken",
"type": "address"
},
{
"internalType": "uint256",
"name": "startedAt",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "basePrice",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "endedAt",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "endedPrice",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "expectedState",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "nonce",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "marketFeePercentage",
"type": "uint256"
}
],
"internalType": "struct MarketOrder.Order",
"name": "_order",
"type": "tuple"
}
],
"name": "settleOrder",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]