Policies

A policy engine is a software component that manages and enforces rules. It operates by evaluating input data against predefined policies to ascertain the appropriate Permit or Forbid decision. In the Armory Stack, policies are a cornerstone component used to govern aspects of the organization's entities such as user or group account access, spending limits over time, the usage of smart-contract functions, and more.

The Armory Policy Engine's flexibility and scalability make it an invaluable tool for organizations seeking to secure usage of digital assets and/or automate decision-making processes with fine-grained control.

What's a policy?

In essence, a policy consists of an action and criteria. For a policy to evaluate the defined action, all criteria must evaluate to true.

{
  when: [
    // Criteria
  ],
  then: Then.PERMIT // or Then.FORBID
}

Writing a policy

This section provides instructions on creating a policy to permit a user, Bob, to transfer up to 10 MATIC from an account on Polygon every 5 hours.

Check out the Policies > Recipies section for more examples.

The goal is to assist you in building a mental model of how policies function in the Armory Stack. Note that each section below builds upon the previous one.

Let's start by permitting Transaction signature requests

{
  when: [
    {
      criterion: Criterion.CHECK_ACTION,
      args: [Action.SIGN_TRANSACTION]
    }
  ],
  then: Then.PERMIT
}

Check if the user is Bob

User IDs are unique ids defined in your Entity Data. For instance, let's assume Bob's ID is bob-id.

{
  when: [
    // ...
    {
      criterion: Criterion.CHECK_PRINCIPAL_ID,
      args: ['bob-id']
    }
  ],
  then: Then.PERMIT
}

Check if the account is the correct one

Let's assume the account address is 0x962Ba468Be802d8c92F0462A368e40813f0b4104.

{
  when: [
    // ...
    {
      criterion: Criterion.CHECK_ACCOUNT_ADDRESS,
      args: ['0x962Ba468Be802d8c92F0462A368e40813f0b4104']
    }
  ],
  then: Then.PERMIT
}

Check if the action is a MATIC transfer

Here, we'll check the action's intent type and the token by combining two criteria.

{
  when: [
    // ...
    {
      criterion: Criterion.CHECK_INTENT_TYPE,
      args: [Intents.TRANSFER_NATIVE]
    },
    {
      criterion: Criterion.CHECK_INTENT_TOKEN,
      args: ['eip155:137/slip44:966']
    }
  ],
  then: Then.PERMIT
}
  • When the action is signTransaction, Armory takes the opaque transaction request (from, to, value, and data) and reverse-engineers it into a more granular data structure, which we refer to as "intent".

  • The Armory widely utilizes the CAIP-19 standard to represent chain-agnostic asset IDs. As a result, MATIC is identified as eip155:137/slip44:966.

Check user's spending limits in the last 5 hours

{
  when: [
    // ...
    {
      criterion: Criterion.CHECK_SPENDING_LIMIT,
      args: {
        limit: '10000000000000000000',
        timeWindow: {
          type: TimeWindow.ROLLING,
          value: 5 * 60 * 60
        },
        filters: {
          tokens: ['eip155:137/slip44:966'],
          users: ['bob-id']
        }
      }
    }
  ],
  then: Then.PERMIT
}

Putting all together

If Bob attempts to Sign a Transaction using the account 0x96..04 where the transaction is a MATIC transfer and he has transferred < 10 MATIC in the last 5 hours, then Permit.

{
  when: [
    {
      criterion: Criterion.CHECK_ACTION,
      args: [Action.SIGN_TRANSACTION]
    },
    {
      criterion: Criterion.CHECK_PRINCIPAL_ID,
      args: ['bob-id']
    },
    {
      criterion: Criterion.CHECK_ACCOUNT_ADDRESS,
      args: ['0x962Ba468Be802d8c92F0462A368e40813f0b4104']
    },
    {
      criterion: Criterion.CHECK_INTENT_TYPE,
      args: [Intents.TRANSFER_NATIVE]
    },
    {
      criterion: Criterion.CHECK_INTENT_TOKEN,
      args: ['eip155:137/slip44:966']
    },
    {
      criterion: Criterion.CHECK_SPENDING_LIMIT,
      args: {
        limit: '10000000000000000000',
        timeWindow: {
          type: TimeWindow.ROLLING,
          value: 5 * 60 * 60
        },
        filters: {
          tokens: ['eip155:137/slip44:966'],
          users: ['bob-id']
        }
      }
    }
  ],
  then: Then.PERMIT
}

Last updated