A rule is the core decision-making unit within a policy. Each rule defines a condition expression that is evaluated during a contract call—and one or more effects that are triggered based on whether that condition expression evaluates to true or false.

Rule Execution Order

Rules can optionally include an order field for explicit sequencing:
  • If any rule has an order field, ALL rules must have unique order values
  • Rules are automatically sorted by order value during policy creation
  • Rules without order fields are processed in their original JSON array order
  • This matters when one rule affects data (like a tracker) used by another
Every rule consists of:
  • Name: The name of the rule (optional, defaults to empty string if not provided)
  • Description: A description of the rule (optional, defaults to empty string if not provided)
  • Condition expression: An expression that must evaluate to a boolean (true or false)
  • Effects when true: What happens if the condition expression evaluates to true
  • Effects when false: What happens if the condition expression evaluates to false
  • Calling function signature: Each rule is only applied when a specific calling function invokes the policy
  • Order: Optional ordering value for rule execution sequence (numeric values only, must be unique across all rules if used)

Condition Expressions

Condition expressions are defined by a sequence of values, operators, and optional parentheses. These expressions evaluate to true or false and control whether the positiveEffects or negativeEffects are triggered. Supported operators include:
TypeOperators
Arithmetic+, -, *, /
Comparators>, <, >=, <=, ==
LogicalAND, OR, (, )
Values in an expression can come from:
  • Config data: static data set at configuration time
  • Encoded values: data sent from the calling contract
  • Trackers: on-chain values managed by the policy (referenced with TR: prefix)
  • Mapped Trackers: key-value storage (referenced with TR: prefix and parentheses for key, e.g., TR:UserBalances(userAddress))
  • Foreign calls: values returned by external smart contract calls (referenced with FC: prefix)

Condition Syntax Requirements and Restrictions

Parentheses Requirements

  • Balanced Parentheses: All opening ( must have matching closing ) parentheses
  • Proper Nesting: Nested parentheses must be properly structured
  • Automatic Spacing: Parentheses are automatically padded with spaces during parsing
  • Group Validation: Each parenthetical group is validated independently for operator consistency

Reference Syntax

  • Foreign Calls: Must use FC: prefix followed by the foreign call name (e.g., FC:GetBalance)
  • Trackers: Must use TR: prefix followed by the tracker name (e.g., TR:UserCount)
  • Mapped Trackers: Must use TR: prefix with parentheses for the key (e.g., TR:UserBalances(userAddress))
  • Case Sensitive: All reference names are case-sensitive and must exactly match component names
  • No Spaces: Reference names cannot contain spaces or special characters except parentheses for mapped trackers

Logical Operator Rules

  • Single Operator Per Group: Each set of parentheses can only contain one instance of AND or OR (either all AND or all OR, not mixed)
  • Case Sensitive: Operators must be in ALL CAPS (AND, OR, NOT)
  • Spacing: Operators are automatically padded with spaces during validation
  • No Multiple Operators: Cannot have multiple AND or OR operators at the same level without proper grouping

String Literals

  • Must be enclosed in single quotes (") for string comparisons
  • Example: TR:UserRole == "admin"
Expressions follow standard operator precedence rules and can use parentheses for grouping.

Effects

Each rule must define at least one effect that takes place if the condition expression evaluates to true or false. You can include multiple effects in either branch. These can be:
  • revert: revert the transaction
    The revert message must be 32 bytes or less. If you attempt to call the createPolicy function with a longer revert message you will receive a SizeOverflowError.
  • emit event: emit an on-chain event
  • update tracker: update a tracker’s value
  • call external contract: call a foreign contract
If the revert effect is triggered, no other effects will happen for that transaction.

Calling Function Signature

Each rule is evaluated only when called by a specific calling function signature. For example, let’s say we have a staking contract with stake(uint256 amount) and unstake(uint256 amount) functions. We want to create a policy that enforces that users cannot stake tokens after September 1st, and cannot unstake tokens until September 15th. We would create two separate rules in the policy, and they would have different function signatures for the callingFunction property:
    "Name": "Staking Deadline",
    "Description": "Limits when staking can occur",
    "condition": "timestamp > 1751452000",
    "positiveEffects": [],
    "negativeEffects": ["revert(\"The staking deadline has passed.\")"],
    "callingFunction": "stake(uint256 amount)"
    "Name": "Unstaking Start",
    "Description": "Limits when unstaking can occur",
    "condition": "timestamp < 1752640000",
    "positiveEffects": [],
    "negativeEffects": ["revert(\"Unstaking is not available yet.\")"],
    "callingFunction": "unstake(uint256 amount)"
Notice that the timestamp value used in the condition is not part of the function signature. This additional variable must be passed via the modifier of the unstake function in the smart contract itself.Refer to the Passing Additional Values to the Rules Engine section of the linked guide for more info.

Encoded Values

When a calling contract invokes the rules engine, it explicitly defines what data to send along with the call. This is the encodedValues field in the rule definition. This can include values from the calling function signature, and/or other values, like in the example above.

Example Rule

    "Name": "Large Transfer",
    "Description": "Alerts when large transfer occurs",
    "condition": "amount > 10000",
    "positiveEffects": ["emit Whale alert"],
    "negativeEffects": [],
    "callingFunction": "transfer(address recipient, uint256 amount)"
For a full explanation of Rule definition syntax, see here.