Policy Condition Language (PCL)

This page provides an overview of how to write conditions for Swivell's Policy Engine.

Language Features

Primitives

TypeDescriptionExamples
stringText values enclosed in single or double quotes'mainnet', 'BTC', "0x123..."
boolTrue/false valuestrue, false
floatNumeric values with decimals100.0, 0.5, 1000.50
listCollections of values['mainnet', 'arbitrum'], [1, 2, 3]
objectStructured data with named fields{ symbol: "USD0" }, { address: "0x123...", risk_score: 0.3 }

Comparisons

Equality and Inequality

  • == - Equal to: deposit.amount == 100.0
  • != - Not equal to: deposit.network != 'mainnet'

Numeric Comparisons

  • < - Less than: deposit.value_usd < 1000.0
  • > - Greater than: deposit.amount > 50.0
  • <= - Less than or equal: deposit.value_usd <= 5000.0
  • >= - Greater than or equal: deposit.amount >= 10.0

Logical Operators

  • && - Logical AND: deposit.amount > 0 && deposit.value_usd < 1000.0
  • || - Logical OR: deposit.network == 'mainnet' || deposit.network == 'arbitrum'
  • ! - Logical NOT: !deposit.asset.is_possible_spam

Membership

  • in - Check if value exists in list: deposit.network in ['mainnet', 'arbitrum']

Objects

Field Access

  • . - Access object properties: deposit.asset.symbol

Lists

Access Elements

  • [index] - Get element at index: deposit.originators[0]

Functions

  • size() - Get list length: size(deposit.originators)
  • .all(item, condition) - Check if all items match: deposit.originators.all(o, o.risk_score < 0.5)
  • .exists(item, condition) - Check if any item matches: deposit.originators.exists(o, o.risk_score > 0.8)

Context

The policy conditions have these variables in scope

KeywordTypeDescriptionAvailable On
depositDepositThe deposit being processedeffect_freeze, effect_forward

Deposit Object

FieldTypeDescription
idstringUnique identifier for the deposit
networkstringNetwork where the deposit occurred (e.g mainnet, solana, base, arbitrum)
assetAssetDetails about the deposited asset
amountfloatAmount of tokens deposited
value_usdfloatUSD value of the deposit (optional)
originatorslist[Originator]The originators of the deposit

Asset Object

FieldTypeDescription
address_checksumstringThe address/mint of the token in case-sensitive format
address_lowercasestringThe address/mint of the token in lowercase format
symbolstringThe symbol for the token (e.g., "BTC", "ETH")
networkstringThe network the token is on (e.g mainnet, solana, base, arbitrum)
is_possible_spamboolWhether the token is flagged as possible spam
namestringThe full name of the token (optional)
pegged_tostringSymbol this token's price is pegged to (optional)

Originator Structure

FieldTypeDescription
address_checksumstringThe address of the originator in case-sensitive format
address_lowercasestringThe address of the originator in lowercase format
risk_scorefloatScore of the originator's fraud risk

Examples Conditions

Amount Limits

// Allow deposits under $1,000 USD
deposit.value_usd < 1000.0

// Limit token amount
deposit.amount <= 100.0

Asset Restrictions

// Only allow specific tokens
deposit.asset.symbol in ['BTC', 'ETH', 'USDC']

// Block spam tokens
!deposit.asset.is_possible_spam

// Check specific token address (case-sensitive)
deposit.asset.address_checksum == '0xA0b86a33E6441d8178E82c5A3f4fa6Afdd59E33e'

// Check address (case-insensitive)
deposit.asset.address_lowercase == '0xa0b86a33e6441d8178e82c5a3f4fa6afdd59e33e'

Network Controls

// Only allow Ethereum mainnet
deposit.network == 'mainnet'

// Allow multiple networks
deposit.network in ['mainnet', 'arbitrum', 'base']

Combined Conditions

// Mainnet deposits under $10k OR L2 deposits under $5k
(deposit.network == 'mainnet' && deposit.value_usd < 10000.0) ||
(deposit.network in ['arbitrum', 'base'] && deposit.value_usd < 5000.0)

// Safe assets only
deposit.asset.symbol in ['ETH', 'USDC'] && !deposit.asset.is_possible_spam

Stablecoin Handling

// USD-pegged tokens with higher limits
deposit.asset.pegged_to == 'USD' && deposit.value_usd < 25000.0

// Specific stablecoins
!deposit.is_possible_spam && deposit.asset.symbol in ['USDC', 'USDT', 'DAI']

Originator Risk Validation

// Block high-risk originators
deposit.originators.all(o, o.risk_score < 0.5)

// Allow deposits if any originator has low risk
deposit.originators.exists(o, o.risk_score < 0.2)

// Check specific originator addresses (case-sensitive)
deposit.originators.exists(o, o.address_checksum in trusted_addresses)

// Check originator addresses (case-insensitive)
deposit.originators.exists(o, o.address_lowercase in trusted_addresses_lower)