Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/7715-permission-types/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Utility functions to create caveats array for each permission type ([#265](https://github.com/MetaMask/smart-accounts-kit/pull/265))
- `createErc20TokenStreamCaveats()`
- `createErc20TokenPeriodicCaveats()`
- `createErc20TokenAllowanceCaveats()`
- `createNativeTokenStreamCaveats()`
- `createNativeTokenPeriodicCaveats()`
- `createNativeTokenAllowanceCaveats()`
- `createTokenApprovalRevocationCaveats()`
- Add `makePermissionDecoderConfigs` to resolve the `PermissionDecoderConfig`s to be used with @metamask/gator-permissions-controller ([#259](https://github.com/MetaMask/smart-accounts-kit/pull/259))

## [0.7.1]
Expand Down
14 changes: 14 additions & 0 deletions packages/7715-permission-types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,21 @@ export type {

export type { PayeeRule, RedeemerRule, ExpiryRule } from './permissions';
export {
createErc20TokenAllowanceCaveats,
type Erc20TokenAllowanceEnforcers,
createErc20TokenPeriodicCaveats,
type Erc20TokenPeriodicEnforcers,
makePermissionDecoderConfigs,
createErc20TokenStreamCaveats,
type Erc20TokenStreamEnforcers,
createNativeTokenAllowanceCaveats,
type NativeTokenAllowanceEnforcers,
createNativeTokenPeriodicCaveats,
type NativeTokenPeriodicEnforcers,
createNativeTokenStreamCaveats,
type NativeTokenStreamEnforcers,
createTokenApprovalRevocationCaveats,
type TokenApprovalRevocationEnforcers,
type DeployedContractsByName,
type PermissionDecoderConfig,
} from './permissions';
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import type { Caveat } from '@metamask/delegation-core';
import {
createERC20TokenPeriodTransferTerms,
createValueLteTerms,
} from '@metamask/delegation-core';
import { hexToNumber } from '@metamask/utils';

import type { Erc20TokenAllowancePermission } from '../../types';
Expand All @@ -8,6 +13,7 @@ import type {
ChecksumCaveat,
ChecksumEnforcersByChainId,
DecodedPermissionData,
DeepRequired,
MakePermissionDecoderConfig,
} from '../types';
import {
Expand Down Expand Up @@ -111,3 +117,49 @@ function validateAndDecodeData(

return { tokenAddress, allowanceAmount, startTime };
}

/**
* Enforcers required to build ERC-20 token allowance caveats.
*/
export type Erc20TokenAllowanceEnforcers = Pick<
ChecksumEnforcersByChainId,
'erc20PeriodicEnforcer' | 'valueLteEnforcer'
>;

/**
* Builds the erc20-token-allowance caveats required for this permission type.
*
* @param options0 - Caveat builder arguments.
* @param options0.permission - Fully populated erc20-token-allowance permission data.
* @param options0.contracts - Enforcer addresses used to construct caveats.
* @returns The ERC-20 allowance and zero-value caveats.
*/
export async function createErc20TokenAllowanceCaveats({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I can’t see any await inside this function, should we delete the async here?

permission,
contracts,
}: {
permission: DeepRequired<Erc20TokenAllowancePermission>;
contracts: Erc20TokenAllowanceEnforcers;
}): Promise<Caveat[]> {
const { tokenAddress, allowanceAmount, startTime } = permission.data;

const erc20PeriodCaveat: Caveat = {
enforcer: contracts.erc20PeriodicEnforcer,
terms: createERC20TokenPeriodTransferTerms({
tokenAddress,
periodAmount: BigInt(allowanceAmount),
// delegation-core accepts bigint for encoding although the type is `number`.
periodDuration: BigInt(UINT256_MAX) as unknown as number,
Comment on lines +151 to +152

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this is a temporary measure, until we migrate to the fixed allowance enforcer.

startDate: startTime,
}),
args: '0x',
};

const valueLteCaveat: Caveat = {
enforcer: contracts.valueLteEnforcer,
terms: createValueLteTerms({ maxValue: 0n }),
args: '0x',
};

return [erc20PeriodCaveat, valueLteCaveat];
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { decodeERC20TokenPeriodTransferTerms } from '@metamask/delegation-core';
import type { Caveat } from '@metamask/delegation-core';
import {
createERC20TokenPeriodTransferTerms,
createValueLteTerms,
decodeERC20TokenPeriodTransferTerms,
} from '@metamask/delegation-core';
import { bigIntToHex } from '@metamask/utils';

import type { Erc20TokenPeriodicPermission } from '../../types';
Expand All @@ -9,6 +14,7 @@ import type {
ChecksumCaveat,
ChecksumEnforcersByChainId,
DecodedPermissionData,
DeepRequired,
MakePermissionDecoderConfig,
} from '../types';
import {
Expand Down Expand Up @@ -117,3 +123,49 @@ function validateAndDecodeData(
startTime,
};
}

/**
* Enforcers required to build ERC-20 token periodic caveats.
*/
export type Erc20TokenPeriodicEnforcers = Pick<
ChecksumEnforcersByChainId,
'erc20PeriodicEnforcer' | 'valueLteEnforcer'
>;

/**
* Builds the erc20-token-periodic caveats required for this permission type.
*
* @param options0 - Caveat builder arguments.
* @param options0.permission - Fully populated erc20-token-periodic permission data.
* @param options0.contracts - Enforcer addresses used to construct caveats.
* @returns The ERC-20 periodic and zero-value caveats.
*/
export async function createErc20TokenPeriodicCaveats({
permission,
contracts,
}: {
permission: DeepRequired<Erc20TokenPeriodicPermission>;
contracts: Erc20TokenPeriodicEnforcers;
}): Promise<Caveat[]> {
const { tokenAddress, periodAmount, periodDuration, startTime } =
permission.data;

const erc20PeriodCaveat: Caveat = {
enforcer: contracts.erc20PeriodicEnforcer,
terms: createERC20TokenPeriodTransferTerms({
tokenAddress,
periodAmount: BigInt(periodAmount),
periodDuration,
startDate: startTime,
}),
args: '0x',
};

const valueLteCaveat: Caveat = {
enforcer: contracts.valueLteEnforcer,
terms: createValueLteTerms({ maxValue: 0n }),
args: '0x',
};

return [erc20PeriodCaveat, valueLteCaveat];
}
Comment thread
jeffsmale90 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { decodeERC20StreamingTerms } from '@metamask/delegation-core';
import type { Caveat } from '@metamask/delegation-core';
import {
createERC20StreamingTerms,
createValueLteTerms,
decodeERC20StreamingTerms,
} from '@metamask/delegation-core';
import { bigIntToHex } from '@metamask/utils';

import type { Erc20TokenStreamPermission } from '../../types';
Expand All @@ -7,9 +12,10 @@ import { erc20PayeeRuleDecoder } from '../rules/payee';
import { redeemerRuleDecoder } from '../rules/redeemer';
import type {
ChecksumCaveat,
ChecksumEnforcersByChainId,
DecodedPermissionData,
MakePermissionDecoderConfig,
DeepRequired,
ChecksumEnforcersByChainId,
PermissionDecoderConfig,
} from '../types';
import { getTermsByEnforcer, ZERO_32_BYTES } from '../utils';

Expand All @@ -21,7 +27,7 @@ import { getTermsByEnforcer, ZERO_32_BYTES } from '../utils';
*/
export function makeErc20TokenStreamDecoderConfig(
contractAddresses: ChecksumEnforcersByChainId,
): MakePermissionDecoderConfig {
): PermissionDecoderConfig {
const {
timestampEnforcer,
erc20StreamingEnforcer,
Expand Down Expand Up @@ -104,3 +110,54 @@ function validateAndDecodeData(
startTime,
};
}

/**
* Enforcers required to build ERC-20 token stream caveats.
*/
export type Erc20TokenStreamEnforcers = Pick<
ChecksumEnforcersByChainId,
'erc20StreamingEnforcer' | 'valueLteEnforcer'
>;

/**
* Builds the ERC-20 stream caveats required for this permission type.
*
* @param options0 - Caveat builder arguments.
* @param options0.permission - Fully populated ERC-20 stream permission data.
* @param options0.contracts - Enforcer addresses used to construct caveats.
* @returns The ERC20 streaming and zero-value caveats.
*/
export async function createErc20TokenStreamCaveats({
permission,
contracts,
}: {
permission: DeepRequired<Erc20TokenStreamPermission>;
contracts: Erc20TokenStreamEnforcers;
}): Promise<Caveat[]> {
const { initialAmount, maxAmount, amountPerSecond, startTime } =
permission.data;

// ERC20StreamingEnforcer: enforce token address, initial/max amount, amount per second, and start time.
const erc20StreamingCaveat: Caveat = {
enforcer: contracts.erc20StreamingEnforcer,
terms: createERC20StreamingTerms({
tokenAddress: permission.data.tokenAddress,
initialAmount: BigInt(initialAmount),
maxAmount: BigInt(maxAmount),
amountPerSecond: BigInt(amountPerSecond),
startTime,
}),
args: '0x',
};

// ValueLteEnforcer: allow no native value (e.g. msg.value must be 0).
const valueLteCaveat: Caveat = {
enforcer: contracts.valueLteEnforcer,
terms: createValueLteTerms({
maxValue: 0n,
}),
args: '0x',
};

return [erc20StreamingCaveat, valueLteCaveat];
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import type { Caveat } from '@metamask/delegation-core';
import {
createExactCalldataTerms,
createNativeTokenPeriodTransferTerms,
} from '@metamask/delegation-core';
import { hexToNumber } from '@metamask/utils';

import type { NativeTokenAllowancePermission } from '../../types';
Expand All @@ -8,6 +13,7 @@ import type {
ChecksumCaveat,
ChecksumEnforcersByChainId,
DecodedPermissionData,
DeepRequired,
MakePermissionDecoderConfig,
} from '../types';
import {
Expand Down Expand Up @@ -115,3 +121,48 @@ function validateAndDecodeData(

return { allowanceAmount, startTime };
}

/**
* Enforcers required to build native token allowance caveats.
*/
export type NativeTokenAllowanceEnforcers = Pick<
ChecksumEnforcersByChainId,
'nativeTokenPeriodicEnforcer' | 'exactCalldataEnforcer'
>;

/**
* Builds the native-token-allowance caveats required for this permission type.
*
* @param options0 - Caveat builder arguments.
* @param options0.permission - Fully populated native-token-allowance permission data.
* @param options0.contracts - Enforcer addresses used to construct caveats.
* @returns The native token allowance and exact-calldata caveats.
*/
export async function createNativeTokenAllowanceCaveats({
permission,
contracts,
}: {
permission: DeepRequired<NativeTokenAllowancePermission>;
contracts: NativeTokenAllowanceEnforcers;
}): Promise<Caveat[]> {
const { allowanceAmount, startTime } = permission.data;

const nativeTokenPeriodTransferCaveat: Caveat = {
enforcer: contracts.nativeTokenPeriodicEnforcer,
terms: createNativeTokenPeriodTransferTerms({
periodAmount: BigInt(allowanceAmount),
// delegation-core accepts bigint for encoding although the type is `number`.
periodDuration: BigInt(UINT256_MAX) as unknown as number,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this is a temporary measure, until we migrate to the fixed allowance enforcer.

startDate: startTime,
}),
args: '0x',
};

const exactCalldataCaveat: Caveat = {
enforcer: contracts.exactCalldataEnforcer,
terms: createExactCalldataTerms({ calldata: '0x' }),
args: '0x',
};

return [nativeTokenPeriodTransferCaveat, exactCalldataCaveat];
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { decodeNativeTokenPeriodTransferTerms } from '@metamask/delegation-core';
import type { Caveat } from '@metamask/delegation-core';
import {
createExactCalldataTerms,
createNativeTokenPeriodTransferTerms,
decodeNativeTokenPeriodTransferTerms,
} from '@metamask/delegation-core';
import { bigIntToHex } from '@metamask/utils';

import type { NativeTokenPeriodicPermission } from '../../types';
Expand All @@ -9,6 +14,7 @@ import type {
ChecksumCaveat,
ChecksumEnforcersByChainId,
DecodedPermissionData,
DeepRequired,
MakePermissionDecoderConfig,
} from '../types';
import { getTermsByEnforcer, MAX_PERIOD_DURATION } from '../utils';
Expand Down Expand Up @@ -112,3 +118,47 @@ function validateAndDecodeData(
startTime,
};
}

/**
* Enforcers required to build native token periodic caveats.
*/
export type NativeTokenPeriodicEnforcers = Pick<
ChecksumEnforcersByChainId,
'nativeTokenPeriodicEnforcer' | 'exactCalldataEnforcer'
>;

/**
* Builds the native-token-periodic caveats required for this permission type.
*
* @param options0 - Caveat builder arguments.
* @param options0.permission - Fully populated native-token-periodic permission data.
* @param options0.contracts - Enforcer addresses used to construct caveats.
* @returns The native token periodic and exact-calldata caveats.
*/
export async function createNativeTokenPeriodicCaveats({
permission,
contracts,
}: {
permission: DeepRequired<NativeTokenPeriodicPermission>;
contracts: NativeTokenPeriodicEnforcers;
}): Promise<Caveat[]> {
const { periodAmount, periodDuration, startTime } = permission.data;

const nativeTokenPeriodTransferCaveat: Caveat = {
enforcer: contracts.nativeTokenPeriodicEnforcer,
terms: createNativeTokenPeriodTransferTerms({
periodAmount: BigInt(periodAmount),
periodDuration,
startDate: startTime,
}),
args: '0x',
};

const exactCalldataCaveat: Caveat = {
enforcer: contracts.exactCalldataEnforcer,
terms: createExactCalldataTerms({ calldata: '0x' }),
args: '0x',
};

return [nativeTokenPeriodTransferCaveat, exactCalldataCaveat];
}
Loading
Loading