Skip to content

feat: add ApprovalRevocationEnforcer#177

Open
jeffsmale90 wants to merge 7 commits intomainfrom
feat/erc20-allowance-revocation-enforcer
Open

feat: add ApprovalRevocationEnforcer#177
jeffsmale90 wants to merge 7 commits intomainfrom
feat/erc20-allowance-revocation-enforcer

Conversation

@jeffsmale90
Copy link
Copy Markdown
Contributor

@jeffsmale90 jeffsmale90 commented Apr 22, 2026

What?

This enforcer grants the authority to revoke allowances granted by either:

  • ERC20 approve(spender,amount)
  • ERC721 approve(to,tokenId)
  • ERC721 setApprovalForAll(operator,approved)

This covers approvals set for ERC20, ERC721 and ERC1155 tokens.

Why?

The enforcer now verifies that the target implements the expected token standard, by first invoking the standard-specific function to check the allowance being revoked.

Advanced Permissions currently has an erc20-token-revocation permission that grants the authority to revoke only ERC20 approvals. NFT approvals are also required.

By combining these revocations into a single enforcer, we get a number of benefits:

  • user must sign only a single permission to revoke all allowances across multiple token types
  • reduced gas cost to invoke a revocation (single caveat, rather than composition of multiple caveats)

How?

The enforcer accepts terms of exactly 1 byte, interpreted as a bitmask of the following values:

  • Bit 0 (0x01) - ERC-20 approve(spender, 0) (spender non-zero, amount zero)
  • Bit 1 (0x02) - ERC-721 per-token approve(address(0), tokenId)
  • Bit 2 (0x04) - ERC-721 / ERC-1155 setApprovalForAll(operator, false)

Indicating which revocation primitives the delegation authorizes. Terms must be non-zero, and the reserved upper bits must not be set.

The beforeHook only runs in single call type and default execution mode. It first performs general verification - no native value is sent (no additional value limiting caveat is required), and execution calldata is the expected length - then dispatches by selector.

setApprovalForAll and approve are distinguished by selector. The two approve signatures share a selector and are distinguished by the spender / to (first) parameter — if it is the zero address, the call is treated as the ERC-721 approve(to, tokenId) form; otherwise it is treated as the ERC-20 approve(spender, amount) form. Any other selector is rejected.

Each branch then performs a check against the delegator's current approval state on the target, ensuring the revocation is to an existing approval - ensuring that the contract implementation is a valid target for the invocation.


Note

Medium Risk
Adds a new on-chain enforcer that constrains delegated calls by decoding calldata and querying token/Pemit2 state; mistakes could block legitimate revocations or allow unintended targets, especially around Permit2 and redelegation semantics.

Overview
Adds ApprovalRevocationEnforcer, a new caveat enforcer that only permits approval-revocation calls in single/default mode, gated by a 1-byte bitmask for ERC-20 approve(spender,0), ERC-721 approve(0,tokenId), ERC-721/1155 setApprovalForAll(_,false), and three canonical Permit2 revocation primitives.

Updates deployment and verification scripts to include the new enforcer, adds extensive unit/integration coverage (including redelegation edge cases), and documents expected behavior, composition guidance, and Permit2 trust/DoS considerations in CaveatEnforcers.md.

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

@jeffsmale90 jeffsmale90 requested a review from a team as a code owner April 22, 2026 03:02
@MoMannn MoMannn changed the title feat: add AllowanceRevocationEnforcer feat: add ApprovalRevocationEnforcer Apr 22, 2026
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 84896cd. Configure here.

Comment thread script/verification/verify-enforcer-contracts.sh
Copy link
Copy Markdown
Contributor Author

@jeffsmale90 jeffsmale90 left a comment

Choose a reason for hiding this comment

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

Looks good to me!

Minor comment regarding using the term permission to refer to the allowed revocation mechanism.

Comment thread src/enforcers/ApprovalRevocationEnforcer.sol Outdated
Comment thread src/enforcers/ApprovalRevocationEnforcer.sol Outdated
@MoMannn MoMannn self-requested a review April 28, 2026 06:59
Comment thread src/enforcers/ApprovalRevocationEnforcer.sol Outdated
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.

3 participants