Web3j: `Unsupported type encountered: tuple` when trying to create contract wrapper

Created on 31 Jan 2021  路  8Comments  路  Source: web3j/web3j

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"}
...
needs-review

Most helpful comment

I also have this problem. How can I solve it?

All 8 comments

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 .web3j 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 .web3j 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.

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

parcool picture parcool  路  6Comments

githubityu picture githubityu  路  5Comments

s1r-mar71n picture s1r-mar71n  路  5Comments

xtuyaowu picture xtuyaowu  路  8Comments

ligi picture ligi  路  3Comments