hyperledger / web3j

Lightweight Java and Android library for integration with Ethereum clients
https://www.web3labs.com/web3j-sdk
Other
5.04k stars 1.67k forks source link

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

Closed kalekale closed 1 year ago

kalekale commented 3 years ago

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"}
...
katoyi120 commented 3 years ago

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

kerimay commented 3 years ago

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!

AlexandrouR commented 3 years ago

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

kerimay commented 3 years ago

@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

AlexandrouR commented 3 years ago

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

kerimay commented 3 years ago

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

lukoyanov commented 3 years ago

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?

MajdT51 commented 3 years ago

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

BarBozz commented 3 years ago

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?

BarBozz commented 3 years ago

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

rach-id commented 3 years ago

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

kristianstoinov commented 2 years ago

Hello @SweeXordious, is this feature still under development or already released?

rach-id commented 2 years ago

@kristianstoinov try the latest release please and see. If it's still not working, then nobody picked it up so far.

njovy commented 2 years ago

I tried the latest version and it still has this issue.

rach-id commented 2 years ago

@njovy Which version did you try exactly ?

njovy commented 2 years ago

@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[].

rach-id commented 2 years ago

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.

davida5 commented 2 years ago

I just built the latest master branch of the web3j-cli it's not able to generate structs just yet...

rach-id commented 2 years ago

@davida5 did you change the following line: https://github.com/web3j/web3j-cli/blob/45c2e095c6fed724b7ab32d97bbd03b6cfea91ae/build.gradle#L22 to:

web3jVersion = '4.9.1'

?

davida5 commented 2 years ago

@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" ----

rach-id commented 2 years ago

Awesome. I will open an issue under web3j-cli to create a new release.

tonghoang196 commented 1 year ago

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

leiiiooo commented 1 year ago
<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

rach-id commented 1 year ago

Just checked, Web3J doesn't currently support structs of array of structs. That's why it's failing

leiiiooo commented 1 year ago

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.

rach-id commented 1 year ago

Yes. I might work on this by the end of the year. But nothing promised.

leiiiooo commented 1 year ago

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?

rach-id commented 1 year ago

That would be really awesome if you could work on this.

The concerned modules are:

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:

tonghoang196 commented 1 year ago

When web3J support structs of array of structs @SweeXordious?

tonghoang196 commented 1 year ago

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"
  }
]
Lokuslick commented 1 year ago

Whenever there is a tuple in ABI its not generating the proper wrapper class. Any updates on when this will be resolved?

tonghoang196 commented 1 year ago

Whenever there is a tuple in ABI its not generating the proper wrapper class. Any updates on when this will be resolved?

they haven't worked for a long time, i think you should switch to using web3 (python) or ethers (nodejs)

NickSneo commented 1 year ago

We are working on this. @lukoyanov @MajdT51 @kerimay I tried to compile and generate abi and java wrappers for your provided Solidity code using latest web3j release, seems it is working fine for me. I didn't get any Unsupported type encountered: tuple when trying to create contract wrapper. This issue was fixed with PR - https://github.com/web3j/web3j/pull/1738

@tonghoang196 Can you please elaborate what issue you are facing and provide the solidity code for your abi so we can look into it.

Kindly all generate java wrappers using latest web3j and let us know if anything fails. For web3j-cli, we will soon have a new release with latest web3j version i.e. 4.10.0

NickSneo commented 1 year ago

Web3j-cli and solidity Gradle plugin released, issue is fixed. Closing the ticket