esaulpaugh / headlong

High-performance Contract ABI and RLP for Ethereum
Apache License 2.0
76 stars 20 forks source link

Encoding a pure uint256[] function parameter #48

Closed p00temkin closed 1 year ago

p00temkin commented 1 year ago

Hi, I have a question on how to encode a uint256[] parameter. Creating a tuple for the following works just fine:

Function func = new Function("test(uint256[],bool)");
BigInteger[] bigints = new BigInteger[] { BigInteger.valueOf(7), BigInteger.valueOf(8), BigInteger.valueOf(9) };
Tuple args = Tuple.of(bigints, true);
ByteBuffer bb = func.encodeCall(args);
System.out.println(Function.formatCall(bb.array())); 

but if the function argument is a pure uint256[] such as

Function func = new Function("test(uint256[])");
BigInteger[] bigints = new BigInteger[] { BigInteger.valueOf(7), BigInteger.valueOf(8), BigInteger.valueOf(9) };
Tuple args = Tuple.of(bigints);
ByteBuffer bb = func.encodeCall(args);
System.out.println(Function.formatCall(bb.array())); 

the encoding fails with the following trace:

java.lang.IllegalArgumentException: tuple length mismatch: actual != expected: 3 != 1
    at com.esaulpaugh.headlong.abi.TupleType.validate(TupleType.java:146)
    at com.esaulpaugh.headlong.abi.Function.validatedCallLength(Function.java:193)
    at com.esaulpaugh.headlong.abi.Function.encodeCall(Function.java:205)

Any suggestions on how to pass the pure uint256[] correctly in this case?

Thank you

p00temkin commented 1 year ago

Solved by using Tuple.singleton() in this case .. realized just after posting :)

esaulpaugh commented 1 year ago

Alternatively you can also do an explicit cast to Object:

Tuple.of((Object) bigints)

so that bigints doesn't accidentally match Object[] and get unpacked: