Skip to content

feat(taco): Add nestedAbiDecode schema for selectorless ABI validation#767

Draft
theref wants to merge 313 commits intonucypher:mainfrom
theref:feat/nested-abi-decode
Draft

feat(taco): Add nestedAbiDecode schema for selectorless ABI validation#767
theref wants to merge 313 commits intonucypher:mainfrom
theref:feat/nested-abi-decode

Conversation

@theref
Copy link
Copy Markdown
Contributor

@theref theref commented Mar 5, 2026

Client-side schema companion to nucypher/nucypher#3723.

What

Adds nestedAbiDecode as a third option on abiParameterValidationSchema, alongside returnValueTest and nestedAbiValidation. Exactly one of the three must be set.

nestedAbiDecode is for validating raw ABI-encoded bytes that don't have a function selector prefix. Where nestedAbiValidation expects function-call bytes (selector + args), nestedAbiDecode takes a Solidity type string and decodes raw bytes against it.

Changes

abiParameterValidationSchema

  • Added optional nestedAbiDecode field
  • XOR check updated from "one of two" to "exactly one of three"

abiDecodeValidationSchema (new)

  • type: validated via ParamType.from() (reuses existing ethers dependency)
  • validations: array of abiParameterValidationSchema (recursive)

validateAllowedAbiCall

  • Added bytes-type guard for nestedAbiDecode (same pattern as nestedAbiValidation)

Exports

  • AbiDecodeValidationProps and abiDecodeValidationSchema re-exported from conditions/base/signing.ts

Tests

  • Valid nestedAbiDecode with inner validations and nested nestedAbiValidation
  • Rejected on non-bytes type (e.g. bytes32) ✓
  • Rejected when both nestedAbiValidation and nestedAbiDecode are set ✓

theref and others added 30 commits July 8, 2025 13:57
- change signUserOp method to use 'data' instead of 'params' for POST request
- aligns with other Porter methods that send data in request body
- fixes 400 Bad Request error when signing user operations
- update test expectations to match new base64-encoded signing request format
- tests now expect btoa(JSON.stringify(...)) instead of JSON.stringify(...)
- change signing request structure to match Python implementation
- use snake_case field names (cohort_id, chain_id, signature_type)
- serialize userOp as 'data' field instead of direct embedding
- update tests to match new request format
- Use sorted JSON keys for user operations to match Python implementation
- Update signing request structure with proper field names
- Add error logging for debugging Porter API responses
- Update tests to match new request format
- Add UserOperation type, UserOperationSignatureRequest class, and convertUserOperationToPython utility to shared/src/types.ts
- Export new types and classes in shared/src/index.ts
- Update taco/src/types.ts to re-export UserOperation from shared package
- Eliminates duplication of UserOperation type definitions across packages
- Fix Porter client to use POST data instead of query params for /sign endpoint
- Fix SigningCoordinator.getThreshold() to use signingCohorts(cohortId).threshold
- Update signUserOp() to use shared conversion utilities and proper base64 encoding
- Update tests to use shared conversion function and correct signature_type 'userOp'
- Remove console.log statements and simplify integration test
- All functionality now uses centralized types from shared package
- Updated SignResponse type to match new API response format with separated signatures and errors
- Enhanced PorterClient.sign() with better error handling and response structure validation
- Added debug logging to signing integration test
- Fixed signer key mapping from operator to provider in signUserOp
- Removed debug code for porter ursulas endpoint
- Remove private key security risk and use dummy address
- Switch to Ethereum Sepolia testnet (chain ID 11155111)
- Update RPC provider URL to publicnode.com
- Change ritual ID to 1
- Fix test skip condition for CI environment
- Fix UserOperationSignatureRequest constructor to accept objects instead of strings
- Remove double JSON stringification that caused address encoding errors
- Update convertUserOperationToPython to handle null/empty values properly
- Fix test expectations to match new data format and provider addresses
- Resolve AddressEncoder errors by ensuring proper hex address format

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update test expectations to use JSON.stringify for user_op field serialization
- Rename digest field to messageHash in SignResult interface and all related code
- Implement strict address validation that fails fast on invalid checksums
- Fix Porter test mock response structure to match API format
- Update integration test to use properly checksummed addresses

Co-Authored-By: Kieran <kieranprasch@gmail.com>
…pt pattern

- Remove complex try-catch blocks and manual error checking in signUserOp
- Use direct destructuring of errors from Porter response
- Trust Porter's response structure instead of adding validation overhead
- Update tests to match new error handling pattern
- Follow same approach as tacoDecrypt for consistent error handling
- Add async forSigningCohort static method to build context from signing cohort conditions
- Fix import ordering and add missing ethers import
- Update integration test to use new signing context method with await
- Add tests for happy path scenario with valid cohort conditions
- Add error handling tests for network failures and invalid responses
- Add tests for invalid hex decoding and JSON parsing errors
- Add tests for complex compound condition structures
- Add tests for invalid condition schema validation
- Fix hex decoding in forSigningCohort method to handle contract responses
…ash validation

- Remove returnAggregated option from SigningOptions type
- Remove unused options parameter from signUserOp method
- Add validation to ensure all Ursulas return same message hash
- Throw error if message hashes don't match across signatures
…ash validation test

- Remove returnAggregated options from existing tests
- Add test case to verify error thrown when message hashes don't match
- Update test calls to match new signUserOp signature
…erface

- Remove SigningOptions import as no longer needed
- Remove options parameter from signUserOp function signature
- Update porter.signUserOp call to remove options parameter
- Remove unused INTERNAL_SIGNING_CONDITION constant
- Update RESERVED_CONTEXT_PARAMS to only include USER_ADDRESS_PARAM_DEFAULT
- Remove returnAggregated options from test calls
- Update function calls to match new signUserOp signature
- Remove unused options variable from test
- Remove returnAggregated option from signUserOp call in integration test
- Change aggregation logic from length > 0 to length >= threshold
- Ensures aggregated signature only provided with sufficient signatures
- Fix existing test expectation for insufficient signatures case
- Add new test to verify no aggregation when threshold not met
- Ensure test coverage for both threshold met and unmet scenarios
- Remove throw for mismatched message hashes
- Include signature processing errors in result errors instead
- Add try-catch for signature decoding failures
- Continue processing other signatures when one fails
- Let caller decide how to handle errors based on SignResult
- Change mismatched hash test to expect error in result instead of thrown
- Verify result contains partial signatures and error details
- Test that processing continues with valid signatures despite errors
- Add SigningOptions parameter with optimistic flag
- Extract signature decoding logic to eliminate duplication
- Optimistic mode: skip hash validation, use all signatures
- Non-optimistic mode: validate hashes, only aggregate when threshold+ nodes agree
- All signatures included in signingResults regardless of mode
- Add comprehensive test coverage for new optimistic signing logic
- Update existing test expectations for new signing behavior
theref and others added 27 commits January 29, 2026 14:26
Add comprehensive test coverage for indexWithinArray feature:
- Valid indexWithinArray with array parameters
- Rejection of indexWithinArray for non-array types
- Combined indexWithinArray and indexWithinTuple for arrays of tuples
- Rejection of indexWithinTuple for arrays of non-tuples
- Nested ABI validation with indexWithinArray for bytes arrays
- Rejection of nested ABI validation for arrays of non-bytes

All tests verify both success and failure cases with appropriate
error messages.
Replace separate indexWithinArray and indexWithinTuple fields with a
single subIndices array that handles arbitrary nesting of arrays and
tuples. This resolves the ambiguity of operation ordering when both
array and tuple indexing are needed.

The subIndices approach interprets each index based on the current ABI
type at that position:
- Arrays (type[]) consume an index and access that element
- Tuples ((a,b,c)) consume an index and access that field
- Supports any depth of nesting

This aligns with the corresponding nucypher/nucypher PR #3685 changes.
Add a new create2 operation to the variable operation system that
computes Ethereum CREATE2 addresses locally, eliminating RPC calls
to factory contracts for counterfactual address resolution.

The operation takes an object value with deployerAddress and
bytecodeHash fields, both supporting context variable resolution.
This enables full Account Abstraction address derivation pipelines.

Implements taco-web equivalent of nucypher/nucypher#3703.
Move create2ValueSchema from context.ts to variable-operation.ts and
remove it from the paramOrContextParamSchema union. This prevents
non-create2 operations from accepting create2-shaped values.

Also tighten validation: deployerAddress and bytecodeHash now require
0x-prefixed hex strings instead of any plain string.
Remove OBJECT_VALUE_OPERATIONS exclusion list so create2 is covered
by the regression backstop test for operations requiring a value.
Use toContain assertion since create2 produces multiple errors.
…ema and the create2 operation schema.

Revert change to test since no longer needed.
Add parametrized test ensuring all non-unary, non-create2 operations
reject create2-shaped object values.
via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
Caches getParticipants and getThreshold results with a 10-second TTL
to avoid redundant contract reads during short time windows. Cache is
keyed by domain and cohortId, with a public clearCache() method for
manual invalidation.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
Covers cache hits, TTL expiry, per-domain and per-cohortId isolation,
and manual cache clearing.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
Move cache logic from SigningCoordinatorAgent into a reusable
TtlCache class. Bump TTL from 10s to 60s per review feedback.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
Reorder cache keys from field:domain:cohortId to domain:cohortId:field
(broader to specific) and extract a cacheKey() helper to keep key
structure consistent, per review feedback.
Replace ':nullAddress' string literals with NULL_ADDRESS_CONTEXT_VAR
constant defined in conditions/const.ts, used in both
AUTOMATICALLY_INJECTED_CONTEXT_PARAMS and RESERVED_CONTEXT_PARAMS.
Replace Buffer.from(...).toString('hex') with the existing toHexString
utility from @nucypher/shared for consistency with the rest of the
codebase.
…dices

Idiomatic TypeScript prefers undefined over null for absent values.
Addresses PR review feedback.
Add abiDecodeValidationSchema and update abiParameterValidationSchema
to support a third option alongside returnValueTest and
nestedAbiValidation. Used for ERC-7579 batch execution payloads.
@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 5, 2026

Deploy Preview for taco-demo ready!

Name Link
🔨 Latest commit da7b8a3
🔍 Latest deploy log https://app.netlify.com/projects/taco-demo/deploys/69a9a985ded1430008bc2889
😎 Deploy Preview https://deploy-preview-767--taco-demo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 5, 2026

Deploy Preview for taco-nft-demo ready!

Name Link
🔨 Latest commit da7b8a3
🔍 Latest deploy log https://app.netlify.com/projects/taco-nft-demo/deploys/69a9a985107dcf000822692b
😎 Deploy Preview https://deploy-preview-767--taco-nft-demo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@derekpierre derekpierre marked this pull request as draft April 21, 2026 14:52
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.

4 participants