Skip to main content
Policies are environment-wide rules that Portal enforces directly in the MPC signing path, before any signature is produced. Unlike checks you might add in your own application layer, a blocked transaction never gets signed at all. There’s no signature for a client to work around or replay. Policies are managed from the Policies page on the Portal Admin Dashboard.

The transaction amount limit rule

Policy Engine v1 ships with one rule kind: a transaction amount limit. For each policy you choose:
  • A name (up to 64 characters), which appears in the error when the policy blocks a transaction
  • A chain
  • A token — the chain’s native asset, a listed stablecoin, or a custom token (contract address on EVM/Tron, or mint address on Solana) along with its decimals
  • A per-transaction cap, entered in display units (e.g. 0.5 ETH, 100 USDC)
  • Optionally, up to 100 recipients the cap applies to
Any single transaction that moves more than the cap for that chain and token is blocked.

Limiting what goes to specific recipients

Add recipients to cap what a single transaction can send to particular addresses, for example “at most 1,000 USDC to this exchange”. The policy then counts only what the transaction sends to the listed recipients, adds it up across all of them, and blocks the transaction when that total is over the cap. Whatever the transaction sends to other addresses doesn’t count. Leave recipients empty to block any transaction above the cap, whoever receives it. A recipient is the address that ends up with the funds, not the contract the transaction calls:
  • Native sends: the transaction’s to
  • Token transfers: the address the token pays, not the token contract. On EVM and Tron that’s the to of a transfer, or of a transferFrom
  • CCTP transfers (EVM): the mint recipient on the destination chain. A transfer to Solana mints to a token account rather than a wallet, so it doesn’t count toward EVM recipients
  • Tron contract calls: TRX sent with a contract call counts toward the contract itself
Recipients use each chain’s own address format. On Solana, list wallet addresses, not token accounts: a token transfer counts when it goes into a listed wallet’s associated token account for the policy’s token. Tron addresses must be in base58 form (T…). Amounts add up across the whole transaction, so a batch of several calls (for example an Account Abstraction user operation) that each stay under the cap is still blocked when together they go over it.

Supported chains

  • EVM chains — Ethereum, Sepolia, Polygon, Base, and Monad (mainnet and testnet) out of the box; amount extraction works on any eip155 chain
  • Solana — mainnet and devnet
  • Tron — mainnet, Shasta, and Nile testnets

How enforcement behaves

All enabled policies in an environment are evaluated for every transaction. If any policy’s rule matches, the transaction is blocked; if none match, the transaction proceeds. There’s no allowlist mode in this version. Policies are purely additive blockers. When a policy blocks a transaction, the request fails with HTTP 400 and no signature is ever produced. Both POST /v1/assets/send and POST /v1/sign on the Enclave MPC API return the same body:
That is the raw Enclave MPC API response body; Portal SDKs expose the same fields through their own error handling. Match on the POLICY_AMOUNT_LIMIT_EXCEEDED identifier rather than on the message text. Responses also carry a legacy numeric code, which is deprecated. For Account Abstraction clients, policies also run when Portal builds the user operation. When one blocks it, build-user-operation returns HTTP 403 with the same identifier and the policy that blocked it:
CCTP transfers for Account Abstraction clients return 403 with the id POLICY_VIOLATION instead.

Managing policies on the dashboard

Step 1: Click on “Policies” in the left sidebar, under Configuration. Step 2: Click “Create policy,” choose a chain and token, set your per-transaction cap, optionally add recipients, and save. Each policy holds one rule. Once created, a policy appears in your list with a toggle and a delete action:
  • Toggle — enable or disable the policy without deleting it. Disabled policies are not evaluated.
  • Delete — permanently remove the policy.
To change a policy’s cap or recipients, create a new policy and delete the old one.

Scope & caveats

Policy Engine v1 is intentionally scoped. A few things to keep in mind:
  • Per-transaction only. Limits are compared against a single transaction’s amount. Velocity or cumulative limits (e.g. “no more than $1,000 per day”) are on the roadmap but not yet available.
  • Direct transfers are covered, not everything that moves value. Token limits inspect direct transfer/transferFrom calls on EVM and Tron, and SPL transfers on Solana, both TransferChecked and plain Transfer sent from a wallet’s associated token account. Value moved through arbitrary contract calls, approve-then-pull flows, or non-standard token accounts is not currently inspected.
  • Raw-signed payloads can’t be policy-checked. If your integration signs an opaque hash rather than a structured transaction, Portal has no transaction contents to evaluate against a policy, by design.
If your use case depends on any of the above, reach out to your Portal contact to discuss options.