Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions src/lib/TypedEncoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,39 @@ library TypedEncoder {
if (s.encodingType == EncodingType.ABI) {
return _encodeAbi(s);
}
// CallWithSelector and CallWithSignature return raw calldata (selector + params)
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];
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.
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);
}
Comment on lines +199 to +227
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?

// Encoding types implemented in later commits
if (
s.encodingType == EncodingType.CallWithSelector || s.encodingType == EncodingType.CallWithSignature
|| s.encodingType == EncodingType.Hash || s.encodingType == EncodingType.Create
s.encodingType == EncodingType.Hash || s.encodingType == EncodingType.Create
|| s.encodingType == EncodingType.Create2 || s.encodingType == EncodingType.Create3
) {
revert EncodingTypeNotImplemented();
Expand Down
Loading
Loading