Skip to content

Add Permit2 preflight validation checks#204

Merged
prestwich merged 9 commits intomainfrom
feat/permit2-preflight-checks
Mar 18, 2026
Merged

Add Permit2 preflight validation checks#204
prestwich merged 9 commits intomainfrom
feat/permit2-preflight-checks

Conversation

@init4samwise
Copy link
Copy Markdown
Contributor

@init4samwise init4samwise commented Feb 27, 2026

Summary

Adds Permit2 preflight validation checks to the signet-orders crate via a Permit2Ext extension trait on any alloy Provider.

Checks performed:

  • Token Balance — verifies user has sufficient ERC20 balance
  • ERC20 Approval — verifies user has approved sufficient allowance to Permit2
  • Permit2 Nonce — checks that the Permit2 nonce hasn't been consumed

Implementation

  • Permit2Ext trait extends any Provider with:
    • Low-level: sufficient_balance, token_approved, nonce_available
    • High-level: check_signed_order, check_unsigned_order, check_orders_and_fills
  • ERC20/Permit2 sol! interfaces moved to signet-constants::contracts for reuse
  • Uses tokio::try_join! for known future groups + try_join_all for dynamic counts (no boxing, no unnecessary collects)

API Usage

use signet_orders::Permit2Ext;

// Check all conditions for a signed order
provider.check_signed_order(&signed_order).await?;

// Or check individual conditions
provider.sufficient_balance(token, user, amount).await?;
provider.token_approved(token, user, amount).await?;
provider.nonce_available(user, nonce).await?;

Closes ENG-1907

Implements ENG-1907 by adding comprehensive preflight validation for orders:

- Token balance verification (balanceOf check)
- ERC20 approval validation (allowance to Permit2)
- Permit2 nonce consumption validation (nonceBitmap check)

Adds PreflightChecker with async validation methods:
- check_token_balance() - verifies sufficient token balance
- check_erc20_approval() - verifies Permit2 allowance
- check_permit2_nonce() - verifies nonce availability
- check_all() - runs all validations together

Includes comprehensive error handling, unit tests, and documentation.

Closes ENG-1907
@init4samwise init4samwise requested a review from a team as a code owner February 27, 2026 13:31
Copy link
Copy Markdown
Member

@prestwich prestwich left a comment

Choose a reason for hiding this comment

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

functions should operate on the high-level types that compose orders and fills.

  • UnsignedOrder (from signet_types)
  • SignedOrder (from signet_types)
  • OrdersAndFills

consider packaging these in an extension trait for Provider

@prestwich
Copy link
Copy Markdown
Member

resolve CI

- Remove Transport generic constraint, use Provider directly
- Make new() and with_permit2_address() const functions
- Fix call() return value handling (single returns don't need field accessor)
- Add u64 suffix to hex literal to fix overflow warning
- Remove network-dependent async test
Copy link
Copy Markdown
Member

@prestwich prestwich left a comment

Choose a reason for hiding this comment

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

previous comments still apply. this API should be higher-level and use an extension trait

Comment thread crates/orders/src/preflight.rs Outdated
}

/// The canonical Permit2 contract address.
pub const PERMIT2_ADDRESS: Address =
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this should be re-used from somewhere else. look for existing definitions, and move them to the constants crate, then import from there

Comment thread crates/orders/src/preflight.rs Outdated
nonce: u64,
) -> Result<(), PreflightError> {
// Check balance
self.check_token_balance(token, user, amount).await?;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

run these in parallel using try_join

…trait

Redesign preflight validation to use an extension trait on Provider
instead of a wrapper struct. This follows alloy's provider extension
pattern and provides a more ergonomic API.

- Add Permit2PreflightExt trait with methods for SignedOrder,
  UnsignedOrder, and OrdersAndFills types
- Use try_join_all for concurrent preflight checks
- Export PERMIT2_ADDRESS from signet-types instead of duplicating it
- Accept U256 nonces to match Permit2Batch types directly

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread crates/orders/src/preflight.rs Outdated
Comment thread crates/orders/src/preflight.rs Outdated
Comment thread crates/orders/src/preflight.rs Outdated
Comment thread crates/orders/src/preflight.rs Outdated
Comment thread crates/orders/src/preflight.rs Outdated
Comment thread crates/orders/src/preflight.rs Outdated
prestwich and others added 6 commits March 17, 2026 13:29
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address review comments on PR #204:
- Rename trait to Permit2Ext, methods to check_*
- Import sol! interfaces from signet-constants
- Make free functions into trait methods
- Use tokio::try_join! for known future counts
- Remove boxed futures and unnecessary collects

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use functional combinators (then_some/ok_or) instead of if/return Err
- Replace tokio::try_join! with futures_util::try_join/try_join3, removing
  unnecessary tokio dependency
- Use .map(|_| ()) instead of trailing Ok(())
- Make contracts module private with selective pub use re-exports
- Replace glob import in tests with explicit imports
- Convert doctest from ignore to no_run

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move contract bindings and Permit2 address constant from
signet-constants and signet-types into signet-zenith where the other
contract bindings live. Add nonce_to_bitmap_position as a method on
IPermit2Instance. Add default impls for check_signed_order,
check_unsigned_order, and check_orders_and_fills on the Permit2Ext
trait.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@prestwich prestwich left a comment

Choose a reason for hiding this comment

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

[Claude Code]

LGTM. All review comments addressed.

@prestwich prestwich merged commit 74c851f into main Mar 18, 2026
6 checks passed
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