Conversation
- Add decoder utility functions (extractBigInt, extractNumber, extractAddress, extractHex, extractRemainingHex) to internalUtils - Implement decoder functions for all 32 caveat types to match existing encoders - Export all decoder functions from caveats/index.ts and main index.ts - Add comprehensive test suite covering all decoder functions - All 435 existing tests continue to pass Co-authored-by: jeffsmale90 <jeffsmale90@users.noreply.github.com>
- Cast extractAddress, extractHex, and extractRemainingHex return types to `0x${string}`
- Update array declarations in decoders to use proper `0x${string}[]` types
- Cast target addresses in ABI decoded results
- Add type assertions in tests for BytesLike comparisons
- All TypeScript build errors resolved
- All 435 tests still passing
Co-authored-by: jeffsmale90 <jeffsmale90@users.noreply.github.com>
- Remove unused hexToBytes import from nonce.ts - Rename 'hex' parameter to 'hexString' in decoder utility functions to comply with id-denylist eslint rule - All linting checks now pass Co-authored-by: jeffsmale90 <jeffsmale90@users.noreply.github.com>
- change type string to Hex - remove unnecessary comments - change parameter name hexString to value - add test coverage for new utilities
6cc446f to
c03605c
Compare
- Add generic TBytesLike parameter to core caveat config types - Rename timestampBuilder config properties in core to match smart-accounts-kit
b0a3392 to
578079e
Compare
578079e to
3f2af91
Compare
| */ | ||
| export function decodeLimitedCallsTerms(terms: BytesLike): LimitedCallsTerms { | ||
| const hexTerms = bytesLikeToHex(terms); | ||
| const limit = extractNumber(hexTerms, 0, 32); |
There was a problem hiding this comment.
We are extracting number here. But limit is uint256 so it can go over number limit. BigInt would be safer. (practically speaking it would be quite an edge case to get to a number that big to break it, but just something to consider - same for other usages of extractNumber). If this is intentional then maybe just add a comment? Or maybe a hybrid where we decode to bigint and if its in correct range we return number otherwise throw an error?
There was a problem hiding this comment.
Yeah, that's a good point.
All of the values that are encoded as a type larger than MAX_SAFE_INTEGER are either a timestamp or duration (seconds) or a count (index or limit). I think for those number type is ergonomic - having to BigInt(Date.now() / 1000) constantly would get tedious.
Saying that, it's not technically correct, so I updated the extractNumber function to convert to BigInt, and throw if it's greater than Number.MAX_SAFE_INTEGER, to provide safety.
The vast majority of use cases would not necessitate a value > MAX_SAFE_INTEGER, and we're not prohibiting encoding values great - just not providing tooling to make it easier.
We can still consider converting them to number, but it'll be a breaking change for existing encoders, so I'd put it into a separate PR.
| | AllowedTargetsTerms<DecodedBytesLike<'bytes'>> { | ||
| const hexTerms = bytesLikeToHex(terms); | ||
|
|
||
| const addressSize = 20; |
There was a problem hiding this comment.
This is more of a question. But should we also check the terms length here to make sure they are correct?
On chain we are checking terms length: https://github.com/MetaMask/delegation-framework/blob/f1d5913120fc772a4b2cc7ba4179450ffa2988c1/src/enforcers/AllowedTargetsEnforcer.sol#L58
So it should not be possible to have different terms length here. But the function could be used on a wrong data or something like that and this would be able to detect this. 🤔
If we should check terms then this should be on other enforcers as well
There was a problem hiding this comment.
Good call - nice little sanity check that might save someone's sanity if they're having to debug!
I've added length checks to all terms decoders.
| * @returns The extracted bigint value. | ||
| */ | ||
| export const extractBigInt = ( | ||
| value: string, |
There was a problem hiding this comment.
should this be Hex like with the others?
There was a problem hiding this comment.
absolutely it should be!
| environment: SmartAccountsEnvironment; | ||
| }): CoreCaveatConfiguration => { | ||
| switch (enforcer) { | ||
| case caveatEnforcers.AllowedCalldataEnforcer: |
There was a problem hiding this comment.
should we make sure that addresses are normalized (always to lowerCase on both sides)?
There was a problem hiding this comment.
Definitely we should - good call!
- throw if extracting a number from hex that exceeds Number.MAX_SAFE_INTEGER - validate Hex length when decoding allowedTargets terms - update argument type to hex for extractBigInt util
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
2651ece to
bdef1a6
Compare
…MultipleOf and ensure that bytelength is not 0
bdef1a6 to
97f6038
Compare
…/smart-accounts-kit/utils

Implements terms decoders in @metamask/delegation-core for every caveat enforcer that already had a terms encoder, so encoded terms bytes can be turned back into structured objects. Adds
decodeCaveatin @metamask/smart-accounts-kit, which usesSmartAccountsEnvironment.caveatEnforcersto map an on-chain enforcer address to the right decoder and returns aCoreCaveatConfiguration(discriminated by type) for builders and tooling.Closes #184.
Changes
@metamask/delegation-core
@metamask/smart-accounts-kit/utils
Note
Medium Risk
Adds a large new surface area of decoding functions and changes the
TimestampTermsfield names, which is a small breaking API change and could affect downstream callers if not updated. Most changes are deterministic parsing/validation logic with good test coverage, but mistakes would cause mis-decoding of on-chain terms.Overview
Adds
decode*Termsfunctions across delegation caveats so encoded terms (Hex/Uint8Array) can be parsed back into structured*Termsobjects, with output configurable tohexorbytesto mirror existing encoding APIs.Introduces shared slicing/validation utilities in
internalUtils.ts(e.g.,extractBigInt,extractAddress, length assertions) and aDecodedBytesLikealias to keep decoded term types correctly parameterized; many*Termstypes are now generic over bytes-like fields.Updates public exports (
caveats/index.ts, packageindex.ts), expands unit tests to cover decoding and invalid payload lengths, and renamesTimestampTermsfields toafterThreshold/beforeThreshold(docs updated accordingly).Written by Cursor Bugbot for commit 7d0bd1d. This will update automatically on new commits. Configure here.