web3j icon indicating copy to clipboard operation
web3j copied to clipboard

Does Web3.j support Solidity's ABIV2?

Open fabioberger opened this issue 5 years ago • 19 comments

Many projects (including 0x) uses the somewhat new ABIV2 feature from Solidity. Does Web3.j already support contracts that use it?

For more information about ABIV2, grep for ABIEncoderV2 in the Solidity release notes or read Ethers.js's blog post about the feature.

fabioberger avatar May 20 '19 15:05 fabioberger

https://github.com/esaulpaugh/headlong supports it. I would like to see headlong incorporated into web3j at some point. Currently web3j is developing its own implementation.

esaulpaugh avatar May 26 '19 00:05 esaulpaugh

@esaulpaugh any idea if Web3.j's own implementation supports ABIV2?

fabioberger avatar May 28 '19 10:05 fabioberger

Yes, I believe this is the work in progress https://github.com/web3j/web3j/tree/feature/653-solidity-structs

esaulpaugh avatar May 28 '19 20:05 esaulpaugh

that work has gone stale - would be cool if someone can pick it up. I will probably get around to it someday but I have other priorities now.

iikirilov avatar Jul 18 '19 23:07 iikirilov

bump

any news?

hazae41 avatar Nov 02 '19 12:11 hazae41

@hazae41 relevant: https://github.com/web3j/web3j/issues/832

esaulpaugh avatar Nov 05 '19 16:11 esaulpaugh

Is there any plan to support struct arrays support as @RobertoArtiles mentioned on #1206 ? @iikirilov

Ferparishuertas avatar Dec 04 '20 12:12 Ferparishuertas

Given the interest here, I'll see what we can do to make this happen.

Let me speak with the team.

conor10 avatar Dec 07 '20 17:12 conor10

Given the interest here, I'll see what we can do to make this happen.

Let me speak with the team.

Has any progress or decision been made on this? It looks like ABIv2 is now default with the release of Solidity v0.8.0.

cryptoDevTrader avatar Dec 24 '20 17:12 cryptoDevTrader

PR #1321 has been created which adds structs array support - it would be great to get input from those on this thread to verify our test coverage is complete enough for their use case. Thanks to @SweeXordious for all the work here.

conor10 avatar Jan 03 '21 14:01 conor10

Fixed and merged 🎉 Now we have support for arrays of structs and multiple arrays of structs returns. Closing... Reopen if needed.

rach-id avatar Jan 08 '21 16:01 rach-id

Hi mates

Thanks for this functionality. It has been very helpful for us, enabling to work on a more structured language way making smart contracts more efficient and readable.

Having said that... using the feature for a while we found a bug decoding strings inside anidated structs.

With the following Smart contract

pragma solidity ^0.7.5;

pragma experimental ABIEncoderV2;

contract Web3jTest {


   struct Address {

       string city;

       string postalCode;

   }


   struct Structure {

       uint256 id;

       string description;

       Address _address;

       bytes notaryDocument;

   }

   Structure private structure;

   function set(Structure memory _structure) external returns(bool) {

       structure = _structure;

       return true;

   }


   function get() external view returns(Structure memory structure_) {

       structure_ = structure;

   }


}

To test the SC we made this quick /dirty test

try {

  Web3jTest web3jTest = Web3jTest.deploy(web3j, transactionManager, gasProvider).send();

  web3jTest.set(new Web3jTest.Structure(BigInteger.ONE, "This is a description", new Web3jTest.Address("This a city", "This is a postal code"), "This is a notarized document".getBytes(StandardCharsets.UTF_8))).send();

  Web3jTest.Structure structure = web3jTest.get().send();

  log.debug("structure: ", structure.toString());

} catch (Exception e) {

  e.printStackTrace();

}

Executing this code the error is the following

java.lang.StringIndexOutOfBoundsException: String index out of range: -234

at java.lang.String.substring(String.java:1967)

at org.web3j.abi.TypeDecoder.decodeDynamicParameterFromStruct(TypeDecoder.java:583)

at org.web3j.abi.TypeDecoder.decodeDynamicStructElements(TypeDecoder.java:546)

at org.web3j.abi.TypeDecoder.decodeDynamicStruct(TypeDecoder.java:472)

at org.web3j.abi.TypeDecoder.decodeDynamicParameterFromStruct(TypeDecoder.java:588)

at org.web3j.abi.TypeDecoder.decodeDynamicStructElements(TypeDecoder.java:546)

at org.web3j.abi.TypeDecoder.decodeDynamicStruct(TypeDecoder.java:472)

at org.web3j.abi.DefaultFunctionReturnDecoder.build(DefaultFunctionReturnDecoder.java:94)

at org.web3j.abi.DefaultFunctionReturnDecoder.decodeFunctionResult(DefaultFunctionReturnDecoder.java:52)

at org.web3j.abi.FunctionReturnDecoder.decode(FunctionReturnDecoder.java:49)

at org.web3j.tx.Contract.executeCall(Contract.java:322)

at org.web3j.tx.Contract.executeCallSingleValueReturn(Contract.java:328)

at org.web3j.tx.Contract.executeCallSingleValueReturn(Contract.java:339)

at org.web3j.tx.Contract.lambda$executeRemoteCallSingleValueReturn$1(Contract.java:428)

at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)

Ferparishuertas avatar Mar 03 '21 10:03 Ferparishuertas

@Ferparishuertas Thank you for reporting this. I will try to reproduce it and come back to you.

rach-id avatar Mar 05 '21 09:03 rach-id

@Ferparishuertas Sorry for the late answer. Please check the following PR https://github.com/web3j/web3j/pull/1383 I added the structs you had issue with as a test case and everything is green currently. Let me know if there are additional cases you are having issues with. Your input is valuable.

Thank you

rach-id avatar Mar 14 '21 18:03 rach-id

@SweeXordious thank you so much for your help. We have found some cases with more complex structs that are still failing in your branch when decoding string fields. Here is the smart contract example:

pragma solidity ^0.7.5;

pragma experimental ABIEncoderV2;

contract Web3jTest {

    struct Struct2 {
        string string1;
        uint256 uintField1;
        uint256 uintField2;
        uint256 uintField3;
        string string2;
    }

    struct Struct1 {
        uint256 uintField1;
        uint256 uintField2;
    }

    struct MainStruct {
        uint256 id;
        string name;
        Struct1 struct1;
        Struct2 struct2;
    }

    MainStruct private structure;

    function set(MainStruct memory _structure) external returns(bool) {
        structure = _structure;
        return true;
    }

    function get() external view returns(MainStruct memory structure_) {
        structure_ = structure;
    }
}

when trying this

Web3jTest web3jTest = Web3jTest.deploy(web3j, transactionManager, gasProvider).send();
web3jTest.set(new Web3jTest.MainStruct(
	BigInteger.ONE,
	"test name",
	new Web3jTest.Struct1(BigInteger.TEN, BigInteger.ZERO),
	new Web3jTest.Struct2(
		"test string 1",
		BigInteger.ONE,
		BigInteger.ZERO,
		BigInteger.TEN,
		"test string 2"
	)
)).send();
Web3jTest.MainStruct mainStruct = web3jTest.get().send();

we get this error, always with index 64:

java.lang.StringIndexOutOfBoundsException: String index out of range: 64

	at java.lang.String.substring(String.java:1963)
	at org.web3j.abi.TypeDecoder.decodeUintAsInt(TypeDecoder.java:275)
	at org.web3j.abi.TypeDecoder.decodeDynamicBytes(TypeDecoder.java:312)
	at org.web3j.abi.TypeDecoder.decodeUtf8String(TypeDecoder.java:324)
	at org.web3j.abi.TypeDecoder.decode(TypeDecoder.java:112)
	at org.web3j.abi.TypeDecoder.decode(TypeDecoder.java:122)
	at org.web3j.abi.TypeDecoder.decodeDynamicParameterFromStruct(TypeDecoder.java:597)
	at org.web3j.abi.TypeDecoder.decodeDynamicStructElements(TypeDecoder.java:545)
	at org.web3j.abi.TypeDecoder.decodeDynamicStruct(TypeDecoder.java:471)
	at org.web3j.abi.DefaultFunctionReturnDecoder.build(DefaultFunctionReturnDecoder.java:94)
	at org.web3j.abi.DefaultFunctionReturnDecoder.decodeFunctionResult(DefaultFunctionReturnDecoder.java:52)
	at org.web3j.abi.FunctionReturnDecoder.decode(FunctionReturnDecoder.java:49)
	at org.web3j.tx.Contract.executeCall(Contract.java:295)
	at org.web3j.tx.Contract.executeCallSingleValueReturn(Contract.java:301)
	at org.web3j.tx.Contract.executeCallSingleValueReturn(Contract.java:312)
	at org.web3j.tx.Contract.lambda$executeRemoteCallSingleValueReturn$1(Contract.java:400)
	at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)

thanks in advance

lfrKain avatar Mar 24 '21 18:03 lfrKain

@lfrKain Thank you so much for letting me know. Will try to work on a more global fix for this.

rach-id avatar Mar 24 '21 18:03 rach-id

@SweeXordious would be very nice to get a more pluggable solution. I am using maven plugin and had to compile a web3j from scratch and the maven plugin due to not distributed on maven repositories and a chain of dependencies.

Didnt find any doc howto handle codegen / solc config independently.

** Structs are not working anymore for me **

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);
}

is not working - i get the tuple error mentioned in #1361

BarBozz avatar May 08 '21 23:05 BarBozz

@BarBozz I am able to compile the interface that you provided no problem. Can you please let us know which versions are you using ? I am using latest web3j version 4.8.4 via the web3j-gradle-plugin:4.8.4

rach-id avatar May 09 '21 09:05 rach-id

Yes, I believe this is the work in progress https://github.com/web3j/web3j/tree/feature/653-solidity-structs

But how to package and install it? I see that the source code is provided on Git, there is no corresponding installation package

1742268440Zhy avatar Jan 18 '22 08:01 1742268440Zhy