-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat: dynamic array encode #2184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: dynamic array encode #2184
Conversation
Signed-off-by: joseph.xiang <xjun0311@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I am not a maintainer (in fact, I just started exploring this project) and was having a hard time finding good first issues to solve myself, so thought of beginning to contribute by reviewing code.
I don't know if the PR is correct or not, as I don't have a lot of context - so pretty sure there will be many more changes when the maintainers take a look, but I left some comments below on code quality which would help you regardless of whether the PR goes in.
@@ -307,16 +306,21 @@ public byte[] encodeData(String primaryType, HashMap<String, Object> data) | |||
|
|||
List<String> encTypes = new ArrayList<>(); | |||
List<Object> encValues = new ArrayList<>(); | |||
List<byte[]> dynamicData = new ArrayList<>(); // Store dynamic data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant comment
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the extra newlines?
if (value == null) continue; | ||
if (value == null) { | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary change?
// Calculate header size (static part) | ||
int headSize = 32; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are not calculating the header size, but hardcoding it - so the comment is misleading.
It's better to convert this into a constant like static final HEADER_SIZE
just after the class declaration above the constructor at and use it wherever needed.
If you name the constant descriptively enough, the comment can also be let go of.
// Track total size of dynamic data | ||
int dynamicDataSize = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant comment
// Handle dynamic array | ||
encTypes.add(baseTypeName); // Use base type instead of array type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be AI-generated.
Nevertheless, if this is correct (I don't have much context), the comment here is useless as it talks about a change, which makes sense in the context of this PR, but won't once merged. Should be removed.
Think - how would the code look like once merged?
// Prepare dynamic data | ||
ByteArrayOutputStream dynamicBuffer = new ByteArrayOutputStream(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant comment.
ByteArrayOutputStream dynamicBuffer = new ByteArrayOutputStream(); | ||
// Write array length | ||
byte[] lengthBytes = | ||
Numeric.toBytesPadded(BigInteger.valueOf(arrayItems.size()), 32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extract magic number to a constant
// Write array elements | ||
for (Object arrayItem : arrayItems) { | ||
BigInteger itemValue = convertToBigInt(arrayItem); | ||
byte[] itemBytes = Numeric.toBytesPadded(itemValue, 32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here ^
// Update total size of dynamic data | ||
dynamicDataSize += dynamicBytes.length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant comment - possibly because of AI
Dynamic Array Encoding Fix in Web3j
Problem Statement
The original implementation did not correctly handle dynamic arrays according to Solidity's ABI encoding specification. In Solidity, when using
abi.encode()
with array parameters, the output includes dynamic offsets pointing to the actual array data.Example in Solidity
When calling this function with:
The encoded output structure should be:
Issue
The original Web3j implementation was concatenating array data directly without proper offset handling:
Solution
Modified the implementation to follow Solidity's ABI encoding specification:
Impact
abi.encode()
functionThis change aligns Web3j's implementation with Ethereum's ABI specification for dynamic array encoding.