web3j icon indicating copy to clipboard operation
web3j copied to clipboard

Wrapper Generation with Array of Structs Parameter

Open abeams opened this issue 3 years ago • 2 comments

Wrapper Generation with Array of Structs Parameter

web3j generates a broken contract wrapper when a function contains a parameter which is an array of structs

Steps To Reproduce

pragma solidity ^0.8.6;
pragma experimental ABIEncoderV2;

contract Test {

    struct Pair {
	uint256 a;
	uint256 b;
    }

    function add(Pair[] calldata pairs) external pure returns (uint256){
        return pairs[0].a + pairs[0].b;
    }   
}

Expected behavior

The wrapper should be generated correctly

Actual behavior

The wrapper does not generate the Pair class as expected. The wrapper also uses org.web3j.abi.Utils.typeMap(pairs, Pair.class) instead of pairs.

public RemoteFunctionCall<BigInteger> add(List<Pair> pairs) {
    final Function function = new Function(FUNC_ADD,
            Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicArray<Pair>(
                    Pair.class,
                    org.web3j.abi.Utils.typeMap(pairs, Pair.class))),
            Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
    return executeRemoteCallSingleValueReturn(function, BigInteger.class);
}

Environment

Describe the environment in which the issue occurs

  • Web3j version 1.4.1

Additional context

Add any other context about the problem here.

abeams avatar Jun 08 '22 14:06 abeams

I can confirm this.

MajdT51 avatar Aug 26 '22 19:08 MajdT51

I'm facing this error too.

ShoaibKakal avatar Aug 27 '22 08:08 ShoaibKakal

I have same error

PouriaN avatar Jul 16 '23 12:07 PouriaN

With latest web3j version 4.10.3 - I tried generating java wrapper for the code you provided -

pragma solidity ^0.8.6;
pragma experimental ABIEncoderV2;

contract Test {

    struct Pair {
	uint256 a;
	uint256 b;
    }

    function add(Pair[] calldata pairs) external pure returns (uint256){
        return pairs[0].a + pairs[0].b;
    }   
}

The Pair class generated -

public static class Pair extends StaticStruct {
        public BigInteger a;

        public BigInteger b;

        public Pair(BigInteger a, BigInteger b) {
            super(new org.web3j.abi.datatypes.generated.Uint256(a), 
                    new org.web3j.abi.datatypes.generated.Uint256(b));
            this.a = a;
            this.b = b;
        }

        public Pair(Uint256 a, Uint256 b) {
            super(a, b);
            this.a = a.getValue();
            this.b = b.getValue();
        }
    }

The add function generated -

public RemoteFunctionCall<BigInteger> add(List<Pair> pairs) {
        final Function function = new Function(FUNC_ADD, 
                Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicArray<Pair>(Pair.class, pairs)), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeRemoteCallSingleValueReturn(function, BigInteger.class);
    }

These seems correct to me.

I am able to deploy the contract and call the add function too using web3j and Besu private QBFT network. Code for reference -

Credentials credentials = Credentials.create(privKey);
Web3j web3j = Web3j.build(new HttpService(nodeUrl));

System.out.println("\nDeploying ArrayOfStructs contract ...");
ArrayOfStructs arrayOfStructs = ArrayOfStructs.deploy(web3j, credentials, new StaticGasProvider(BigInteger.valueOf(4_100_000_000L),BigInteger.valueOf(9_000_000L))).send();
System.out.println("Contract address: " + arrayOfStructs.getContractAddress());
System.out.println("ArrayOfStructs addition method result: " + arrayOfStructs.add(List.of(new ArrayOfStructs.Pair(BigInteger.ONE, BigInteger.TWO))).send());

Closing this ticket, in case someone still faces a issue with Array of Structs plz reopen the ticket.

NickSneo avatar Oct 10 '23 20:10 NickSneo