Skip to content
Draft
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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"sharp": "0.34.5",
"glob@npm:^10.2.2": "10.5.0",
"tar": "^7.5.3",
"body-parser@npm:^2.2.0": "2.2.1"
"body-parser@npm:^2.2.0": "2.2.1",
"@metamask/smart-accounts-kit": "link:../smart-accounts-kit/packages/smart-accounts-kit"
}
}
25 changes: 23 additions & 2 deletions packages/gator-permissions-snap/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@
"message": "Unknown chain $1"
},
"permissionRequestSubtitleRevocation": {
"message": "This site wants permissions to revoke your ERC-20 token approvals."
"message": "This site wants permissions to revoke your token approvals."
},
"introAdvancedPermissionsTitle": {
"message": "Advanced permissions keep you in control"
Expand Down Expand Up @@ -251,7 +251,7 @@
"message": "Token revocation request"
},
"introManageTokenApprovalsDescription": {
"message": "Token revocation allows sites to revoke token approvals on your behalf."
"message": "Token revocation allows sites to revoke ERC-20, NFT, and Permit2 approvals on your behalf."
},
"introAllowanceTitle": {
"message": "Token allowance request"
Expand Down Expand Up @@ -318,6 +318,27 @@
},
"revokeTokenApprovalsLabel": {
"message": "Revoke token approvals"
},
"approvalRevocationMechanismsLabel": {
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.

nit; we've used the term Primitive to refer to the different ways that a permit can be revoked - at least in code I think it's a good idea to standardise that.

"message": "Revocation methods"
},
"erc20ApproveRevocationLabel": {
"message": "ERC-20 approve(spender, 0)"
},
"erc721ApproveRevocationLabel": {
"message": "ERC-721 approve(address(0), tokenId)"
},
"erc721SetApprovalForAllRevocationLabel": {
"message": "ERC-721/ERC-1155 setApprovalForAll(false)"
},
"permit2ApproveZeroRevocationLabel": {
"message": "Permit2 approve(token, spender, 0, 0)"
},
"permit2LockdownRevocationLabel": {
"message": "Permit2 lockdown"
},
"permit2InvalidateNoncesRevocationLabel": {
"message": "Permit2 invalidate nonces"
}
}
}
2 changes: 1 addition & 1 deletion packages/gator-permissions-snap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
},
"dependencies": {
"@metamask/abi-utils": "3.0.0",
"@metamask/delegation-core": "^2.0.0",
"@metamask/delegation-core": "^2.2.0",
"@metamask/profile-sync-controller": "28.1.0",
"@metamask/snaps-sdk": "11.1.0",
"@metamask/utils": "11.11.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/gator-permissions-snap/src/core/chainMetadata.ts
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.

Maybe not for this PR, but we should probably just import @metamask/delegation-deployments instead of copying the contract addresses 🤔

Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export type DelegationContracts = {
allowedCalldataEnforcer: Hex;
redeemerEnforcer: Hex;
allowedTargetsEnforcer: Hex;
approvalRevocationEnforcer: Hex;
};

const contracts: DelegationContracts = {
Expand All @@ -38,6 +39,7 @@ const contracts: DelegationContracts = {
allowedCalldataEnforcer: '0xc2b0d624c1c4319760C96503BA27C347F3260f55',
redeemerEnforcer: '0xE144b0b2618071B4E56f746313528a669c7E65c5',
allowedTargetsEnforcer: '0x7F20f61b1f09b08D970938F6fa563634d65c4EeB',
approvalRevocationEnforcer: '0xe264F1f09A19505a1ca1a86D5b01E8bFdb64324A',
};

// derived from https://chainid.network/chains.json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { hexToNumber } from '@metamask/utils';
import type { Hex } from '@metamask/utils';

import { DEFAULT_MAX_AMOUNT } from '../../permissions/erc20TokenStream/context';
import { TOKEN_APPROVAL_REVOCATION_PRIMITIVES } from '../../permissions/tokenApprovalRevocation/types';
import type { TokenMetadataService } from '../../services/tokenMetadataService';
import { t } from '../../utils/i18n';
import { getClosestTimePeriod } from '../../utils/time';
Expand Down Expand Up @@ -88,9 +89,15 @@ function extractPermissionDetails(
}

// For revocation-type permissions
if (permissionType === 'erc20-token-revocation') {
if (permissionType === 'token-approval-revocation') {
const revokeLabel = t('revokeTokenApprovalsLabel');
const revokeValue = t('allTokens');
const revocationMechanisms = TOKEN_APPROVAL_REVOCATION_PRIMITIVES.filter(
({ key }) => permissionData[key] === true,
).map(({ labelKey }) => t(labelKey));
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.

what does t() return if there's no match? should we default to the labelKey, or throw?

const revokeValue =
revocationMechanisms.length > 0
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.

are we saying that if none of the booleans values in the data bag are true, then all primitives are allowed?

I had considered this an invalid request.

But maybe it would be a good idea, if all of the revocation primitives are true that we should say "All revocation primitives" or something instead of listing them all out. I suspect that would be the more common experience.

? revocationMechanisms.join(', ')
: t('allTokens');
details.tokenApprovals = {
label: revokeLabel,
value: revokeValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ import { extractDescriptorName } from '@metamask/7715-permissions-shared/utils';
import { InvalidInputError } from '@metamask/snaps-sdk';

import type { AccountController } from './accountController';
import { PermissionHandler } from './permissionHandler';
import type { PermissionRequestLifecycleOrchestrator } from './permissionRequestLifecycleOrchestrator';
import type {
BaseContext,
DeepRequired,
PermissionDefinition,
PermissionHandlerType,
} from './types';
import { erc20TokenAllowancePermissionDefinition } from '../permissions/erc20TokenAllowance';
import { erc20TokenPeriodicPermissionDefinition } from '../permissions/erc20TokenPeriodic';
import { erc20TokenRevocationPermissionDefinition } from '../permissions/erc20TokenRevocation';
import { erc20TokenStreamPermissionDefinition } from '../permissions/erc20TokenStream';
import { nativeTokenAllowancePermissionDefinition } from '../permissions/nativeTokenAllowance';
import { nativeTokenPeriodicPermissionDefinition } from '../permissions/nativeTokenPeriodic';
import { nativeTokenStreamPermissionDefinition } from '../permissions/nativeTokenStream';
import { tokenApprovalRevocationPermissionDefinition } from '../permissions/tokenApprovalRevocation';
import type { TokenMetadataService } from '../services/tokenMetadataService';
import type { TokenPricesService } from '../services/tokenPricesService';
import type { UserEventDispatcher } from '../userEventDispatcher';
import { PermissionHandler } from './permissionHandler';
import type { PermissionRequestLifecycleOrchestrator } from './permissionRequestLifecycleOrchestrator';
import type {
BaseContext,
DeepRequired,
PermissionDefinition,
PermissionHandlerType,
} from './types';

/**
* Factory for creating permission-specific orchestrators.
Expand Down Expand Up @@ -121,9 +121,9 @@ export class PermissionHandlerFactory {
erc20TokenAllowancePermissionDefinition,
);
break;
case 'erc20-token-revocation':
case 'token-approval-revocation':
handler = createPermissionHandler(
erc20TokenRevocationPermissionDefinition,
tokenApprovalRevocationPermissionDefinition,
);
break;
case 'erc20-token-stream':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export const permissionIntroductionConfigs: Record<
page1: allowancePage1Content,
page2: fixedPage2Content,
},
'erc20-token-revocation': {
'token-approval-revocation': {
page1: revocationPage1Content,
page2: fixedPage2Content,
},
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const DEFAULT_GATOR_PERMISSION_TO_OFFER: PermissionOffer[] = [
proposedName: 'ERC20 Token Allowance',
},
{
type: 'erc20-token-revocation',
proposedName: 'ERC20 Token Revocation',
type: 'token-approval-revocation',
proposedName: 'Token Approval Revocation',
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ZERO_ADDRESS } from '@metamask/7715-permissions-shared/types';
import type { Caveat } from '@metamask/delegation-core';
import { createApprovalRevocationTerms } from '@metamask/delegation-core';
import { InvalidInputError } from '@metamask/snaps-sdk';

import type { PopulatedTokenApprovalRevocationPermission } from './types';
import type { DelegationContracts } from '../../core/chainMetadata';

/**
* Appends permission-specific caveats for token approval revocation.
* @param args - The options object containing the permission and caveat builder.
* @param args.permission - The complete token approval revocation permission.
* @param args.contracts - The contracts to use for the caveats.
* @returns The permission caveats.
*/
export async function createPermissionCaveats({
permission,
contracts,
}: {
permission: PopulatedTokenApprovalRevocationPermission;
contracts: DelegationContracts;
}): Promise<Caveat[]> {
if (contracts.approvalRevocationEnforcer === ZERO_ADDRESS) {
throw new InvalidInputError(
'ApprovalRevocationEnforcer address is not configured.',
);
}
Comment on lines +23 to +27
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.

is this a temporary check until we add the revocation enforcer? I don't think we have this check on the other enforcers.


const approvalRevocationCaveat: Caveat = {
enforcer: contracts.approvalRevocationEnforcer,
terms: createApprovalRevocationTerms(permission.data),
args: '0x',
};

return [approvalRevocationCaveat];
}
Loading
Loading