Call policy allows to filter out transactions based on the call data and ether value.

Within a policy, you can set up to 16 rules. Each rule consists of a condition, the calldata offset, and a reference value to compare.

When checking a transaction, the policy checks it against every rule. For a policy to accept a transaction, every rule of that policy should pass.

Conditions

Available conditions are:

  • equal (x=Ax = A)
  • greater than (x>Ax > A)
  • less than (x<Ax < A)
  • greater than or equal (xAx \geq A)
  • less than or equal (xAx \leq A)
  • not equal (xAx \neq A)
  • in range (AxBA \leq x \leq B)

Calldata Offset

The number of bytes to offset from the start (excluding the function selector).

The resulting value is a hex string of 32 bytes.

In other words, if the offset is 10, the compared value will be formed from the calldata with the starting index of 4 + 10 = 14 and an end index of 4 + 10 + 32 = 46.

Reference Value

Value to compare the calldata against.

The reference value is a hex string of 32 bytes. For convenience, you can pass the hex string of a smaller length or a bigint, and the SDK will convert it for you.

Usage

To enable a call policy:

const receiver = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'

const session: Session = {
  owners: {
    type: 'ecdsa',
    accounts: [sessionOwnerAccount],
  },
  policies: [
    {
      type: 'universal-action',
      rules: [
        {
          condition: 'equal',
          calldataOffset: 0n,
          referenceValue: receiver,
        },
      ],
    },
  ],
  // ERC20 transfer action
  action: [
    target: usdcAddress,
    selector: toFunctionSelector(
      getAbiItem({
        abi: erc20,
        name: 'transfer',
      }),
    ),
  ]
}

Together with an ERC20 transfer action, this policy will only allow USDC transfers to a single receiver address.

Param Accumulator

You can limit the total accumulated value of a param across all session uses.

This can be helpful if you want to e.g. limit the total value of tokens passed through the session.

const session: Session = {
  owners: {
    type: 'ecdsa',
    accounts: [sessionOwnerAccount],
  },
  policies: [
    {
      type: 'universal-action',
      rules: [
        {
          condition: 'lessThan',
          calldataOffset: 20n,
          referenceValue: parseUnits("10", 6),
          usageLimit: parseUnits("50", 6),
        },
      ],
    },
  ],
  // ERC20 transfer action
  action: [
    // …
  ]
}

Together with an ERC20 transfer action, this will limit the token transferred to 10 USDC per session use, and 50 USDC for a total lifespan of the session.

Value Limit

To limit the maximum value to pass for a single session use:

const receiver = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'

const session: Session = {
  owners: {
    type: 'ecdsa',
    accounts: [sessionOwnerAccount],
  },
  policies: [
    {
      type: 'universal-action',
      valueLimitPerUse: parseUnits("0.1", 18),
      rules: [
        {
          condition: 'equal',
          calldataOffset: 0n,
          referenceValue: receiver,
        },
      ],
    },
  ],
  // ERC20 transfer action
  action: [
    // …
  ]
}

This will limit the value per session use to 0.1 ETH.