Skip to main content
This is the shortest path from “zero” to “a live, validated strategy POSTed to the Strategy Engine.” Follow it top to bottom and you end up with two curl-ready payloads — a deposit half and a withdrawal half — that form a closed-loop reserve manager for one yield source.

What we’re building

A drift-trigger rebalance pair. The strategy contract holds an idle reserve (vault_free_assets = on-chain balanceOf(strategy)). When that reserve drifts above 10% of vault TVL there is excess idle to deploy, so a DEPOSIT strategy fires and pushes it into a single yield source (“Yield Source A”). When the reserve drifts below 5% of TVL the vault is liquidity-thin, so a WITHDRAWAL strategy fires and pulls assets back from Yield Source A to refill the buffer toward a 7.5% target. Two strategies, one yield source, one EXPR rule each, no indicators.

Step 1 — Understand the lanes

Strategy actions group into three priority lanes. Which lane your action lives in determines which UI column it shows up in and how ordering works. Full lane reference: Strategy Canvas.

Step 2 — Pick the action

Each strategy has exactly one action_config.action. Pick DEPOSIT for the inflow strategy and WITHDRAWAL for the outflow strategy. The other required action_config fields tell the OMS how to execute:
  • execution_name — the hook identifier from the Erebor hook registry (ApproveAndDeposit4626VaultHook and ApproveAndWithdraw4626VaultHook for ERC-4626 sources).
  • execution_address — the deployed hook contract on the target chain.
  • target_address — the yield source you’re moving assets into or out of.
  • from_address — the account that executes the intent.
  • target_type — the yield source family (erc4626 here).
  • objectiveMIN_SLIPPAGE, MIN_TIME, or BALANCED.
Field-by-field reference: see the strategy schema.

Step 3 — Write the trigger

The trigger is a rules tree. The simplest form is a single EXPR leaf that returns a boolean.
vault_free_assets is sourced live from chain as IERC20(asset).balanceOf(strategy) through the EVM RPC datafeed, so the trigger reflects the strategy contract’s actual idle balance. vault_tvl is derived from yield-source allocations on the subgraph cadence. Both are in the underlying asset’s base units.
Avoid division in trigger expressions. The validator dry-runs every expression against an empty EvalSnapshot (all zeros) to catch type errors. vault_free_assets / vault_tvl > 0.10 would fail with division by zero at POST /strategies time, even though it’s semantically equivalent. Use the multiplicative form vault_free_assets > 0.10 * vault_tvl instead.
The full EvalSnapshot variable list (vault_*, ys_<addr>_*, merkl_*, tick_*, indicator aliases) lives in the strategy schema reference.

Step 4 — Size the action

action_config.size_expr is a separate expression evaluated when the rule fires. It must return a positive number at runtime — that’s the amount, in base units, sent to the OMS. For the deposit half we deploy everything idle:
For the withdrawal half we pull back the shortfall to the 7.5% target:
Both are positive whenever their trigger fires. A size_expr that evaluates to ≤ 0 at runtime is dropped before reaching the OMS. Indicators (SMA, RSI, MACD, etc.) and conviction tuning (graded confidence, dead bands) are out of scope here — they live in the Cookbook and Conviction pages.

Step 5 — Full strategy JSON

These two payloads are the literal contents of superman-strategy/testdata/cookbook/drift_rebalance_{deposit,withdraw}.json and are asserted by CI to pass the engine’s StrategyValidator on every push. Replace 0x000…0001 with the real yield source address, the 8453:0xdef… vault id with yours, and from_address / execution_address with the values from your environment.

Deposit half

Withdrawal half

Step 6 — POST it

Each strategy is one POST /api/v1/strategies call. Save the deposit payload to deposit.json, then:
Repeat with withdraw.json. A 200 returns the persisted strategy with state: "CREATED". To start ticking, transition each one:
Full endpoint reference: Strategy Engine API.

What to watch

Once both strategies are RUNNING, the Dashboard and Intent History views surface what’s happening:
  • Strategy Canvas — both strategies should show in their respective lanes in RUNNING state with priority assigned.
  • Dashboardvault_free_assets / vault_tvl should oscillate between roughly 5% and 10%, settling near 7.5% after the first few rebalances.
  • Intent History — every fired rule produces an intent. Look for DEPOSIT intents when reserve was high and WITHDRAWAL intents when it was low. Inspect events and fills per intent to confirm OMS execution succeeded.
  • Emergency locks — if a paired emergency exit is armed on Yield Source A, the deposit half is blocked from publishing new intents while the lock holds. The withdrawal half remains operable.

Common rejections

The validator runs at POST and PUT time only. Most first-time rejections fall into a handful of buckets — unknown identifier, division-by-zero in a dry-run, missing objective, non-hex address. The full list with example error strings is on the Troubleshooting page.