Skip to content

DefaultFunctionEncoder calculates offset incorrectly for nested structs #2052

Closed
@bladekp

Description

@bladekp

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())

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA bug in behaviour or functionality

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions