Skip to content

feat(#3): support call encodings#50

Open
re1ro wants to merge 1 commit intofeature/typed-encoder-step2from
feature/typed-encoder-step3
Open

feat(#3): support call encodings#50
re1ro wants to merge 1 commit intofeature/typed-encoder-step2from
feature/typed-encoder-step3

Conversation

@re1ro
Copy link
Collaborator

@re1ro re1ro commented Oct 31, 2025

  • enable CallWithSelector and CallWithSignature encoding types with validation
  • extend calldata tests to cover selector and signature based calls

- enable CallWithSelector and CallWithSignature encoding types with validation
- extend calldata tests to cover selector and signature based calls
@re1ro re1ro requested review from Copilot and fish-sammy October 31, 2025 12:17
@re1ro re1ro self-assigned this Oct 31, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements CallWithSelector and CallWithSignature encoding types for the TypedEncoder library, enabling dynamic construction of contract call data at runtime. These encoding types allow encoding function calls by either providing a bytes4 selector directly or computing it from a function signature string.

  • Adds validation logic in the encode() function to verify structural requirements for both call encoding types
  • Implements _encodeCallWithSelector() and _encodeCallWithSignature() helper functions (implementation details not visible in diff)
  • Removes CallWithSelector/CallWithSignature from the unimplemented encoding types list

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/lib/TypedEncoder.sol Adds validation and routing logic for CallWithSelector and CallWithSignature encoding types in the encode() function
test/libs/TypedEncoderCalldata.t.sol Adds comprehensive test coverage for CallWithSelector and CallWithSignature encoding types with various parameter configurations

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (chunk.primitives.length != 1 || chunk.structs.length != 1 || chunk.arrays.length != 0) {
revert InvalidCallEncodingStructure();
}
Primitive memory selectorPrim = chunk.primitives[0];
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation checks selectorPrim.data.length != 4, but this checks the length of the bytes array itself, not the actual selector content. When using abi.encodePacked(bytes4), the resulting bytes array has a length field followed by 4 bytes of data. The check should validate that the data contains exactly 4 bytes of selector data. Consider using assembly to extract and validate the actual 4-byte content, or document that data should be created with abi.encodePacked(selector) which produces a 4-byte array.

Suggested change
Primitive memory selectorPrim = chunk.primitives[0];
Primitive memory selectorPrim = chunk.primitives[0];
// selectorPrim.data must be constructed using abi.encodePacked(bytes4) to ensure length == 4

Copilot uses AI. Check for mistakes.
@re1ro re1ro changed the title feat: support call encodings feat(#3): support call encodings Oct 31, 2025
Comment on lines +199 to +227
if (s.encodingType == EncodingType.CallWithSelector) {
// Validate CallWithSelector encoding structure before forwarding
if (s.chunks.length != 1) {
revert InvalidCallEncodingStructure();
}
Chunk memory chunk = s.chunks[0];
if (chunk.primitives.length != 1 || chunk.structs.length != 1 || chunk.arrays.length != 0) {
revert InvalidCallEncodingStructure();
}
Primitive memory selectorPrim = chunk.primitives[0];
if (selectorPrim.isDynamic || selectorPrim.data.length != 4) {
revert InvalidCallEncodingStructure();
}
return _encodeCallWithSelector(s);
}
if (s.encodingType == EncodingType.CallWithSignature) {
// Validate CallWithSignature encoding structure before forwarding
if (s.chunks.length != 1) {
revert InvalidCallEncodingStructure();
}
Chunk memory chunk = s.chunks[0];
if (chunk.primitives.length != 1 || chunk.structs.length != 1 || chunk.arrays.length != 0) {
revert InvalidCallEncodingStructure();
}
if (!chunk.primitives[0].isDynamic) {
revert InvalidCallEncodingStructure();
}
return _encodeCallWithSignature(s);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not do the validations inside the corresponding _encode method? These validations right now don't happen for _encodeChunkFields, why?


// ============ Section 4: Error Cases ============

function testCallWithSelectorInvalidStructure() public {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this test and all below skipped? Isn't the error there now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants