Skip to main content
This feature is available for all Dynamic v3 embedded wallets (TSS-MPC). Upgrade is required if you are on v2 or earlier.

Overview

Policy and Rules gives developers fine-grained control over how wallets interact. Policies are enforced before a transaction is signed ensuring there is validation before execution. This allows you to:
  • Block malicious or unauthorized counterparties
  • Create custom workflows around wallet interactions
  • Ensure transactions are simulated and verified before execution
Policies are chain-agnostic, working seamlessly across EVM including Account Abstraction wallets and interactions on Solana

Security Model

Dynamic’s policy system is designed with security and transparency at its core:
  • Tamper Resistance: Policies are created and enforced in a trusted execution environment, ensuring they cannot be bypassed at the client level. Only administrators and those with permissions can update and modify rules
  • Auditability: Every policy update is logged and traceable.
  • Transaction Simulation: Before a transaction is signed, it is simulated against your rules. Non-compliant requests are automatically rejected.
  • Malicious Transaction Detection: Before a transaction is signed, all transactions will be validated to ensure they are not being sent to a malicious address.
  • Pre-Signing Enforcement: Rules apply at signing time, not just after execution. This means developers can trust that no transaction leaves the wallet unless it passes policy checks.

Allowlist Mode

When you configure an allowlist, only addresses included in your allow rules are permitted. Everything not on the list is blocked.

Address Evaluation

Policies evaluate all participant addresses involved in a transaction’s execution path. If a transaction calls contract A that then calls contract B, every touched address (A and B) is considered a participant for evaluation. When using an allowlist (only listed addresses are permitted), ensure you include all relevant contract addresses, including proxies and their underlying implementations, to avoid unintended rejections.

Value Limits

You can add a value limit to any rule to restrict the maximum amount that can be transferred in a single transaction. When a value limit is set, the policy will evaluate the transaction amount and automatically block any transaction that exceeds the specified limit. Value limits work for both EVM and Solana (SVM) chains, and can be applied to native tokens (like ETH or SOL) as well as custom tokens (such as ERC-20 or SPL tokens). To set a value limit for the native token of the chain, simply leave the address field for the value limit blank.

Creating a Rule

Step 1: Navigate to the Policies Tab

On the developer dashboard, navigate to the Policies tab under the Wallets section. Click on Create your first rule to get started.
Policies Setup Screenshot

Step 2: Configure the Rule

In Basic Settings, you can configure the following for the rule:
  • Rule Name: A descriptive name for the rule
  • Rule Description: A description of the rule
  • Rule Type: The type of rule to create. You can choose between:
    • Allow: This rule allows the operation to proceed
    • Deny: This rule blocks the operation
  • Network/Environment: The specific network or environment, such as Sepolia, Base Sepolia, etc.
  • Addresses: The addresses the rule applies to
Below is an example of configuring a rule to only allow users interacting with the WETH contract on Ethereum mainnet.
Policies Setup Screenshot

Step 3: Add/Update a Rule

There are two ways to add/update a rule: you can either update using the dashboard or send an API request with your authorized token.

Creating a Rule

  1. Click on Save Rule to create a rule by clicking on Add Rule in Basic Settings once you have configured the rule.
  2. You can also send an API request with your authorized token to create/update a rule. The payload can be found in the JSON tab of the Rule creation page.
Below is an example of creating a rule via curl:
curl -X POST \
"https://app.dynamicauth.com/api/v0/environments/<environment_id>/waas/policies" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your_token>" \
-d '{
  "rulesToAdd": [
    {
        "chain": "EVM",
        "chainIds": [1],
        "name": "Allow only transaction with WETH contract on ETH mainnet",
        "ruleType": "allow",
        "addresses": ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"]
    }
  ]
}'

Update a Rule

If you have active rules, you will see the Policy & Rules Management tab in the Policies tab.
  1. Click on the rule you want to update, which will expand to the Edit Rule page
  2. Update the rule configuration and click on Save Rule to update the rule
Policies Setup Screenshot
Below is an example of updating a rule via curl:
curl -X PUT \
"https://app.dynamicauth.com/api/v0/environments/<environment_id>/waas/policies" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your_token>" \
-d '{
  "rulesToUpdate": [
    {
        "id": <existing_rule_id>,
        "chain": "EVM",
        "chainIds": [1],
        "name": "Allow only transaction with WETH contract on ETH mainnet",
        "ruleType": "allow",
        "addresses": ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"]
    }
  ]
}'

Step 4: Verifying Policy

To confirm that your policy rule is enforced, attempt to send a transaction that matches or violates the rule you configured. We recommend performing these tests on a testnet within a sandbox environment. Expected Behavior:
  • If the transaction complies with the policy, it will be processed as normal.
  • If the transaction violates the policy, the SDK or wallet connector will return an error indicating that the operation is not permitted.
Below is an example of a policy violation error displayed when a transaction does not meet the configured rule criteria:
Policies Setup Screenshot

Step 5: Deleting a Rule

If you have active rules, you will see the Policy & Rules Management tab in the Policies tab.
  1. Click ... next to the rule you want to delete, which will expand a dropdown menu with the option to delete the rule
  2. Check the box to confirm you want to delete the rule and click on Delete Rule button
Policies Setup Screenshot
Below is an example of deleting a rule via curl:
curl -X DELETE \
"https://app.dynamicauth.com/api/v0/environments/<environment_id>/waas/policies" \
-H "Authorization: Bearer <your_token>" \
-H "Content-Type: application/json" \
-d '{
  "ruleIdsToDelete": ["<existing_rule_id>"]
}'

Creating, Updating, and Deleting Rules in Bulk

You can programmatically create or update multiple policy rules at once using the API. To do this, provide an array of rules in the rulesToAdd, rulesToUpdate, or ruleIdsToDelete fields of your request payload. Here is an example of how to create multiple rules using a POST request (SDKs or HTTP clients):
curl -X POST \
"https://app.dynamicauth.com/api/v0/environments/<environment_id>/waas/policies" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your_token>" \
-d '{
  "rulesToAdd": [
    {
        "chain": "EVM",
        "chainIds": [1],
        "name": "Allow only transaction with the WETH contract on ETH mainnet",
        "ruleType": "allow",
        "addresses": ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"]
    },
    {
        "chain": "EVM",
        "chainIds": [8453],
        "name": "Allow only transaction with USDC contract on Base mainnet",
        "ruleType": "allow",
        "addresses": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"]
    }
  ]
}'
Here is an example of how to update multiple rules using curl:
curl -X PUT \
"https://app.dynamicauth.com/api/v0/environments/<environment_id>/waas/policies" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your_token>" \
-d '{
  "rulesToUpdate": [
    {
        "id": <existing_rule_id>,
        "chain": "EVM",
        "chainIds": [1],
        "name": "Allow only transaction with the WETH contract on ETH mainnet",
        "ruleType": "allow",
        "addresses": ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"]
    },
    {
        "id": <existing_rule_id>,
        "chain": "EVM",
        "chainIds": [8453],
        "name": "Allow only transaction with USDC contract on Base mainnet",
        "ruleType": "allow",
        "addresses": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"]
    }
  ]
}'
Here is an example of how to delete multiple rules using curl:
curl -X DELETE \
"https://app.dynamicauth.com/api/v0/environments/<environment_id>/waas/policies" \
-H "Authorization: Bearer <your_token>" \
-H "Content-Type: application/json" \
-d '{
  "ruleIdsToDelete": ["<existing_rule_id>", "<existing_rule_id>"]
}'

USDC allowlist example (Ethereum mainnet, proxy + implementation) to a single address:

USDC on Ethereum mainnet uses a proxy pattern. To allow interactions, add both the proxy and the current implementation addresses to your allowlist, on this example we are allowing interactions to a single address (0x5f09B2caaafD345EaE7B711A32CcBdf59befB4bB):
curl -X POST \
"https://app.dynamicauth.com/api/v0/environments/<environment_id>/waas/policies" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your_token>" \
-d '{
  "rulesToAdd": [
    {
        "chain": "EVM",
        "chainIds": [1],
        "name": "Allow USDC proxy (ETH mainnet)",
        "ruleType": "allow",
        "addresses": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48","0x43506849d7c04f9138d1a2050bbf3a0c054402dd","0x5f09B2caaafD345EaE7B711A32CcBdf59befB4bB"]
    }
  ]
}'

Value Limit Example (Ethereum mainnet):

On this example we are allowing interactions to a single address (0x5f09B2caaafD345EaE7B711A32CcBdf59befB4bB) with a value limit of 100 USDC:
curl -X POST \
"https://app.dynamicauth.com/api/v0/environments/<environment_id>/waas/policies" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your_token>" \
-d '{
  "rulesToAdd": [
    {
      "chain": "EVM",
      "chainIds": [1],
      "name": "Allow USDC (ETH mainnet) with value limit",
      "ruleType": "allow",
      "addresses": ["0x43506849d7c04f9138d1a2050bbf3a0c054402dd","0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0x5f09B2caaafD345EaE7B711A32CcBdf59befB4bB"],
      "valueLimit": {
        "asset": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
        "maxPerCall": "100000000000", // 100 USDC
      }
    }
  ]
}'

Policy Violation Webhook

Dynamic emits a waas.policy.violation webhook event whenever a transaction is blocked by your configured policy rules. This event provides detailed information about what was blocked and why, making it invaluable for monitoring security, debugging rules, and discovering which addresses your users need to interact with.

Use Cases

  • Building Allow-Only Rules: The webhook includes all counterparties involved in a transaction, helping you identify which addresses to add to your allowlist
  • Security Monitoring: Track blocked transactions and identify potential threats or unusual activity
  • Rule Debugging: Understand why legitimate transactions are being blocked and adjust rules accordingly
  • Audit Trail: Maintain a complete log of all policy violations for compliance and security review

Event Payload

The webhook payload structure varies based on the violation type. Below are the fields you can expect:

Always Present

FieldDescription
eventNameAlways waas.policy.violation
data.errorMessageHuman-readable description of the violation
data.reasonCodeType of violation (see Violation Types section for all possible codes)
data.publicKeyMost violationsThe wallet’s public key that attempted the transaction
data.walletIdMost violationsThe wallet ID that attempted the transaction
data.operationTypeTransaction/operation violationsType of operation blocked: evmTransaction, evmUserOperation, svmTransaction, or svmMessage
data.chainIdTransaction/operation violationsThe chain ID where the violation occurred

Conditionally Present

The following fields may be included depending on the violation type and context:
FieldWhen PresentDescription
data.deniedAddressesAddress-related violationsArray of addresses that triggered the violation
data.notAllowedAddressesAllowlist violationsArray of addresses not on the allowlist
data.counterpartiesAddress and security violationsArray of all counterparties involved with address and label fields
data.assetValue limit violationsObject containing asset details (address, type, symbol)
data.maxPerCallLimitValue limit violationsThe configured maximum value limit
data.totalOutgoingValueValue limit violationsThe attempted transaction value that exceeded the limit
data.simulationStatusSecurity validation failuresStatus of the transaction simulation
data.validationResultTypeSecurity risk violationsType of security validation result (e.g., “Malicious”)
data.addressAuthentication violationsSpecific address involved in the violation

Example Payloads

Below are examples of policy violation webhooks for different violation types:

Address Denied Violation

When a transaction is blocked due to an address not being on the allowlist:
{
  "messageId": "8ada4f21-a1ad-43bf-92eb-9f42ad9f30fc",
  "eventId": "32d6be06-f069-434f-a345-6609e83961cc",
  "eventName": "waas.policy.violation",
  "timestamp": "2025-10-14T22:23:16.853Z",
  "webhookId": "b94e376c-795a-4ecb-a8b5-b216288c6d23",
  "userId": null,
  "environmentId": "5d76149e-a703-48d0-9977-f46f1ec6ad5a",
  "environmentName": "sandbox",
  "data": {
    "errorMessage": "Policy violation: This action was blocked because '0xf892...fe9c' is not allowed due to a security policy. These policies help protect your account.",
    "publicKey": "0x5d6d4764bd316f25a0048fd5e4aa606c5ebf1569",
    "walletId": "026f9b53-eacf-46a2-bbd6-0174ec670b60",
    "reasonCode": "address_denied",
    "operationType": "evmUserOperation",
    "chainId": "11155111",
    "deniedAddresses": ["0xf892531a10b0060d3f0eceea2da5dfbe7c41fe9c"],
    "counterparties": [
      {
        "address": "0xf892531a10b0060d3f0eceea2da5dfbe7c41fe9c",
        "label": ""
      }
    ]
  }
}

Value Limit Exceeded Violation

When a transaction exceeds the configured value limit for an asset:
{
  "messageId": "9bda5f32-b2be-54cg-03fc-0g53bf0g41gd",
  "eventId": "43e7cf17-g180-545g-b456-7710g94f72dd",
  "eventName": "waas.policy.violation",
  "timestamp": "2025-10-14T22:25:30.123Z",
  "webhookId": "b94e376c-795a-4ecb-a8b5-b216288c6d23",
  "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c",
  "environmentId": "5d76149e-a703-48d0-9977-f46f1ec6ad5a",
  "environmentName": "sandbox",
  "data": {
    "errorMessage": "Policy violation: Transaction value exceeds the maximum allowed limit",
    "publicKey": "0x5d6d4764bd316f25a0048fd5e4aa606c5ebf1569",
    "walletId": "026f9b53-eacf-46a2-bbd6-0174ec670b60",
    "reasonCode": "value_limit_exceeded",
    "operationType": "evmTransaction",
    "chainId": "1",
    "asset": {
      "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "type": "ERC20",
      "symbol": "USDC"
    },
    "maxPerCallLimit": "100000000",
    "totalOutgoingValue": "150000000"
  }
}

Security Risk Malicious Violation

When a transaction is identified as malicious during security validation:
{
  "messageId": "7cda6f43-c3cf-65dh-14gd-1h64ch1h52he",
  "eventId": "54f8dg28-h291-656h-c567-8821h05g83ee",
  "eventName": "waas.policy.violation",
  "timestamp": "2025-10-14T22:27:45.456Z",
  "webhookId": "b94e376c-795a-4ecb-a8b5-b216288c6d23",
  "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c",
  "environmentId": "5d76149e-a703-48d0-9977-f46f1ec6ad5a",
  "environmentName": "sandbox",
  "data": {
    "errorMessage": "Policy violation: This transaction was blocked because it was identified as potentially malicious",
    "publicKey": "0x5d6d4764bd316f25a0048fd5e4aa606c5ebf1569",
    "walletId": "026f9b53-eacf-46a2-bbd6-0174ec670b60",
    "reasonCode": "security_risk_malicious",
    "operationType": "evmTransaction",
    "chainId": "1",
    "validationResultType": "Malicious",
    "counterparties": [
      {
        "address": "0x1234567890123456789012345678901234567890",
        "label": "Phishing Contract"
      }
    ]
  }
}

Violation Types

The reasonCode field indicates the type of policy violation. The webhook payload structure varies based on the violation type, but always includes the core fields needed to understand what was blocked and why.
  • address_denied: Transaction blocked because an address is explicitly denied or not on the allowlist
    • Additional fields: deniedAddresses, counterparties, operationType, chainId
  • address_not_allowed: Transaction blocked because address is not explicitly allowed in an allowlist-only configuration
    • Additional fields: notAllowedAddresses, counterparties, operationType, chainId

Value Limit Violations

  • value_limit_exceeded: Transaction blocked because it exceeds the configured value limit
    • Additional fields: asset (address, type, symbol), maxPerCallLimit, totalOutgoingValue, operationType, chainId

Security Validation Violations

  • security_validation_failed: Transaction simulation failed during security validation
    • Additional fields: simulationStatus, operationType, chainId
  • security_risk_malicious: Transaction identified as malicious by security validation
    • Additional fields: counterparties, validationResultType, operationType, chainId

Message Format Violations

  • invalid_message_format: Message format validation failed (EVM personal message, EIP-712, UserOperation, or SVM transaction/message format issues)

Setting Up Webhooks

To receive policy violation events, configure a webhook endpoint in your Developer Dashboard and subscribe to the waas.policy.violation event. For more information on webhook setup and signature validation, see the webhooks documentation.

Additional Notes

  • The list of available chains in the dashboard depends on your configuration settings. Some networks may not be available for policy validation.
  • Policies and rules are currently supported only for most EVM and Solana chains, including their respective testnets.
  • Sui embedded wallets are not supported at this time.
I