hyperledger-web3j/web3j

DefaultFunctionEncoder calculates offset incorrectly for nested structs

bladekp opened this issue · 2 comments

DefaultFunctionEncoder calculates offset incorrectly for nested structs

Steps To Reproduce

Minimal example:

  1. Create function which has nested structs as parameters, like:
	var f = new org.web3j.abi.datatypes.Function(
		"myCustomFunction",
		Arrays.asList(
			new StaticStruct(
				new StaticStruct(
					new org.web3j.abi.datatypes.Address("0x1"),
					new org.web3j.abi.datatypes.Address("0x2"))),
			new org.web3j.abi.datatypes.DynamicBytes(new byte[]{1,2,3})),
		Collections.emptyList());

Note that first argument is StaticStruct having one property which is also StaticStruct, nested one have two Address properties, which is important in this example. Also having dynamic type as second argument is important.

  1. Execute FunctionEncoder.encode(f). Result will be:
0x76a4d94f
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000003
0102030000000000000000000000000000000000000000000000000000000000
  1. In result, since second argument is dynamic (DynamicBytes type) offset is included.

Expected behavior

Offset value in that case should equal to 0x60.

Actual behavior

Offset value is (as you can see above) 0x40, this is because nested StaticStruct is calculated to have size of 1 (but 2 addresses are inside, so size should be 2).

Environment

  • Web3j version 4.10.3
  • Java 17
  • Operating System Fedora 38 x64, kernel Linux 6.8.7-100.fc38.x86_64

Additional context

My production case, Im attaching two executions:

  • first one with wrong offset (0xe0 in my case), failure:
MethodID: 0x30f28b7a
[0]:  00000000000000000000000002567e4b14b25549331fcee2b56c647a8bab16fd
[1]:  0000000000000000000000000000000000000000000000000de0b6b3a7640000
[2]:  0000000000000000000000000000000000000000000000000000000000000006
[3]:  ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
[4]:  000000000000000000000000f909259faf3f052792d7d28fb25ae54c43243041
[5]:  0000000000000000000000000000000000000000000000000de0b6b3a7640000
[6]:  000000000000000000000000d1f92a7f86cc94639ed6f3acd2ed540c742602dc
[7]:  00000000000000000000000000000000000000000000000000000000000000e0
[8]:  0000000000000000000000000000000000000000000000000000000000000041
[9]:  7d117587f7976edc3e9043e2ed79be2aa61b49d4513a410bfcc915b146663854
[10]: 253ccba5465141beb4f92adafdef1ab510a5854a61cdb860a1a3ceb1ae86d971
[11]: 1c00000000000000000000000000000000000000000000000000000000000000
  • second with adjusted offset (0x100), succeeded:
MethodID: 0x30f28b7a
[0]:  00000000000000000000000002567e4b14b25549331fcee2b56c647a8bab16fd
[1]:  0000000000000000000000000000000000000000000000000de0b6b3a7640000
[2]:  0000000000000000000000000000000000000000000000000000000000000006
[3]:  ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
[4]:  000000000000000000000000f909259faf3f052792d7d28fb25ae54c43243041
[5]:  0000000000000000000000000000000000000000000000000de0b6b3a7640000
[6]:  000000000000000000000000d1f92a7f86cc94639ed6f3acd2ed540c742602dc
[7]:  0000000000000000000000000000000000000000000000000000000000000100
[8]:  0000000000000000000000000000000000000000000000000000000000000041
[9]:  7d117587f7976edc3e9043e2ed79be2aa61b49d4513a410bfcc915b146663854
[10]: 253ccba5465141beb4f92adafdef1ab510a5854a61cdb860a1a3ceb1ae86d971
[11]: 1c00000000000000000000000000000000000000000000000000000000000000

I think the solution is to make getLength function recursive, and change line:
https://github.com/hyperledger/web3j/blob/5173684412b4d816fc1b4b8bf6c112424a37c7ce/abi/src/main/java/org/web3j/abi/DefaultFunctionEncoder.java#L102
to count += getLength(((StaticArray) type).getValue())

Hey @bladekp , thanks for opening the issue.
If you feel to contribute by fixing it, feel free to open up a PR, we will review and merge it.

Thanks

Looks like fix was prepared by @penuel-leo in #2054 and merged, and was released in https://github.com/hyperledger/web3j/releases/tag/v4.12.0 so I think we can close this issue. Thanks.