Skip to content

Add AllowedCalldataAnyOfEnforcer#175

Open
jeffsmale90 wants to merge 2 commits intomainfrom
feat/allowed-calldata-any-of-enforcer
Open

Add AllowedCalldataAnyOfEnforcer#175
jeffsmale90 wants to merge 2 commits intomainfrom
feat/allowed-calldata-any-of-enforcer

Conversation

@jeffsmale90
Copy link
Copy Markdown
Contributor

@jeffsmale90 jeffsmale90 commented Apr 14, 2026

What?

Enforces that calldata starting at the specified startIndex matches exactly one of the values specified

Why?

This allows for more flexibility than the AllowedCalldataEnforcer, by specifying that the value starting at startIndex is one of a number of different values.

For instance, the EIP-7715 "Payment to" rule can enforce that the to argument passed to transfer(address,uint256) is one of a number of specified addresses.

The startIndex is specified as the first 32 bytes, for consistency with the AllowedCalldataEnforcer, while ABI encoding was chosen for the values argument, to allow for different length values.

If one of the entries in the values array were of zero length, the caveat would effectly allow any operation, so the enforcer requires that all entries are at least 1 byte in length.


Note

Medium Risk
Adds a new caveat enforcer that affects delegation execution authorization; incorrect term encoding or offset/length assumptions could allow unintended call data to pass or cause unexpected reverts.

Overview
Adds AllowedCalldataAnyOfEnforcer, a new caveat enforcer that restricts single, default-mode executions by requiring a fixed-length calldata slice at startIndex to match any one of multiple allowed candidate byte sequences encoded in _terms.

Includes a comprehensive Foundry test suite covering candidate matching, term decoding/validation failures (size, zero length, padding), mode restrictions, and an end-to-end ERC20 transfer integration case.

Reviewed by Cursor Bugbot for commit 60dddc6. Bugbot is set up for automated code reviews on this repo. Configure here.

Enforces that calldata starting at the specified startIndex matches exactly one of the values specified
@jeffsmale90 jeffsmale90 requested a review from a team as a code owner April 14, 2026 00:14
- specified values must now be of equal size, with the startIndex | length encoded in the first 32 bytes
- uses direct bytes comparison, rather than keccak hash
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 60dddc6. Configure here.

bytes memory terms_ = abi.encodePacked(bytes32(metadataWord_));
vm.expectRevert("AllowedCalldataAnyOfEnforcer:no-allowed-values");
allowedCalldataAnyOfEnforcer.getTermsInfo(terms_);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Test expects wrong revert from unreachable check

Medium Severity

test_getTermsInfoFailsForEmptyCandidatesTail will fail. It constructs 32-byte terms via abi.encodePacked(bytes32(...)) and expects revert "AllowedCalldataAnyOfEnforcer:no-allowed-values". However, the contract's getTermsInfo checks _terms.length > 32 first (line 64), which fails for exactly 32 bytes, reverting with "AllowedCalldataAnyOfEnforcer:invalid-terms-size" instead. The concatenatedValuesLength_ != 0 check on line 72 is unreachable dead code since _terms.length > 32 already guarantees concatenatedValuesLength_ >= 1.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 60dddc6. Configure here.

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.

1 participant