Skip to main content
In Railnet Advanced Strategies, the policy engine is a Zodiac Roles Modifier v2 contract enabled as a module on the Strategy. Every rule is transparent, auditable, and verifiable on-chain.
The policy engine is the on-chain governance layer that defines what an operator can and cannot do. There are no off-chain co-signers, no black-box policy services. Every constraint is visible on-chain and verifiable by depositors, platforms, and auditors. Traditional wallet infrastructure relies on web2 co-signer services for policy enforcement. These systems are not publicly auditable, not verifiable on-chain, and not standardized. The policy engine replaces that trust assumption with deterministic, on-chain rule enforcement.

How it works

An operator (the “member signer”) never calls the Strategy directly. Every transaction routes through the policy engine, which checks the operator’s role and validates every parameter before forwarding the call. The operator builds their protocol calldata as usual (e.g., an Aave supply call), wraps it in a single execTransactionWithRole call, and sends it to the policy engine address with the associated role key. The policy engine validates the call against the operator’s role permissions. If all checks pass, the policy engine forwards the call through the Strategy, which executes it on the target protocol. From the protocol’s perspective, msg.sender == STRATEGY_ADDRESS. The target contract sees no difference between a call from the policy engine and a direct call from the Safe. The operator’s signer address is never visible to the target protocol.
The operator’s existing execution pipeline stays unchanged. The integration is one extra ABI-encoding step and a change to the to address. See Operate an Advanced Strategy for the full integration guide.

Permission layers

The policy engine enforces four layers of constraints, each narrowing what an operator can do. Every layer is configured on-chain and readable by anyone.

Contract whitelists

The first layer controls which contracts the operator can interact with. Only explicitly whitelisted target addresses are allowed — any call to a non-whitelisted contract reverts. For example, an operator managing a lending strategy might have three whitelisted targets: the Aave V3 Pool, the USDC token contract (for approvals), and the Morpho Blue contract. Any attempt to call a contract outside this set fails at the policy engine before reaching the Strategy.

Function-level permissions

The second layer controls which functions on whitelisted contracts the operator can call. Each function is identified by its 4-byte selector. Functions are categorized by risk level, which determines their default state:
Risk levelDefault stateExamples
LowEnabledwithdraw, repay, claimWithdrawals
MediumEnabled (with spending limits)supply, borrow, swap
HighDisabledliquidate, absorb, admin functions
Low-risk functions like withdraw and repay are enabled by default because they move funds back to the Strategy. Medium-risk functions like supply and borrow are enabled but prompt for spending limits. High-risk functions like liquidate and admin functions are disabled by default and require explicit opt-in.
Disabling a function at the policy engine level means the operator cannot call it at all, regardless of other permissions. The function selector is simply not in the allowed set.

Calldata-level checks

The third layer inspects the actual parameter values in each function call. The policy engine defines condition trees using these operators:
OperatorWhat it checksExample use
EqualToParameter must match an exact valueRestrict to specific tokens or pool IDs
EqualToAvatarParameter must equal the Strategy addressLock recipients so funds cannot leave the Strategy
GreaterThanParameter must exceed a thresholdEnforce minimum slippage protection (amountOutMinimum > 0)
LessThanParameter must be below a thresholdCap individual transaction sizes
WithinAllowanceParameter must fit within a spending budgetRate-limit operations with periodic refills
These operators combine to express precise constraints on every parameter. Three examples:
The most critical constraint. Any parameter named to, recipient, receiver, onBehalfOf, or owner is constrained to EqualToAvatar — meaning it must equal the Strategy’s own address. This prevents the operator from sending funds to any external address.This constraint is non-overridable. It applies automatically to every function that has a recipient-like parameter, and the operator cannot remove it.
supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)
                                             ^
                                      must == Strategy address
The asset or tokenIn parameter is constrained to a specific set of approved tokens using EqualTo. The operator can only interact with tokens explicitly listed in the policy — for example, USDC and WETH but not any arbitrary ERC-20.
exactInputSingle(ExactInputSingleParams)
    tokenIn: EqualTo(USDC) OR EqualTo(WETH)    // only approved tokens
    recipient: EqualToAvatar                     // locked to Strategy
Parameters like amountOutMinimum are constrained with GreaterThan(0) to prevent zero-slippage swaps that could be exploited by MEV bots. The operator can set a higher minimum, but cannot set it to zero.

Non-overridable constraints

Three calldata constraints are safety-critical and cannot be removed by anyone, including the guardian:
  1. Recipient = Strategy address — prevents funds from being sent to external addresses
  2. Approve spender = known protocol contract — prevents arbitrary token approvals
  3. delegatecall = false — always disabled on all permissions, preventing code injection

Spending limits and allowances

The fourth layer rate-limits how much capital the operator can deploy within a time period. Spending limits use the WithinAllowance operator with a periodic refill mechanism. Each allowance is defined by:
  • Refill amount — how much budget is restored each period (e.g., 100,000 USDC)
  • Period — how often the budget refills (daily, weekly, or monthly)
  • Max accrual — the maximum budget that can accumulate (prevents rollover)
When the operator executes a transaction, the amount parameter is deducted from the allowance balance. If the balance is insufficient, the transaction reverts. The balance refills automatically at the start of each period.
Spending limits apply to inbound operations only — supply, deposit, borrow, and swap inputs. Exit operations like withdraw, repay, and claim are unconstrained because they move funds back to the Strategy.
Allowances can be scoped per function, per protocol, or shared across multiple functions:
ScopeAllowance key exampleEffect
Per-protocolaave_v3_dailyCaps all Aave V3 operations combined
Per-routeeth_arb_usdc_dailyCaps a specific bridge route
Global outboundeth_outbound_usdc_dailyCaps all outbound operations from one chain
When multiple allowances apply (e.g., a per-route cap and a global cap), both are deducted on each transaction. If either is exhausted, the transaction reverts.

Cross-chain policies

Advanced Strategies can operate across multiple EVM chains using the same Safe address, deployed deterministically via CREATE2. Each chain has its own Roles Modifier instance with its own set of permissions.
            Same Safe address (0xSafe...) on all chains
            ============================================

  Ethereum          Arbitrum          Base           Optimism
  Safe + Roles      Safe + Roles      Safe + Roles   Safe + Roles

How cross-chain scoping works

The Roles Modifier on each chain controls outbound operations only — bridge calls, token transfers, and cross-chain messages originating from that chain’s Safe. Inbound bridged funds are permissionless. Anyone can send tokens to the Safe address, and the funds arrive without any Roles configuration. For bridge operations, the policy engine enforces:
  • Bridge contract whitelist — only approved bridge contracts (e.g., Across SpokePool) can be called
  • Recipient locked to Strategy address — the recipient parameter in bridge calls must equal the Safe address, which is the same on all chains due to deterministic deployment
  • Approved destination chains — the operator can only bridge to explicitly allowed chain IDs
  • Per-route spending caps — each source-destination pair has its own daily allowance (e.g., eth_arb_usdc_daily)
Because the Safe has the same address on all chains, locking the bridge recipient to EqualToAvatar guarantees funds arrive at the organization’s own Safe on the destination chain. Even if an operator key is compromised, bridged funds cannot leave the organization’s wallets.

Per-chain, per-route spending caps

Each bridge route has an independent allowance. An operator bridging from Ethereum can have separate daily caps for Ethereum-to-Arbitrum, Ethereum-to-Base, and Ethereum-to-Optimism routes. For stricter control, routes from the same source chain can share a single allowance key. This enforces a global outbound cap — the total bridged across all destinations from one chain cannot exceed the shared limit.

Comparing guardrail models

Railnet offers two guardrail architectures. Allocation Strategies use the External Access Control (EAC) system built into Railnet’s smart contracts. Advanced Strategies use the Zodiac Roles Modifier as an external policy engine.
AspectAdvanced StrategyAllocation Strategy
EngineZodiac Roles Modifier v2External Access Control (EAC)
ScopeAny contract call on any chainRailnet operational roles
GranularityCalldata-level parameter checksRole-based access control
Spending limitsPer-function allowances with period refillAllocation queue targets
GovernanceGuardian timelockAdmin role retention
VisibilityAll rules on-chain, verifiableAll roles on-chain, verifiable
Both models enforce constraints on-chain with no off-chain trust assumptions. The choice depends on what the strategy needs to do: Allocation Strategies work within Railnet’s standard yield source framework, while Advanced Strategies interact with arbitrary contracts across any EVM chain.

Operate an Advanced Strategy

Integration guide for routing transactions through the policy engine.

Advanced Strategies overview

What Advanced Strategies are, why they exist, and how they connect to Railnet.

Allocation Strategy guardrails

Role-based access control for standard Allocation Strategies.

Risk management

Portfolio-level risk parameters, circuit breakers, and monitoring.