Advanced Permissions cannot express `target + selector + native value cap` — request for a new permission type

Hi MetaMask team,
We are building a game on Polygon (POL as the native asset) where users execute in-game actions by calling `Game.join(uint8)`. To remove the per-transaction popup friction, we want to grant a session account scoped execution authority. The minimum scope we need is:

- target restricted to a single contract (`Game`)

- method restricted to a single selector (`join(uint8)`)

- native POL value capped per stream or per period

- timestamp expiry

Description:

Add a new family of Advanced Permission types that combine a target/selector restriction with a native-token (or ERC-20) value cap. The currently supported permission types — native-token-stream, native-token-periodic, erc20-token-stream, erc20-token-periodic, erc20-token-revocation — only express value caps and timing. None of them restricts the call target or the function selector.

Proposed new permission types:

ts

// Native token, streaming

{

type: “native-token-function-call-stream”,

data: {

target: Address,

selectors: Hex[], // 4-byte function selectors

amountPerSecond: bigint,

initialAmount?: bigint,

maxAmount?: bigint,

startTime?: number,

justification?: string

}

}

// Native token, periodic

{

type: “native-token-function-call-periodic”,

data: {

target: Address,

selectors: Hex[],

periodAmount: bigint,

periodDuration: number,

startTime?: number,

justification?: string

}

}

ERC-20 equivalents (erc20-token-function-call-stream, erc20-token-function-call-periodic) would cover token-paid contract calls in the same shape.

Suggested confirmation UI copy:

“This dapp can call join(uint8) on 0x1234…ABCD and spend up to 100 POL over 12 hours.”

The required onchain primitives are already shipped and audited in the Delegation Framework: AllowedTargetsEnforcer, AllowedMethodsEnforcer, NativeTokenStreamingEnforcer, NativeTokenTransferAmountEnforcer. The remaining work sits at the ERC-7715 schema level — permission type definition, handler in the Gator Permissions Snap, and the permission picker UI — not at the smart contract level.

Purpose:

Concrete use case: game on Polygon. Users place bets by calling Game.join(uint8) with a native POL value. To remove per-transaction popup friction, we need to grant a session account scoped execution authority with:

  • target restricted to the Game contract only

  • method restricted to the join(uint8) selector only

  • native POL capped per stream or per period

  • timestamp expiry

Both supported paths fail today:

  1. ERC-7715 native-token-stream — no target / selector field. If the session key is compromised, an attacker can drain POL within the stream limit to any address. Unsafe for a betting product where the session key lives in the browser. We also confirmed that reusing a native-token-stream permission context to call join(uint8) reverts onchain with ExactCalldataEnforcer:invalid-calldata, because the streaming context is shaped for plain native transfers, not contract calls.

  2. Custom ERC-7710 delegation with caveats (AllowedTargets + AllowedMethods + NativeTokenStreaming) — blocked at the MetaMask Extension signing layer:

InternalRpcError: An internal error was received.

Details: External signature requests cannot sign delegations for internal accounts.

The rejection happens in MetaMask/core → packages/signature-controller/src/utils/validation.ts → validateDelegation().

We understand the security reasoning behind blocking Path B — an unconstrained delegation typed-data is not human-readable and could expose the entire wallet — and we agree it should remain closed for general dapps. Hence this request for a new Advanced Permission type that fills the schema gap safely, with a human-readable confirmation UI.

Beyond our use case, this gap blocks essentially every non-trivial agent or session-execution pattern that needs to call a specific contract method instead of transferring raw value: gaming, DeFi strategy bots, perp / auto-rebalance agents, scheduled liquidations, vesting claims, on-chain voting agents. Today the only escape routes are (a) move the signer outside MetaMask using an embedded wallet, or (b) redesign the protocol around deposit/escrow. Both undermine the value proposition of Advanced Permissions for these workflows.

Extension/Mobile/Both:

Both. The schema itself is platform-agnostic. The immediate, observable blocker is on the Extension (signature-controller validateDelegation), but a new permission type with this shape would benefit Mobile equally as Advanced Permissions roll out there.

Images/Attachments:

No screenshots — the failure occurs at the signing layer before any UI is rendered, so there is nothing visible to capture. Reference material:

  • Source of the rejection: MetaMask/core, packages/signature-controller/src/utils/validation.ts, function validateDelegation()

Happy to share a minimal PoC repo, full error logs and the exact typed-data payload, or to open a draft schema PR against MetaMask/snap-7715-permissions on request.
t handle: @me2jay

Hi, this is great , thanks for submitting it. If you have any questions or run into any specific issues, you can also reach out to MetaMask support about it