Policy Engine

The control plane for every action onchain

Set the rules for money movement, token operations, user access, and platform changes.

Policy Engine dashboard
Rules, in code

TransactionAmountLimit. TransactionVelocity. RecipientWhitelist. AlwaysTrigger. KYT. Composable primitives, version-controlled like any other infrastructure.

Approvals that scale

M-of-N quorums. Multiple groups required. Service accounts in the mix. Compliance signs off without anyone leaving the dashboard.

Enforcement by cryptography

MPC-backed signing. No policy bypass, no shadow approvers, no exceptions hidden in code. Rules apply to every wallet, every transaction, every chain.

KYT and Travel Rule built in

Chainalysis, Global Ledger, Notabene — first-class rule conditions. Block, freeze, or escalate on red flags, not after.


Rules

Pre-built conditions
for every governance need

Amount limits in USD. Velocity caps over time windows. Recipient allowlists. KYT screening. Travel Rule. Compose them. Layer them. Apply them to every wallet, every chain.

Limits & velocity

Single-transaction caps, hourly velocity, daily caps, frequency limits. Set in USD, evaluated in real time, applied per-wallet or per-tag.

Allowlists

Restrict transfers to known counterparties. Maintain the address book centrally. Non-whitelisted recipients require approval or get blocked outright.

Compliance screening

Chainalysis KYT, Global Ledger KYT, Notabene Travel Rule — first-class rule kinds. Red flags trigger policies, not support tickets.

Wallets dashboard
Actions

Block, or require approval
— your call

When a rule triggers, the platform either blocks the action outright or holds it until enough approvers sign off. Block on certainty. Approve on judgment. Audit either way.

Approval quorums

M-of-N from any group. Name specific users or wildcard the role. Set auto-reject timeouts. Capture rejection reasons.

Multi-group approval

Compliance signs off AND treasury signs off. Each group has its own quorum. The transaction only proceeds when every group reaches its threshold.

Service account approvers

Machine identities in the approval group. Service accounts handle the routine cases programmatically. Humans handle the exceptions. The four-eyes principle, encoded.

Wallets dashboard
Scope

Policies target exactly
what they should

Apply by wallet, wallet tag, or activity kind. Different rules for hot, warm, and cold wallets. Different rules for treasury vs operations. Different rules for token issuance vs settlement.

Wallet tags

Tag wallets by entity, function, risk band. Target policies by tag. Hot wallets get tight caps. Treasury wallets get full quorum approval. One engine, many regimes.

Activity kinds

Policies apply to Wallets:Sign, but also to permission grants, policy modifications, credential rotations. Foundation policies protect the configuration itself.

Filters and exclusions

Untagged wallets bypass tagged-only policies. Automated wallets stay automated. Human-controlled wallets stay supervised. Same engine, different scopes.

Wallets dashboard
Enforcement

Cryptographic guarantees,
not optimistic guardrails

Every policy evaluation runs inside the MPC signing path. No “we forgot to check.” No “the admin overrode it.” Either the policy passes, or the signature doesn’t happen.

No bypass

Policies are enforced at the signing layer, not the application layer. Even DFNS staff can't override an active policy on your wallets.

All policies, all evaluated

Every matching policy runs. Any Block blocks. Every RequestApproval collects approvals. No order-dependent gotchas, no policy precedence games.

Audit by construction

Every triggered policy, every approval, every decision is signed and timestamped. The audit trail isn't generated after the fact — it's what actually happened.

Wallets dashboard

Discover how SolideFinance secures assets on DFNS.

“DFNS gives us the control we need to secure customer assets without managing private keys ourselves. The policy system is fine-grained and powerful enough for complex enterprise requirements, while the product remains easy to use, easy to configure at the right level, well documented, and backed by a responsive technical team.”

Olivier Scherrer CTO, SolideFinance

Four steps to a policy that holds up

Define the rule. Set the scope. Wire the approvers. Watch it enforce. The same engine, whether the rule comes from compliance, treasury, or risk.

Every signature across 100+ chains evaluated · Every approval signed and audited · Multiple policies per action, no order dependency

Pick a rule. Set a threshold.

Choose from pre-built rule kinds. Set the amount, the velocity, the allowlist. No DSL. No custom parsing. The rule definition is the source of truth.

// Trigger approval when a single transaction exceeds $100,000
const rule = {
  kind: "TransactionAmountLimit",
  configuration: { limit: "100000", currency: "USD" }
};

// Or velocity-based: cap outflows at $500k per 24-hour window
const velocityRule = {
  kind: "TransactionAmountVelocity",
  configuration: { limit: "500000", currency: "USD", timeframeSeconds: 86400 }
};

// Or KYT-based: block transactions flagged Severe by Chainalysis
const kytRule = {
  kind: "ChainalysisTransactionPrescreening",
  configuration: { riskScore: "Severe" }
};
Stack rules. A single wallet can have an amount cap, a velocity cap, AND a KYT screen — they're additive. Any one of them triggers the action. Layered rules, defense in depth.

Target exactly what the rule applies to.

Wallet tags, wallet IDs, activity kinds. Apply broadly, narrow precisely. Hot wallets get one policy. Treasury wallets get another. Issuance wallets get a third.

// Scope to wallets tagged 'treasury' OR 'cold-storage'
const filters = {
  walletTags: { hasAny: ["treasury", "cold-storage"] }
};

// Or by activity kind — protect the policy configuration itself
// 'Policies:Modify' requires approval from the Risk Committee
const metaPolicy = {
  name: "Policy Modification Protection",
  activityKind: "Policies:Modify",
  rule: { kind: "AlwaysTrigger" },
  action: {
    kind: "RequestApproval",
    approvalGroups: [{
      name: "Risk Committee",
      quorum: 3,
      approvers: { userId: { in: [/* 5 risk officers */] } }
    }]
  }
};
Always protect your policy configuration with a meta-policy. Policy modifications themselves should require approval — otherwise the rule is only as strong as the least-trusted admin.

Configure the approval matrix.

One quorum or two. One group or two. Service accounts can vote alongside humans. Initiators can't approve their own transactions. The four-eyes principle, encoded in JSON.

// Two-group approval: compliance signs off AND treasury signs off
const action = {
  kind: "RequestApproval",
  approvalGroups: [
    {
      name: "Compliance",
      quorum: 1,
      approvers: { userId: { in: ["us-compliance-1", "us-compliance-2", "us-compliance-3"] } }
    },
    {
      name: "Treasury Council",
      quorum: 2,
      approvers: { userId: { in: ["us-treasurer-1", "us-treasurer-2", "us-treasurer-3"] } }
    }
  ],
  autoRejectTimeout: 86400,        // auto-reject after 24h
  initiatorCanApprove: false       // four-eyes principle enforced
};
Use multi-group approval for high-risk actions. Compliance and treasury aren't the same function — both should sign off independently. Keep initiatorCanApprove: false unless you have an explicit reason otherwise.

Activate. Watch. Audit.

Activate the policy. Every matching action runs through it. Every triggered approval is signed and stored. Every decision queryable forever.

const policy = await dfnsApi.policies.createPolicy({
  body: {
    name: "Large Transfer Approval",
    activityKind: "Wallets:Sign",
    rule, action, filters,
    status: "Active"
  }
});

// Subscribe to policy events for live dashboards and alerting
await dfnsApi.webhooks.createWebhook({
  body: {
    url: "https://risk.yourbank.com/dfns/policies",
    events: [
      "policy.approval.pending",
      "policy.approval.resolved",
      "policy.triggered.block"
    ]
  }
});

// Pull the audit trail anytime
const decisions = await dfnsApi.policies.listApprovalDecisions({
  query: { policyId: policy.id, dateFrom: "2026-05-01" }
});
Watch the metrics. Approval latency, escalation rate, block rate. If a policy never triggers, the threshold may be too loose. If it always triggers, the threshold may be too tight. Tune like any other production system.
Org → Policies → New Policy → Rule Type → Configure
Org → Policies → New Policy → Rule Type → Configure
New Policy → Filters → Wallet Tags / Activity Kind
New Policy → Filters → Wallet Tags / Activity Kind
New Policy → Approval Matrix Builder → Add Group → Quorum + Members
New Policy → Approval Matrix Builder → Add Group → Quorum + Members
Org → Policies → Active Policies → Decisions Log
Org → Policies → Active Policies → Decisions Log
Contact us