Skip to content

Commit 5a0710e

Browse files
committed
Update all caveat builder functions to reflect validation in related validateAndDecode function
1 parent 04ace06 commit 5a0710e

12 files changed

Lines changed: 454 additions & 22 deletions

packages/7715-permission-types/src/permissions/caveats/erc20TokenAllowance.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
createERC20TokenPeriodTransferTerms,
44
createValueLteTerms,
55
} from '@metamask/delegation-core';
6-
import { hexToNumber } from '@metamask/utils';
6+
import { hexToBigInt, hexToNumber } from '@metamask/utils';
77

88
import type { Erc20TokenAllowancePermission, Populated } from '../../types';
99
import { expiryRuleDecoder } from '../rules/expiry';
@@ -141,12 +141,25 @@ export function createErc20TokenAllowanceCaveats({
141141
contracts: Erc20TokenAllowanceEnforcers;
142142
}): Caveat[] {
143143
const { tokenAddress, allowanceAmount, startTime } = permission.data;
144+
const allowanceAmountBigInt = hexToBigInt(allowanceAmount);
145+
146+
if (allowanceAmountBigInt === 0n) {
147+
throw new Error(
148+
'Invalid erc20-token-allowance permission: allowanceAmount must be a positive number.',
149+
);
150+
}
151+
152+
if (startTime <= 0) {
153+
throw new Error(
154+
'Invalid erc20-token-allowance permission: startTime must be a positive number.',
155+
);
156+
}
144157

145158
const erc20PeriodCaveat: Caveat = {
146159
enforcer: contracts.erc20PeriodicEnforcer,
147160
terms: createERC20TokenPeriodTransferTerms({
148161
tokenAddress,
149-
periodAmount: BigInt(allowanceAmount),
162+
periodAmount: allowanceAmountBigInt,
150163
// delegation-core accepts bigint for encoding although the type is `number`.
151164
periodDuration: BigInt(UINT256_MAX) as unknown as number,
152165
startDate: startTime,

packages/7715-permission-types/src/permissions/caveats/erc20TokenPeriodic.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
createValueLteTerms,
55
decodeERC20TokenPeriodTransferTerms,
66
} from '@metamask/delegation-core';
7-
import { bigIntToHex } from '@metamask/utils';
7+
import { bigIntToHex, hexToBigInt } from '@metamask/utils';
88

99
import type { Erc20TokenPeriodicPermission, Populated } from '../../types';
1010
import { expiryRuleDecoder } from '../rules/expiry';
@@ -148,12 +148,37 @@ export function createErc20TokenPeriodicCaveats({
148148
}): Caveat[] {
149149
const { tokenAddress, periodAmount, periodDuration, startTime } =
150150
permission.data;
151+
const periodAmountBigInt = hexToBigInt(periodAmount);
152+
153+
if (periodAmountBigInt === 0n) {
154+
throw new Error(
155+
'Invalid erc20-token-periodic permission: periodAmount must be a positive number.',
156+
);
157+
}
158+
159+
if (periodDuration <= 0) {
160+
throw new Error(
161+
'Invalid erc20-token-periodic permission: periodDuration must be a positive number.',
162+
);
163+
}
164+
165+
if (periodDuration > MAX_PERIOD_DURATION) {
166+
throw new Error(
167+
'Invalid erc20-token-periodic permission: periodDuration must be less than or equal to MAX_PERIOD_DURATION.',
168+
);
169+
}
170+
171+
if (startTime <= 0) {
172+
throw new Error(
173+
'Invalid erc20-token-periodic permission: startTime must be a positive number.',
174+
);
175+
}
151176

152177
const erc20PeriodCaveat: Caveat = {
153178
enforcer: contracts.erc20PeriodicEnforcer,
154179
terms: createERC20TokenPeriodTransferTerms({
155180
tokenAddress,
156-
periodAmount: BigInt(periodAmount),
181+
periodAmount: periodAmountBigInt,
157182
periodDuration,
158183
startDate: startTime,
159184
}),

packages/7715-permission-types/src/permissions/caveats/erc20TokenStream.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
createValueLteTerms,
55
decodeERC20StreamingTerms,
66
} from '@metamask/delegation-core';
7-
import { bigIntToHex } from '@metamask/utils';
7+
import { bigIntToHex, hexToBigInt } from '@metamask/utils';
88

99
import type { Erc20TokenStreamPermission, Populated } from '../../types';
1010
import { expiryRuleDecoder } from '../rules/expiry';
@@ -135,15 +135,36 @@ export function createErc20TokenStreamCaveats({
135135
}): Caveat[] {
136136
const { initialAmount, maxAmount, amountPerSecond, startTime } =
137137
permission.data;
138+
const initialAmountBigInt = hexToBigInt(initialAmount);
139+
const maxAmountBigInt = hexToBigInt(maxAmount);
140+
const amountPerSecondBigInt = hexToBigInt(amountPerSecond);
141+
142+
if (maxAmountBigInt <= initialAmountBigInt) {
143+
throw new Error(
144+
'Invalid erc20-token-stream permission: maxAmount must be greater than initialAmount.',
145+
);
146+
}
147+
148+
if (amountPerSecondBigInt === 0n) {
149+
throw new Error(
150+
'Invalid erc20-token-stream permission: amountPerSecond must be a positive number.',
151+
);
152+
}
153+
154+
if (startTime <= 0) {
155+
throw new Error(
156+
'Invalid erc20-token-stream permission: startTime must be a positive number.',
157+
);
158+
}
138159

139160
// ERC20StreamingEnforcer: enforce token address, initial/max amount, amount per second, and start time.
140161
const erc20StreamingCaveat: Caveat = {
141162
enforcer: contracts.erc20StreamingEnforcer,
142163
terms: createERC20StreamingTerms({
143164
tokenAddress: permission.data.tokenAddress,
144-
initialAmount: BigInt(initialAmount),
145-
maxAmount: BigInt(maxAmount),
146-
amountPerSecond: BigInt(amountPerSecond),
165+
initialAmount: initialAmountBigInt,
166+
maxAmount: maxAmountBigInt,
167+
amountPerSecond: amountPerSecondBigInt,
147168
startTime,
148169
}),
149170
args: '0x',

packages/7715-permission-types/src/permissions/caveats/nativeTokenAllowance.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
createExactCalldataTerms,
44
createNativeTokenPeriodTransferTerms,
55
} from '@metamask/delegation-core';
6-
import { hexToNumber } from '@metamask/utils';
6+
import { hexToBigInt, hexToNumber } from '@metamask/utils';
77

88
import type { NativeTokenAllowancePermission, Populated } from '../../types';
99
import { expiryRuleDecoder } from '../rules/expiry';
@@ -145,11 +145,24 @@ export function createNativeTokenAllowanceCaveats({
145145
contracts: NativeTokenAllowanceEnforcers;
146146
}): Caveat[] {
147147
const { allowanceAmount, startTime } = permission.data;
148+
const allowanceAmountBigInt = hexToBigInt(allowanceAmount);
149+
150+
if (allowanceAmountBigInt === 0n) {
151+
throw new Error(
152+
'Invalid native-token-allowance permission: allowanceAmount must be a positive number.',
153+
);
154+
}
155+
156+
if (startTime <= 0) {
157+
throw new Error(
158+
'Invalid native-token-allowance permission: startTime must be a positive number.',
159+
);
160+
}
148161

149162
const nativeTokenPeriodTransferCaveat: Caveat = {
150163
enforcer: contracts.nativeTokenPeriodicEnforcer,
151164
terms: createNativeTokenPeriodTransferTerms({
152-
periodAmount: BigInt(allowanceAmount),
165+
periodAmount: allowanceAmountBigInt,
153166
// delegation-core accepts bigint for encoding although the type is `number`.
154167
periodDuration: BigInt(UINT256_MAX) as unknown as number,
155168
startDate: startTime,

packages/7715-permission-types/src/permissions/caveats/nativeTokenPeriodic.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
createNativeTokenPeriodTransferTerms,
55
decodeNativeTokenPeriodTransferTerms,
66
} from '@metamask/delegation-core';
7-
import { bigIntToHex } from '@metamask/utils';
7+
import { bigIntToHex, hexToBigInt } from '@metamask/utils';
88

99
import type { NativeTokenPeriodicPermission, Populated } from '../../types';
1010
import { expiryRuleDecoder } from '../rules/expiry';
@@ -142,11 +142,36 @@ export function createNativeTokenPeriodicCaveats({
142142
contracts: NativeTokenPeriodicEnforcers;
143143
}): Caveat[] {
144144
const { periodAmount, periodDuration, startTime } = permission.data;
145+
const periodAmountBigInt = hexToBigInt(periodAmount);
146+
147+
if (periodAmountBigInt === 0n) {
148+
throw new Error(
149+
'Invalid native-token-periodic permission: periodAmount must be a positive number.',
150+
);
151+
}
152+
153+
if (periodDuration <= 0) {
154+
throw new Error(
155+
'Invalid native-token-periodic permission: periodDuration must be a positive number.',
156+
);
157+
}
158+
159+
if (periodDuration > MAX_PERIOD_DURATION) {
160+
throw new Error(
161+
'Invalid native-token-periodic permission: periodDuration must be less than or equal to MAX_PERIOD_DURATION.',
162+
);
163+
}
164+
165+
if (startTime <= 0) {
166+
throw new Error(
167+
'Invalid native-token-periodic permission: startTime must be a positive number.',
168+
);
169+
}
145170

146171
const nativeTokenPeriodTransferCaveat: Caveat = {
147172
enforcer: contracts.nativeTokenPeriodicEnforcer,
148173
terms: createNativeTokenPeriodTransferTerms({
149-
periodAmount: BigInt(periodAmount),
174+
periodAmount: periodAmountBigInt,
150175
periodDuration,
151176
startDate: startTime,
152177
}),

packages/7715-permission-types/src/permissions/caveats/nativeTokenStream.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
createNativeTokenStreamingTerms,
55
decodeNativeTokenStreamingTerms,
66
} from '@metamask/delegation-core';
7-
import { bigIntToHex } from '@metamask/utils';
7+
import { bigIntToHex, hexToBigInt } from '@metamask/utils';
88

99
import type { NativeTokenStreamPermission, Populated } from '../../types';
1010
import { expiryRuleDecoder } from '../rules/expiry';
@@ -135,13 +135,34 @@ export function createNativeTokenStreamCaveats({
135135
}): Caveat[] {
136136
const { initialAmount, maxAmount, amountPerSecond, startTime } =
137137
permission.data;
138+
const initialAmountBigInt = hexToBigInt(initialAmount);
139+
const maxAmountBigInt = hexToBigInt(maxAmount);
140+
const amountPerSecondBigInt = hexToBigInt(amountPerSecond);
141+
142+
if (maxAmountBigInt <= initialAmountBigInt) {
143+
throw new Error(
144+
'Invalid native-token-stream permission: maxAmount must be greater than initialAmount.',
145+
);
146+
}
147+
148+
if (amountPerSecondBigInt === 0n) {
149+
throw new Error(
150+
'Invalid native-token-stream permission: amountPerSecond must be a positive number.',
151+
);
152+
}
153+
154+
if (startTime <= 0) {
155+
throw new Error(
156+
'Invalid native-token-stream permission: startTime must be a positive number.',
157+
);
158+
}
138159

139160
const nativeTokenStreamingCaveat: Caveat = {
140161
enforcer: contracts.nativeTokenStreamingEnforcer,
141162
terms: createNativeTokenStreamingTerms({
142-
initialAmount: BigInt(initialAmount),
143-
maxAmount: BigInt(maxAmount),
144-
amountPerSecond: BigInt(amountPerSecond),
163+
initialAmount: initialAmountBigInt,
164+
maxAmount: maxAmountBigInt,
165+
amountPerSecond: amountPerSecondBigInt,
145166
startTime,
146167
}),
147168
args: '0x',

packages/7715-permission-types/test/permissions/caveats/erc20TokenAllowance.test.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,40 @@ describe('createErc20TokenAllowanceCaveats()', () => {
230230
).toThrow();
231231
});
232232

233+
it('rejects zero allowanceAmount', () => {
234+
expect(() =>
235+
createErc20TokenAllowanceCaveats({
236+
permission: {
237+
...permission,
238+
data: {
239+
...permission.data,
240+
allowanceAmount: '0x0',
241+
},
242+
},
243+
contracts,
244+
}),
245+
).toThrow(
246+
'Invalid erc20-token-allowance permission: allowanceAmount must be a positive number.',
247+
);
248+
});
249+
250+
it('rejects when startTime is zero', () => {
251+
expect(() =>
252+
createErc20TokenAllowanceCaveats({
253+
permission: {
254+
...permission,
255+
data: {
256+
...permission.data,
257+
startTime: 0,
258+
},
259+
},
260+
contracts,
261+
}),
262+
).toThrow(
263+
'Invalid erc20-token-allowance permission: startTime must be a positive number.',
264+
);
265+
});
266+
233267
it('keeps valueLte caveat fixed at zero across varied inputs', () => {
234268
const variedPermission: Populated<Erc20TokenAllowancePermission> = {
235269
...permission,
@@ -252,7 +286,8 @@ describe('createErc20TokenAllowanceCaveats()', () => {
252286
});
253287

254288
it('encodes provided token address in allowance terms', () => {
255-
const alternateTokenAddress = '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
289+
const alternateTokenAddress =
290+
'0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' as Hex;
256291
const permissionWithAltToken = {
257292
...permission,
258293
data: {
@@ -265,10 +300,11 @@ describe('createErc20TokenAllowanceCaveats()', () => {
265300
permission: permissionWithAltToken,
266301
contracts,
267302
});
303+
const erc20AllowanceTerms = caveats[0]?.terms as Hex;
268304

269305
expect(caveats[0]?.enforcer).toBe(contracts.erc20PeriodicEnforcer);
270306
expect(
271-
caveats[0]?.terms.startsWith(`0x${alternateTokenAddress.slice(2)}`),
307+
erc20AllowanceTerms.startsWith(`0x${alternateTokenAddress.slice(2)}`),
272308
).toBe(true);
273309
});
274310
});

0 commit comments

Comments
 (0)