From 6058406d3ec057de3a630b3138527b575bd9bb3a Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Wed, 2 Jul 2025 12:38:06 +1200 Subject: [PATCH 1/9] Make caveat builders more secure - rename allowEmptyCaveats to allowInsecureFullAuthorityDelegations - require allowInsecureFullAuthorityDelegations when signing and creating delegations --- .../src/caveatBuilder/caveatBuilder.ts | 25 ++- packages/delegation-toolkit/src/delegation.ts | 16 +- .../test/caveatBuilder/CaveatBuilder.test.ts | 8 +- .../caveatBuilder/createCaveatBuilder.test.ts | 6 +- .../nativeTokenPaymentBuilder.test.ts | 6 +- .../test/delegation.test.ts | 166 +++++++++++++++--- packages/delegation-toolkit/test/utils.ts | 15 +- .../test/caveats/nativeTokenPayment.test.ts | 2 +- .../test/delegateAndRedeem.test.ts | 2 +- ...c7710sendTransactionWithDelegation.test.ts | 2 +- ...710sendUserOperationWithDelegation.test.ts | 4 +- 11 files changed, 200 insertions(+), 52 deletions(-) diff --git a/packages/delegation-toolkit/src/caveatBuilder/caveatBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/caveatBuilder.ts index 095035bd..a83be433 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/caveatBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/caveatBuilder.ts @@ -6,13 +6,25 @@ type CaveatWithOptionalArgs = Omit & { args?: Caveat['args']; }; +const INSECURE_UNRESTRICTED_DELEGATION_ERROR_MESSAGE = + 'No caveats found. If you definitely want to create an empty caveat collection, set `allowInsecureUnrestrictedDelegation` to `true`.'; + /** * Resolves the array of Caveat from a Caveats argument. * @param caveats - The caveats to be resolved, which can be either a CaveatBuilder or an array of Caveat. * @returns The resolved array of caveats. */ -export const resolveCaveats = (caveats: Caveats) => { +export const resolveCaveats = ({ + caveats, + allowInsecureUnrestrictedDelegation = false, +}: { + caveats: Caveats; + allowInsecureUnrestrictedDelegation?: boolean; +}) => { if (Array.isArray(caveats)) { + if (caveats.length === 0 && !allowInsecureUnrestrictedDelegation) { + throw new Error(INSECURE_UNRESTRICTED_DELEGATION_ERROR_MESSAGE); + } return caveats; } return caveats.build(); @@ -33,7 +45,7 @@ type CaveatBuilderMap = { }; export type CaveatBuilderConfig = { - allowEmptyCaveats?: boolean; + allowInsecureUnrestrictedDelegation?: boolean; }; /** @@ -150,10 +162,11 @@ export class CaveatBuilder< throw new Error('This CaveatBuilder has already been built.'); } - if (this.#results.length === 0 && !this.#config.allowEmptyCaveats) { - throw new Error( - 'No caveats found. If you definitely want to create an empty caveat collection, set `allowEmptyCaveats`.', - ); + if ( + this.#results.length === 0 && + !this.#config.allowInsecureUnrestrictedDelegation + ) { + throw new Error(INSECURE_UNRESTRICTED_DELEGATION_ERROR_MESSAGE); } this.#hasBeenBuilt = true; diff --git a/packages/delegation-toolkit/src/delegation.ts b/packages/delegation-toolkit/src/delegation.ts index 1d99aca3..d4cbebe5 100644 --- a/packages/delegation-toolkit/src/delegation.ts +++ b/packages/delegation-toolkit/src/delegation.ts @@ -193,6 +193,7 @@ type BaseCreateDelegationOptions = { caveats: Caveats; parentDelegation?: Delegation | Hex; salt?: Hex; + allowInsecureUnrestrictedDelegation?: boolean; }; /** @@ -236,7 +237,7 @@ export const createDelegation = ( delegate: options.to, delegator: options.from, authority: resolveAuthority(options.parentDelegation), - caveats: resolveCaveats(options.caveats), + caveats: resolveCaveats(options), salt: options.salt ?? '0x', signature: '0x', }; @@ -254,7 +255,7 @@ export const createOpenDelegation = ( delegate: ANY_BENEFICIARY, delegator: options.from, authority: resolveAuthority(options.parentDelegation), - caveats: resolveCaveats(options.caveats), + caveats: resolveCaveats(options), salt: options.salt ?? '0x', signature: '0x', }; @@ -278,6 +279,7 @@ export const signDelegation = async ({ chainId, name = 'DelegationManager', version = '1', + allowInsecureUnrestrictedDelegation = false, }: { signer: WalletClient; delegation: Omit; @@ -285,12 +287,22 @@ export const signDelegation = async ({ chainId: number; name?: string; version?: string; + allowInsecureUnrestrictedDelegation?: boolean; }) => { const delegationStruct = toDelegationStruct({ ...delegation, signature: '0x', }); + if ( + delegationStruct.caveats.length === 0 && + !allowInsecureUnrestrictedDelegation + ) { + throw new Error( + 'No caveats found. If you definitely want to sign a delegation without caveats, set `allowInsecureUnrestrictedDelegation` to `true`.', + ); + } + return signer.signTypedData({ account: signer.account, domain: { diff --git a/packages/delegation-toolkit/test/caveatBuilder/CaveatBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/CaveatBuilder.test.ts index 088b79df..01137cdc 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/CaveatBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/CaveatBuilder.test.ts @@ -27,18 +27,18 @@ describe('CaveatBuilder', () => { }); }); - describe('allowEmptyCaveats', () => { + describe('allowInsecureUnrestrictedDelegation', () => { it('should disallow empty caveats', () => { const builder = new CaveatBuilder({} as DeleGatorEnvironment); expect(() => builder.build()).to.throw( - 'No caveats found. If you definitely want to create an empty caveat collection, set `allowEmptyCaveats`.', + 'No caveats found. If you definitely want to create an empty caveat collection, set `allowInsecureUnrestrictedDelegation` to `true`.', ); }); it('should allow empty caveats', () => { const builder = new CaveatBuilder({} as DeleGatorEnvironment, { - allowEmptyCaveats: true, + allowInsecureUnrestrictedDelegation: true, }); expect(() => builder.build()).to.not.throw(); @@ -46,7 +46,7 @@ describe('CaveatBuilder', () => { it('should allow empty caveats when extended', () => { const builder = new CaveatBuilder({} as DeleGatorEnvironment, { - allowEmptyCaveats: true, + allowInsecureUnrestrictedDelegation: true, }).extend('caveat', () => caveat1); expect(() => builder.build()).to.not.throw(); diff --git a/packages/delegation-toolkit/test/caveatBuilder/createCaveatBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/createCaveatBuilder.test.ts index d49e7ae7..2d86ddbe 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/createCaveatBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/createCaveatBuilder.test.ts @@ -41,13 +41,13 @@ describe('createCaveatBuilder()', () => { const builder = createCaveatBuilder(environment); expect(() => builder.build()).to.throw( - 'No caveats found. If you definitely want to create an empty caveat collection, set `allowEmptyCaveats`.', + 'No caveats found. If you definitely want to create an empty caveat collection, set `allowInsecureUnrestrictedDelegation` to `true`.', ); }); it('should allow empty caveats, when configured', () => { const builder = createCaveatBuilder(environment, { - allowEmptyCaveats: true, + allowInsecureUnrestrictedDelegation: true, }); expect(() => builder.build()).to.not.throw(); @@ -391,7 +391,7 @@ describe('createCaveatBuilder()', () => { it("should add a 'nativeTokenPayment' caveat", () => { const builder = createCaveatBuilder(environment); const amount = 1000000000000000000n; // 1 ETH in wei - const recipient = randomAddress(true); + const recipient = randomAddress('lowercase'); const caveats = builder .addCaveat('nativeTokenPayment', recipient, amount) diff --git a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPaymentBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPaymentBuilder.test.ts index b6fbbd53..ef03ad4a 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPaymentBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPaymentBuilder.test.ts @@ -36,7 +36,7 @@ describe('nativeTokenPaymentBuilder()', () => { describe('builds a caveat', () => { it('should build a caveat with valid amount and recipient', () => { const amount = 1000000000000000000n; // 1 ETH - const recipient = randomAddress(true); // lowerCase because abi encoding lowercases addresses + const recipient = randomAddress('lowercase'); // lowerCase because abi encoding lowercases addresses const caveat = buildWithAmountAndRecipient(recipient, amount); const amountHex = toHex(amount, { size: 32 }); @@ -51,7 +51,7 @@ describe('nativeTokenPaymentBuilder()', () => { it('should build a caveat with minimum possible amount', () => { const amount = 1n; - const recipient = randomAddress(true); // lowerCase because abi encoding lowercases addressesç + const recipient = randomAddress('lowercase'); // lowerCase because abi encoding lowercases addressesç const caveat = buildWithAmountAndRecipient(recipient, amount); @@ -68,7 +68,7 @@ describe('nativeTokenPaymentBuilder()', () => { it('should create a caveat with terms length matching number of targets', () => { const amount = 1000000000000000000n; // 1 ETH - const recipient = randomAddress(true); // lowerCase because abi encoding lowercases addresses + const recipient = randomAddress('lowercase'); // lowerCase because abi encoding lowercases addresses const caveat = buildWithAmountAndRecipient(recipient, amount); diff --git a/packages/delegation-toolkit/test/delegation.test.ts b/packages/delegation-toolkit/test/delegation.test.ts index 824b9a9f..99f5b57d 100644 --- a/packages/delegation-toolkit/test/delegation.test.ts +++ b/packages/delegation-toolkit/test/delegation.test.ts @@ -13,21 +13,32 @@ import { decodeDelegations, encodePermissionContexts, decodePermissionContexts, + signDelegation, } from '../src/delegation'; import type { Caveat, Delegation } from '../src/types'; +import { randomAddress } from './utils'; +import { getAddress } from 'viem'; const mockDelegate = '0x1234567890123456789012345678901234567890' as const; const mockDelegator = '0x0987654321098765432109876543210987654321' as const; const mockSignature = '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890' as const; +// delegation encoding in @metamask/delegation-core will lowercase any Hex strings +const mockCaveat: Caveat = { + enforcer: randomAddress('lowercase'), + terms: '0x', + args: '0x', +}; + describe('toDelegationStruct', () => { it('should convert a basic delegation to struct', () => { + // toDelegationStruct will checksum the addresses const delegation: Delegation = { delegate: mockDelegate, delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: '0x123', signature: mockSignature, }; @@ -37,7 +48,7 @@ describe('toDelegationStruct', () => { delegate: mockDelegate, delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [{ ...mockCaveat, enforcer: getAddress(mockCaveat.enforcer) }], salt: 291n, signature: mockSignature, }); @@ -113,7 +124,7 @@ describe('resolveAuthority', () => { delegate: mockDelegate, delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: '0x', signature: '0x', }; @@ -128,14 +139,14 @@ describe('createDelegation', () => { const result = createDelegation({ to: mockDelegate, from: mockDelegator, - caveats: [], + caveats: [mockCaveat], }); expect(result).to.deep.equal({ delegate: mockDelegate, delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: '0x', signature: '0x', }); @@ -147,7 +158,7 @@ describe('createDelegation', () => { const result = createDelegation({ to: mockDelegate, from: mockDelegator, - caveats: [], + caveats: [mockCaveat], parentDelegation: parentHash, }); @@ -155,7 +166,7 @@ describe('createDelegation', () => { delegate: mockDelegate, delegator: mockDelegator, authority: parentHash, - caveats: [], + caveats: [mockCaveat], salt: '0x', signature: '0x', }); @@ -197,14 +208,14 @@ describe('createDelegation', () => { const result = createDelegation({ to: mockDelegate, from: mockDelegator, - caveats: [], + caveats: [mockCaveat], salt: customSalt, }); expect(result).to.deep.equal({ delegate: mockDelegate, delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: customSalt, signature: '0x', }); @@ -215,14 +226,14 @@ describe('createOpenDelegation', () => { it('should create a basic open delegation with root authority', () => { const result = createOpenDelegation({ from: mockDelegator, - caveats: [], + caveats: [mockCaveat], }); expect(result).to.deep.equal({ delegate: '0x0000000000000000000000000000000000000a11', delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: '0x', signature: '0x', }); @@ -233,7 +244,7 @@ describe('createOpenDelegation', () => { '0x1234567890123456789012345678901234567890123456789012345678901234' as const; const result = createOpenDelegation({ from: mockDelegator, - caveats: [], + caveats: [mockCaveat], parentDelegation: parentHash, }); @@ -241,7 +252,7 @@ describe('createOpenDelegation', () => { delegate: '0x0000000000000000000000000000000000000a11', delegator: mockDelegator, authority: parentHash, - caveats: [], + caveats: [mockCaveat], salt: '0x', signature: '0x', }); @@ -281,18 +292,50 @@ describe('createOpenDelegation', () => { const customSalt = '0xdeadbeef'; const result = createOpenDelegation({ from: mockDelegator, - caveats: [], + caveats: [mockCaveat], salt: customSalt, }); expect(result).to.deep.equal({ delegate: '0x0000000000000000000000000000000000000a11', delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: customSalt, signature: '0x', }); }); + + it('should throw an error if no caveats are provided', () => { + expect(() => + createOpenDelegation({ + from: mockDelegator, + caveats: [], + }), + ).to.throw( + 'No caveats found. If you definitely want to create an empty caveat collection, set `allowInsecureUnrestrictedDelegation` to `true`.', + ); + }); + + it('should throw an error if no caveats are provided and allowInsecureUnrestrictedDelegation is false', () => { + expect(() => + createOpenDelegation({ + from: mockDelegator, + caveats: [], + }), + ).to.throw( + 'No caveats found. If you definitely want to create an empty caveat collection, set `allowInsecureUnrestrictedDelegation` to `true`.', + ); + }); + + it('should not throw an error if no caveats are provided and allowInsecureUnrestrictedDelegation is true', () => { + expect(() => + createOpenDelegation({ + from: mockDelegator, + caveats: [], + allowInsecureUnrestrictedDelegation: true, + }), + ).to.not.throw(); + }); }); describe('resolveCaveats', () => { @@ -305,7 +348,7 @@ describe('resolveCaveats', () => { }, ]; - const result = resolveCaveats(caveats); + const result = resolveCaveats({ caveats }); expect(result).to.equal(caveats); expect(result).to.deep.equal(caveats); }); @@ -323,7 +366,7 @@ describe('resolveCaveats', () => { build: stub().returns(mockCaveats), }; - const result = resolveCaveats(mockBuilder as any); + const result = resolveCaveats({ caveats: mockBuilder as any }); expect(mockBuilder.build.calledOnce).to.equal(true); expect(result).to.deep.equal(mockCaveats); @@ -334,7 +377,9 @@ describe('resolveCaveats', () => { build: stub().throws(new Error('Build failed')), }; - expect(() => resolveCaveats(mockBuilder as any)).to.throw('Build failed'); + expect(() => resolveCaveats({ caveats: mockBuilder as any })).to.throw( + 'Build failed', + ); expect(mockBuilder.build.calledOnce).to.equal(true); }); }); @@ -344,7 +389,7 @@ describe('encodeDelegations', () => { delegate: mockDelegate, delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: '0x123', signature: mockSignature, }; @@ -396,7 +441,7 @@ describe('decodeDelegations', () => { delegate: mockDelegate, delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: '0x123', signature: mockSignature, }; @@ -448,7 +493,7 @@ describe('encodePermissionContexts', () => { delegate: mockDelegate, delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: '0x123', signature: mockSignature, }; @@ -509,7 +554,7 @@ describe('decodePermissionContexts', () => { delegate: mockDelegate, delegator: mockDelegator, authority: ROOT_AUTHORITY, - caveats: [], + caveats: [mockCaveat], salt: '0x123', signature: mockSignature, }; @@ -564,3 +609,80 @@ describe('decodePermissionContexts', () => { expect(decoded).to.have.length(0); }); }); + +describe('signDelegation', () => { + const mockSigner = { + signTypedData: stub().resolves('mockSignature'), + account: { address: '0xSignerAccount' }, + cacheTime: 0, + chain: {}, + key: 'mockKey', + name: 'mockName', + transport: {}, + }; + + const mockDelegation = { + delegate: mockDelegate, + delegator: mockDelegator, + authority: ROOT_AUTHORITY as `0x${string}`, + caveats: [mockCaveat], + salt: '0x123' as `0x${string}`, + }; + + const delegationManager = '0xDelegationManager' as `0x${string}`; + const chainId = 1; + + beforeEach(() => { + mockSigner.signTypedData.resetHistory(); + }); + + it('should sign a delegation successfully', async () => { + const signature = await signDelegation({ + signer: mockSigner as any, + delegation: mockDelegation, + delegationManager, + chainId, + }); + + expect(signature).to.equal('mockSignature'); + expect(mockSigner.signTypedData.calledOnce).to.be.true; + }); + + it('should throw an error if no caveats are provided and allowInsecureUnrestrictedDelegation is false', async () => { + const delegationWithoutCaveats = { + ...mockDelegation, + caveats: [], + salt: '0x123' as `0x${string}`, + }; + + await expect( + signDelegation({ + signer: mockSigner as any, + delegation: delegationWithoutCaveats, + delegationManager, + chainId, + }), + ).to.be.rejectedWith( + 'No caveats found. If you definitely want to sign a delegation without caveats, set `allowInsecureUnrestrictedDelegation` to `true`.', + ); + }); + + it('should sign a delegation without caveats if allowInsecureUnrestrictedDelegation is true', async () => { + const delegationWithoutCaveats = { + ...mockDelegation, + caveats: [], + salt: '0x123' as `0x${string}`, + }; + + const signature = await signDelegation({ + signer: mockSigner as any, + delegation: delegationWithoutCaveats, + delegationManager, + chainId, + allowInsecureUnrestrictedDelegation: true, + }); + + expect(signature).to.equal('mockSignature'); + expect(mockSigner.signTypedData.calledOnce).to.equal(true); + }); +}); diff --git a/packages/delegation-toolkit/test/utils.ts b/packages/delegation-toolkit/test/utils.ts index c45bf61b..d7d308ad 100644 --- a/packages/delegation-toolkit/test/utils.ts +++ b/packages/delegation-toolkit/test/utils.ts @@ -1,5 +1,5 @@ import hre from 'hardhat'; -import { bytesToHex } from 'viem'; +import { bytesToHex, getAddress } from 'viem'; import type { Chain, Hex, @@ -29,13 +29,16 @@ export const PRIVATE_KEY_Y = 3540107420755600117661092318610451508057836103782892212756062701855335759222n; export const THRESHOLD = 1; -export const randomAddress = (lowerCase = false) => { +export const randomAddress = ( + mode: 'lowercase' | 'checksum' | 'none' = 'none', +) => { const address = privateKeyToAddress(generatePrivateKey()); - if (!lowerCase) { - return address; + if (mode === 'lowercase') { + return address.toLowerCase() as Hex; + } else if (mode === 'checksum') { + return getAddress(address); } - - return address.toLowerCase() as Hex; + return address; }; export const randomBytes = (byteLength: number): Hex => { diff --git a/packages/delegator-e2e/test/caveats/nativeTokenPayment.test.ts b/packages/delegator-e2e/test/caveats/nativeTokenPayment.test.ts index 7f67ceba..0dbd0154 100644 --- a/packages/delegator-e2e/test/caveats/nativeTokenPayment.test.ts +++ b/packages/delegator-e2e/test/caveats/nativeTokenPayment.test.ts @@ -142,7 +142,7 @@ test('Bob attempts to redeem the delegation without an argsEqualityCheckEnforcer to: bobSmartAccount.environment.caveatEnforcers.NativeTokenPaymentEnforcer!, from: bobSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment, { - allowEmptyCaveats: true, + allowInsecureUnrestrictedDelegation: true, }), }); diff --git a/packages/delegator-e2e/test/delegateAndRedeem.test.ts b/packages/delegator-e2e/test/delegateAndRedeem.test.ts index 23d9c311..e6914d3c 100644 --- a/packages/delegator-e2e/test/delegateAndRedeem.test.ts +++ b/packages/delegator-e2e/test/delegateAndRedeem.test.ts @@ -18,12 +18,12 @@ import { signDelegation, aggregateSignature, type MetaMaskSmartAccount, + type PartialSignature, } from '@metamask/delegation-toolkit'; import { encodePermissionContexts, encodeExecutionCalldatas, SINGLE_DEFAULT_MODE, - type PartialSignature, } from '@metamask/delegation-toolkit/utils'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; import { diff --git a/packages/delegator-e2e/test/experimental/erc7710sendTransactionWithDelegation.test.ts b/packages/delegator-e2e/test/experimental/erc7710sendTransactionWithDelegation.test.ts index 72aec458..dea90f15 100644 --- a/packages/delegator-e2e/test/experimental/erc7710sendTransactionWithDelegation.test.ts +++ b/packages/delegator-e2e/test/experimental/erc7710sendTransactionWithDelegation.test.ts @@ -146,7 +146,7 @@ test('Bob redelegates to Carol, who redeems the delegation to call increment() o from: bob.address, parentDelegation: signedDelegation, caveats: createCaveatBuilder(aliceSmartAccount.environment, { - allowEmptyCaveats: true, + allowInsecureUnrestrictedDelegation: true, }), }); diff --git a/packages/delegator-e2e/test/experimental/erc7710sendUserOperationWithDelegation.test.ts b/packages/delegator-e2e/test/experimental/erc7710sendUserOperationWithDelegation.test.ts index 9d5407fa..cd7f5512 100644 --- a/packages/delegator-e2e/test/experimental/erc7710sendUserOperationWithDelegation.test.ts +++ b/packages/delegator-e2e/test/experimental/erc7710sendUserOperationWithDelegation.test.ts @@ -65,9 +65,7 @@ beforeEach(async () => { const aliceCounter = await deployCounter(aliceSmartAccount.address); aliceCounterContractAddress = aliceCounter.address; - const caveats = createCaveatBuilder(aliceSmartAccount.environment, { - allowEmptyCaveats: true, - }) + const caveats = createCaveatBuilder(aliceSmartAccount.environment) .addCaveat('allowedTargets', [aliceCounterContractAddress]) .addCaveat('allowedMethods', ['increment()']) .addCaveat('valueLte', 0n); From b1ecdecb42d8daa683b224c3e191949e5e97a20f Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Tue, 8 Jul 2025 10:38:27 +1200 Subject: [PATCH 2/9] Update calldata casing to be consistent in delegation-core package --- packages/delegation-core/README.md | 86 ++++++++++++------- .../src/caveats/exactCalldata.ts | 14 +-- .../test/caveats/exactCalldata.test.ts | 82 +++++++++--------- 3 files changed, 104 insertions(+), 78 deletions(-) diff --git a/packages/delegation-core/README.md b/packages/delegation-core/README.md index b9f1c1aa..4d7bb52e 100644 --- a/packages/delegation-core/README.md +++ b/packages/delegation-core/README.md @@ -17,6 +17,7 @@ yarn add @metamask/delegation-core ## Overview This package provides utilities for: + - Creating caveat terms for various delegation constraints - Encoding and decoding delegations - Type definitions for delegation structures @@ -32,6 +33,7 @@ Caveat terms builders create encoded parameters for different types of delegatio Creates terms for a ValueLte caveat that limits the maximum value of native tokens that can be spent. **Parameters:** + - `terms: ValueLteTerms` - `maxValue: bigint` - The maximum value allowed for the transaction - `options?: EncodingOptions` - Optional encoding options (`'hex'` | `'bytes'`) @@ -39,19 +41,23 @@ Creates terms for a ValueLte caveat that limits the maximum value of native toke **Returns:** `Hex | Uint8Array` - 32-byte encoded terms **Example:** + ```typescript import { createValueLteTerms } from '@metamask/delegation-core'; // Limit to 1 ETH maximum const terms = createValueLteTerms({ - maxValue: 1000000000000000000n // 1 ETH in wei + maxValue: 1000000000000000000n, // 1 ETH in wei }); // Returns: '0x0000000000000000000000000000000000000000000000000de0b6b3a7640000' // Get as Uint8Array -const bytesTerms = createValueLteTerms({ - maxValue: 1000000000000000000n -}, { out: 'bytes' }); +const bytesTerms = createValueLteTerms( + { + maxValue: 1000000000000000000n, + }, + { out: 'bytes' }, +); ``` #### `createTimestampTerms(terms, options?)` @@ -59,6 +65,7 @@ const bytesTerms = createValueLteTerms({ Creates terms for a Timestamp caveat that enforces time-based constraints on delegation usage. **Parameters:** + - `terms: TimestampTerms` - `timestampAfterThreshold: number` - Timestamp (seconds) after which delegation can be used - `timestampBeforeThreshold: number` - Timestamp (seconds) before which delegation can be used @@ -67,19 +74,20 @@ Creates terms for a Timestamp caveat that enforces time-based constraints on del **Returns:** `Hex | Uint8Array` - 32-byte encoded terms (16 bytes per timestamp) **Example:** + ```typescript import { createTimestampTerms } from '@metamask/delegation-core'; // Valid between Jan 1, 2022 and Jan 1, 2023 const terms = createTimestampTerms({ - timestampAfterThreshold: 1640995200, // 2022-01-01 00:00:00 UTC - timestampBeforeThreshold: 1672531200 // 2023-01-01 00:00:00 UTC + timestampAfterThreshold: 1640995200, // 2022-01-01 00:00:00 UTC + timestampBeforeThreshold: 1672531200, // 2023-01-01 00:00:00 UTC }); // Only valid after a certain time (no end time) const openEndedTerms = createTimestampTerms({ timestampAfterThreshold: 1640995200, - timestampBeforeThreshold: 0 + timestampBeforeThreshold: 0, }); ``` @@ -88,24 +96,27 @@ const openEndedTerms = createTimestampTerms({ Creates terms for an ExactCalldata caveat that ensures execution calldata matches exactly. **Parameters:** + - `terms: ExactCalldataTerms` - - `callData: BytesLike` - The expected calldata (hex string or Uint8Array) + - `calldata: BytesLike` - The expected calldata (hex string or Uint8Array) - `options?: EncodingOptions` - Optional encoding options **Returns:** `Hex | Uint8Array` - The calldata itself (variable length) **Example:** + ```typescript import { createExactCalldataTerms } from '@metamask/delegation-core'; // Exact calldata for a specific function call const terms = createExactCalldataTerms({ - callData: '0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b8d40ec49b0e8baa5e0000000000000000000000000000000000000000000000000de0b6b3a7640000' + calldata: + '0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b8d40ec49b0e8baa5e0000000000000000000000000000000000000000000000000de0b6b3a7640000', }); // From Uint8Array const terms2 = createExactCalldataTerms({ - callData: new Uint8Array([0xa9, 0x05, 0x9c, 0xbb, /* ... */]) + calldata: new Uint8Array([0xa9, 0x05, 0x9c, 0xbb /* ... */]), }); ``` @@ -114,6 +125,7 @@ const terms2 = createExactCalldataTerms({ Creates terms for periodic native token transfer limits with time-based resets. **Parameters:** + - `terms: NativeTokenPeriodTransferTerms` - `periodAmount: bigint` - Maximum amount transferable per period (wei) - `periodDuration: number` - Duration of each period (seconds) @@ -123,14 +135,15 @@ Creates terms for periodic native token transfer limits with time-based resets. **Returns:** `Hex | Uint8Array` - 96-byte encoded terms (32 bytes per parameter) **Example:** + ```typescript import { createNativeTokenPeriodTransferTerms } from '@metamask/delegation-core'; // Allow 1 ETH per day starting from a specific date const terms = createNativeTokenPeriodTransferTerms({ - periodAmount: 1000000000000000000n, // 1 ETH in wei - periodDuration: 86400, // 24 hours in seconds - startDate: 1640995200 // 2022-01-01 00:00:00 UTC + periodAmount: 1000000000000000000n, // 1 ETH in wei + periodDuration: 86400, // 24 hours in seconds + startDate: 1640995200, // 2022-01-01 00:00:00 UTC }); ``` @@ -139,6 +152,7 @@ const terms = createNativeTokenPeriodTransferTerms({ Creates terms for linear streaming allowance of native tokens. **Parameters:** + - `terms: NativeTokenStreamingTerms` - `initialAmount: bigint` - Amount available immediately (wei) - `maxAmount: bigint` - Maximum total transferable amount (wei) @@ -149,15 +163,16 @@ Creates terms for linear streaming allowance of native tokens. **Returns:** `Hex | Uint8Array` - 128-byte encoded terms (32 bytes per parameter) **Example:** + ```typescript import { createNativeTokenStreamingTerms } from '@metamask/delegation-core'; // Stream 0.5 ETH per second, starting with 1 ETH, max 10 ETH const terms = createNativeTokenStreamingTerms({ - initialAmount: 1000000000000000000n, // 1 ETH available immediately - maxAmount: 10000000000000000000n, // 10 ETH maximum - amountPerSecond: 500000000000000000n, // 0.5 ETH per second - startTime: 1640995200 // Start streaming at this time + initialAmount: 1000000000000000000n, // 1 ETH available immediately + maxAmount: 10000000000000000000n, // 10 ETH maximum + amountPerSecond: 500000000000000000n, // 0.5 ETH per second + startTime: 1640995200, // Start streaming at this time }); ``` @@ -166,6 +181,7 @@ const terms = createNativeTokenStreamingTerms({ Creates terms for linear streaming allowance of ERC20 tokens. **Parameters:** + - `terms: ERC20StreamingTerms` - `tokenAddress: string` - ERC20 token contract address - `initialAmount: bigint` - Amount available immediately @@ -177,16 +193,17 @@ Creates terms for linear streaming allowance of ERC20 tokens. **Returns:** `Hex | Uint8Array` - 148-byte encoded terms (20 bytes + 32 bytes × 4 parameters) **Example:** + ```typescript import { createERC20StreamingTerms } from '@metamask/delegation-core'; // Stream USDC tokens const terms = createERC20StreamingTerms({ tokenAddress: '0xA0b86a33E6441E74C65c6BF2A6d73B895B9b34A2', - initialAmount: 1000000n, // 1 USDC (6 decimals) - maxAmount: 10000000n, // 10 USDC maximum - amountPerSecond: 100000n, // 0.1 USDC per second - startTime: 1640995200 + initialAmount: 1000000n, // 1 USDC (6 decimals) + maxAmount: 10000000n, // 10 USDC maximum + amountPerSecond: 100000n, // 0.1 USDC per second + startTime: 1640995200, }); ``` @@ -195,6 +212,7 @@ const terms = createERC20StreamingTerms({ Creates terms for an ERC20TokenPeriodTransfer caveat that validates that ERC20 token transfers do not exceed a specified amount within a given time period. **Parameters:** + - `terms: ERC20TokenPeriodTransferTerms` - `tokenAddress: BytesLike` - The address of the ERC20 token. - `periodAmount: bigint` - The maximum amount that can be transferred within each period. @@ -205,15 +223,16 @@ Creates terms for an ERC20TokenPeriodTransfer caveat that validates that ERC20 t **Returns:** `Hex | Uint8Array` - 116-byte encoded terms (20 bytes for address + 32 bytes per parameter) **Example:** + ```typescript import { createERC20TokenPeriodTransferTerms } from '@metamask/delegation-core'; // Allow 100 tokens per day starting from a specific date const terms = createERC20TokenPeriodTransferTerms({ tokenAddress: '0xA0b86a33E6441E74C65c6BF2A6d73B895B9b34A2', - periodAmount: 100n, // 100 tokens - periodDuration: 86400, // 24 hours in seconds - startDate: 1640995200 // 2022-01-01 00:00:00 UTC + periodAmount: 100n, // 100 tokens + periodDuration: 86400, // 24 hours in seconds + startDate: 1640995200, // 2022-01-01 00:00:00 UTC }); ``` @@ -224,11 +243,13 @@ const terms = createERC20TokenPeriodTransferTerms({ Encodes an array of delegations into a format suitable for on-chain submission. **Parameters:** + - `delegations: Delegation[]` - Array of delegation objects **Returns:** Encoded delegation data **Example:** + ```typescript import { encodeDelegations } from '@metamask/delegation-core'; @@ -239,8 +260,8 @@ const delegations = [ authority: '0x...', caveats: [], salt: 0n, - signature: '0x...' - } + signature: '0x...', + }, ]; const encoded = encodeDelegations(delegations); @@ -251,11 +272,13 @@ const encoded = encodeDelegations(delegations); Decodes encoded delegation data back into delegation objects. **Parameters:** + - `data` - Encoded delegation data **Returns:** `Delegation[]` - Array of decoded delegation objects **Example:** + ```typescript import { decodeDelegations } from '@metamask/delegation-core'; @@ -267,6 +290,7 @@ const delegations = decodeDelegations(encodedData); A constant representing the root authority in the delegation hierarchy. **Example:** + ```typescript import { ROOT_AUTHORITY } from '@metamask/delegation-core'; @@ -278,11 +302,13 @@ console.log(ROOT_AUTHORITY); // Root authority identifier Computes a hash for a given delegation object. **Parameters:** + - `delegation: DelegationStruct` - The delegation object to hash **Returns:** `Hex` - The hash of the delegation **Example:** + ```typescript import { hashDelegation } from '@metamask/delegation-core'; @@ -292,7 +318,7 @@ const delegation = { authority: '0x...', caveats: [], salt: 0n, - signature: '0x...' + signature: '0x...', }; const hash = hashDelegation(delegation); @@ -333,7 +359,7 @@ export type TimestampTerms = { }; export type ExactCalldataTerms = { - callData: BytesLike; + calldata: BytesLike; }; export type NativeTokenPeriodTransferTerms = { @@ -365,7 +391,7 @@ All caveat builders include validation and will throw descriptive errors: ```typescript try { const terms = createValueLteTerms({ - maxValue: -1n // Invalid: negative value + maxValue: -1n, // Invalid: negative value }); } catch (error) { console.error(error.message); // "Invalid maxValue: must be greater than or equal to zero" @@ -381,4 +407,4 @@ try { ## Links - [MetaMask Delegation Framework](https://github.com/MetaMask/delegation-framework) -- [EIP-7715: Delegated Authorization](https://eips.ethereum.org/EIPS/eip-7715) \ No newline at end of file +- [EIP-7715: Delegated Authorization](https://eips.ethereum.org/EIPS/eip-7715) diff --git a/packages/delegation-core/src/caveats/exactCalldata.ts b/packages/delegation-core/src/caveats/exactCalldata.ts index e944d73f..c5a5a5d7 100644 --- a/packages/delegation-core/src/caveats/exactCalldata.ts +++ b/packages/delegation-core/src/caveats/exactCalldata.ts @@ -13,7 +13,7 @@ import type { Hex } from '../types'; */ export type ExactCalldataTerms = { /** The expected calldata to match against. */ - callData: BytesLike; + calldata: BytesLike; }; /** @@ -23,7 +23,7 @@ export type ExactCalldataTerms = { * @param terms - The terms for the ExactCalldata caveat. * @param encodingOptions - The encoding options for the result. * @returns The terms as the calldata itself. - * @throws Error if the `callData` is invalid. + * @throws Error if the `calldata` is invalid. */ export function createExactCalldataTerms( terms: ExactCalldataTerms, @@ -39,18 +39,18 @@ export function createExactCalldataTerms( * @param terms - The terms for the ExactCalldata caveat. * @param encodingOptions - The encoding options for the result. * @returns The terms as the calldata itself. - * @throws Error if the `callData` is invalid. + * @throws Error if the `calldata` is invalid. */ export function createExactCalldataTerms( terms: ExactCalldataTerms, encodingOptions: EncodingOptions = defaultOptions, ): Hex | Uint8Array { - const { callData } = terms; + const { calldata } = terms; - if (typeof callData === 'string' && !callData.startsWith('0x')) { - throw new Error('Invalid callData: must be a hex string starting with 0x'); + if (typeof calldata === 'string' && !calldata.startsWith('0x')) { + throw new Error('Invalid calldata: must be a hex string starting with 0x'); } // For exact calldata, the terms are simply the expected calldata - return prepareResult(callData, encodingOptions); + return prepareResult(calldata, encodingOptions); } diff --git a/packages/delegation-core/test/caveats/exactCalldata.test.ts b/packages/delegation-core/test/caveats/exactCalldata.test.ts index d5a2faea..719de866 100644 --- a/packages/delegation-core/test/caveats/exactCalldata.test.ts +++ b/packages/delegation-core/test/caveats/exactCalldata.test.ts @@ -6,53 +6,53 @@ import type { Hex } from '../../src/types'; describe('createExactCalldataTerms', () => { // Note: ExactCalldata terms length varies based on input calldata length it('creates valid terms for simple calldata', () => { - const callData = '0x1234567890abcdef'; - const result = createExactCalldataTerms({ callData }); + const calldata = '0x1234567890abcdef'; + const result = createExactCalldataTerms({ calldata }); - expect(result).toStrictEqual(callData); + expect(result).toStrictEqual(calldata); }); it('creates valid terms for empty calldata', () => { - const callData = '0x'; - const result = createExactCalldataTerms({ callData }); + const calldata = '0x'; + const result = createExactCalldataTerms({ calldata }); expect(result).toStrictEqual('0x'); }); it('creates valid terms for function call with parameters', () => { // Example: transfer(address,uint256) function call - const callData = + const calldata = '0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b8d40ec49b0e8baa5e0000000000000000000000000000000000000000000000000de0b6b3a7640000'; - const result = createExactCalldataTerms({ callData }); + const result = createExactCalldataTerms({ calldata }); - expect(result).toStrictEqual(callData); + expect(result).toStrictEqual(calldata); }); it('creates valid terms for complex calldata', () => { - const callData = + const calldata = '0x23b872dd000000000000000000000000742d35cc6634c0532925a3b8d40ec49b0e8baa5e000000000000000000000000742d35cc6634c0532925a3b8d40ec49b0e8baa5f0000000000000000000000000000000000000000000000000de0b6b3a7640000'; - const result = createExactCalldataTerms({ callData }); + const result = createExactCalldataTerms({ calldata }); - expect(result).toStrictEqual(callData); + expect(result).toStrictEqual(calldata); }); it('creates valid terms for uppercase hex calldata', () => { - const callData = '0x1234567890ABCDEF'; - const result = createExactCalldataTerms({ callData }); + const calldata = '0x1234567890ABCDEF'; + const result = createExactCalldataTerms({ calldata }); - expect(result).toStrictEqual(callData); + expect(result).toStrictEqual(calldata); }); it('creates valid terms for mixed case hex calldata', () => { - const callData = '0x1234567890AbCdEf'; - const result = createExactCalldataTerms({ callData }); + const calldata = '0x1234567890AbCdEf'; + const result = createExactCalldataTerms({ calldata }); - expect(result).toStrictEqual(callData); + expect(result).toStrictEqual(calldata); }); it('creates valid terms for very long calldata', () => { const longCalldata: Hex = `0x${'a'.repeat(1000)}`; - const result = createExactCalldataTerms({ callData: longCalldata }); + const result = createExactCalldataTerms({ calldata: longCalldata }); expect(result).toStrictEqual(longCalldata); }); @@ -61,50 +61,50 @@ describe('createExactCalldataTerms', () => { const invalidCallData = '1234567890abcdef'; expect(() => - createExactCalldataTerms({ callData: invalidCallData as Hex }), - ).toThrow('Invalid callData: must be a hex string starting with 0x'); + createExactCalldataTerms({ calldata: invalidCallData as Hex }), + ).toThrow('Invalid calldata: must be a hex string starting with 0x'); }); it('throws an error for empty string', () => { const invalidCallData = ''; expect(() => - createExactCalldataTerms({ callData: invalidCallData as Hex }), - ).toThrow('Invalid callData: must be a hex string starting with 0x'); + createExactCalldataTerms({ calldata: invalidCallData as Hex }), + ).toThrow('Invalid calldata: must be a hex string starting with 0x'); }); it('throws an error for malformed hex prefix', () => { const invalidCallData = '0X1234'; // uppercase X expect(() => - createExactCalldataTerms({ callData: invalidCallData as Hex }), - ).toThrow('Invalid callData: must be a hex string starting with 0x'); + createExactCalldataTerms({ calldata: invalidCallData as Hex }), + ).toThrow('Invalid calldata: must be a hex string starting with 0x'); }); it('throws an error for undefined callData', () => { expect(() => - createExactCalldataTerms({ callData: undefined as any }), + createExactCalldataTerms({ calldata: undefined as any }), ).toThrow(); }); it('throws an error for null callData', () => { - expect(() => createExactCalldataTerms({ callData: null as any })).toThrow(); + expect(() => createExactCalldataTerms({ calldata: null as any })).toThrow(); }); it('throws an error for non-string non-Uint8Array callData', () => { - expect(() => createExactCalldataTerms({ callData: 1234 as any })).toThrow(); + expect(() => createExactCalldataTerms({ calldata: 1234 as any })).toThrow(); }); it('handles single function selector', () => { const functionSelector = '0xa9059cbb'; // transfer(address,uint256) selector - const result = createExactCalldataTerms({ callData: functionSelector }); + const result = createExactCalldataTerms({ calldata: functionSelector }); expect(result).toStrictEqual(functionSelector); }); it('handles calldata with odd length', () => { const oddLengthCalldata = '0x123'; - const result = createExactCalldataTerms({ callData: oddLengthCalldata }); + const result = createExactCalldataTerms({ calldata: oddLengthCalldata }); expect(result).toStrictEqual(oddLengthCalldata); }); @@ -112,8 +112,8 @@ describe('createExactCalldataTerms', () => { // Tests for bytes return type describe('bytes return type', () => { it('returns Uint8Array when bytes encoding is specified', () => { - const callData = '0x1234567890abcdef'; - const result = createExactCalldataTerms({ callData }, { out: 'bytes' }); + const calldata = '0x1234567890abcdef'; + const result = createExactCalldataTerms({ calldata }, { out: 'bytes' }); expect(result).toBeInstanceOf(Uint8Array); expect(Array.from(result)).toEqual([ @@ -122,17 +122,17 @@ describe('createExactCalldataTerms', () => { }); it('returns Uint8Array for empty calldata with bytes encoding', () => { - const callData = '0x'; - const result = createExactCalldataTerms({ callData }, { out: 'bytes' }); + const calldata = '0x'; + const result = createExactCalldataTerms({ calldata }, { out: 'bytes' }); expect(result).toBeInstanceOf(Uint8Array); expect(result).toHaveLength(0); }); it('returns Uint8Array for complex calldata with bytes encoding', () => { - const callData = + const calldata = '0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b8d40ec49b0e8baa5e0000000000000000000000000000000000000000000000000de0b6b3a7640000'; - const result = createExactCalldataTerms({ callData }, { out: 'bytes' }); + const result = createExactCalldataTerms({ calldata }, { out: 'bytes' }); expect(result).toBeInstanceOf(Uint8Array); expect(result).toHaveLength(68); // 4 bytes selector + 32 bytes address + 32 bytes amount @@ -141,18 +141,18 @@ describe('createExactCalldataTerms', () => { // Tests for Uint8Array input parameter describe('Uint8Array input parameter', () => { - it('accepts Uint8Array as callData parameter', () => { + it('accepts Uint8Array as calldata parameter', () => { const callDataBytes = new Uint8Array([ 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, ]); - const result = createExactCalldataTerms({ callData: callDataBytes }); + const result = createExactCalldataTerms({ calldata: callDataBytes }); expect(result).toStrictEqual('0x1234567890abcdef'); }); - it('accepts empty Uint8Array as callData parameter', () => { + it('accepts empty Uint8Array as calldata parameter', () => { const callDataBytes = new Uint8Array([]); - const result = createExactCalldataTerms({ callData: callDataBytes }); + const result = createExactCalldataTerms({ calldata: callDataBytes }); expect(result).toStrictEqual('0x'); }); @@ -229,7 +229,7 @@ describe('createExactCalldataTerms', () => { 0x00, 0x00, // amount ]); - const result = createExactCalldataTerms({ callData: callDataBytes }); + const result = createExactCalldataTerms({ calldata: callDataBytes }); expect(result).toStrictEqual( '0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b8d40ec49b0e8baa5e0000000000000000000000000000000000000000000000000de0b6b3a7640000', @@ -239,7 +239,7 @@ describe('createExactCalldataTerms', () => { it('returns Uint8Array when input is Uint8Array and bytes encoding is specified', () => { const callDataBytes = new Uint8Array([0x12, 0x34, 0x56, 0x78]); const result = createExactCalldataTerms( - { callData: callDataBytes }, + { calldata: callDataBytes }, { out: 'bytes' }, ); From 97a3a2dff4844ec5c52ec4cbf441a9e06efaa36a Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Tue, 8 Jul 2025 10:38:41 +1200 Subject: [PATCH 3/9] Update CaveatBuilders to accept config parameter. --- .../caveatBuilder/allowedCalldataBuilder.ts | 13 ++- .../caveatBuilder/allowedMethodsBuilder.ts | 10 +- .../caveatBuilder/allowedTargetsBuilder.ts | 10 +- .../caveatBuilder/argsEqualityCheckBuilder.ts | 17 ++-- .../src/caveatBuilder/blockNumberBuilder.ts | 28 +++--- .../src/caveatBuilder/deployedBuilder.ts | 12 ++- .../erc1155BalanceChangeBuilder.ts | 22 +++-- .../erc20BalanceChangeBuilder.ts | 19 ++-- .../erc20PeriodTransferBuilder.ts | 14 ++- .../caveatBuilder/erc20StreamingBuilder.ts | 17 +++- .../erc20TransferAmountBuilder.ts | 10 +- .../erc721BalanceChangeBuilder.ts | 19 ++-- .../caveatBuilder/erc721TransferBuilder.ts | 24 ++--- .../exactCalldataBatchBuilder.ts | 12 ++- .../src/caveatBuilder/exactCalldataBuilder.ts | 12 ++- .../exactExecutionBatchBuilder.ts | 14 ++- .../caveatBuilder/exactExecutionBuilder.ts | 12 ++- .../src/caveatBuilder/idBuilder.ts | 30 +++--- .../src/caveatBuilder/index.ts | 5 + .../src/caveatBuilder/limitedCallsBuilder.ts | 10 +- .../caveatBuilder/multiTokenPeriodBuilder.ts | 6 +- .../nativeBalanceChangeBuilder.ts | 16 +-- .../nativeTokenPaymentBuilder.ts | 15 ++- .../nativeTokenPeriodTransferBuilder.ts | 16 +-- .../nativeTokenStreamingBuilder.ts | 19 ++-- .../nativeTokenTransferAmountBuilder.ts | 18 ++-- .../src/caveatBuilder/nonceBuilder.ts | 14 ++- .../caveatBuilder/ownershipTransferBuilder.ts | 16 ++- .../src/caveatBuilder/redeemerBuilder.ts | 10 +- ...specificActionERC20TransferBatchBuilder.ts | 24 +++-- .../src/caveatBuilder/timestampBuilder.ts | 17 ++-- .../src/caveatBuilder/types.ts | 4 + .../src/caveatBuilder/valueLteBuilder.ts | 10 +- packages/delegation-toolkit/src/index.ts | 4 +- .../delegation-toolkit/src/utils/index.ts | 4 +- .../allowedCalldataBuilder.test.ts | 3 +- .../allowedMethodsBuilder.test.ts | 3 +- .../allowedTargetsBuilder.test.ts | 3 +- .../argsEqualityCheckBuilder.test.ts | 9 +- .../caveatBuilder/blockNumberBuilder.test.ts | 74 ++++++-------- .../caveatBuilder/createCaveatBuilder.test.ts | 98 ++++++++++--------- .../caveatBuilder/deployedBuilder.test.ts | 3 +- .../erc1155BalanceChangeBuilder.test.ts | 10 +- .../erc20BalanceChangeBuilder.test.ts | 9 +- .../erc20PeriodTransferBuilder.test.ts | 9 +- .../erc20StreamingBuilder.test.ts | 6 +- .../erc20TransferAmountBuilder.test.ts | 3 +- .../erc721BalanceChangeBuilder.test.ts | 11 +-- .../erc721TransferBuilder.test.ts | 30 +++--- .../exactCalldataBatchBuilder.test.ts | 5 +- .../exactCalldataBuilder.test.ts | 15 +-- .../exactExecutionBatchBuilder.test.ts | 5 +- .../exactExecutionBuilder.test.ts | 77 +++++++++------ .../test/caveatBuilder/idBuilder.test.ts | 7 +- .../caveatBuilder/limitedCallsBuilder.test.ts | 3 +- .../nativeBalanceChangeBuilder.test.ts | 8 +- .../nativeTokenPaymentBuilder.test.ts | 3 +- .../nativeTokenPeriodTransferBuilder.test.ts | 8 +- .../nativeTokenStreamingBuilder.test.ts | 9 +- .../nativeTokenTransferAmountBuilder.test.ts | 7 +- .../test/caveatBuilder/nonceBuilder.test.ts | 3 +- .../ownershipTransferBuilder.test.ts | 15 +-- .../caveatBuilder/redeemerBuilder.test.ts | 3 +- ...ficActionERC20TransferBatchBuilder.test.ts | 38 +++---- .../caveatBuilder/timestampBuilder.test.ts | 3 +- .../caveatBuilder/valueLteBuilder.test.ts | 3 +- 66 files changed, 569 insertions(+), 417 deletions(-) diff --git a/packages/delegation-toolkit/src/caveatBuilder/allowedCalldataBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/allowedCalldataBuilder.ts index 0308a799..e8b72afe 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/allowedCalldataBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/allowedCalldataBuilder.ts @@ -4,20 +4,25 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const allowedCalldata = 'allowedCalldata'; +export type AllowedCalldataBuilderConfig = { + startIndex: number; + value: Hex; +}; + /** * Builds a caveat struct for AllowedCalldataEnforcer that restricts calldata to a specific value at a given index. * * @param environment - The DeleGator environment. - * @param startIndex - The start index of the subset of calldata bytes. - * @param value - The expected value for the subset of calldata. + * @param config - The configuration object containing startIndex and value. * @returns The Caveat. * @throws Error if the value is not a valid hex string, if startIndex is negative, or if startIndex is not a whole number. */ export const allowedCalldataBuilder = ( environment: DeleGatorEnvironment, - startIndex: number, - value: Hex, + config: AllowedCalldataBuilderConfig, ): Caveat => { + const { startIndex, value } = config; + if (!isHex(value)) { throw new Error('Invalid value: must be a valid hex string'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/allowedMethodsBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/allowedMethodsBuilder.ts index fc3564f4..066a8afd 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/allowedMethodsBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/allowedMethodsBuilder.ts @@ -10,18 +10,24 @@ export type MethodSelector = Hex | string | AbiFunction; // length of function selector in chars, _including_ 0x prefix const FUNCTION_SELECTOR_STRING_LENGTH = 10; +export type AllowedMethodsBuilderConfig = { + selectors: MethodSelector[]; +}; + /** * Builds a caveat struct for the AllowedMethodsEnforcer. * * @param environment - The DeleGator environment. - * @param selectors - The allowed function selectors. + * @param config - The configuration object containing the allowed function selectors. * @returns The Caveat. * @throws Error if no selectors are provided or if any selector is invalid. */ export const allowedMethodsBuilder = ( environment: DeleGatorEnvironment, - selectors: MethodSelector[], + config: AllowedMethodsBuilderConfig, ): Caveat => { + const { selectors } = config; + if (selectors.length === 0) { throw new Error('Invalid selectors: must provide at least one selector'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/allowedTargetsBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/allowedTargetsBuilder.ts index 5f8ac733..14fb9b71 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/allowedTargetsBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/allowedTargetsBuilder.ts @@ -4,18 +4,24 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const allowedTargets = 'allowedTargets'; +export type AllowedTargetsBuilderConfig = { + targets: Address[]; +}; + /** * Builds a caveat struct for AllowedTargetsEnforcer. * * @param environment - The DeleGator environment. - * @param targets - The array of allowed target addresses. + * @param config - The configuration object containing the targets. * @returns The Caveat. * @throws Error if no targets are provided or if any of the addresses are invalid. */ export const allowedTargetsBuilder = ( environment: DeleGatorEnvironment, - targets: Address[], + config: AllowedTargetsBuilderConfig, ): Caveat => { + const { targets } = config; + if (targets.length === 0) { throw new Error( 'Invalid targets: must provide at least one target address', diff --git a/packages/delegation-toolkit/src/caveatBuilder/argsEqualityCheckBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/argsEqualityCheckBuilder.ts index 936c41a6..691b5bb5 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/argsEqualityCheckBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/argsEqualityCheckBuilder.ts @@ -4,24 +4,27 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const argsEqualityCheck = 'argsEqualityCheck'; +export type ArgsEqualityCheckBuilderConfig = { + args: Hex; +}; + /** * Builds a caveat struct for the ArgsEqualityCheckEnforcer. * * @param environment - The DeleGator environment. - * @param args - The expected value for args. + * @param config - The configuration object for the builder. * @returns The Caveat. - * @throws Error if the args is invalid. + * @throws Error if the config is invalid. */ export const argsEqualityCheckBuilder = ( environment: DeleGatorEnvironment, - args: Hex, + config: ArgsEqualityCheckBuilderConfig, ): Caveat => { + const { args } = config; if (!isHex(args)) { - throw new Error('Invalid args: must be a valid hex string'); + throw new Error('Invalid config: args must be a valid hex string'); } - const terms = args; - const { caveatEnforcers: { ArgsEqualityCheckEnforcer }, } = environment; @@ -32,7 +35,7 @@ export const argsEqualityCheckBuilder = ( return { enforcer: ArgsEqualityCheckEnforcer, - terms, + terms: args, args: '0x', }; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/blockNumberBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/blockNumberBuilder.ts index 1460edb6..ef62c585 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/blockNumberBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/blockNumberBuilder.ts @@ -4,40 +4,42 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const blockNumber = 'blockNumber'; +export type BlockNumberBuilderConfig = { + afterThreshold: bigint; + beforeThreshold: bigint; +}; + /** * Builds a caveat struct for the BlockNumberEnforcer. * * @param environment - The DeleGator environment. - * @param blockAfterThreshold - The earliest block number after which the delegation can be used. - * @param blockBeforeThreshold - The latest block number before which the delegation can be used. + * @param config - The configuration object for the BlockNumberEnforcer. * @returns The Caveat. * @throws Error if both thresholds are zero, if blockAfterThreshold is greater than or equal to blockBeforeThreshold, or if BlockNumberEnforcer is not available in the environment. */ export const blockNumberBuilder = ( environment: DeleGatorEnvironment, - blockAfterThreshold: bigint, - blockBeforeThreshold: bigint, + config: BlockNumberBuilderConfig, ): Caveat => { - if (blockAfterThreshold === 0n && blockBeforeThreshold === 0n) { + const { afterThreshold, beforeThreshold } = config; + + if (afterThreshold === 0n && beforeThreshold === 0n) { throw new Error( - 'Invalid thresholds: At least one of blockAfterThreshold or blockBeforeThreshold must be specified', + 'Invalid thresholds: At least one of afterThreshold or beforeThreshold must be specified', ); } - if ( - blockBeforeThreshold !== 0n && - blockAfterThreshold >= blockBeforeThreshold - ) { + if (beforeThreshold !== 0n && afterThreshold >= beforeThreshold) { throw new Error( - 'Invalid thresholds: blockAfterThreshold must be less than blockBeforeThreshold if both are specified', + 'Invalid thresholds: afterThreshold must be less than beforeThreshold if both are specified', ); } const terms = concat([ - toHex(blockAfterThreshold, { + toHex(afterThreshold, { size: 16, }), - toHex(blockBeforeThreshold, { + toHex(beforeThreshold, { size: 16, }), ]); diff --git a/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts index e8b4679e..c1aa5511 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts @@ -4,6 +4,12 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const deployed = 'deployed'; +export type DeployedBuilderConfig = { + contractAddress: Address; + salt: Hex; + bytecode: Hex; +}; + /** * Builds a caveat struct for a DeployedEnforcer. * @@ -16,10 +22,10 @@ export const deployed = 'deployed'; */ export const deployedBuilder = ( environment: DeleGatorEnvironment, - contractAddress: Address, - salt: Hex, - bytecode: Hex, + config: DeployedBuilderConfig, ): Caveat => { + const { contractAddress, salt, bytecode } = config; + // we check that the addresses are valid, but don't need to be checksummed if (!isAddress(contractAddress, { strict: false })) { throw new Error( diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts index d48fe737..793c07e3 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts @@ -5,26 +5,28 @@ import { BalanceChangeType } from './types'; export const erc1155BalanceChange = 'erc1155BalanceChange'; +export type Erc1155BalanceChangeBuilderConfig = { + tokenAddress: Address; + recipient: Address; + tokenId: bigint; + balance: bigint; + changeType: BalanceChangeType; +}; + /** * Builds a caveat struct for the ERC1155BalanceChangeEnforcer. * * @param environment - The DeleGator environment. - * @param tokenAddress - The tokenAddress of the ERC1155 token. - * @param recipient - The address of the recipient whose balance must change. - * @param tokenId - The ID of the ERC1155 token. - * @param balance - The amount by which the recipient's balance must change. - * @param changeType - The type of balance change (increase or decrease). + * @param config - The configuration object for the ERC1155 balance change. * @returns The Caveat. * @throws Error if the token address is invalid, the recipient address is invalid, or the amount is not a positive number. */ export const erc1155BalanceChangeBuilder = ( environment: DeleGatorEnvironment, - tokenAddress: Address, - recipient: Address, - tokenId: bigint, - balance: bigint, - changeType: BalanceChangeType, + config: Erc1155BalanceChangeBuilderConfig, ): Caveat => { + const { tokenAddress, recipient, tokenId, balance, changeType } = config; + if (!isAddress(tokenAddress, { strict: false })) { throw new Error('Invalid tokenAddress: must be a valid address'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20BalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20BalanceChangeBuilder.ts index 603302ac..78f9f494 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20BalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20BalanceChangeBuilder.ts @@ -5,24 +5,27 @@ import { BalanceChangeType } from './types'; export const erc20BalanceChange = 'erc20BalanceChange'; +export type Erc20BalanceChangeBuilderConfig = { + tokenAddress: Address; + recipient: Address; + balance: bigint; + changeType: BalanceChangeType; +}; + /** * Builds a caveat struct for the ERC20BalanceChangeEnforcer. * * @param environment - The DeleGator environment. - * @param tokenAddress - The tokenAddress of the ERC20 token. - * @param recipient - The address of the recipient whose balance must change. - * @param balance - The minimum balance amount required. - * @param changeType - Whether the balance should increase or decrease. + * @param config - The configuration object for the ERC20 balance change. * @returns The Caveat. * @throws Error if the token address is invalid, the amount is not a positive number, or the change type is invalid. */ export const erc20BalanceChangeBuilder = ( environment: DeleGatorEnvironment, - tokenAddress: Address, - recipient: Address, - balance: bigint, - changeType: BalanceChangeType, + config: Erc20BalanceChangeBuilderConfig, ): Caveat => { + const { tokenAddress, recipient, balance, changeType } = config; + if (!isAddress(tokenAddress, { strict: false })) { throw new Error('Invalid tokenAddress: must be a valid address'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts index 528793f3..24bcd547 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts @@ -5,6 +5,13 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const erc20PeriodTransfer = 'erc20PeriodTransfer'; +export type Erc20PeriodTransferBuilderConfig = { + tokenAddress: Address; + periodAmount: bigint; + periodDuration: number; + startDate: number; +}; + /** * Builds a caveat struct for ERC20PeriodTransferEnforcer. * This enforcer validates that ERC20 token transfers do not exceed a specified amount @@ -21,11 +28,10 @@ export const erc20PeriodTransfer = 'erc20PeriodTransfer'; */ export const erc20PeriodTransferBuilder = ( environment: DeleGatorEnvironment, - tokenAddress: Address, - periodAmount: bigint, - periodDuration: number, - startDate: number, + config: Erc20PeriodTransferBuilderConfig, ): Caveat => { + const { tokenAddress, periodAmount, periodDuration, startDate } = config; + const terms = createERC20TokenPeriodTransferTerms({ tokenAddress, periodAmount, diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts index bcd63f50..f2e680b1 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts @@ -5,6 +5,14 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const erc20Streaming = 'erc20Streaming'; +export type Erc20StreamingBuilderConfig = { + tokenAddress: Address; + initialAmount: bigint; + maxAmount: bigint; + amountPerSecond: bigint; + startTime: number; +}; + /** * Builds a caveat for ERC20 token streaming with configurable parameters. * @@ -24,12 +32,11 @@ export const erc20Streaming = 'erc20Streaming'; */ export const erc20StreamingBuilder = ( environment: DeleGatorEnvironment, - tokenAddress: Address, - initialAmount: bigint, - maxAmount: bigint, - amountPerSecond: bigint, - startTime: number, + config: Erc20StreamingBuilderConfig, ): Caveat => { + const { tokenAddress, initialAmount, maxAmount, amountPerSecond, startTime } = + config; + const terms = createERC20StreamingTerms({ tokenAddress, initialAmount, diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts index d53bf7c2..a74ba416 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts @@ -5,6 +5,11 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const erc20TransferAmount = 'erc20TransferAmount'; +export type Erc20TransferAmountBuilderConfig = { + tokenAddress: Address; + maxAmount: bigint; +}; + /** * Builds a caveat struct for ERC20TransferAmountEnforcer. * @@ -16,9 +21,10 @@ export const erc20TransferAmount = 'erc20TransferAmount'; */ export const erc20TransferAmountBuilder = ( environment: DeleGatorEnvironment, - tokenAddress: Address, - maxAmount: bigint, + config: Erc20TransferAmountBuilderConfig, ): Caveat => { + const { tokenAddress, maxAmount } = config; + if (!isAddress(tokenAddress, { strict: false })) { throw new Error('Invalid tokenAddress: must be a valid address'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts index 54b4e12d..78c7d94d 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts @@ -5,24 +5,27 @@ import { BalanceChangeType } from './types'; export const erc721BalanceChange = 'erc721BalanceChange'; +export type Erc721BalanceChangeBuilderConfig = { + tokenAddress: Address; + recipient: Address; + amount: bigint; + changeType: BalanceChangeType; +}; + /** * Builds a caveat struct for the ERC721BalanceChangeEnforcer. * * @param environment - The DeleGator environment. - * @param tokenAddress - The tokenAddress of the ERC721 token. - * @param recipient - The address of the recipient whose balance must change. - * @param amount - The amount by which the recipient's balance must change. - * @param changeType - The type of balance change (increase or decrease). + * @param config - The configuration object for the ERC721 balance change. * @returns The Caveat. * @throws Error if the token address is invalid, the recipient address is invalid, or the amount is not a positive number. */ export const erc721BalanceChangeBuilder = ( environment: DeleGatorEnvironment, - tokenAddress: Address, - recipient: Address, - amount: bigint, - changeType: BalanceChangeType, + config: Erc721BalanceChangeBuilderConfig, ): Caveat => { + const { tokenAddress, recipient, amount, changeType } = config; + if (!isAddress(tokenAddress, { strict: false })) { throw new Error('Invalid tokenAddress: must be a valid address'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts index d425c54f..f6280f49 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts @@ -4,32 +4,34 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const erc721Transfer = 'erc721Transfer'; +export type Erc721TransferBuilderConfig = { + tokenAddress: Address; + tokenId: bigint; +}; + /** * Builds a caveat struct for the ERC721TransferEnforcer. * * @param environment - The DeleGator environment. - * @param permittedContract - The permitted contract address for the ERC721 token. - * @param permittedTokenId - The permitted token ID as a bigint. + * @param config - The configuration object for the ERC721 transfer builder. * @returns The Caveat representing the caveat for ERC721 transfer. * @throws Error if the permitted contract address is invalid. */ export const erc721TransferBuilder = ( environment: DeleGatorEnvironment, - permittedContract: Address, - permittedTokenId: bigint, + config: Erc721TransferBuilderConfig, ): Caveat => { - if (!isAddress(permittedContract, { strict: false })) { + const { tokenAddress, tokenId } = config; + + if (!isAddress(tokenAddress, { strict: false })) { throw new Error('Invalid tokenAddress: must be a valid address'); } - if (permittedTokenId < 0) { - throw new Error('Invalid permittedTokenId: must be a non-negative number'); + if (tokenId < 0) { + throw new Error('Invalid tokenId: must be a non-negative number'); } - const terms = concat([ - permittedContract, - toHex(permittedTokenId, { size: 32 }), - ]); + const terms = concat([tokenAddress, toHex(tokenId, { size: 32 })]); const { caveatEnforcers: { ERC721TransferEnforcer }, diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBatchBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBatchBuilder.ts index 8fe5c99f..93a2bdcb 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBatchBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBatchBuilder.ts @@ -5,20 +5,26 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const exactCalldataBatch = 'exactCalldataBatch'; +export type ExactCalldataBatchBuilderConfig = { + executions: ExecutionStruct[]; +}; + /** * Builds a caveat struct for ExactCalldataBatchEnforcer. * This enforcer ensures that the provided batch execution calldata matches exactly * the expected calldata for each execution. * * @param environment - The DeleGator environment. - * @param executions - Array of expected executions, each containing target address, value, and calldata. + * @param config - Configuration object containing executions. * @returns The Caveat. * @throws Error if any of the executions have invalid parameters. */ export const exactCalldataBatchBuilder = ( environment: DeleGatorEnvironment, - executions: ExecutionStruct[], + config: ExactCalldataBatchBuilderConfig, ): Caveat => { + const { executions } = config; + if (executions.length === 0) { throw new Error('Invalid executions: array cannot be empty'); } @@ -35,7 +41,7 @@ export const exactCalldataBatchBuilder = ( if (!execution.callData.startsWith('0x')) { throw new Error( - 'Invalid callData: must be a hex string starting with 0x', + 'Invalid calldata: must be a hex string starting with 0x', ); } } diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts index 5117e811..dffb0cc2 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts @@ -4,21 +4,27 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const exactCalldata = 'exactCalldata'; +export type ExactCalldataBuilderConfig = { + calldata: `0x${string}`; +}; + /** * Builds a caveat struct for ExactCalldataEnforcer. * This enforcer ensures that the provided execution calldata matches exactly * the expected calldata. * * @param environment - The DeleGator environment. - * @param callData - The expected calldata to match against. + * @param config - The configuration for the ExactCalldataBuilder. * @returns The Caveat. * @throws Error if any of the parameters are invalid. */ export const exactCalldataBuilder = ( environment: DeleGatorEnvironment, - callData: `0x${string}`, + config: ExactCalldataBuilderConfig, ): Caveat => { - const terms = createExactCalldataTerms({ callData }); + const { calldata } = config; + + const terms = createExactCalldataTerms({ calldata }); const { caveatEnforcers: { ExactCalldataEnforcer }, diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts index 12c3f836..4955939f 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts @@ -1,24 +1,30 @@ -import { encodeAbiParameters, isAddress } from 'viem'; +import { encodeAbiParameters, isAddress, encodePacked } from 'viem'; import type { ExecutionStruct } from '../executions'; import type { Caveat, DeleGatorEnvironment } from '../types'; export const exactExecutionBatch = 'exactExecutionBatch'; +export type ExactExecutionBatchBuilderConfig = { + executions: ExecutionStruct[]; +}; + /** * Builds a caveat struct for ExactExecutionBatchEnforcer. * This enforcer ensures that each execution in the batch matches exactly * with the expected execution (target, value, and calldata). * * @param environment - The DeleGator environment. - * @param executions - Array of expected executions to match against. + * @param config - Configuration object containing executions. * @returns The Caveat. * @throws Error if any of the execution parameters are invalid. */ export const exactExecutionBatchBuilder = ( environment: DeleGatorEnvironment, - executions: ExecutionStruct[], + config: ExactExecutionBatchBuilderConfig, ): Caveat => { + const { executions } = config; + if (executions.length === 0) { throw new Error('Invalid executions: array cannot be empty'); } @@ -35,7 +41,7 @@ export const exactExecutionBatchBuilder = ( if (!execution.callData.startsWith('0x')) { throw new Error( - 'Invalid callData: must be a hex string starting with 0x', + 'Invalid calldata: must be a hex string starting with 0x', ); } } diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBuilder.ts index 804c4275..d7234f70 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBuilder.ts @@ -5,20 +5,26 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const exactExecution = 'exactExecution'; +export type ExactExecutionBuilderConfig = { + execution: ExecutionStruct; +}; + /** * Builds a caveat struct for ExactExecutionEnforcer. * This enforcer ensures that the provided execution matches exactly * with the expected execution (target, value, and calldata). * * @param environment - The DeleGator environment. - * @param execution - The expected execution to match against. + * @param config - The configuration object containing the execution. * @returns The Caveat. * @throws Error if any of the execution parameters are invalid. */ export const exactExecutionBuilder = ( environment: DeleGatorEnvironment, - execution: ExecutionStruct, + config: ExactExecutionBuilderConfig, ): Caveat => { + const { execution } = config; + if (!isAddress(execution.target, { strict: false })) { throw new Error('Invalid target: must be a valid address'); } @@ -28,7 +34,7 @@ export const exactExecutionBuilder = ( } if (!execution.callData.startsWith('0x')) { - throw new Error('Invalid callData: must be a hex string starting with 0x'); + throw new Error('Invalid calldata: must be a hex string starting with 0x'); } const terms = concat([ diff --git a/packages/delegation-toolkit/src/caveatBuilder/idBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/idBuilder.ts index eb7edd39..fce5c2da 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/idBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/idBuilder.ts @@ -2,43 +2,49 @@ import { maxUint256, toHex } from 'viem'; import type { DeleGatorEnvironment, Caveat } from '../types'; +export type IdBuilderConfig = { + id: bigint | number; +}; + export const id = 'id'; /** * Builds a caveat struct for the IdEnforcer. * * @param environment - The DeleGator environment. - * @param idValue - The id to use in the caveat. + * @param config - The configuration object containing the id to use in the caveat. * @returns The Caveat. * @throws Error if the provided id is not a number, not an integer, or is not 32 bytes or fewer in length. */ -export function idBuilder( +export const idBuilder = ( environment: DeleGatorEnvironment, - idValue: bigint | number, -): Caveat { - let idValueBigInt: bigint; + config: IdBuilderConfig, +): Caveat => { + const { id: idValue } = config; + + let idBigInt: bigint; if (typeof idValue === 'number') { if (!Number.isInteger(idValue)) { throw new Error('Invalid id: must be an integer'); } - idValueBigInt = BigInt(idValue); + idBigInt = BigInt(idValue); } else if (typeof idValue === 'bigint') { - idValueBigInt = idValue; + idBigInt = idValue; } else { throw new Error('Invalid id: must be a bigint or number'); } - if (idValueBigInt < 0n) { - throw new Error('Invalid id: must be positive'); + if (idBigInt < 0n) { + throw new Error('Invalid id: must be a non-negative number'); } - if (idValueBigInt > maxUint256) { + if (idBigInt > maxUint256) { throw new Error('Invalid id: must be less than 2^256'); } - const terms = toHex(idValueBigInt, { size: 32 }); + const terms = toHex(idBigInt, { size: 32 }); const { caveatEnforcers: { IdEnforcer }, @@ -53,4 +59,4 @@ export function idBuilder( terms, args: '0x', }; -} +}; diff --git a/packages/delegation-toolkit/src/caveatBuilder/index.ts b/packages/delegation-toolkit/src/caveatBuilder/index.ts index e7d70c32..6db9f763 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/index.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/index.ts @@ -72,6 +72,10 @@ import { nativeTokenTransferAmountBuilder, } from './nativeTokenTransferAmountBuilder'; import { nonce, nonceBuilder } from './nonceBuilder'; +import { + ownershipTransfer, + ownershipTransferBuilder, +} from './ownershipTransferBuilder'; import { redeemer, redeemerBuilder } from './redeemerBuilder'; import { specificActionERC20TransferBatch, @@ -113,6 +117,7 @@ export const createCaveatBuilder = ( .extend(redeemer, redeemerBuilder) .extend(nativeTokenPayment, nativeTokenPaymentBuilder) .extend(argsEqualityCheck, argsEqualityCheckBuilder) + .extend(ownershipTransfer, ownershipTransferBuilder) .extend( specificActionERC20TransferBatch, specificActionERC20TransferBatchBuilder, diff --git a/packages/delegation-toolkit/src/caveatBuilder/limitedCallsBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/limitedCallsBuilder.ts index e2bb65b1..65d1a1b8 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/limitedCallsBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/limitedCallsBuilder.ts @@ -4,18 +4,24 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const limitedCalls = 'limitedCalls'; +export type LimitedCallsBuilderConfig = { + limit: number; +}; + /** * Builds a caveat struct for the LimitedCallsEnforcer. * * @param environment - The DeleGator environment. - * @param limit - The maximum number of calls allowed. + * @param config - The configuration object containing the limit. * @returns The Caveat. * @throws Error if the limit is not a positive integer. */ export const limitedCallsBuilder = ( environment: DeleGatorEnvironment, - limit: number, + config: LimitedCallsBuilderConfig, ): Caveat => { + const { limit } = config; + if (!Number.isInteger(limit)) { throw new Error('Invalid limit: must be an integer'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/multiTokenPeriodBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/multiTokenPeriodBuilder.ts index e2bad964..73d6b1b0 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/multiTokenPeriodBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/multiTokenPeriodBuilder.ts @@ -10,6 +10,8 @@ export type TokenPeriodConfig = { startDate: number; }; +export type MultiTokenPeriodBuilderConfig = TokenPeriodConfig[]; + export const multiTokenPeriod = 'multiTokenPeriod'; /** @@ -18,12 +20,12 @@ export const multiTokenPeriod = 'multiTokenPeriod'; * Each token can have its own period amount, duration, and start date. * * @param environment - The DeleGator environment. - * @param configs - Array of token period configurations. + * @param configs - The configurations for the MultiTokenPeriodBuilder. * @returns The caveat object for the MultiTokenPeriodEnforcer. */ export const multiTokenPeriodBuilder = ( environment: DeleGatorEnvironment, - configs: TokenPeriodConfig[], + configs: MultiTokenPeriodBuilderConfig, ): Caveat => { if (!configs || configs.length === 0) { throw new Error('MultiTokenPeriodBuilder: configs array cannot be empty'); diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeBalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeBalanceChangeBuilder.ts index 6fe1e57f..77156bae 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeBalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeBalanceChangeBuilder.ts @@ -5,22 +5,26 @@ import { BalanceChangeType } from './types'; export const nativeBalanceChange = 'nativeBalanceChange'; +export type NativeBalanceChangeBuilderConfig = { + recipient: Address; + balance: bigint; + changeType: BalanceChangeType; +}; + /** * Builds a caveat struct for the NativeBalanceChangeEnforcer. * * @param environment - The DeleGator environment. - * @param recipient - The address that should receive the balance change. - * @param balance - The minimum balance amount required. - * @param changeType - Whether the balance should increase or decrease. + * @param config - The configuration object for the NativeBalanceChangeEnforcer. * @returns The Caveat. * @throws Error if the recipient address is invalid or the amount is not a positive number. */ export const nativeBalanceChangeBuilder = ( environment: DeleGatorEnvironment, - recipient: Address, - balance: bigint, - changeType: BalanceChangeType, + config: NativeBalanceChangeBuilderConfig, ): Caveat => { + const { recipient, balance, changeType } = config; + if (!isAddress(recipient)) { throw new Error('Invalid recipient: must be a valid Address'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPaymentBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPaymentBuilder.ts index e7fabc57..c1c1d3c0 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPaymentBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPaymentBuilder.ts @@ -1,23 +1,28 @@ -import { type Hex, encodePacked, isAddress } from 'viem'; +import { type Address, encodePacked, isAddress } from 'viem'; import type { Caveat, DeleGatorEnvironment } from '../types'; export const nativeTokenPayment = 'nativeTokenPayment'; +export type NativeTokenPaymentBuilderConfig = { + recipient: Address; + amount: bigint; +}; + /** * Builds a caveat struct for the NativeTokenPaymentEnforcer. * * @param environment - The DeleGator environment. - * @param recipient - The address of the recipient of the payment. - * @param amount - The amount of native tokens required for the payment. + * @param config - The configuration object for the NativeTokenPaymentEnforcer. * @returns The Caveat. * @throws Error if the amount is invalid or the recipient address is invalid. */ export const nativeTokenPaymentBuilder = ( environment: DeleGatorEnvironment, - recipient: Hex, - amount: bigint, + config: NativeTokenPaymentBuilderConfig, ): Caveat => { + const { recipient, amount } = config; + if (amount <= 0n) { throw new Error('Invalid amount: must be positive'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPeriodTransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPeriodTransferBuilder.ts index dc84acca..ca62025c 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPeriodTransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPeriodTransferBuilder.ts @@ -4,6 +4,12 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const nativeTokenPeriodTransfer = 'nativeTokenPeriodTransfer'; +export type NativeTokenPeriodTransferBuilderConfig = { + periodAmount: bigint; + periodDuration: number; + startDate: number; +}; + /** * Builds a caveat struct for NativeTokenPeriodTransferEnforcer. * This enforcer validates that native token (ETH) transfers do not exceed a specified amount @@ -11,18 +17,16 @@ export const nativeTokenPeriodTransfer = 'nativeTokenPeriodTransfer'; * and any unused ETH is forfeited once the period ends. * * @param environment - The DeleGator environment. - * @param periodAmount - The maximum amount of ETH (in wei) that can be transferred per period. - * @param periodDuration - The duration of each period in seconds. - * @param startDate - The timestamp when the first period begins. + * @param config - The configuration object containing periodAmount, periodDuration, and startDate. * @returns The Caveat. * @throws Error if any of the parameters are invalid. */ export const nativeTokenPeriodTransferBuilder = ( environment: DeleGatorEnvironment, - periodAmount: bigint, - periodDuration: number, - startDate: number, + config: NativeTokenPeriodTransferBuilderConfig, ): Caveat => { + const { periodAmount, periodDuration, startDate } = config; + const terms = createNativeTokenPeriodTransferTerms({ periodAmount, periodDuration, diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenStreamingBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenStreamingBuilder.ts index 6d89860e..20ff93e5 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenStreamingBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenStreamingBuilder.ts @@ -4,24 +4,27 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const nativeTokenStreaming = 'nativeTokenStreaming'; +export type NativeTokenStreamingBuilderConfig = { + initialAmount: bigint; + maxAmount: bigint; + amountPerSecond: bigint; + startTime: number; +}; + /** * Builds a caveat struct for the NativeTokenStreamingEnforcer. * * @param environment - The DeleGator environment. - * @param initialAmount - The initial amount of tokens to release at start time. - * @param maxAmount - The maximum amount of tokens that can be released. - * @param amountPerSecond - The rate at which the allowance increases per second. - * @param startTime - The timestamp from which the allowance streaming begins. + * @param config - The configuration object for the NativeTokenStreamingEnforcer. * @returns The Caveat. * @throws Error if any of the parameters are invalid. */ export const nativeTokenStreamingBuilder = ( environment: DeleGatorEnvironment, - initialAmount: bigint, - maxAmount: bigint, - amountPerSecond: bigint, - startTime: number, + config: NativeTokenStreamingBuilderConfig, ): Caveat => { + const { initialAmount, maxAmount, amountPerSecond, startTime } = config; + const terms = createNativeTokenStreamingTerms({ initialAmount, maxAmount, diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenTransferAmountBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenTransferAmountBuilder.ts index 0bd9ea17..0df403be 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenTransferAmountBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenTransferAmountBuilder.ts @@ -4,23 +4,29 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const nativeTokenTransferAmount = 'nativeTokenTransferAmount'; +export type NativeTokenTransferAmountBuilderConfig = { + maxAmount: bigint; +}; + /** * Builds a caveat struct for the NativeTokenTransferAmountEnforcer. * * @param environment - The DeleGator environment. - * @param allowance - The maximum amount of native tokens allowed (in wei). + * @param config - The configuration object containing the maxAmount. * @returns The Caveat. - * @throws Error if the allowance is negative. + * @throws Error if the maxAmount is negative. */ export const nativeTokenTransferAmountBuilder = ( environment: DeleGatorEnvironment, - allowance: bigint, + config: NativeTokenTransferAmountBuilderConfig, ): Caveat => { - if (allowance < 0n) { - throw new Error('Invalid allowance: must be zero or positive'); + const { maxAmount } = config; + + if (maxAmount < 0n) { + throw new Error('Invalid maxAmount: must be zero or positive'); } - const terms = encodePacked(['uint256'], [allowance]); + const terms = encodePacked(['uint256'], [maxAmount]); const { caveatEnforcers: { NativeTokenTransferAmountEnforcer }, diff --git a/packages/delegation-toolkit/src/caveatBuilder/nonceBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nonceBuilder.ts index b776b336..d9377856 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nonceBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nonceBuilder.ts @@ -7,18 +7,24 @@ export const nonce = 'nonce'; // char length of 32 byte hex string const MAX_NONCE_STRING_LENGTH = 66; +export type NonceBuilderConfig = { + nonce: Hex; +}; + /** * Builds a caveat struct for the NonceEnforcer. * * @param environment - The DeleGator environment. - * @param nonceValue - The nonce value as a hexadecimal string. + * @param config - The configuration object containing the nonce value. * @returns The Caveat. * @throws Error if the nonce is invalid. */ export const nonceBuilder = ( environment: DeleGatorEnvironment, - nonceValue: Hex, + config: NonceBuilderConfig, ): Caveat => { + const { nonce: nonceValue } = config; + if (!nonceValue || nonceValue === '0x') { throw new Error('Invalid nonce: must be a non-empty hex string'); } @@ -31,6 +37,8 @@ export const nonceBuilder = ( throw new Error('Invalid nonce: must be 32 bytes or less in length'); } + const terms = pad(nonceValue, { size: 32 }); + const { caveatEnforcers: { NonceEnforcer }, } = environment; @@ -41,7 +49,7 @@ export const nonceBuilder = ( return { enforcer: NonceEnforcer, - terms: pad(nonceValue, { size: 32 }), + terms, args: '0x', }; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/ownershipTransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/ownershipTransferBuilder.ts index fd1958cb..a96181a2 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/ownershipTransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/ownershipTransferBuilder.ts @@ -4,23 +4,29 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const ownershipTransfer = 'ownershipTransfer'; +export type OwnershipTransferBuilderConfig = { + contractAddress: Address; +}; + /** * Builds a caveat struct for the OwnershipTransferEnforcer. * * @param environment - The DeleGator environment. - * @param targetContract - The target contract address for the ownership transfer. + * @param config - The configuration object for the ownership transfer builder. * @returns The Caveat representing the caveat for ownership transfer. * @throws Error if the target contract address is invalid. */ export const ownershipTransferBuilder = ( environment: DeleGatorEnvironment, - targetContract: Address, + config: OwnershipTransferBuilderConfig, ): Caveat => { - if (!isAddress(targetContract, { strict: false })) { - throw new Error('Invalid targetContract: must be a valid address'); + const { contractAddress } = config; + + if (!isAddress(contractAddress, { strict: false })) { + throw new Error('Invalid contractAddress: must be a valid address'); } - const terms = targetContract; + const terms = contractAddress; const { caveatEnforcers: { OwnershipTransferEnforcer }, diff --git a/packages/delegation-toolkit/src/caveatBuilder/redeemerBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/redeemerBuilder.ts index 31fe102e..7cb484f2 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/redeemerBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/redeemerBuilder.ts @@ -4,18 +4,24 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const redeemer = 'redeemer'; +export type RedeemerBuilderConfig = { + redeemers: Address[]; +}; + /** * Builds a caveat struct for the RedeemerEnforcer. * * @param environment - The DeleGator environment. - * @param redeemers - The addresses which will be allowed as redeemers. + * @param config - The configuration object containing redeemers. * @returns The Caveat. * @throws Error if the redeemer address is invalid or the array is empty. */ export const redeemerBuilder = ( environment: DeleGatorEnvironment, - redeemers: Address[], + config: RedeemerBuilderConfig, ): Caveat => { + const { redeemers } = config; + if (redeemers.length === 0) { throw new Error( 'Invalid redeemers: must specify at least one redeemer address', diff --git a/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts index 5c9c609a..ca462cbf 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts @@ -5,6 +5,14 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const specificActionERC20TransferBatch = 'specificActionERC20TransferBatch'; +export type SpecificActionErc20TransferBatchBuilderConfig = { + tokenAddress: Address; + recipient: Address; + amount: bigint; + target: Address; + calldata: Hex; +}; + /** * Builds a caveat struct for SpecificActionERC20TransferBatchEnforcer. * Enforces a batch of exactly 2 transactions: a specific action followed by an ERC20 transfer. @@ -20,12 +28,10 @@ export const specificActionERC20TransferBatch = */ export const specificActionERC20TransferBatchBuilder = ( environment: DeleGatorEnvironment, - tokenAddress: Address, - recipient: Address, - amount: bigint, - firstTarget: Address, - firstCalldata: Hex, + config: SpecificActionErc20TransferBatchBuilderConfig, ): Caveat => { + const { tokenAddress, recipient, amount, target, calldata } = config; + if (!isAddress(tokenAddress, { strict: false })) { throw new Error('Invalid tokenAddress: must be a valid address'); } @@ -34,8 +40,8 @@ export const specificActionERC20TransferBatchBuilder = ( throw new Error('Invalid recipient: must be a valid address'); } - if (!isAddress(firstTarget, { strict: false })) { - throw new Error('Invalid firstTarget: must be a valid address'); + if (!isAddress(target, { strict: false })) { + throw new Error('Invalid target: must be a valid address'); } if (amount <= 0n) { @@ -46,8 +52,8 @@ export const specificActionERC20TransferBatchBuilder = ( tokenAddress, recipient, toHex(amount, { size: 32 }), - firstTarget, - firstCalldata, + target, + calldata, ]); const { diff --git a/packages/delegation-toolkit/src/caveatBuilder/timestampBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/timestampBuilder.ts index 2573c278..e6a4c4dc 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/timestampBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/timestampBuilder.ts @@ -4,23 +4,28 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const timestamp = 'timestamp'; +export type TimestampBuilderConfig = { + afterThreshold: number; + beforeThreshold: number; +}; + /** * Builds a caveat struct for the TimestampEnforcer. * * @param environment - The DeleGator environment. - * @param timestampAfterThreshold - The timestamp (in seconds) after which the delegation can be used. - * @param timestampBeforeThreshold - The timestamp (in seconds) before which the delegation can be used. + * @param config - The configuration object for the TimestampEnforcer. * @returns The Caveat. * @throws Error if any of the parameters are invalid. */ export const timestampBuilder = ( environment: DeleGatorEnvironment, - timestampAfterThreshold: number, - timestampBeforeThreshold: number, + config: TimestampBuilderConfig, ): Caveat => { + const { afterThreshold, beforeThreshold } = config; + const terms = createTimestampTerms({ - timestampAfterThreshold, - timestampBeforeThreshold, + timestampAfterThreshold: afterThreshold, + timestampBeforeThreshold: beforeThreshold, }); const { diff --git a/packages/delegation-toolkit/src/caveatBuilder/types.ts b/packages/delegation-toolkit/src/caveatBuilder/types.ts index ec48f4c1..5fb28731 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/types.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/types.ts @@ -1,4 +1,8 @@ +import { DeleGatorEnvironment } from 'src/types'; + export enum BalanceChangeType { Increase = 0x0, Decrease = 0x1, } + +export type UnitOfAuthorityBaseConfig = { environment: DeleGatorEnvironment }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/valueLteBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/valueLteBuilder.ts index 74e9e5cd..be1696e5 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/valueLteBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/valueLteBuilder.ts @@ -4,18 +4,24 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const valueLte = 'valueLte'; +export type ValueLteBuilderConfig = { + maxValue: bigint; +}; + /** * Builds a caveat struct for ValueLteEnforcer. * * @param environment - The DeleGator environment. - * @param maxValue - The maximum value allowed for the transaction. + * @param config - The configuration object containing the maximum value allowed for the transaction. * @returns The Caveat. * @throws Error if any of the parameters are invalid. */ export const valueLteBuilder = ( environment: DeleGatorEnvironment, - maxValue: bigint, + config: ValueLteBuilderConfig, ): Caveat => { + const { maxValue } = config; + const terms = createValueLteTerms({ maxValue }); const { diff --git a/packages/delegation-toolkit/src/index.ts b/packages/delegation-toolkit/src/index.ts index eec7062a..79e0fbaf 100644 --- a/packages/delegation-toolkit/src/index.ts +++ b/packages/delegation-toolkit/src/index.ts @@ -42,9 +42,7 @@ export { createExecution } from './executions'; export type { ExecutionStruct, CreateExecutionArgs } from './executions'; -export { createCaveatBuilder, CaveatBuilder } from './caveatBuilder'; - -export type { Caveats, CaveatBuilderConfig } from './caveatBuilder'; +export type { Caveats } from './caveatBuilder'; export { createCaveat } from './caveats'; diff --git a/packages/delegation-toolkit/src/utils/index.ts b/packages/delegation-toolkit/src/utils/index.ts index e62671d8..91aca7d2 100644 --- a/packages/delegation-toolkit/src/utils/index.ts +++ b/packages/delegation-toolkit/src/utils/index.ts @@ -42,4 +42,6 @@ export { deployDeleGatorEnvironment, } from '../delegatorEnvironment'; -export type { CoreCaveatBuilder } from '../caveatBuilder'; +export type { CoreCaveatBuilder, CaveatBuilderConfig } from '../caveatBuilder'; + +export { createCaveatBuilder, CaveatBuilder } from '../caveatBuilder'; diff --git a/packages/delegation-toolkit/test/caveatBuilder/allowedCalldataBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/allowedCalldataBuilder.test.ts index 614a6543..4be801ff 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/allowedCalldataBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/allowedCalldataBuilder.test.ts @@ -13,7 +13,8 @@ describe('allowedCalldataBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithParams = (dataStart: number, value: Hex) => { - return allowedCalldataBuilder(environment, dataStart, value); + const config = { startIndex: dataStart, value }; + return allowedCalldataBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/allowedMethodsBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/allowedMethodsBuilder.test.ts index 676c0a7d..adae76d1 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/allowedMethodsBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/allowedMethodsBuilder.test.ts @@ -15,7 +15,8 @@ describe('allowedMethodsBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithSelectors = (selectors: MethodSelector[]) => { - return allowedMethodsBuilder(environment, selectors); + const config = { selectors }; + return allowedMethodsBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/allowedTargetsBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/allowedTargetsBuilder.test.ts index 7d5df2aa..4215766b 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/allowedTargetsBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/allowedTargetsBuilder.test.ts @@ -14,7 +14,8 @@ describe('allowedTargetsBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithTargets = (targets: Address[]) => { - return allowedTargetsBuilder(environment, targets); + const config = { targets }; + return allowedTargetsBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/argsEqualityCheckBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/argsEqualityCheckBuilder.test.ts index b0aeba6f..2b1130a7 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/argsEqualityCheckBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/argsEqualityCheckBuilder.test.ts @@ -11,23 +11,24 @@ describe('argsEqualityCheckBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithArgs = (args: Hex) => { - return argsEqualityCheckBuilder(environment, args); + const config = { args }; + return argsEqualityCheckBuilder(environment, config); }; describe('validation', () => { it('should fail when args is not hex', () => { expect(() => buildWithArgs('not-hex' as Hex)).to.throw( - 'Invalid args: must be a valid hex string', + 'Invalid config: args must be a valid hex string', ); }); it('should fail when args is not defined', () => { expect(() => buildWithArgs(undefined as any as Hex)).to.throw( - 'Invalid args: must be a valid hex string', + 'Invalid config: args must be a valid hex string', ); expect(() => buildWithArgs(null as any as Hex)).to.throw( - 'Invalid args: must be a valid hex string', + 'Invalid config: args must be a valid hex string', ); }); }); diff --git a/packages/delegation-toolkit/test/caveatBuilder/blockNumberBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/blockNumberBuilder.test.ts index ae8d2f05..e37cdac1 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/blockNumberBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/blockNumberBuilder.test.ts @@ -13,48 +13,45 @@ describe('blockNumberBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithThresholds = ( - blockAfterThreshold: bigint, - blockBeforeThreshold: bigint, + afterThreshold: bigint, + beforeThreshold: bigint, ) => { - return blockNumberBuilder( - environment, - blockAfterThreshold, - blockBeforeThreshold, - ); + const config = { + afterThreshold, + beforeThreshold, + }; + return blockNumberBuilder(environment, config); }; describe('validation', () => { it('should fail when both thresholds are zero', () => { expect(() => buildWithThresholds(0n, 0n)).to.throw( - 'Invalid thresholds: At least one of blockAfterThreshold or blockBeforeThreshold must be specified', + 'Invalid thresholds: At least one of afterThreshold or beforeThreshold must be specified', ); }); - it('should fail when blockAfterThreshold is greater than or equal to blockBeforeThreshold', () => { + it('should fail when afterThreshold is greater than or equal to beforeThreshold', () => { expect(() => buildWithThresholds(10n, 5n)).to.throw( - 'Invalid thresholds: blockAfterThreshold must be less than blockBeforeThreshold if both are specified', + 'Invalid thresholds: afterThreshold must be less than beforeThreshold if both are specified', ); expect(() => buildWithThresholds(10n, 10n)).to.throw( - 'Invalid thresholds: blockAfterThreshold must be less than blockBeforeThreshold if both are specified', + 'Invalid thresholds: afterThreshold must be less than beforeThreshold if both are specified', ); }); }); describe('builds a caveat', () => { it('should build a caveat with valid thresholds', () => { - const blockAfterThreshold = 5n; - const blockBeforeThreshold = 10n; + const afterThreshold = 5n; + const beforeThreshold = 10n; - const caveat = buildWithThresholds( - blockAfterThreshold, - blockBeforeThreshold, - ); + const caveat = buildWithThresholds(afterThreshold, beforeThreshold); const terms = concat([ - toHex(blockAfterThreshold, { + toHex(afterThreshold, { size: 16, }), - toHex(blockBeforeThreshold, { + toHex(beforeThreshold, { size: 16, }), ]); @@ -66,19 +63,16 @@ describe('blockNumberBuilder()', () => { }); }); - it('should build a caveat with only blockAfterThreshold', () => { - const blockAfterThreshold = 5n; - const blockBeforeThreshold = 0n; + it('should build a caveat with only afterThreshold', () => { + const afterThreshold = 5n; + const beforeThreshold = 0n; - const caveat = buildWithThresholds( - blockAfterThreshold, - blockBeforeThreshold, - ); + const caveat = buildWithThresholds(afterThreshold, beforeThreshold); const terms = concat([ - toHex(blockAfterThreshold, { + toHex(afterThreshold, { size: 16, }), - toHex(blockBeforeThreshold, { + toHex(beforeThreshold, { size: 16, }), ]); @@ -90,19 +84,16 @@ describe('blockNumberBuilder()', () => { }); }); - it('should build a caveat with only blockBeforeThreshold', () => { - const blockAfterThreshold = 0n; - const blockBeforeThreshold = 10n; + it('should build a caveat with only beforeThreshold', () => { + const afterThreshold = 0n; + const beforeThreshold = 10n; - const caveat = buildWithThresholds( - blockAfterThreshold, - blockBeforeThreshold, - ); + const caveat = buildWithThresholds(afterThreshold, beforeThreshold); const terms = concat([ - toHex(blockAfterThreshold, { + toHex(afterThreshold, { size: 16, }), - toHex(blockBeforeThreshold, { + toHex(beforeThreshold, { size: 16, }), ]); @@ -116,13 +107,10 @@ describe('blockNumberBuilder()', () => { }); it('should create a caveat with terms length matching number of targets', () => { - const blockAfterThreshold = 5n; - const blockBeforeThreshold = 10n; + const afterThreshold = 5n; + const beforeThreshold = 10n; - const caveat = buildWithThresholds( - blockAfterThreshold, - blockBeforeThreshold, - ); + const caveat = buildWithThresholds(afterThreshold, beforeThreshold); expect(size(caveat.terms)).to.equal(EXPECTED_TERMS_LENGTH); }); diff --git a/packages/delegation-toolkit/test/caveatBuilder/createCaveatBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/createCaveatBuilder.test.ts index 2d86ddbe..72244d16 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/createCaveatBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/createCaveatBuilder.test.ts @@ -60,7 +60,9 @@ describe('createCaveatBuilder()', () => { const selectors = [randomBytes(4), randomBytes(4)]; - const caveats = builder.addCaveat('allowedMethods', selectors).build(); + const caveats = builder + .addCaveat('allowedMethods', { selectors }) + .build(); expect(caveats).to.deep.equal([ { @@ -82,7 +84,7 @@ describe('createCaveatBuilder()', () => { const targets: [Address, Address] = [randomAddress(), randomAddress()]; - const caveats = builder.addCaveat('allowedTargets', targets).build(); + const caveats = builder.addCaveat('allowedTargets', { targets }).build(); expect(caveats).to.deep.equal([ { @@ -108,7 +110,7 @@ describe('createCaveatBuilder()', () => { const bytecode = randomBytes(256); const caveats = builder - .addCaveat('deployed', contractAddress, salt, bytecode) + .addCaveat('deployed', { contractAddress, salt, bytecode }) .build(); expect(caveats).to.deep.equal([ @@ -134,7 +136,7 @@ describe('createCaveatBuilder()', () => { const startIndex = Math.floor(Math.random() * 2 ** 32); const caveats = builder - .addCaveat('allowedCalldata', startIndex, value) + .addCaveat('allowedCalldata', { startIndex, value }) .build(); expect(caveats).to.deep.equal([ @@ -156,20 +158,19 @@ describe('createCaveatBuilder()', () => { it("should add an 'erc20BalanceChange' caveat", () => { const builder = createCaveatBuilder(environment); - const token = randomAddress(); + const tokenAddress = randomAddress(); const recipient = randomAddress(); const balance = BigInt( Math.floor(Math.random() * Number.MAX_SAFE_INTEGER), ); const caveats = builder - .addCaveat( - 'erc20BalanceChange', - token, + .addCaveat('erc20BalanceChange', { + tokenAddress, recipient, balance, - BalanceChangeType.Increase, - ) + changeType: BalanceChangeType.Increase, + }) .build(); expect(caveats).to.deep.equal([ @@ -177,7 +178,7 @@ describe('createCaveatBuilder()', () => { enforcer: environment.caveatEnforcers.ERC20BalanceChangeEnforcer, terms: encodePacked( ['uint8', 'address', 'address', 'uint256'], - [BalanceChangeType.Increase, token, recipient, balance], + [BalanceChangeType.Increase, tokenAddress, recipient, balance], ), args: '0x', }, @@ -197,7 +198,7 @@ describe('createCaveatBuilder()', () => { Math.floor(Math.random() * Number.MAX_SAFE_INTEGER), ); - const caveats = builder.addCaveat('valueLte', maxValue).build(); + const caveats = builder.addCaveat('valueLte', { maxValue }).build(); expect(caveats).to.deep.equal([ { @@ -217,13 +218,13 @@ describe('createCaveatBuilder()', () => { it("should add a 'limitedCalls' caveat", () => { const builder = createCaveatBuilder(environment); - const maxCalls = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); - const caveats = builder.addCaveat('limitedCalls', maxCalls).build(); + const limit = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); + const caveats = builder.addCaveat('limitedCalls', { limit }).build(); expect(caveats).to.deep.equal([ { enforcer: environment.caveatEnforcers.LimitedCallsEnforcer, - terms: toHex(maxCalls, { size: 32 }), + terms: toHex(limit, { size: 32 }), args: '0x', }, ]); @@ -238,13 +239,13 @@ describe('createCaveatBuilder()', () => { it("should add an 'id' caveat", () => { const builder = createCaveatBuilder(environment); - const id = BigInt(Math.floor(Math.random() * 2 ** 32)); - const caveats = builder.addCaveat('id', id).build(); + const idValue = BigInt(Math.floor(Math.random() * 2 ** 32)); + const caveats = builder.addCaveat('id', { id: idValue }).build(); expect(caveats).to.deep.equal([ { enforcer: environment.caveatEnforcers.IdEnforcer, - terms: toHex(id, { size: 32 }), + terms: toHex(idValue, { size: 32 }), args: '0x', }, ]); @@ -260,7 +261,7 @@ describe('createCaveatBuilder()', () => { const builder = createCaveatBuilder(environment); const nonce = randomBytes(16); - const caveats = builder.addCaveat('nonce', nonce).build(); + const caveats = builder.addCaveat('nonce', { nonce }).build(); expect(caveats).to.deep.equal([ { @@ -280,17 +281,22 @@ describe('createCaveatBuilder()', () => { it("should add a 'timestamp' caveat", () => { const builder = createCaveatBuilder(environment); - const after = 1000; - const before = 2000; + const afterThreshold = 1000; + const beforeThreshold = 2000; - const caveats = builder.addCaveat('timestamp', after, before).build(); + const caveats = builder + .addCaveat('timestamp', { + afterThreshold, + beforeThreshold, + }) + .build(); expect(caveats).to.deep.equal([ { enforcer: environment.caveatEnforcers.TimestampEnforcer, terms: concat([ - toHex(after, { size: 16 }), - toHex(before, { size: 16 }), + toHex(afterThreshold, { size: 16 }), + toHex(beforeThreshold, { size: 16 }), ]), args: '0x', }, @@ -306,19 +312,22 @@ describe('createCaveatBuilder()', () => { it("should add a 'blockNumber' caveat", () => { const builder = createCaveatBuilder(environment); - const blockAfterThreshold = 1000n; - const blockBeforeThreshold = 2000n; + const afterThreshold = 1000n; + const beforeThreshold = 2000n; const caveats = builder - .addCaveat('blockNumber', blockAfterThreshold, blockBeforeThreshold) + .addCaveat('blockNumber', { + afterThreshold, + beforeThreshold, + }) .build(); expect(caveats).to.deep.equal([ { enforcer: environment.caveatEnforcers.BlockNumberEnforcer, terms: concat([ - toHex(blockAfterThreshold, { size: 16 }), - toHex(blockBeforeThreshold, { size: 16 }), + toHex(afterThreshold, { size: 16 }), + toHex(beforeThreshold, { size: 16 }), ]), args: '0x', }, @@ -333,17 +342,17 @@ describe('createCaveatBuilder()', () => { it("should add a 'nativeTokenTransferAmount' caveat", () => { const builder = createCaveatBuilder(environment); - const allowance = 1000000000000000000n; // 1 ETH in wei + const maxAmount = 1000000000000000000n; // 1 ETH in wei const caveats = builder - .addCaveat('nativeTokenTransferAmount', allowance) + .addCaveat('nativeTokenTransferAmount', { maxAmount }) .build(); expect(caveats).to.deep.equal([ { enforcer: environment.caveatEnforcers.NativeTokenTransferAmountEnforcer, - terms: toHex(allowance, { size: 32 }), + terms: toHex(maxAmount, { size: 32 }), args: '0x', }, ]); @@ -362,12 +371,11 @@ describe('createCaveatBuilder()', () => { const minBalance = 500000000000000000n; // 0.5 ETH in wei const caveats = builder - .addCaveat( - 'nativeBalanceChange', + .addCaveat('nativeBalanceChange', { recipient, - minBalance, - BalanceChangeType.Increase, - ) + balance: minBalance, + changeType: BalanceChangeType.Increase, + }) .build(); expect(caveats).to.deep.equal([ { @@ -394,7 +402,7 @@ describe('createCaveatBuilder()', () => { const recipient = randomAddress('lowercase'); const caveats = builder - .addCaveat('nativeTokenPayment', recipient, amount) + .addCaveat('nativeTokenPayment', { recipient, amount }) .build(); expect(caveats).to.deep.equal([ @@ -415,17 +423,17 @@ describe('createCaveatBuilder()', () => { it("should add an 'erc20TransferAmount' caveat", () => { const builder = createCaveatBuilder(environment); - const token = randomAddress(); - const amount = 2000n; + const tokenAddress = randomAddress(); + const maxAmount = 2000n; const caveats = builder - .addCaveat('erc20TransferAmount', token, amount) + .addCaveat('erc20TransferAmount', { tokenAddress, maxAmount }) .build(); expect(caveats).to.deep.equal([ { enforcer: environment.caveatEnforcers.ERC20TransferAmountEnforcer, - terms: concat([token, toHex(amount, { size: 32 })]), + terms: concat([tokenAddress, toHex(maxAmount, { size: 32 })]), args: '0x', }, ]); @@ -442,7 +450,9 @@ describe('createCaveatBuilder()', () => { const builder = createCaveatBuilder(environment); const redeemerAddress = randomAddress(); - const caveats = builder.addCaveat('redeemer', [redeemerAddress]).build(); + const caveats = builder + .addCaveat('redeemer', { redeemers: [redeemerAddress] }) + .build(); expect(caveats).to.deep.equal([ { @@ -463,7 +473,7 @@ describe('createCaveatBuilder()', () => { const builder = createCaveatBuilder(environment); const args = '0x1234567890'; - const caveats = builder.addCaveat('argsEqualityCheck', args).build(); + const caveats = builder.addCaveat('argsEqualityCheck', { args }).build(); expect(caveats).to.deep.equal([ { diff --git a/packages/delegation-toolkit/test/caveatBuilder/deployedBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/deployedBuilder.test.ts index 0431ac09..d7f28c7c 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/deployedBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/deployedBuilder.test.ts @@ -18,7 +18,8 @@ describe('deployedBuilder()', () => { salt: Hex, bytecode: Hex, ) => { - return deployedBuilder(environment, contractAddress, salt, bytecode); + const config = { contractAddress, salt, bytecode }; + return deployedBuilder(environment, config); }; const validContractAddress = randomAddress(); diff --git a/packages/delegation-toolkit/test/caveatBuilder/erc1155BalanceChangeBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/erc1155BalanceChangeBuilder.test.ts index 5ee544e6..1b38a68a 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/erc1155BalanceChangeBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/erc1155BalanceChangeBuilder.test.ts @@ -20,14 +20,8 @@ describe('erc1155BalanceChangeBuilder', () => { balance: bigint, changeType: BalanceChangeType, ) => { - return erc1155BalanceChangeBuilder( - environment, - tokenAddress, - recipient, - tokenId, - balance, - changeType, - ); + const config = { tokenAddress, recipient, tokenId, balance, changeType }; + return erc1155BalanceChangeBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/erc20BalanceChangeBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/erc20BalanceChangeBuilder.test.ts index e735cfe6..221d9b53 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/erc20BalanceChangeBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/erc20BalanceChangeBuilder.test.ts @@ -19,13 +19,8 @@ describe('erc20BalanceChangeBuilder', () => { balance: bigint, changeType: BalanceChangeType, ) => { - return erc20BalanceChangeBuilder( - environment, - token, - recipient, - balance, - changeType, - ); + const config = { tokenAddress: token, recipient, balance, changeType }; + return erc20BalanceChangeBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/erc20PeriodTransferBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/erc20PeriodTransferBuilder.test.ts index 4c5bb4b9..18c5a333 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/erc20PeriodTransferBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/erc20PeriodTransferBuilder.test.ts @@ -20,13 +20,8 @@ describe('erc20PeriodTransferBuilder()', () => { periodDuration: number, startDate: number, ) => { - return erc20PeriodTransferBuilder( - environment, - tokenAddress, - periodAmount, - periodDuration, - startDate, - ); + const config = { tokenAddress, periodAmount, periodDuration, startDate }; + return erc20PeriodTransferBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/erc20StreamingBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/erc20StreamingBuilder.test.ts index 91365975..c3859aa1 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/erc20StreamingBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/erc20StreamingBuilder.test.ts @@ -21,14 +21,14 @@ describe('erc20StreamingBuilder()', () => { amountPerSecond: bigint, startTime: number, ) => { - return erc20StreamingBuilder( - environment, + const config = { tokenAddress, initialAmount, maxAmount, amountPerSecond, startTime, - ); + }; + return erc20StreamingBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/erc20TransferAmountBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/erc20TransferAmountBuilder.test.ts index b1f59a0b..d6d9deac 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/erc20TransferAmountBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/erc20TransferAmountBuilder.test.ts @@ -14,7 +14,8 @@ describe('erc20TransferAmountBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithParams = (tokenAddress: Address, maxAmount: bigint) => { - return erc20TransferAmountBuilder(environment, tokenAddress, maxAmount); + const config = { tokenAddress, maxAmount }; + return erc20TransferAmountBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/erc721BalanceChangeBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/erc721BalanceChangeBuilder.test.ts index e9bb1ed3..4888f027 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/erc721BalanceChangeBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/erc721BalanceChangeBuilder.test.ts @@ -15,16 +15,11 @@ describe('erc721BalanceChangeBuilder()', () => { const buildWithParams = ( tokenAddress: Address, recipient: Address, - balance: bigint, + amount: bigint, changeType: BalanceChangeType, ) => { - return erc721BalanceChangeBuilder( - environment, - tokenAddress, - recipient, - balance, - changeType, - ); + const config = { tokenAddress, recipient, amount, changeType }; + return erc721BalanceChangeBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/erc721TransferBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/erc721TransferBuilder.test.ts index 9c05799c..ac6d999f 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/erc721TransferBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/erc721TransferBuilder.test.ts @@ -13,15 +13,9 @@ describe('erc721TransferBuilder()', () => { caveatEnforcers: { ERC721TransferEnforcer: randomAddress() }, } as any as DeleGatorEnvironment; - const buildWithParams = ( - permittedContract: Address, - permittedTokenId: bigint, - ) => { - return erc721TransferBuilder( - environment, - permittedContract, - permittedTokenId, - ); + const buildWithParams = (tokenAddress: Address, tokenId: bigint) => { + const config = { tokenAddress, tokenId }; + return erc721TransferBuilder(environment, config); }; describe('validation', () => { @@ -35,7 +29,7 @@ describe('erc721TransferBuilder()', () => { it('should fail with a negative token ID', () => { const validAddress = randomAddress(); expect(() => buildWithParams(validAddress, -1n)).to.throw( - 'Invalid permittedTokenId: must be a non-negative number', + 'Invalid tokenId: must be a non-negative number', ); }); @@ -52,13 +46,13 @@ describe('erc721TransferBuilder()', () => { describe('builds a caveat', () => { it('should build a caveat with valid parameters', () => { - const permittedContract = randomAddress(); - const permittedTokenId = 1n; + const tokenAddress = randomAddress(); + const tokenId = 1n; - const caveat = buildWithParams(permittedContract, permittedTokenId); + const caveat = buildWithParams(tokenAddress, tokenId); const expectedTerms = concat([ - permittedContract, - toHex(permittedTokenId, { size: 32 }), + tokenAddress, + toHex(tokenId, { size: 32 }), ]).toLowerCase(); expect({ ...caveat, terms: caveat.terms.toLowerCase() }).to.deep.equal({ @@ -70,10 +64,10 @@ describe('erc721TransferBuilder()', () => { }); it('should create a caveat with terms of the correct length', () => { - const permittedContract = randomAddress(); - const permittedTokenId = 1n; + const tokenAddress = randomAddress(); + const tokenId = 1n; - const caveat = buildWithParams(permittedContract, permittedTokenId); + const caveat = buildWithParams(tokenAddress, tokenId); expect(size(caveat.terms)).to.equal(EXPECTED_TERMS_LENGTH); }); diff --git a/packages/delegation-toolkit/test/caveatBuilder/exactCalldataBatchBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/exactCalldataBatchBuilder.test.ts index cea4a747..62d787a4 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/exactCalldataBatchBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/exactCalldataBatchBuilder.test.ts @@ -18,7 +18,8 @@ describe('exactCalldataBatchBuilder()', () => { callData: `0x${string}`; }[], ) => { - return exactCalldataBatchBuilder(environment, executions); + const config = { executions }; + return exactCalldataBatchBuilder(environment, config); }; describe('validation', () => { @@ -62,7 +63,7 @@ describe('exactCalldataBatchBuilder()', () => { callData: 'invalid' as `0x${string}`, }, ]), - ).to.throw('Invalid callData: must be a hex string starting with 0x'); + ).to.throw('Invalid calldata: must be a hex string starting with 0x'); }); it('should allow valid addresses that are not checksummed', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/exactCalldataBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/exactCalldataBuilder.test.ts index 83e15f30..abcefa2e 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/exactCalldataBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/exactCalldataBuilder.test.ts @@ -9,29 +9,30 @@ describe('exactCalldataBuilder()', () => { caveatEnforcers: { ExactCalldataEnforcer: randomAddress() }, } as any as DeleGatorEnvironment; - const buildWithParams = (callData: `0x${string}`) => { - return exactCalldataBuilder(environment, callData); + const buildWithParams = (calldata: `0x${string}`) => { + const config = { calldata }; + return exactCalldataBuilder(environment, config); }; describe('validation', () => { - it('should fail with invalid callData format', () => { + it('should fail with invalid calldata format', () => { expect(() => buildWithParams('invalid' as `0x${string}`)).to.throw( - 'Invalid callData: must be a hex string starting with 0x', + 'Invalid calldata: must be a hex string starting with 0x', ); }); }); describe('builds a caveat', () => { it('should build a caveat with valid parameters', () => { - const callData = '0x1234567890abcdef' as const; + const calldata = '0x1234567890abcdef' as const; - const caveat = buildWithParams(callData); + const caveat = buildWithParams(calldata); expect(caveat.enforcer).to.equal( environment.caveatEnforcers.ExactCalldataEnforcer, ); expect(caveat.args).to.equal('0x'); - expect(caveat.terms).to.equal(callData); + expect(caveat.terms).to.equal(calldata); }); }); }); diff --git a/packages/delegation-toolkit/test/caveatBuilder/exactExecutionBatchBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/exactExecutionBatchBuilder.test.ts index 68c2a731..43c2307a 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/exactExecutionBatchBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/exactExecutionBatchBuilder.test.ts @@ -18,7 +18,8 @@ describe('exactExecutionBatchBuilder()', () => { callData: `0x${string}`; }[], ) => { - return exactExecutionBatchBuilder(environment, executions); + const config = { executions }; + return exactExecutionBatchBuilder(environment, config); }; describe('validation', () => { @@ -62,7 +63,7 @@ describe('exactExecutionBatchBuilder()', () => { callData: 'invalid' as `0x${string}`, }, ]), - ).to.throw('Invalid callData: must be a hex string starting with 0x'); + ).to.throw('Invalid calldata: must be a hex string starting with 0x'); }); it('should allow valid addresses that are not checksummed', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/exactExecutionBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/exactExecutionBuilder.test.ts index 782a82f3..e427d86a 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/exactExecutionBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/exactExecutionBuilder.test.ts @@ -16,50 +16,63 @@ describe('exactExecutionBuilder()', () => { value: bigint; callData: `0x${string}`; }) => { - return exactExecutionBuilder(environment, execution); + const config = { execution }; + return exactExecutionBuilder(environment, config); }; describe('validation', () => { it('should fail with an invalid target address', () => { const invalidAddress = 'invalid-address' as Address; - expect(() => - buildWithParams({ - target: invalidAddress, - value: 0n, - callData: '0x', - }), - ).to.throw('Invalid target: must be a valid address'); + expect(() => { + const config = { + execution: { + target: invalidAddress, + value: 0n, + callData: '0x' as `0x${string}`, + }, + }; + buildWithParams(config.execution); + }).to.throw('Invalid target: must be a valid address'); }); it('should fail with a negative value', () => { - expect(() => - buildWithParams({ - target: randomAddress(), - value: -1n, - callData: '0x', - }), - ).to.throw('Invalid value: must be a non-negative number'); + expect(() => { + const config = { + execution: { + target: randomAddress(), + value: -1n, + callData: '0x' as `0x${string}`, + }, + }; + buildWithParams(config.execution); + }).to.throw('Invalid value: must be a non-negative number'); }); it('should fail with invalid callData format', () => { - expect(() => - buildWithParams({ - target: randomAddress(), - value: 0n, - callData: 'invalid' as `0x${string}`, - }), - ).to.throw('Invalid callData: must be a hex string starting with 0x'); + expect(() => { + const config = { + execution: { + target: randomAddress(), + value: 0n, + callData: 'invalid' as `0x${string}`, + }, + }; + buildWithParams(config.execution); + }).to.throw('Invalid calldata: must be a hex string starting with 0x'); }); it('should allow valid addresses that are not checksummed', () => { const nonChecksummedAddress = randomAddress().toLowerCase() as Address; - expect(() => - buildWithParams({ - target: nonChecksummedAddress, - value: 0n, - callData: '0x', - }), - ).to.not.throw(); + expect(() => { + const config = { + execution: { + target: nonChecksummedAddress, + value: 0n, + callData: '0x' as `0x${string}`, + }, + }; + buildWithParams(config.execution); + }).to.not.throw(); }); }); @@ -68,10 +81,10 @@ describe('exactExecutionBuilder()', () => { const execution = { target: randomAddress(), value: 1000000000000000000n, // 1 ETH - callData: '0x12345678' as const, + callData: '0x12345678' as `0x${string}`, }; - - const caveat = buildWithParams(execution); + const config = { execution }; + const caveat = buildWithParams(config.execution); expect(caveat.enforcer).to.equal( environment.caveatEnforcers.ExactExecutionEnforcer, diff --git a/packages/delegation-toolkit/test/caveatBuilder/idBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/idBuilder.test.ts index bcc84f3b..34972ac2 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/idBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/idBuilder.test.ts @@ -11,8 +11,9 @@ describe('idBuilder()', () => { caveatEnforcers: { IdEnforcer: randomAddress() }, } as any as DeleGatorEnvironment; - const buildWithId = (id: bigint | number) => { - return idBuilder(environment, id); + const buildWithId = (idValue: bigint | number) => { + const config = { id: idValue }; + return idBuilder(environment, config); }; describe('validation', () => { @@ -26,7 +27,7 @@ describe('idBuilder()', () => { it('should fail with an invalid id (negative)', () => { const invalidId = -1n; expect(() => buildWithId(invalidId)).to.throw( - 'Invalid id: must be positive', + 'Invalid id: must be a non-negative number', ); }); diff --git a/packages/delegation-toolkit/test/caveatBuilder/limitedCallsBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/limitedCallsBuilder.test.ts index 10b63229..e8e1e758 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/limitedCallsBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/limitedCallsBuilder.test.ts @@ -12,7 +12,8 @@ describe('limitedCallsBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithLimit = (limit: number) => { - return limitedCallsBuilder(environment, limit); + const config = { limit }; + return limitedCallsBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/nativeBalanceChangeBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/nativeBalanceChangeBuilder.test.ts index a04bb015..0d9f3755 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/nativeBalanceChangeBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/nativeBalanceChangeBuilder.test.ts @@ -18,12 +18,8 @@ describe('nativeBalanceChangeBuilder', () => { balance: bigint, changeType: BalanceChangeType, ) => { - return nativeBalanceChangeBuilder( - environment, - recipient, - balance, - changeType, - ); + const config = { recipient, balance, changeType }; + return nativeBalanceChangeBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPaymentBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPaymentBuilder.test.ts index ef03ad4a..31bffc8f 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPaymentBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPaymentBuilder.test.ts @@ -13,7 +13,8 @@ describe('nativeTokenPaymentBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithAmountAndRecipient = (recipient: Hex, amount: bigint) => { - return nativeTokenPaymentBuilder(environment, recipient, amount); + const config = { recipient, amount }; + return nativeTokenPaymentBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPeriodTransferBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPeriodTransferBuilder.test.ts index 64df40d2..b47db467 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPeriodTransferBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenPeriodTransferBuilder.test.ts @@ -16,12 +16,8 @@ describe('nativeTokenPeriodTransferBuilder()', () => { periodDuration: number, startDate: number, ) => { - return nativeTokenPeriodTransferBuilder( - environment, - periodAmount, - periodDuration, - startDate, - ); + const config = { periodAmount, periodDuration, startDate }; + return nativeTokenPeriodTransferBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenStreamingBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenStreamingBuilder.test.ts index c106c474..4a40072c 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenStreamingBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenStreamingBuilder.test.ts @@ -21,13 +21,8 @@ describe('nativeTokenStreamingBuilder()', () => { amountPerSecond: bigint, startTime: number, ) => { - return nativeTokenStreamingBuilder( - environment, - initialAmount, - maxAmount, - amountPerSecond, - startTime, - ); + const config = { initialAmount, maxAmount, amountPerSecond, startTime }; + return nativeTokenStreamingBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenTransferAmountBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenTransferAmountBuilder.test.ts index 743e4d2e..73889d6e 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/nativeTokenTransferAmountBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/nativeTokenTransferAmountBuilder.test.ts @@ -12,14 +12,15 @@ describe('nativeTokenTransferAmountBuilder()', () => { caveatEnforcers: { NativeTokenTransferAmountEnforcer: randomAddress() }, } as any as DeleGatorEnvironment; - const buildWithAllowance = (allowance: bigint) => { - return nativeTokenTransferAmountBuilder(environment, allowance); + const buildWithAllowance = (maxAmount: bigint) => { + const config = { maxAmount }; + return nativeTokenTransferAmountBuilder(environment, config); }; describe('validation', () => { it('should fail with negative allowance', () => { expect(() => buildWithAllowance(-1n)).to.throw( - 'Invalid allowance: must be zero or positive', + 'Invalid maxAmount: must be zero or positive', ); }); }); diff --git a/packages/delegation-toolkit/test/caveatBuilder/nonceBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/nonceBuilder.test.ts index 9886b78f..09fb730a 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/nonceBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/nonceBuilder.test.ts @@ -13,7 +13,8 @@ describe('nonceBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithNonce = (nonce: Hex) => { - return nonceBuilder(environment, nonce); + const config = { nonce }; + return nonceBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/ownershipTransferBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/ownershipTransferBuilder.test.ts index ace7caba..6873a289 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/ownershipTransferBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/ownershipTransferBuilder.test.ts @@ -12,28 +12,29 @@ describe('ownershipTransferBuilder()', () => { caveatEnforcers: { OwnershipTransferEnforcer: randomAddress() }, } as any as DeleGatorEnvironment; - const buildWithParams = (targetContract: Address) => { - return ownershipTransferBuilder(environment, targetContract); + const buildWithParams = (contractAddress: Address) => { + const config = { contractAddress }; + return ownershipTransferBuilder(environment, config); }; describe('builds a caveat', () => { it('should build a caveat with valid parameters', () => { - const targetContract = randomAddress(); + const contractAddress = randomAddress(); - const caveat = buildWithParams(targetContract); + const caveat = buildWithParams(contractAddress); expect(caveat).to.deep.equal({ enforcer: environment.caveatEnforcers.OwnershipTransferEnforcer, - terms: targetContract, + terms: contractAddress, args: '0x', }); }); }); it('should create a caveat with terms of the correct length', () => { - const targetContract = randomAddress(); + const contractAddress = randomAddress(); - const caveat = buildWithParams(targetContract); + const caveat = buildWithParams(contractAddress); expect(size(caveat.terms)).to.equal(EXPECTED_TERMS_LENGTH); }); diff --git a/packages/delegation-toolkit/test/caveatBuilder/redeemerBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/redeemerBuilder.test.ts index dfb35db1..25c8f9a9 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/redeemerBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/redeemerBuilder.test.ts @@ -17,7 +17,8 @@ describe('redeemerBuilder()', () => { }); const buildWithRedeemerAddresses = (redeemers: Address[]) => { - return redeemerBuilder(environment, redeemers); + const config = { redeemers }; + return redeemerBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/specificActionERC20TransferBatchBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/specificActionERC20TransferBatchBuilder.test.ts index 4672832c..ade339e6 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/specificActionERC20TransferBatchBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/specificActionERC20TransferBatchBuilder.test.ts @@ -18,17 +18,17 @@ describe('specificActionERC20TransferBatchBuilder()', () => { tokenAddress: Address, recipient: Address, amount: bigint, - firstTarget: Address, - firstCalldata: `0x${string}`, + target: Address, + calldata: `0x${string}`, ) => { - return specificActionERC20TransferBatchBuilder( - environment, + const config = { tokenAddress, recipient, amount, - firstTarget, - firstCalldata, - ); + target, + calldata, + }; + return specificActionERC20TransferBatchBuilder(environment, config); }; describe('validation', () => { @@ -58,7 +58,7 @@ describe('specificActionERC20TransferBatchBuilder()', () => { ).to.throw('Invalid recipient: must be a valid address'); }); - it('should fail with an invalid first target address', () => { + it('should fail with an invalid target address', () => { const invalidAddress = 'invalid-address' as Address; expect(() => buildWithParams( @@ -68,7 +68,7 @@ describe('specificActionERC20TransferBatchBuilder()', () => { invalidAddress, '0x', ), - ).to.throw('Invalid firstTarget: must be a valid address'); + ).to.throw('Invalid target: must be a valid address'); }); it('should fail with a non-positive amount', () => { @@ -111,15 +111,15 @@ describe('specificActionERC20TransferBatchBuilder()', () => { const tokenAddress = randomAddress(); const recipient = randomAddress(); const amount = 1000000n; - const firstTarget = randomAddress(); - const firstCalldata = '0x12345678' as const; + const target = randomAddress(); + const calldata = '0x12345678' as const; const caveat = buildWithParams( tokenAddress, recipient, amount, - firstTarget, - firstCalldata, + target, + calldata, ); expect(caveat.enforcer).to.equal( @@ -132,8 +132,8 @@ describe('specificActionERC20TransferBatchBuilder()', () => { tokenAddress, recipient, toHex(amount, { size: 32 }), - firstTarget, - firstCalldata, + target, + calldata, ]); expect(caveat.terms).to.equal(expectedTerms); }); @@ -142,15 +142,15 @@ describe('specificActionERC20TransferBatchBuilder()', () => { const tokenAddress = randomAddress(); const recipient = randomAddress(); const amount = 1000000n; - const firstTarget = randomAddress(); - const firstCalldata = '0x' as const; + const target = randomAddress(); + const calldata = '0x' as const; const caveat = buildWithParams( tokenAddress, recipient, amount, - firstTarget, - firstCalldata, + target, + calldata, ); expect(size(caveat.terms)).to.be.greaterThanOrEqual( diff --git a/packages/delegation-toolkit/test/caveatBuilder/timestampBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/timestampBuilder.test.ts index cf445e6a..81db3905 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/timestampBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/timestampBuilder.test.ts @@ -16,7 +16,8 @@ describe('timestampBuilder()', () => { afterThreshold: number, beforeThreshold: number, ) => { - return timestampBuilder(environment, afterThreshold, beforeThreshold); + const config = { afterThreshold, beforeThreshold }; + return timestampBuilder(environment, config); }; describe('validation', () => { diff --git a/packages/delegation-toolkit/test/caveatBuilder/valueLteBuilder.test.ts b/packages/delegation-toolkit/test/caveatBuilder/valueLteBuilder.test.ts index 53d247ca..ce737d09 100644 --- a/packages/delegation-toolkit/test/caveatBuilder/valueLteBuilder.test.ts +++ b/packages/delegation-toolkit/test/caveatBuilder/valueLteBuilder.test.ts @@ -13,7 +13,8 @@ describe('valueLteEnforcerBuilder()', () => { } as any as DeleGatorEnvironment; const buildWithMaxValue = (maxValue: bigint) => { - return valueLteBuilder(environment, maxValue); + const config = { maxValue }; + return valueLteBuilder(environment, config); }; describe('validation', () => { From d7c42e0aec50fce701aa47c689f8314c830cc11d Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Tue, 8 Jul 2025 07:46:00 +1200 Subject: [PATCH 4/9] Fix linting issues --- .../delegation-toolkit/src/caveatBuilder/caveatBuilder.ts | 4 +++- .../delegation-toolkit/src/caveatBuilder/deployedBuilder.ts | 4 +--- .../src/caveatBuilder/erc20PeriodTransferBuilder.ts | 5 +---- .../src/caveatBuilder/erc20StreamingBuilder.ts | 6 +----- .../src/caveatBuilder/erc20TransferAmountBuilder.ts | 3 +-- .../src/caveatBuilder/exactExecutionBatchBuilder.ts | 2 +- .../specificActionERC20TransferBatchBuilder.ts | 6 +----- packages/delegation-toolkit/src/caveatBuilder/types.ts | 2 +- packages/delegation-toolkit/src/delegation.ts | 1 + packages/delegation-toolkit/test/delegation.test.ts | 6 +++--- 10 files changed, 14 insertions(+), 25 deletions(-) diff --git a/packages/delegation-toolkit/src/caveatBuilder/caveatBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/caveatBuilder.ts index a83be433..d4cf3a72 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/caveatBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/caveatBuilder.ts @@ -11,7 +11,9 @@ const INSECURE_UNRESTRICTED_DELEGATION_ERROR_MESSAGE = /** * Resolves the array of Caveat from a Caveats argument. - * @param caveats - The caveats to be resolved, which can be either a CaveatBuilder or an array of Caveat. + * @param options - The caveats to be resolved, which can be either a CaveatBuilder or an array of Caveat. + * @param options.caveats - The caveats to be resolved, which can be either a CaveatBuilder or an array of Caveat. + * @param options.allowInsecureUnrestrictedDelegation - Whether to allow insecure unrestricted delegation. * @returns The resolved array of caveats. */ export const resolveCaveats = ({ diff --git a/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts index c1aa5511..2daedcf4 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts @@ -14,9 +14,7 @@ export type DeployedBuilderConfig = { * Builds a caveat struct for a DeployedEnforcer. * * @param environment - The DeleGator environment. - * @param contractAddress - The address of the contract that must be deployed. - * @param salt - The address of the factory contract. - * @param bytecode - The bytecode of the contract to be deployed. + * @param config - The configuration for the deployed builder. * @returns The Caveat. * @throws Error if the contract address, factory address, or bytecode is invalid. */ diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts index 24bcd547..0f68fe61 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts @@ -19,10 +19,7 @@ export type Erc20PeriodTransferBuilderConfig = { * and any unused tokens are forfeited once the period ends. * * @param environment - The DeleGator environment. - * @param tokenAddress - The address of the ERC20 token contract. - * @param periodAmount - The maximum amount of tokens that can be transferred per period. - * @param periodDuration - The duration of each period in seconds. - * @param startDate - The timestamp when the first period begins. + * @param config - The configuration for the ERC20 period transfer builder. * @returns The Caveat. * @throws Error if the token address is invalid or if any of the numeric parameters are invalid. */ diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts index f2e680b1..84f5c870 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts @@ -17,11 +17,7 @@ export type Erc20StreamingBuilderConfig = { * Builds a caveat for ERC20 token streaming with configurable parameters. * * @param environment - The DeleGator environment. - * @param tokenAddress - The tokenAddress of the ERC20 token. - * @param initialAmount - The initial amount of tokens to release at start time. - * @param maxAmount - The maximum amount of tokens that can be released. - * @param amountPerSecond - The rate at which the allowance increases per second. - * @param startTime - The timestamp from which the allowance streaming begins. + * @param config - The configuration for the ERC20 streaming builder. * @returns The Caveat. * @throws Error if the token address is invalid. * @throws Error if the initial amount is a negative number. diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts index a74ba416..8f0a5b19 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts @@ -14,8 +14,7 @@ export type Erc20TransferAmountBuilderConfig = { * Builds a caveat struct for ERC20TransferAmountEnforcer. * * @param environment - The DeleGator environment. - * @param tokenAddress - The address of the ERC20 token contract. - * @param maxAmount - The maximum amount of tokens that can be transferred. + * @param config - The configuration for the ERC20 transfer amount builder. * @returns The Caveat. * @throws Error if the token address is invalid or if the max amount is not a positive number. */ diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts index 4955939f..12f3fef9 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts @@ -1,4 +1,4 @@ -import { encodeAbiParameters, isAddress, encodePacked } from 'viem'; +import { encodeAbiParameters, isAddress } from 'viem'; import type { ExecutionStruct } from '../executions'; import type { Caveat, DeleGatorEnvironment } from '../types'; diff --git a/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts index ca462cbf..843eb038 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts @@ -18,11 +18,7 @@ export type SpecificActionErc20TransferBatchBuilderConfig = { * Enforces a batch of exactly 2 transactions: a specific action followed by an ERC20 transfer. * * @param environment - The DeleGator environment. - * @param tokenAddress - The address of the ERC20 token contract. - * @param recipient - The address that will receive the tokens. - * @param amount - The amount of tokens to transfer. - * @param firstTarget - The target address for the first transaction. - * @param firstCalldata - The calldata for the first transaction. + * @param config - The configuration for the specific action ERC20 transfer batch builder. * @returns The Caveat. * @throws Error if any of the addresses are invalid or if the amount is not a positive number. */ diff --git a/packages/delegation-toolkit/src/caveatBuilder/types.ts b/packages/delegation-toolkit/src/caveatBuilder/types.ts index 5fb28731..060f67e5 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/types.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/types.ts @@ -1,4 +1,4 @@ -import { DeleGatorEnvironment } from 'src/types'; +import type { DeleGatorEnvironment } from 'src/types'; export enum BalanceChangeType { Increase = 0x0, diff --git a/packages/delegation-toolkit/src/delegation.ts b/packages/delegation-toolkit/src/delegation.ts index d4cbebe5..c2552f3d 100644 --- a/packages/delegation-toolkit/src/delegation.ts +++ b/packages/delegation-toolkit/src/delegation.ts @@ -270,6 +270,7 @@ export const createOpenDelegation = ( * @param params.chainId - The chain ID for the signature. * @param params.name - The name of the contract. * @param params.version - The version of the contract. + * @param params.allowInsecureUnrestrictedDelegation - Whether to allow insecure unrestricted delegation. * @returns The signed delegation. */ export const signDelegation = async ({ diff --git a/packages/delegation-toolkit/test/delegation.test.ts b/packages/delegation-toolkit/test/delegation.test.ts index 99f5b57d..694fa7d6 100644 --- a/packages/delegation-toolkit/test/delegation.test.ts +++ b/packages/delegation-toolkit/test/delegation.test.ts @@ -1,6 +1,8 @@ import { expect } from 'chai'; import { stub } from 'sinon'; +import { getAddress } from 'viem'; +import { randomAddress } from './utils'; import { resolveCaveats } from '../src/caveatBuilder'; import { type DelegationStruct, @@ -16,8 +18,6 @@ import { signDelegation, } from '../src/delegation'; import type { Caveat, Delegation } from '../src/types'; -import { randomAddress } from './utils'; -import { getAddress } from 'viem'; const mockDelegate = '0x1234567890123456789012345678901234567890' as const; const mockDelegator = '0x0987654321098765432109876543210987654321' as const; @@ -645,7 +645,7 @@ describe('signDelegation', () => { }); expect(signature).to.equal('mockSignature'); - expect(mockSigner.signTypedData.calledOnce).to.be.true; + expect(mockSigner.signTypedData.calledOnce).to.equal(true); }); it('should throw an error if no caveats are provided and allowInsecureUnrestrictedDelegation is false', async () => { From f002d564455b7e7f286d8267c75ef3b425900348 Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Tue, 8 Jul 2025 08:15:41 +1200 Subject: [PATCH 5/9] Update e2e tests to match new caveatBuilder interface --- .../test/caveats/allowedCalldata.test.ts | 12 ++- .../test/caveats/allowedMethods.test.ts | 6 +- .../test/caveats/allowedTargets.test.ts | 6 +- .../test/caveats/argsEqualityCheck.test.ts | 10 +-- .../test/caveats/blockNumber.test.ts | 14 ++-- .../test/caveats/deployed.test.ts | 18 +++-- .../test/caveats/erc20PeriodTransfer.test.ts | 78 ++++++++----------- .../test/caveats/erc20Streaming.test.ts | 63 ++++++++------- .../test/caveats/exactCalldata.test.ts | 14 ++-- .../test/caveats/exactCalldataBatch.test.ts | 16 ++-- .../test/caveats/exactExecution.test.ts | 14 ++-- .../test/caveats/exactExecutionBatch.test.ts | 16 ++-- .../delegator-e2e/test/caveats/id.test.ts | 13 ++-- .../test/caveats/limitedCalls.test.ts | 4 +- .../test/caveats/multiTokenPeriod.test.ts | 4 +- .../test/caveats/nativeBalanceChange.test.ts | 31 ++++---- .../test/caveats/nativeTokenPayment.test.ts | 41 ++++++---- .../caveats/nativeTokenPeriodTransfer.test.ts | 49 ++++++------ .../test/caveats/nativeTokenStreaming.test.ts | 41 +++++----- .../caveats/nativeTokenTransferAmount.test.ts | 6 +- .../delegator-e2e/test/caveats/nonce.test.ts | 6 +- .../test/caveats/redeemer.test.ts | 6 +- .../specificActionERC20TransferBatch.test.ts | 34 ++++---- .../test/caveats/timestamp.test.ts | 14 ++-- .../test/caveats/valueLte.test.ts | 4 +- .../test/delegateAndRedeem.test.ts | 20 +++-- ...c7710sendTransactionWithDelegation.test.ts | 13 ++-- ...710sendUserOperationWithDelegation.test.ts | 12 +-- 28 files changed, 295 insertions(+), 270 deletions(-) diff --git a/packages/delegator-e2e/test/caveats/allowedCalldata.test.ts b/packages/delegator-e2e/test/caveats/allowedCalldata.test.ts index 4731804d..9380a617 100644 --- a/packages/delegator-e2e/test/caveats/allowedCalldata.test.ts +++ b/packages/delegator-e2e/test/caveats/allowedCalldata.test.ts @@ -1,6 +1,5 @@ import { beforeEach, test, expect } from 'vitest'; import { - createCaveatBuilder, createDelegation, createExecution, Implementation, @@ -8,6 +7,7 @@ import { type MetaMaskSmartAccount, } from '@metamask/delegation-toolkit'; import { + createCaveatBuilder, encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, @@ -143,7 +143,10 @@ const runTest_expectSuccess = async ( to: bobSmartAccount.address, from: aliceSmartAccount.address, caveats: caveats.reduce((builder, caveat) => { - builder.addCaveat('allowedCalldata', caveat.from, caveat.calldata); + builder.addCaveat('allowedCalldata', { + startIndex: caveat.from, + value: caveat.calldata, + }); return builder; }, createCaveatBuilder(environment)), }); @@ -211,7 +214,10 @@ const runTest_expectFailure = async ( to: bobSmartAccount.address, from: aliceSmartAccount.address, caveats: caveats.reduce((builder, caveat) => { - builder.addCaveat('allowedCalldata', caveat.from, caveat.calldata); + builder.addCaveat('allowedCalldata', { + startIndex: caveat.from, + value: caveat.calldata, + }); return builder; }, createCaveatBuilder(aliceSmartAccount.environment)), }); diff --git a/packages/delegator-e2e/test/caveats/allowedMethods.test.ts b/packages/delegator-e2e/test/caveats/allowedMethods.test.ts index caa6ea9d..d9329331 100644 --- a/packages/delegator-e2e/test/caveats/allowedMethods.test.ts +++ b/packages/delegator-e2e/test/caveats/allowedMethods.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createExecution, createDelegation, Implementation, @@ -140,7 +140,7 @@ const runTest_expectSuccess = async ( from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'allowedMethods', - allowedMethods, + { selectors: allowedMethods }, ), }); @@ -206,7 +206,7 @@ const runTest_expectFailure = async ( from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'allowedMethods', - allowedMethods, + { selectors: allowedMethods }, ), }); diff --git a/packages/delegator-e2e/test/caveats/allowedTargets.test.ts b/packages/delegator-e2e/test/caveats/allowedTargets.test.ts index 8f64650a..dac1e42b 100644 --- a/packages/delegator-e2e/test/caveats/allowedTargets.test.ts +++ b/packages/delegator-e2e/test/caveats/allowedTargets.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createExecution, createDelegation, Implementation, @@ -110,7 +110,7 @@ const runTest_expectSuccess = async ( from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'allowedTargets', - allowedTargets, + { targets: allowedTargets }, ), }); @@ -176,7 +176,7 @@ const runTest_expectFailure = async ( from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'allowedTargets', - allowedTargets, + { targets: allowedTargets }, ), }); diff --git a/packages/delegator-e2e/test/caveats/argsEqualityCheck.test.ts b/packages/delegator-e2e/test/caveats/argsEqualityCheck.test.ts index 2676f481..af3b1096 100644 --- a/packages/delegator-e2e/test/caveats/argsEqualityCheck.test.ts +++ b/packages/delegator-e2e/test/caveats/argsEqualityCheck.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createExecution, createDelegation, Implementation, @@ -128,13 +128,13 @@ test('Bob attempts to redeem the delegation with args when none are expected', a ); }); -const runTest_expectSuccess = async (expectedArgs: Hex, actualArgs: Hex) => { +const runTest_expectSuccess = async (args: Hex, actualArgs: Hex) => { const delegation = createDelegation({ to: bobSmartAccount.address, from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'argsEqualityCheck', - expectedArgs, + { args }, ), }); @@ -193,7 +193,7 @@ const runTest_expectSuccess = async (expectedArgs: Hex, actualArgs: Hex) => { }; const runTest_expectFailure = async ( - expectedArgs: Hex, + args: Hex, actualArgs: Hex, expectedError: string, ) => { @@ -202,7 +202,7 @@ const runTest_expectFailure = async ( from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'argsEqualityCheck', - expectedArgs, + { args }, ), }); diff --git a/packages/delegator-e2e/test/caveats/blockNumber.test.ts b/packages/delegator-e2e/test/caveats/blockNumber.test.ts index 3107860d..3aad5a42 100644 --- a/packages/delegator-e2e/test/caveats/blockNumber.test.ts +++ b/packages/delegator-e2e/test/caveats/blockNumber.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createExecution, createDelegation, Implementation, @@ -178,8 +178,10 @@ const runTest_expectSuccess = async ( from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'blockNumber', - afterThreshold, - beforeThreshold, + { + afterThreshold, + beforeThreshold, + }, ), }); @@ -248,8 +250,10 @@ const runTest_expectFailure = async ( from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'blockNumber', - afterThreshold, - beforeThreshold, + { + afterThreshold, + beforeThreshold, + }, ), }); diff --git a/packages/delegator-e2e/test/caveats/deployed.test.ts b/packages/delegator-e2e/test/caveats/deployed.test.ts index 14b0d82c..9e24e8ed 100644 --- a/packages/delegator-e2e/test/caveats/deployed.test.ts +++ b/packages/delegator-e2e/test/caveats/deployed.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createDelegation, createExecution, Implementation, @@ -163,9 +163,11 @@ const runTest_expectSuccess = async (deployedAddress: Hex, salt: Hex) => { from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'deployed', - deployedAddress, - salt, - CounterMetadata.bytecode.object as Hex, + { + contractAddress: deployedAddress, + salt, + bytecode: CounterMetadata.bytecode.object as Hex, + }, ), }); @@ -244,9 +246,11 @@ const runTest_expectFailure = async ( from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'deployed', - deployedAddress, - salt, - CounterMetadata.bytecode.object as Hex, + { + contractAddress: deployedAddress, + salt, + bytecode: CounterMetadata.bytecode.object as Hex, + }, ), }); diff --git a/packages/delegator-e2e/test/caveats/erc20PeriodTransfer.test.ts b/packages/delegator-e2e/test/caveats/erc20PeriodTransfer.test.ts index 9988f078..678a29db 100644 --- a/packages/delegator-e2e/test/caveats/erc20PeriodTransfer.test.ts +++ b/packages/delegator-e2e/test/caveats/erc20PeriodTransfer.test.ts @@ -3,10 +3,10 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { createDelegation, - createCaveatBuilder, createExecution, Implementation, toMetaMaskSmartAccount, @@ -106,13 +106,12 @@ const runTest_expectSuccess = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, + caveats: createCaveatBuilder(environment).addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, periodAmount, periodDuration, startDate, - ), + }), }); const signedDelegation = { @@ -187,13 +186,12 @@ const runTest_expectFailure = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, + caveats: createCaveatBuilder(environment).addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, periodAmount, periodDuration, startDate, - ), + }), }); const signedDelegation = { @@ -332,13 +330,12 @@ test('Bob attempts to redeem with invalid terms length', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, + .addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, periodAmount, periodDuration, startDate, - ) + }) .build(); // Create invalid terms length by appending an empty byte @@ -400,13 +397,12 @@ test('Bob attempts to redeem with invalid execution length', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, + .addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, periodAmount, periodDuration, startDate, - ) + }) .build(); const delegation = createDelegation({ @@ -470,13 +466,12 @@ test('Bob attempts to redeem with invalid contract', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, // valid token address + .addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, periodAmount, periodDuration, startDate, - ) + }) .build(); const delegation = createDelegation({ @@ -536,13 +531,12 @@ test('Bob attempts to redeem with invalid method', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, + .addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, periodAmount, periodDuration, startDate, - ) + }) .build(); const delegation = createDelegation({ @@ -602,13 +596,12 @@ test('Bob attempts to redeem with zero start date', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, + .addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, periodAmount, periodDuration, - currentTime, // valid start date - ) + startDate: 1, // we need a valid start date to pass validation + }) .build(); // Modify the terms to encode zero start date @@ -675,13 +668,12 @@ test('Bob attempts to redeem with zero period amount', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, - 1n, // valid period amount + .addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, + periodAmount: 1n, // we need a valid period amount to pass validation periodDuration, startDate, - ) + }) .build(); // Modify the terms to encode zero period amount @@ -748,13 +740,12 @@ test('Bob attempts to redeem with zero period duration', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, + .addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, periodAmount, - 3600, // valid period duration + periodDuration: 1, // we need a valid period duration to pass validation startDate, - ) + }) .build(); // Modify the terms to encode zero period duration @@ -821,13 +812,12 @@ test('Bob attempts to redeem before start date', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20PeriodTransfer', - erc20TokenAddress, + .addCaveat('erc20PeriodTransfer', { + tokenAddress: erc20TokenAddress, periodAmount, periodDuration, startDate, - ) + }) .build(); const delegation = createDelegation({ diff --git a/packages/delegator-e2e/test/caveats/erc20Streaming.test.ts b/packages/delegator-e2e/test/caveats/erc20Streaming.test.ts index 885732f9..b46770d4 100644 --- a/packages/delegator-e2e/test/caveats/erc20Streaming.test.ts +++ b/packages/delegator-e2e/test/caveats/erc20Streaming.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createExecution, createDelegation, Implementation, @@ -389,14 +389,13 @@ test('Bob attempts to redeem with invalid terms length', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20Streaming', - erc20TokenAddress, + .addCaveat('erc20Streaming', { + tokenAddress: erc20TokenAddress, initialAmount, maxAmount, amountPerSecond, startTime, - ) + }) .build(); // create invalid terms length by appending an empty byte @@ -461,14 +460,13 @@ test('Bob attempts to redeem with maxAmount less than initialAmount', async () = const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20Streaming', - erc20TokenAddress, - 0n, // valid initialAmount - 1n, // valid maxAmount + .addCaveat('erc20Streaming', { + tokenAddress: erc20TokenAddress, + initialAmount, + maxAmount: initialAmount + 1n, // we need a valid maxAmount amountPerSecond, startTime, - ) + }) .build(); // Modify the terms to encode maxAmount < initialAmount @@ -539,14 +537,13 @@ test('Bob attempts to redeem with zero start time', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'erc20Streaming', - erc20TokenAddress, + .addCaveat('erc20Streaming', { + tokenAddress: erc20TokenAddress, initialAmount, maxAmount, amountPerSecond, - currentTime, // valid start time - ) + startTime: currentTime, // valid start time + }) .build(); // Modify the terms to encode zero start time @@ -621,14 +618,15 @@ const runTest_expectSuccess = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'erc20Streaming', - erc20TokenAddress, - initialAmount, - maxAmount, - amountPerSecond, - startTime, - ), + caveats: createCaveatBuilder(environment) + .addCaveat('erc20Streaming', { + tokenAddress: erc20TokenAddress, + initialAmount, + maxAmount, + amountPerSecond, + startTime, + }) + .build(), }); const signedDelegation = { @@ -708,14 +706,15 @@ const runTest_expectFailure = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'erc20Streaming', - erc20TokenAddress, - initialAmount, - maxAmount, - amountPerSecond, - startTime, - ), + caveats: createCaveatBuilder(environment) + .addCaveat('erc20Streaming', { + tokenAddress: erc20TokenAddress, + initialAmount, + maxAmount, + amountPerSecond, + startTime, + }) + .build(), }); const signedDelegation = { diff --git a/packages/delegator-e2e/test/caveats/exactCalldata.test.ts b/packages/delegator-e2e/test/caveats/exactCalldata.test.ts index b465328e..3039afc1 100644 --- a/packages/delegator-e2e/test/caveats/exactCalldata.test.ts +++ b/packages/delegator-e2e/test/caveats/exactCalldata.test.ts @@ -1,6 +1,5 @@ import { beforeEach, test, expect } from 'vitest'; import { - createCaveatBuilder, createExecution, createDelegation, Implementation, @@ -8,6 +7,7 @@ import { type MetaMaskSmartAccount, } from '@metamask/delegation-toolkit'; import { + createCaveatBuilder, encodePermissionContexts, encodeExecutionCalldatas, SINGLE_DEFAULT_MODE, @@ -84,10 +84,9 @@ const runTest_expectSuccess = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'exactCalldata', + caveats: createCaveatBuilder(environment).addCaveat('exactCalldata', { calldata, - ), + }), }); const signedDelegation = { @@ -142,10 +141,9 @@ const runTest_expectFailure = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'exactCalldata', - expectedCalldata, - ), + caveats: createCaveatBuilder(environment).addCaveat('exactCalldata', { + calldata: expectedCalldata, + }), }); const signedDelegation = { diff --git a/packages/delegator-e2e/test/caveats/exactCalldataBatch.test.ts b/packages/delegator-e2e/test/caveats/exactCalldataBatch.test.ts index 9a982f36..1874a836 100644 --- a/packages/delegator-e2e/test/caveats/exactCalldataBatch.test.ts +++ b/packages/delegator-e2e/test/caveats/exactCalldataBatch.test.ts @@ -1,6 +1,5 @@ import { beforeEach, test, expect } from 'vitest'; import { - createCaveatBuilder, createDelegation, Implementation, toMetaMaskSmartAccount, @@ -8,6 +7,7 @@ import { type ExecutionStruct, } from '@metamask/delegation-toolkit'; import { + createCaveatBuilder, BATCH_DEFAULT_MODE, encodeExecutionCalldatas, encodePermissionContexts, @@ -81,10 +81,9 @@ const runTest_expectSuccess = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'exactCalldataBatch', - expectedExecutions, - ), + caveats: createCaveatBuilder(environment).addCaveat('exactCalldataBatch', { + executions: expectedExecutions, + }), }); const signedDelegation = { @@ -134,10 +133,9 @@ const runTest_expectFailure = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'exactCalldataBatch', - expectedExecutions, - ), + caveats: createCaveatBuilder(environment).addCaveat('exactCalldataBatch', { + executions: expectedExecutions, + }), }); const signedDelegation = { diff --git a/packages/delegator-e2e/test/caveats/exactExecution.test.ts b/packages/delegator-e2e/test/caveats/exactExecution.test.ts index 830eb91d..38c1bfa8 100644 --- a/packages/delegator-e2e/test/caveats/exactExecution.test.ts +++ b/packages/delegator-e2e/test/caveats/exactExecution.test.ts @@ -3,10 +3,10 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { createDelegation, - createCaveatBuilder, Implementation, toMetaMaskSmartAccount, type ExecutionStruct, @@ -77,10 +77,9 @@ const runTest_expectSuccess = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'exactExecution', + caveats: createCaveatBuilder(environment).addCaveat('exactExecution', { execution, - ), + }), }); const signedDelegation = { @@ -130,10 +129,9 @@ const runTest_expectFailure = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'exactExecution', - expectedExecution, - ), + caveats: createCaveatBuilder(environment).addCaveat('exactExecution', { + execution: expectedExecution, + }), }); const signedDelegation = { diff --git a/packages/delegator-e2e/test/caveats/exactExecutionBatch.test.ts b/packages/delegator-e2e/test/caveats/exactExecutionBatch.test.ts index 900f3855..e1bfd28b 100644 --- a/packages/delegator-e2e/test/caveats/exactExecutionBatch.test.ts +++ b/packages/delegator-e2e/test/caveats/exactExecutionBatch.test.ts @@ -3,10 +3,10 @@ import { encodeExecutionCalldatas, encodePermissionContexts, BATCH_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { createDelegation, - createCaveatBuilder, Implementation, toMetaMaskSmartAccount, type ExecutionStruct, @@ -79,10 +79,9 @@ const runTest_expectSuccess = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'exactExecutionBatch', - executions, - ), + caveats: createCaveatBuilder(environment).addCaveat('exactExecutionBatch', { + executions: executions, + }), }); const signedDelegation = { @@ -132,10 +131,9 @@ const runTest_expectFailure = async ( const delegation = createDelegation({ to: delegate, from: delegator.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'exactExecutionBatch', - expectedExecutions, - ), + caveats: createCaveatBuilder(environment).addCaveat('exactExecutionBatch', { + executions: expectedExecutions, + }), }); const signedDelegation = { diff --git a/packages/delegator-e2e/test/caveats/id.test.ts b/packages/delegator-e2e/test/caveats/id.test.ts index feb7a00d..24191284 100644 --- a/packages/delegator-e2e/test/caveats/id.test.ts +++ b/packages/delegator-e2e/test/caveats/id.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createDelegation, createExecution, Implementation, @@ -104,7 +104,7 @@ test('Bob attempts to redeem a second delegation with the same id', async () => await runTest_expectFailure(id, 'IdEnforcer:id-already-used'); }); -const runTest_expectSuccess = async (id: number) => { +const runTest_expectSuccess = async (idValue: number) => { const newCount = hexToBigInt(randomBytes(32)); const delegation = createDelegation({ @@ -112,7 +112,7 @@ const runTest_expectSuccess = async (id: number) => { from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'id', - id, + { id: idValue }, ), }); @@ -170,7 +170,10 @@ const runTest_expectSuccess = async (id: number) => { expect(countAfter).toEqual(newCount); }; -const runTest_expectFailure = async (id: number, expectedError: string) => { +const runTest_expectFailure = async ( + idValue: number, + expectedError: string, +) => { const newCount = hexToBigInt(randomBytes(32)); const delegation = createDelegation({ @@ -178,7 +181,7 @@ const runTest_expectFailure = async (id: number, expectedError: string) => { from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'id', - id, + { id: idValue }, ), }); diff --git a/packages/delegator-e2e/test/caveats/limitedCalls.test.ts b/packages/delegator-e2e/test/caveats/limitedCalls.test.ts index c94417ab..5badcdbc 100644 --- a/packages/delegator-e2e/test/caveats/limitedCalls.test.ts +++ b/packages/delegator-e2e/test/caveats/limitedCalls.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createDelegation, createExecution, Implementation, @@ -100,7 +100,7 @@ const runTest = async (limit: number, runs: number) => { from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'limitedCalls', - limit, + { limit }, ), }); diff --git a/packages/delegator-e2e/test/caveats/multiTokenPeriod.test.ts b/packages/delegator-e2e/test/caveats/multiTokenPeriod.test.ts index a9547d97..eb30d6c8 100644 --- a/packages/delegator-e2e/test/caveats/multiTokenPeriod.test.ts +++ b/packages/delegator-e2e/test/caveats/multiTokenPeriod.test.ts @@ -3,10 +3,10 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { createDelegation, - createCaveatBuilder, createExecution, Implementation, toMetaMaskSmartAccount, @@ -274,7 +274,7 @@ const runTest_expectFailure = async ( ).rejects.toThrow(expectedError); }; -test('Bob redeems the delegation within period limit', async () => { +test('maincase: Bob redeems the delegation within period limit', async () => { const recipient = randomAddress(); const configs = [ diff --git a/packages/delegator-e2e/test/caveats/nativeBalanceChange.test.ts b/packages/delegator-e2e/test/caveats/nativeBalanceChange.test.ts index a2989b1b..302d760e 100644 --- a/packages/delegator-e2e/test/caveats/nativeBalanceChange.test.ts +++ b/packages/delegator-e2e/test/caveats/nativeBalanceChange.test.ts @@ -1,6 +1,5 @@ import { beforeEach, test, expect } from 'vitest'; import { - createCaveatBuilder, createDelegation, createExecution, BalanceChangeType, @@ -9,6 +8,7 @@ import { type MetaMaskSmartAccount, } from '@metamask/delegation-toolkit'; import { + createCaveatBuilder, encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, @@ -124,12 +124,11 @@ test('Bob attempts to redeem with invalid terms length', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'nativeBalanceChange', + .addCaveat('nativeBalanceChange', { recipient, - requiredIncrease, - BalanceChangeType.Increase, - ) + balance: requiredIncrease, + changeType: BalanceChangeType.Increase, + }) .build(); // Create invalid terms length by appending an empty byte @@ -196,9 +195,11 @@ const testRun_expectSuccess = async ( from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'nativeBalanceChange', - target, - requiredChange, - changeType, + { + recipient: target, + balance: requiredChange, + changeType, + }, ), }); @@ -277,18 +278,16 @@ const testRun_expectFailure = async ( ? recipient : aliceSmartAccount.address; - const balanceBefore = await publicClient.getBalance({ - address: target, - }); - const delegation = createDelegation({ to: bobSmartAccount.address, from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'nativeBalanceChange', - target, - requiredChange, - changeType, + { + recipient: target, + balance: requiredChange, + changeType, + }, ), }); diff --git a/packages/delegator-e2e/test/caveats/nativeTokenPayment.test.ts b/packages/delegator-e2e/test/caveats/nativeTokenPayment.test.ts index 0dbd0154..76f20af4 100644 --- a/packages/delegator-e2e/test/caveats/nativeTokenPayment.test.ts +++ b/packages/delegator-e2e/test/caveats/nativeTokenPayment.test.ts @@ -5,9 +5,9 @@ import { encodePermissionContexts, getDelegationHashOffchain, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createDelegation, createExecution, Implementation, @@ -87,8 +87,10 @@ test('maincase: Bob redeems the delegation with a permissions context allowing p from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'nativeTokenPayment', - recipient, - requiredValue, + { + recipient, + amount: requiredValue, + }, ), }); @@ -103,7 +105,9 @@ test('maincase: Bob redeems the delegation with a permissions context allowing p from: bobSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'argsEqualityCheck', - args, + { + args, + }, ), }); @@ -133,8 +137,10 @@ test('Bob attempts to redeem the delegation without an argsEqualityCheckEnforcer from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'nativeTokenPayment', - recipient, - requiredValue, + { + recipient, + amount: requiredValue, + }, ), }); @@ -172,8 +178,10 @@ test('Bob attempts to redeem the delegation without providing a valid permission from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'nativeTokenPayment', - recipient, - requiredValue, + { + recipient, + amount: requiredValue, + }, ), }); @@ -193,7 +201,10 @@ test('Bob attempts to redeem with invalid terms length', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat('nativeTokenPayment', recipient, requiredValue) + .addCaveat('nativeTokenPayment', { + recipient, + amount: requiredValue, + }) .build(); // Create invalid terms length by appending an empty byte @@ -214,10 +225,9 @@ test('Bob attempts to redeem with invalid terms length', async () => { const paymentDelegation = createDelegation({ to: bobSmartAccount.environment.caveatEnforcers.NativeTokenPaymentEnforcer!, from: bobSmartAccount.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'argsEqualityCheck', + caveats: createCaveatBuilder(environment).addCaveat('argsEqualityCheck', { args, - ), + }), }); const signedPaymentDelegation = { @@ -245,11 +255,10 @@ test('Bob attempts to redeem with empty allowance delegations', async () => { const delegationRequiringNativeTokenPayment = createDelegation({ to: bobSmartAccount.address, from: aliceSmartAccount.address, - caveats: createCaveatBuilder(environment).addCaveat( - 'nativeTokenPayment', + caveats: createCaveatBuilder(environment).addCaveat('nativeTokenPayment', { recipient, - requiredValue, - ), + amount: requiredValue, + }), }); // Create empty allowance delegations array diff --git a/packages/delegator-e2e/test/caveats/nativeTokenPeriodTransfer.test.ts b/packages/delegator-e2e/test/caveats/nativeTokenPeriodTransfer.test.ts index 42deee8e..aa5d8a3b 100644 --- a/packages/delegator-e2e/test/caveats/nativeTokenPeriodTransfer.test.ts +++ b/packages/delegator-e2e/test/caveats/nativeTokenPeriodTransfer.test.ts @@ -3,10 +3,10 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { createDelegation, - createCaveatBuilder, Implementation, toMetaMaskSmartAccount, type MetaMaskSmartAccount, @@ -90,9 +90,11 @@ const runTest_expectSuccess = async ( from: delegator.address, caveats: createCaveatBuilder(environment).addCaveat( 'nativeTokenPeriodTransfer', - periodAmount, - periodDuration, - startDate, + { + periodAmount, + periodDuration, + startDate, + }, ), }); @@ -160,9 +162,11 @@ const runTest_expectFailure = async ( from: delegator.address, caveats: createCaveatBuilder(environment).addCaveat( 'nativeTokenPeriodTransfer', - periodAmount, - periodDuration, - startDate, + { + periodAmount, + periodDuration, + startDate, + }, ), }); @@ -288,12 +292,11 @@ test('Bob attempts to redeem with invalid terms length', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'nativeTokenPeriodTransfer', + .addCaveat('nativeTokenPeriodTransfer', { periodAmount, periodDuration, startDate, - ) + }) .build(); // Create invalid terms length by appending an empty byte @@ -348,12 +351,11 @@ test('Bob attempts to redeem with zero start date', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'nativeTokenPeriodTransfer', + .addCaveat('nativeTokenPeriodTransfer', { periodAmount, periodDuration, - currentTime, // valid start date - ) + startDate: currentTime, // valid start date + }) .build(); // Modify the terms to encode zero start date @@ -414,12 +416,11 @@ test('Bob attempts to redeem with zero period amount', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'nativeTokenPeriodTransfer', - 1n, // valid period amount + .addCaveat('nativeTokenPeriodTransfer', { + periodAmount: 1n, // valid period amount periodDuration, startDate, - ) + }) .build(); // Modify the terms to encode zero period amount @@ -480,12 +481,11 @@ test('Bob attempts to redeem with zero period duration', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'nativeTokenPeriodTransfer', + .addCaveat('nativeTokenPeriodTransfer', { periodAmount, - 3600, // valid period duration + periodDuration: 3600, // valid period duration startDate, - ) + }) .build(); // Modify the terms to encode zero period duration @@ -546,12 +546,11 @@ test('Bob attempts to redeem before start date', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'nativeTokenPeriodTransfer', + .addCaveat('nativeTokenPeriodTransfer', { periodAmount, periodDuration, startDate, - ) + }) .build(); const delegation = createDelegation({ diff --git a/packages/delegator-e2e/test/caveats/nativeTokenStreaming.test.ts b/packages/delegator-e2e/test/caveats/nativeTokenStreaming.test.ts index 4a72ea71..82dfab13 100644 --- a/packages/delegator-e2e/test/caveats/nativeTokenStreaming.test.ts +++ b/packages/delegator-e2e/test/caveats/nativeTokenStreaming.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createExecution, createDelegation, Implementation, @@ -315,13 +315,12 @@ test('Bob attempts to redeem with invalid terms length', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'nativeTokenStreaming', + .addCaveat('nativeTokenStreaming', { initialAmount, maxAmount, amountPerSecond, startTime, - ) + }) .build(); // Create invalid terms length by appending an empty byte @@ -380,13 +379,12 @@ test('Bob attempts to redeem with invalid max amount', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'nativeTokenStreaming', + .addCaveat('nativeTokenStreaming', { initialAmount, - parseEther('20'), // valid maxAmount + maxAmount: initialAmount + 1n, // we need a valid maxAmount amountPerSecond, startTime, - ) + }) .build(); caveats[0].terms = concat([ @@ -449,13 +447,12 @@ test('Bob attempts to redeem with zero start time', async () => { const { environment } = aliceSmartAccount; const caveats = createCaveatBuilder(environment) - .addCaveat( - 'nativeTokenStreaming', + .addCaveat('nativeTokenStreaming', { initialAmount, maxAmount, amountPerSecond, - currentTime, // valid start time - ) + startTime: currentTime, // valid start time + }) .build(); // Modify the terms to encode zero start time @@ -525,10 +522,12 @@ const runTest_expectSuccess = async ( from: delegator.address, caveats: createCaveatBuilder(environment).addCaveat( 'nativeTokenStreaming', - initialAmount, - maxAmount, - amountPerSecond, - startTime, + { + initialAmount, + maxAmount, + amountPerSecond, + startTime, + }, ), }); @@ -603,10 +602,12 @@ const runTest_expectFailure = async ( from: delegator.address, caveats: createCaveatBuilder(environment).addCaveat( 'nativeTokenStreaming', - initialAmount, - maxAmount, - amountPerSecond, - startTime, + { + initialAmount, + maxAmount, + amountPerSecond, + startTime, + }, ), }); diff --git a/packages/delegator-e2e/test/caveats/nativeTokenTransferAmount.test.ts b/packages/delegator-e2e/test/caveats/nativeTokenTransferAmount.test.ts index 3f54f51b..59b924a4 100644 --- a/packages/delegator-e2e/test/caveats/nativeTokenTransferAmount.test.ts +++ b/packages/delegator-e2e/test/caveats/nativeTokenTransferAmount.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createDelegation, createExecution, Implementation, @@ -90,7 +90,7 @@ const runTest_expectSuccess = async ( from: aliceAddress, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'nativeTokenTransferAmount', - allowance, + { maxAmount: allowance }, ), }); @@ -160,7 +160,7 @@ const runTest_expectFailure = async ( from: aliceAddress, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'nativeTokenTransferAmount', - allowance, + { maxAmount: allowance }, ), }); diff --git a/packages/delegator-e2e/test/caveats/nonce.test.ts b/packages/delegator-e2e/test/caveats/nonce.test.ts index 5369e8ab..983df28e 100644 --- a/packages/delegator-e2e/test/caveats/nonce.test.ts +++ b/packages/delegator-e2e/test/caveats/nonce.test.ts @@ -4,9 +4,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createDelegation, createExecution, Implementation, @@ -121,7 +121,7 @@ const runTest_expectSuccess = async (newCount: bigint, nonce: bigint) => { from: aliceAddress, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'nonce', - toHex(nonce), + { nonce: toHex(nonce) }, ), }); @@ -191,7 +191,7 @@ const runTest_expectFailure = async ( from: aliceAddress, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'nonce', - toHex(nonce), + { nonce: toHex(nonce) }, ), }); diff --git a/packages/delegator-e2e/test/caveats/redeemer.test.ts b/packages/delegator-e2e/test/caveats/redeemer.test.ts index ddce4a5a..59d505a2 100644 --- a/packages/delegator-e2e/test/caveats/redeemer.test.ts +++ b/packages/delegator-e2e/test/caveats/redeemer.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createDelegation, createExecution, Implementation, @@ -97,7 +97,7 @@ const runTest_expectSuccess = async ( from: aliceAddress, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'redeemer', - allowedRedeemers, + { redeemers: allowedRedeemers }, ), }); @@ -174,7 +174,7 @@ const runTest_expectFailure = async ( from: aliceAddress, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'redeemer', - allowedRedeemers, + { redeemers: allowedRedeemers }, ), }); diff --git a/packages/delegator-e2e/test/caveats/specificActionERC20TransferBatch.test.ts b/packages/delegator-e2e/test/caveats/specificActionERC20TransferBatch.test.ts index 883244b4..05329239 100644 --- a/packages/delegator-e2e/test/caveats/specificActionERC20TransferBatch.test.ts +++ b/packages/delegator-e2e/test/caveats/specificActionERC20TransferBatch.test.ts @@ -3,10 +3,10 @@ import { BATCH_DEFAULT_MODE, encodeExecutionCalldatas, encodePermissionContexts, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { createDelegation, - createCaveatBuilder, Implementation, toMetaMaskSmartAccount, type ExecutionStruct, @@ -87,8 +87,8 @@ const runTest_expectSuccess = async ( tokenAddress: Hex, recipient: Hex, amount: bigint, - firstTarget: Hex, - firstCalldata: Hex, + target: Hex, + calldata: Hex, executions: ExecutionStruct[], ) => { const { environment } = aliceSmartAccount; @@ -98,11 +98,13 @@ const runTest_expectSuccess = async ( from: delegator.address, caveats: createCaveatBuilder(environment).addCaveat( 'specificActionERC20TransferBatch', - tokenAddress, - recipient, - amount, - firstTarget, - firstCalldata, + { + tokenAddress, + recipient, + amount, + target, + calldata, + }, ), }); @@ -151,8 +153,8 @@ const runTest_expectFailure = async ( tokenAddress: Hex, recipient: Hex, amount: bigint, - firstTarget: Hex, - firstCalldata: Hex, + target: Hex, + calldata: Hex, executions: { target: Hex; value: bigint; @@ -167,11 +169,13 @@ const runTest_expectFailure = async ( from: delegator.address, caveats: createCaveatBuilder(environment).addCaveat( 'specificActionERC20TransferBatch', - tokenAddress, - recipient, - amount, - firstTarget, - firstCalldata, + { + tokenAddress, + recipient, + amount, + target, + calldata, + }, ), }); diff --git a/packages/delegator-e2e/test/caveats/timestamp.test.ts b/packages/delegator-e2e/test/caveats/timestamp.test.ts index 5150e4dd..bb241207 100644 --- a/packages/delegator-e2e/test/caveats/timestamp.test.ts +++ b/packages/delegator-e2e/test/caveats/timestamp.test.ts @@ -1,6 +1,5 @@ import { beforeEach, test, expect } from 'vitest'; import { - createCaveatBuilder, createExecution, createDelegation, Implementation, @@ -8,6 +7,7 @@ import { type MetaMaskSmartAccount, } from '@metamask/delegation-toolkit'; import { + createCaveatBuilder, encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, @@ -158,8 +158,10 @@ const runTest_expectSuccess = async ( from: aliceAddress, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'timestamp', - afterThreshold, - beforeThreshold, + { + afterThreshold, + beforeThreshold, + }, ), }); @@ -237,8 +239,10 @@ const runTest_expectFailure = async ( from: aliceAddress, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'timestamp', - afterThreshold, - beforeThreshold, + { + afterThreshold, + beforeThreshold, + }, ), }); diff --git a/packages/delegator-e2e/test/caveats/valueLte.test.ts b/packages/delegator-e2e/test/caveats/valueLte.test.ts index e86d93fb..43aff045 100644 --- a/packages/delegator-e2e/test/caveats/valueLte.test.ts +++ b/packages/delegator-e2e/test/caveats/valueLte.test.ts @@ -3,9 +3,9 @@ import { encodeExecutionCalldatas, encodePermissionContexts, SINGLE_DEFAULT_MODE, + createCaveatBuilder, } from '@metamask/delegation-toolkit/utils'; import { - createCaveatBuilder, createDelegation, createExecution, Implementation, @@ -122,7 +122,7 @@ const submitUserOperationForTest = async ( from: aliceAddress, caveats: createCaveatBuilder(aliceSmartAccount.environment).addCaveat( 'valueLte', - maxValue, + { maxValue }, ), }); diff --git a/packages/delegator-e2e/test/delegateAndRedeem.test.ts b/packages/delegator-e2e/test/delegateAndRedeem.test.ts index e6914d3c..6161cceb 100644 --- a/packages/delegator-e2e/test/delegateAndRedeem.test.ts +++ b/packages/delegator-e2e/test/delegateAndRedeem.test.ts @@ -10,7 +10,6 @@ import { import { expectCodeAt, expectUserOperationToSucceed } from './utils/assertions'; import { - createCaveatBuilder, createExecution, createDelegation, Implementation, @@ -21,6 +20,7 @@ import { type PartialSignature, } from '@metamask/delegation-toolkit'; import { + createCaveatBuilder, encodePermissionContexts, encodeExecutionCalldatas, SINGLE_DEFAULT_MODE, @@ -97,8 +97,10 @@ test('maincase: Bob increments the counter with a delegation from Alice', async to: bobSmartAccount.address, from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment) - .addCaveat('allowedTargets', [aliceCounterContractAddress]) - .addCaveat('allowedMethods', ['increment()']), + .addCaveat('allowedTargets', { + targets: [aliceCounterContractAddress], + }) + .addCaveat('allowedMethods', { selectors: ['increment()'] }), }); const signedDelegation = { @@ -201,8 +203,10 @@ test("Bob attempts to increment the counter with a delegation from Alice that do to: bobSmartAccount.address, from: aliceSmartAccount.address, caveats: createCaveatBuilder(aliceSmartAccount.environment) - .addCaveat('allowedTargets', [aliceCounterContractAddress]) - .addCaveat('allowedMethods', ['notTheRightFunction()']), + .addCaveat('allowedTargets', { + targets: [aliceCounterContractAddress], + }) + .addCaveat('allowedMethods', { selectors: ['notTheRightFunction()'] }), }); const signedDelegation = { @@ -279,8 +283,10 @@ test('Bob increments the counter with a delegation from a multisig account', asy to: bobSmartAccount.address, from: multisigSmartAccount.address, caveats: createCaveatBuilder(multisigSmartAccount.environment) - .addCaveat('allowedTargets', [counterContract.address]) - .addCaveat('allowedMethods', ['increment()']), + .addCaveat('allowedTargets', { + targets: [counterContract.address], + }) + .addCaveat('allowedMethods', { selectors: ['increment()'] }), }); // Get signatures from each signer diff --git a/packages/delegator-e2e/test/experimental/erc7710sendTransactionWithDelegation.test.ts b/packages/delegator-e2e/test/experimental/erc7710sendTransactionWithDelegation.test.ts index dea90f15..b49399b8 100644 --- a/packages/delegator-e2e/test/experimental/erc7710sendTransactionWithDelegation.test.ts +++ b/packages/delegator-e2e/test/experimental/erc7710sendTransactionWithDelegation.test.ts @@ -11,7 +11,6 @@ import { chain } from '../../src/config'; import { Implementation, toMetaMaskSmartAccount, - createCaveatBuilder, createDelegation, signDelegation, type MetaMaskSmartAccount, @@ -28,7 +27,10 @@ import { encodeFunctionData, Hex, } from 'viem'; -import { encodeDelegations } from '@metamask/delegation-toolkit/utils'; +import { + encodeDelegations, + createCaveatBuilder, +} from '@metamask/delegation-toolkit/utils'; import CounterMetadata from '../utils/counter/metadata.json'; @@ -57,9 +59,9 @@ beforeEach(async () => { aliceCounterContractAddress = aliceCounter.address; const caveats = createCaveatBuilder(aliceSmartAccount.environment) - .addCaveat('allowedTargets', [aliceCounterContractAddress]) - .addCaveat('allowedMethods', ['increment()']) - .addCaveat('valueLte', 0n); + .addCaveat('allowedTargets', { targets: [aliceCounterContractAddress] }) + .addCaveat('allowedMethods', { selectors: ['increment()'] }) + .addCaveat('valueLte', { maxValue: 0n }); const delegation = createDelegation({ to: bob.address, @@ -161,6 +163,7 @@ test('Bob redelegates to Carol, who redeems the delegation to call increment() o delegation: redelegation, delegationManager, chainId: chain.id, + allowInsecureUnrestrictedDelegation: true, }), }; diff --git a/packages/delegator-e2e/test/experimental/erc7710sendUserOperationWithDelegation.test.ts b/packages/delegator-e2e/test/experimental/erc7710sendUserOperationWithDelegation.test.ts index cd7f5512..4f9ab784 100644 --- a/packages/delegator-e2e/test/experimental/erc7710sendUserOperationWithDelegation.test.ts +++ b/packages/delegator-e2e/test/experimental/erc7710sendUserOperationWithDelegation.test.ts @@ -15,7 +15,6 @@ import { Implementation, toMetaMaskSmartAccount, type MetaMaskSmartAccount, - createCaveatBuilder, createDelegation, type Delegation, } from '@metamask/delegation-toolkit'; @@ -28,7 +27,10 @@ import { Hex, encodeFunctionData, } from 'viem'; -import { encodeDelegations } from '@metamask/delegation-toolkit/utils'; +import { + encodeDelegations, + createCaveatBuilder, +} from '@metamask/delegation-toolkit/utils'; import CounterMetadata from '../utils/counter/metadata.json'; import { expectUserOperationToSucceed } from '../utils/assertions'; @@ -66,9 +68,9 @@ beforeEach(async () => { aliceCounterContractAddress = aliceCounter.address; const caveats = createCaveatBuilder(aliceSmartAccount.environment) - .addCaveat('allowedTargets', [aliceCounterContractAddress]) - .addCaveat('allowedMethods', ['increment()']) - .addCaveat('valueLte', 0n); + .addCaveat('allowedTargets', { targets: [aliceCounterContractAddress] }) + .addCaveat('allowedMethods', { selectors: ['increment()'] }) + .addCaveat('valueLte', { maxValue: 0n }); const delegation = createDelegation({ to: bobSmartAccount.address, From 0b819d2e83b4965bc1c953700cf066b4f37b741d Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Wed, 9 Jul 2025 16:20:46 +1200 Subject: [PATCH 6/9] Fix references to chai and mocha --- packages/delegation-toolkit/test/delegation.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/delegation-toolkit/test/delegation.test.ts b/packages/delegation-toolkit/test/delegation.test.ts index 17207d66..71560bba 100644 --- a/packages/delegation-toolkit/test/delegation.test.ts +++ b/packages/delegation-toolkit/test/delegation.test.ts @@ -1,6 +1,6 @@ import { stub } from 'sinon'; import { getAddress } from 'viem'; -import { describe, it, expect } from 'vitest'; +import { describe, it, expect, beforeEach } from 'vitest'; import { randomAddress } from './utils'; import { resolveCaveats } from '../src/caveatBuilder'; @@ -662,7 +662,7 @@ describe('signDelegation', () => { delegationManager, chainId, }), - ).to.be.rejectedWith( + ).rejects.toThrow( 'No caveats found. If you definitely want to sign a delegation without caveats, set `allowInsecureUnrestrictedDelegation` to `true`.', ); }); From cfaab8220086b4468c42b92bb9418eaabd63429d Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Wed, 9 Jul 2025 16:50:58 +1200 Subject: [PATCH 7/9] Add tsdoc comments to build config types --- .../src/caveatBuilder/allowedCalldataBuilder.ts | 7 +++++++ .../src/caveatBuilder/allowedMethodsBuilder.ts | 4 ++++ .../src/caveatBuilder/allowedTargetsBuilder.ts | 4 ++++ .../caveatBuilder/argsEqualityCheckBuilder.ts | 3 +++ .../src/caveatBuilder/blockNumberBuilder.ts | 8 ++++++++ .../src/caveatBuilder/deployedBuilder.ts | 9 +++++++++ .../erc1155BalanceChangeBuilder.ts | 17 +++++++++++++++++ .../caveatBuilder/erc20BalanceChangeBuilder.ts | 14 ++++++++++++++ .../caveatBuilder/erc20PeriodTransferBuilder.ts | 12 ++++++++++++ .../src/caveatBuilder/erc20StreamingBuilder.ts | 15 +++++++++++++++ .../caveatBuilder/erc20TransferAmountBuilder.ts | 6 ++++++ .../caveatBuilder/erc721BalanceChangeBuilder.ts | 14 ++++++++++++++ .../src/caveatBuilder/erc721TransferBuilder.ts | 6 ++++++ .../caveatBuilder/exactCalldataBatchBuilder.ts | 4 ++++ .../src/caveatBuilder/exactCalldataBuilder.ts | 3 +++ .../caveatBuilder/exactExecutionBatchBuilder.ts | 4 ++++ .../src/caveatBuilder/exactExecutionBuilder.ts | 4 ++++ .../src/caveatBuilder/idBuilder.ts | 3 +++ .../src/caveatBuilder/limitedCallsBuilder.ts | 3 +++ .../caveatBuilder/multiTokenPeriodBuilder.ts | 12 ++++++++++++ .../caveatBuilder/nativeBalanceChangeBuilder.ts | 11 +++++++++++ .../caveatBuilder/nativeTokenPaymentBuilder.ts | 6 ++++++ .../nativeTokenPeriodTransferBuilder.ts | 9 +++++++++ .../nativeTokenStreamingBuilder.ts | 12 ++++++++++++ .../nativeTokenTransferAmountBuilder.ts | 3 +++ .../src/caveatBuilder/nonceBuilder.ts | 3 +++ .../caveatBuilder/ownershipTransferBuilder.ts | 3 +++ .../src/caveatBuilder/redeemerBuilder.ts | 4 ++++ .../specificActionERC20TransferBatchBuilder.ts | 15 +++++++++++++++ .../src/caveatBuilder/timestampBuilder.ts | 8 ++++++++ .../src/caveatBuilder/valueLteBuilder.ts | 3 +++ 31 files changed, 229 insertions(+) diff --git a/packages/delegation-toolkit/src/caveatBuilder/allowedCalldataBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/allowedCalldataBuilder.ts index e8b72afe..9226d940 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/allowedCalldataBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/allowedCalldataBuilder.ts @@ -5,7 +5,14 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const allowedCalldata = 'allowedCalldata'; export type AllowedCalldataBuilderConfig = { + /** + * The index in the calldata byte array (including the 4-byte method selector) + * where the expected calldata starts. + */ startIndex: number; + /** + * The expected calldata as a hex string that must match at the specified index. + */ value: Hex; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/allowedMethodsBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/allowedMethodsBuilder.ts index 066a8afd..639e04c5 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/allowedMethodsBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/allowedMethodsBuilder.ts @@ -11,6 +11,10 @@ export type MethodSelector = Hex | string | AbiFunction; const FUNCTION_SELECTOR_STRING_LENGTH = 10; export type AllowedMethodsBuilderConfig = { + /** + * An array of method selectors that the delegate is allowed to call. + * Can be 4-byte hex strings, ABI function signatures, or ABIFunction objects. + */ selectors: MethodSelector[]; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/allowedTargetsBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/allowedTargetsBuilder.ts index 14fb9b71..6c8dfb6d 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/allowedTargetsBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/allowedTargetsBuilder.ts @@ -5,6 +5,10 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const allowedTargets = 'allowedTargets'; export type AllowedTargetsBuilderConfig = { + /** + * An array of addresses that the delegate is allowed to call. + * Each address must be a valid hex string. + */ targets: Address[]; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/argsEqualityCheckBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/argsEqualityCheckBuilder.ts index 691b5bb5..7440608a 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/argsEqualityCheckBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/argsEqualityCheckBuilder.ts @@ -5,6 +5,9 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const argsEqualityCheck = 'argsEqualityCheck'; export type ArgsEqualityCheckBuilderConfig = { + /** + * The expected args as a hex string that must match exactly when redeeming the delegation. + */ args: Hex; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/blockNumberBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/blockNumberBuilder.ts index ef62c585..b3af0952 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/blockNumberBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/blockNumberBuilder.ts @@ -5,7 +5,15 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const blockNumber = 'blockNumber'; export type BlockNumberBuilderConfig = { + /** + * The block number after which the delegation is valid. + * Set to 0n to disable this threshold. + */ afterThreshold: bigint; + /** + * The block number before which the delegation is valid. + * Set to 0n to disable this threshold. + */ beforeThreshold: bigint; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts index 2daedcf4..8d98c9b7 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/deployedBuilder.ts @@ -5,8 +5,17 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const deployed = 'deployed'; export type DeployedBuilderConfig = { + /** + * The contract address as a hex string. + */ contractAddress: Address; + /** + * The salt to use with the deployment, as a hex string. + */ salt: Hex; + /** + * The bytecode of the contract as a hex string. + */ bytecode: Hex; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts index 793c07e3..359361c6 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts @@ -6,10 +6,27 @@ import { BalanceChangeType } from './types'; export const erc1155BalanceChange = 'erc1155BalanceChange'; export type Erc1155BalanceChangeBuilderConfig = { + /** + * The ERC-1155 contract address as a hex string. + */ tokenAddress: Address; + /** + * The recipient's address as a hex string. + */ recipient: Address; + /** + * The ID of the ERC-1155 token as a bigint. + */ tokenId: bigint; + /** + * The amount by which the balance must have changed as a bigint. + */ balance: bigint; + /** + * The balance change type for the ERC-1155 token. + * Specifies whether the balance should have increased or decreased. + * Valid parameters are BalanceChangeType.Increase and BalanceChangeType.Decrease. + */ changeType: BalanceChangeType; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20BalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20BalanceChangeBuilder.ts index 78f9f494..b4b45fb2 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20BalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20BalanceChangeBuilder.ts @@ -6,9 +6,23 @@ import { BalanceChangeType } from './types'; export const erc20BalanceChange = 'erc20BalanceChange'; export type Erc20BalanceChangeBuilderConfig = { + /** + * The ERC-20 contract address as a hex string. + */ tokenAddress: Address; + /** + * The recipient's address as a hex string. + */ recipient: Address; + /** + * The amount by which the balance must have changed as a bigint. + */ balance: bigint; + /** + * The balance change type for the ERC-20 token. + * Specifies whether the balance should have increased or decreased. + * Valid parameters are BalanceChangeType.Increase and BalanceChangeType.Decrease. + */ changeType: BalanceChangeType; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts index 0f68fe61..c79e7746 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20PeriodTransferBuilder.ts @@ -6,9 +6,21 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const erc20PeriodTransfer = 'erc20PeriodTransfer'; export type Erc20PeriodTransferBuilderConfig = { + /** + * The ERC-20 contract address as a hex string. + */ tokenAddress: Address; + /** + * The maximum amount of tokens that can be transferred per period. + */ periodAmount: bigint; + /** + * The duration of each period in seconds. + */ periodDuration: number; + /** + * The timestamp when the first period begins in seconds. + */ startDate: number; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts index 84f5c870..4e04fd89 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20StreamingBuilder.ts @@ -6,10 +6,25 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const erc20Streaming = 'erc20Streaming'; export type Erc20StreamingBuilderConfig = { + /** + * The ERC-20 contract address as a hex string. + */ tokenAddress: Address; + /** + * The initial amount available at start time as a bigint. + */ initialAmount: bigint; + /** + * Maximum total amount that can be unlocked as a bigint. + */ maxAmount: bigint; + /** + * Rate at which tokens accrue per second as a bigint. + */ amountPerSecond: bigint; + /** + * The start timestamp in seconds. + */ startTime: number; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts index 8f0a5b19..64762c49 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc20TransferAmountBuilder.ts @@ -6,7 +6,13 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const erc20TransferAmount = 'erc20TransferAmount'; export type Erc20TransferAmountBuilderConfig = { + /** + * The ERC-20 contract address as a hex string. + */ tokenAddress: Address; + /** + * The maximum amount of tokens that can be transferred as a bigint. + */ maxAmount: bigint; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts index 78c7d94d..9f5e27b6 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts @@ -6,9 +6,23 @@ import { BalanceChangeType } from './types'; export const erc721BalanceChange = 'erc721BalanceChange'; export type Erc721BalanceChangeBuilderConfig = { + /** + * The ERC-721 contract address as a hex string. + */ tokenAddress: Address; + /** + * The recipient's address as a hex string. + */ recipient: Address; + /** + * The amount by which the balance must have changed as a bigint. + */ amount: bigint; + /** + * The balance change type for the ERC-721 token. + * Specifies whether the balance should have increased or decreased. + * Valid parameters are BalanceChangeType.Increase and BalanceChangeType.Decrease. + */ changeType: BalanceChangeType; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts index f6280f49..d1e91c82 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts @@ -5,7 +5,13 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const erc721Transfer = 'erc721Transfer'; export type Erc721TransferBuilderConfig = { + /** + * The ERC-721 contract address as a hex string. + */ tokenAddress: Address; + /** + * The token ID as a bigint. + */ tokenId: bigint; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBatchBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBatchBuilder.ts index 93a2bdcb..2056444a 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBatchBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBatchBuilder.ts @@ -6,6 +6,10 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const exactCalldataBatch = 'exactCalldataBatch'; export type ExactCalldataBatchBuilderConfig = { + /** + * An array of executions that must be matched exactly in the batch. + * Each execution specifies a target address, value, and calldata. + */ executions: ExecutionStruct[]; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts index dffb0cc2..38b49d52 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts @@ -5,6 +5,9 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const exactCalldata = 'exactCalldata'; export type ExactCalldataBuilderConfig = { + /** + * The exact calldata that must be matched as a hex string. + */ calldata: `0x${string}`; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts index 12f3fef9..ba52afa5 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBatchBuilder.ts @@ -6,6 +6,10 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const exactExecutionBatch = 'exactExecutionBatch'; export type ExactExecutionBatchBuilderConfig = { + /** + * An array of executions that must be matched exactly in the batch. + * Each execution specifies a target address, value, and calldata. + */ executions: ExecutionStruct[]; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBuilder.ts index d7234f70..dd836c79 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactExecutionBuilder.ts @@ -6,6 +6,10 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const exactExecution = 'exactExecution'; export type ExactExecutionBuilderConfig = { + /** + * The execution that must be matched exactly. + * Specifies the target address, value, and calldata. + */ execution: ExecutionStruct; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/idBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/idBuilder.ts index fce5c2da..061ac127 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/idBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/idBuilder.ts @@ -3,6 +3,9 @@ import { maxUint256, toHex } from 'viem'; import type { DeleGatorEnvironment, Caveat } from '../types'; export type IdBuilderConfig = { + /** + * An id for the delegation. Only one delegation may be redeemed with any given id. + */ id: bigint | number; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/limitedCallsBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/limitedCallsBuilder.ts index 65d1a1b8..e8436bb8 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/limitedCallsBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/limitedCallsBuilder.ts @@ -5,6 +5,9 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const limitedCalls = 'limitedCalls'; export type LimitedCallsBuilderConfig = { + /** + * The maximum number of times this delegation may be redeemed. + */ limit: number; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/multiTokenPeriodBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/multiTokenPeriodBuilder.ts index 73d6b1b0..0ae67d0e 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/multiTokenPeriodBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/multiTokenPeriodBuilder.ts @@ -4,9 +4,21 @@ import { concat, isAddress, pad, toHex } from 'viem'; import type { DeleGatorEnvironment, Caveat } from '../types'; export type TokenPeriodConfig = { + /** + * The token contract address as a hex string. + */ token: Hex; + /** + * The maximum amount of tokens that can be transferred per period. + */ periodAmount: bigint; + /** + * The duration of each period in seconds. + */ periodDuration: number; + /** + * The timestamp when the first period begins in seconds. + */ startDate: number; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeBalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeBalanceChangeBuilder.ts index 77156bae..9ff51fa9 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeBalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeBalanceChangeBuilder.ts @@ -6,8 +6,19 @@ import { BalanceChangeType } from './types'; export const nativeBalanceChange = 'nativeBalanceChange'; export type NativeBalanceChangeBuilderConfig = { + /** + * The recipient's address as a hex string. + */ recipient: Address; + /** + * The amount by which the balance must have changed as a bigint. + */ balance: bigint; + /** + * The balance change type for the native currency. + * Specifies whether the balance should have increased or decreased. + * Valid parameters are BalanceChangeType.Increase and BalanceChangeType.Decrease. + */ changeType: BalanceChangeType; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPaymentBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPaymentBuilder.ts index c1c1d3c0..0a6213b1 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPaymentBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPaymentBuilder.ts @@ -5,7 +5,13 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const nativeTokenPayment = 'nativeTokenPayment'; export type NativeTokenPaymentBuilderConfig = { + /** + * The recipient's address as a hex string. + */ recipient: Address; + /** + * The amount that must be paid as a bigint. + */ amount: bigint; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPeriodTransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPeriodTransferBuilder.ts index ca62025c..a77df63e 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPeriodTransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenPeriodTransferBuilder.ts @@ -5,8 +5,17 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const nativeTokenPeriodTransfer = 'nativeTokenPeriodTransfer'; export type NativeTokenPeriodTransferBuilderConfig = { + /** + * The maximum amount of tokens that can be transferred per period. + */ periodAmount: bigint; + /** + * The duration of each period in seconds. + */ periodDuration: number; + /** + * The timestamp when the first period begins in seconds. + */ startDate: number; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenStreamingBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenStreamingBuilder.ts index 20ff93e5..cbb3d29b 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenStreamingBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenStreamingBuilder.ts @@ -5,9 +5,21 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const nativeTokenStreaming = 'nativeTokenStreaming'; export type NativeTokenStreamingBuilderConfig = { + /** + * The initial amount available at start time as a bigint. + */ initialAmount: bigint; + /** + * Maximum total amount that can be unlocked as a bigint. + */ maxAmount: bigint; + /** + * Rate at which tokens accrue per second as a bigint. + */ amountPerSecond: bigint; + /** + * Start timestamp as a number in seconds. + */ startTime: number; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenTransferAmountBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenTransferAmountBuilder.ts index 0df403be..ac2bd060 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nativeTokenTransferAmountBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nativeTokenTransferAmountBuilder.ts @@ -5,6 +5,9 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const nativeTokenTransferAmount = 'nativeTokenTransferAmount'; export type NativeTokenTransferAmountBuilderConfig = { + /** + * The maximum amount of native tokens that can be transferred. + */ maxAmount: bigint; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/nonceBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/nonceBuilder.ts index d9377856..2c385108 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/nonceBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/nonceBuilder.ts @@ -8,6 +8,9 @@ export const nonce = 'nonce'; const MAX_NONCE_STRING_LENGTH = 66; export type NonceBuilderConfig = { + /** + * A nonce as a hex string to allow bulk revocation of delegations. + */ nonce: Hex; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/ownershipTransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/ownershipTransferBuilder.ts index a96181a2..f5c2306d 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/ownershipTransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/ownershipTransferBuilder.ts @@ -5,6 +5,9 @@ import type { DeleGatorEnvironment, Caveat } from '../types'; export const ownershipTransfer = 'ownershipTransfer'; export type OwnershipTransferBuilderConfig = { + /** + * The target contract address as a hex string for which ownership transfers are allowed. + */ contractAddress: Address; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/redeemerBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/redeemerBuilder.ts index 7cb484f2..e83b5bdb 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/redeemerBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/redeemerBuilder.ts @@ -5,6 +5,10 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const redeemer = 'redeemer'; export type RedeemerBuilderConfig = { + /** + * An array of addresses that are allowed to redeem the delegation. + * Each address must be a valid hex string. + */ redeemers: Address[]; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts index 843eb038..210e7530 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts @@ -6,10 +6,25 @@ export const specificActionERC20TransferBatch = 'specificActionERC20TransferBatch'; export type SpecificActionErc20TransferBatchBuilderConfig = { + /** + * The address of the ERC-20 token contract. + */ tokenAddress: Address; + /** + * The address that will receive the tokens. + */ recipient: Address; + /** + * The amount of tokens to transfer. + */ amount: bigint; + /** + * The target address for the first transaction. + */ target: Address; + /** + * The calldata for the first transaction. + */ calldata: Hex; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/timestampBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/timestampBuilder.ts index e6a4c4dc..3ee08e38 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/timestampBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/timestampBuilder.ts @@ -5,7 +5,15 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const timestamp = 'timestamp'; export type TimestampBuilderConfig = { + /** + * The timestamp after which the delegation is valid in seconds. + * Set to 0 to disable this threshold. + */ afterThreshold: number; + /** + * The timestamp before which the delegation is valid. + * Set to 0 to disable this threshold. + */ beforeThreshold: number; }; diff --git a/packages/delegation-toolkit/src/caveatBuilder/valueLteBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/valueLteBuilder.ts index be1696e5..719f446a 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/valueLteBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/valueLteBuilder.ts @@ -5,6 +5,9 @@ import type { Caveat, DeleGatorEnvironment } from '../types'; export const valueLte = 'valueLte'; export type ValueLteBuilderConfig = { + /** + * The maximum value that may be specified when redeeming this delegation. + */ maxValue: bigint; }; From d561e3e06e824dcd5f71b289010369cdd027ea0c Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Wed, 9 Jul 2025 16:55:07 +1200 Subject: [PATCH 8/9] Fix incorrect type in tokenId comparsion --- .../src/caveatBuilder/erc1155BalanceChangeBuilder.ts | 2 +- .../src/caveatBuilder/erc721TransferBuilder.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts index 359361c6..cd640702 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc1155BalanceChangeBuilder.ts @@ -56,7 +56,7 @@ export const erc1155BalanceChangeBuilder = ( throw new Error('Invalid balance: must be a positive number'); } - if (tokenId < 0) { + if (tokenId < 0n) { throw new Error('Invalid tokenId: must be a non-negative number'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts index d1e91c82..d6d61f11 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc721TransferBuilder.ts @@ -33,7 +33,7 @@ export const erc721TransferBuilder = ( throw new Error('Invalid tokenAddress: must be a valid address'); } - if (tokenId < 0) { + if (tokenId < 0n) { throw new Error('Invalid tokenId: must be a non-negative number'); } From 8b8dfd0ef216f0178925752859aa6b5150205eb5 Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Thu, 10 Jul 2025 07:09:39 +1200 Subject: [PATCH 9/9] Remove 0xstring type, fix bigint <> number comparison --- .../src/caveatBuilder/erc721BalanceChangeBuilder.ts | 2 +- .../src/caveatBuilder/exactCalldataBuilder.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts index 9f5e27b6..103907a1 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/erc721BalanceChangeBuilder.ts @@ -48,7 +48,7 @@ export const erc721BalanceChangeBuilder = ( throw new Error('Invalid recipient: must be a valid address'); } - if (amount <= 0) { + if (amount <= 0n) { throw new Error('Invalid balance: must be a positive number'); } diff --git a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts index 38b49d52..a0ff8588 100644 --- a/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts +++ b/packages/delegation-toolkit/src/caveatBuilder/exactCalldataBuilder.ts @@ -1,4 +1,5 @@ import { createExactCalldataTerms } from '@metamask/delegation-core'; +import type { Hex } from 'viem'; import type { Caveat, DeleGatorEnvironment } from '../types'; @@ -8,7 +9,7 @@ export type ExactCalldataBuilderConfig = { /** * The exact calldata that must be matched as a hex string. */ - calldata: `0x${string}`; + calldata: Hex; }; /**