Create a Policy

A policy is a set of rules that can block signing requests. Signing requests include blockchain transactions and requests to sign data, such as EIP-712 typed data. Each stored rule has a scope, conditions, and a BLOCK response. Enabled rules apply cumulatively: if any applicable rule matches, the request is denied.

If policy evaluation completes successfully and no applicable rule returns a BLOCK response, the request can proceed after UWaaS Wallet Manager (UWM) authenticates the caller, authorizes the wallet and key, and validates the signing request.

For information about the UWaaS Wallet Manager, see Universal Wallet as a Service (UWaaS). For API request fields and operations, see the Universal Wallet Manager APIs, including:

Define Rule Conditions

A rule combines conditions with all, any, and not. You can nest these groups to define a restriction:

  • all matches when every child condition matches.
  • any matches when at least one child condition matches.
  • not matches when its child condition does not match.

Define condition groups inline. Named condition references are not supported for UWM signing rules.

A condition leaf specifies a fact, an operator, and a value. Use path to select a nested property from a fact. Higher priority values are evaluated first.

{
  "fact": "to_address",
  "operator": "in",
  "value": ["<blocked-address>"]
}

The in operator matches when the fact equals one of the listed values. Use all to combine this condition with an operation condition. Use any when one of several conditions can trigger the restriction.

Operators

Operator Use it when
equal, notEqual A scalar fact must equal or differ from a value of the same type.
in, notIn A scalar fact must appear or not appear in a list of values.
contains, doesNotContain An array fact must contain or not contain a value.
lessThan, lessThanEquals (lessThanInclusive) A numeric fact must be lower than, or lower than or equal to, a numeric value.
greaterThan, greaterThanEquals (greaterThanInclusive) A numeric fact must be higher than, or higher than or equal to, a numeric value.

Ordered comparisons on amount, amount_atomic, and native_value_atomic use exact decimal arithmetic on both /evaluate and /internal/v1/authorize.

Use decimal strings for atomic quantities and large thresholds. For example:

{ "fact": "amount_atomic", "operator": "greaterThanEquals", "value": "1000000000000000000" }

UWM supplies amount_atomic in base units and does not convert it to token decimals. The amount fact is supported when supplied by a caller of /evaluate; UWM does not add it to the signing facts.

Decimal JSON numbers within the safe numeric range are accepted. Send larger numeric values as strings; larger numeric literals are rejected. The greaterThanInclusive and lessThanInclusive operator names remain supported. The equal and notEqual operators compare values by type. Other facts retain their existing comparison behavior.

Array Decorators

Prefix an operator with a decorator and a colon, such as someFact:equal. Decorators change how the operator handles arrays or its result.

Decorator Use it when
someFact At least one item in an array fact matches.
everyFact Every item in an array fact matches.
someValue The fact matches at least one item in an array value.
everyValue The fact matches every item in an array value.
swap The comparison uses the value as the fact and the fact as the value.
not The base operator result must be negated.

For example, someFact:equal can match one token ID in the token_ids array provided for a decoded ERC-1155 batch call:

{
  "fact": "token_ids",
  "operator": "someFact:equal",
  "value": "42"
}

Use the not condition group for Boolean logic and the not: decorator to negate an individual operator. Condition and rule priorities set evaluation order. They do not allow one rule to override another matching BLOCK.

Set the Rule Scope

Set scopelevels and targets to specify which signing requests a rule covers. Every selected scope must match. Targets within one scope are alternatives.

Scope Required target Use it for
global None; specify
scopelevels:
                    ["global"]
by itself.
A restriction that applies to every signing request.
org targets.orgIds A restriction for one or more organizations.
wallet targets.walletIds A restriction for one or more wallets.
instance targets.instanceIds A restriction for one or more network instances.
asset targets.assetIds Existing asset-scoped rules; retained for compatibility.
Combine scopes when a rule depends on more than one dimension. For example,
scopelevels: ["org",
        "wallet"]
requires both the organization and wallet targets to match. A wallet-only rule does not have an implicit organization boundary. Use IDs returned by UWM, not display names.

To restrict a contract method, match contract_address and function_selector in the conditions. Add the instance scope if the same method requires different restrictions on different networks. The asset scope is retained for existing rules; these conditions do not require it.

For targets.instanceIds, use the public instanceId shown by UWM's wallet or network API. This is the registered infra_instance_id, not the numeric database key or chain ID. Update older instance-scoped rules that use a database key; UWM now sends only the public instance identifier.

Match the Signing Request

Conditions can use only facts supplied for the request's operation. The operation fact is available for every signing request.

operation Additional facts
native-transfer amount_atomic, to_address
erc20-transfer amount_atomic, to_address, contract_address
contract-deployment amount_atomic, init_code_hash
contract-call contract_address, native_value_atomic, function_selector, calldata_hash
eip712 primary_type, verifying_contract, typed_data

UWM recognizes canonical ERC-20 transfer(address,uint256) calls with zero native value without token registration. UWM no longer reads capability.approved-token-contracts.

The erc20-transfer profile also provides native_value_atomic ("0"), function_selector ("0xa9059cbb"), and calldata_hash. These facts allow existing contract-call rules to retain their full restrictions.

An erc20-transfer operation is also a contract-call for operation conditions. Both rule types can match the same request, and any matching BLOCK denies it. This behavior applies to equal, notEqual, in, notIn, and nested Boolean conditions on both evaluation endpoints. Other facts retain their normal equality semantics.

The erc20-transfer operation matches transfer, not transferFrom or ERC-1155 methods. Always include the intended contract_address in token rules.

Canonical ERC-20 transferFrom, ERC-1155 safeTransferFrom, and ERC-1155 safeBatchTransferFrom calls provide additional contract-call facts:

Call Additional facts
ERC-20 transferFrom owner_address, to_address, amount_atomic
ERC-1155 safeTransferFrom owner_address, to_address, token_id, amount_atomic
ERC-1155 safeBatchTransferFrom owner_address, to_address, parallel token_ids and amounts arrays

UWM decodes only calls with a supported canonical ABI layout. Other calls retain the generic contract-call facts.

owner_address is the source address in the call data, not the signing wallet. A selector identifies the call-data layout, not the deployed contract's behavior. ERC-20 and ERC-721 share the transferFrom selector, so apply amount conditions only to a contract known to implement ERC-20. Addresses and selectors are normalized to lowercase; use lowercase condition values. For batch calls, do not total amounts for different token IDs.

amount_atomic and native_value_atomic are decimal strings in base units; native value is in wei. EIP-712 integer values are also decimal strings. For EIP-712, typed_data contains the signed domain and message. A path is relative to that fact: use $.message.value for the message value and $.domain.chainId for the signed chain ID.

Wallet, organization, and network restrictions belong in the wallet, org, and instance scopes. Signer, gas, and nonce metadata are not condition facts. The asset scope target does not add an asset condition fact.

Before You Enable a Signing Rule

Use only the facts listed for the operation under Match the Signing Request. Include an operation condition when a rule uses operation-specific facts.

Saving a rule does not confirm that UWM can evaluate it during signing. For example, UWM does not supply a tier fact. A rule that checks whether tier equals gold can cause signing to fail with a generic 500 error.

If signing fails after you enable a rule, review its facts, conditions, and scope. Correct the rule, or ask an authorized administrator to disable it if it is an unintended placeholder. Disabling a required restriction removes its protection.

Before enabling the rule in production, enable it for the intended scope in a test context and verify that actual signing requests are allowed or blocked as intended when they are submitted. The /evaluate endpoint alone does not verify behavior during signing because it accepts user-supplied facts, which may differ from those supplied during signing.

Create a Rule

This example blocks native transfers to one address for one organization. Replace the example IDs and address with the values for your environment. The rule is disabled and will not block requests until you enable it. Review the scope and conditions before enabling the rule.

{
  "name": "block-restricted-native-recipient",
  "description": "Block native transfers to the restricted recipient",
  "category": "transaction-policy",
  "enabled": false,
  "scopelevels": ["org"],
  "targets": {
    "orgIds": ["<organization-id>"]
  },
  "conditions": {
    "all": [
      {
        "fact": "operation",
        "operator": "equal",
        "value": "native-transfer",
        "priority": 100
      },
      {
        "fact": "to_address",
        "operator": "equal",
        "value": "0x3333333333333333333333333333333333333333",
        "priority": 1
      }
    ]
  },
  "response": {
    "type": "BLOCK",
    "params": {
      "reason": "restricted-recipient"
    }
  }
}

Put the operation condition first and assign it a higher priority than operation-specific facts. During signing authorization, evaluation fails if it reads a missing fact; the request is not silently allowed.

The evaluation endpoints check rules against facts you submit. Live signing uses facts from UWM's validated request and scope targets from its resolved wallet. Use evaluation to inspect a condition, then confirm the result through the intended signing flow.