Rebalance engine
The rebalance engine sits on top of the priceless-synth contracts. Where the position manager, optimistic oracle, and liquidation keep a single synth solvent against one reference, the rebalance engine adjusts the collateral mix of an event-triggered synth when its referenced event resolves.
Event reference
Each synth commits an optimistic-oracle price identifier and ancillary data that encodes the event question and its resolution source. The pair is set once at registration and is immutable.
bytes32 priceIdentifier; // e.g. "TRANT_EVENT_V1" bytes ancillaryData; // "q:Will the FOMC cut at the Sep 2026 meeting?,src:federalreserve.gov"
A keeper's initiateRebalance call turns this into a live price request. A proposer answers it, a liveness window opens, and a disputer can escalate. The engine only ever reads a settled value.
Bounded, pre-committed weight formula
Registration also commits the entire rebalancing policy:
- Asset bands: the basket, each asset with a hard
[floorWeight, ceilWeight]on its post-rebalance share. - Outcome schedule: a step function from resolved value to target mix. Steps are sorted ascending by threshold; the engine picks the highest step whose threshold is at or below the resolved value.
- Max weight delta: the most any single weight may move in one rebalance.
On execution the engine clamps the committed target into each asset's window and renormalises so the basket sums to one:
max(floor_i, w_i − Δ) ≤ applied_i ≤ min(ceil_i, w_i + Δ)
Σ applied_i = 1e18
The applied mix is bounded regardless of what the schedule says and regardless of how far the basket has drifted. If the bands genuinely can't host a basket that sums to one this round, the call reverts and the keeper retries after the interval.
Rebalance lifecycle
One rebalance can be in flight per synth at a time. Only completed rebalances are rate-limited by the minimum interval; a cancelled one can be retried immediately. Every state-changing entrypoint is non-reentrant.
| Call | Caller | Effect |
|---|---|---|
| registerSynth | Governor | Once per synth. Commits the event reference, asset bands, outcome schedule, bond and interval parameters. Immutable after. |
| fundRewards | Anyone | Tops up the synth's keeper-reward pool in the bond currency. |
| initiateRebalance | Keeper | Pulls the oracle reward, final fee, and rebalance bond; opens a price request for the event; the engine holds the bond. |
| executeRebalance | Anyone | Settles the oracle value, selects the step, clamps against the bands and max delta, pushes the bounded target to the vault, returns the bond, and pays the keeper reward. |
| cancelRebalance | Anyone | After the resolve window with no settlement: unwinds the pending state and refunds the held bond. |
Keeper incentive
Triggering a rebalance costs capital up front and returns it once the oracle validates the outcome, the same shape as an EMP liquidation bond.
| Flow | On initiate | On execute | On cancel |
|---|---|---|---|
| Oracle reward + final fee | keeper → oracle | , | , (not reclaimed in the scaffold) |
| Rebalance bond | keeper → engine | engine → keeper | engine → keeper |
| Keeper reward | , | pool → keeper | , |
Net keeper result on a completed rebalance = keeper reward − oracle reward − final fee − gas. The reward has to be set above the oracle cost or keepers won't call; executeRebalance reverts if the pool can't cover it.
Guards
- One pending rebalance per synth; a minimum interval between completed rebalances.
executeRebalancereverts through the oracle until the request is finalised.- The basket vault reverts if post-rebalance weights miss the target by more than its drift tolerance, the backstop against a bad executor fill.
- Registration rejects bands that can't host a basket summing to one, non-ascending schedule thresholds, and step weights outside their bands.
- Event reference, bands, and schedule are set once and never mutable.
The engine is a Solidity scaffold (Foundry, solc 0.8.19) with an end-to-end test suite. It has not been audited or deployed. Token-decimal normalisation, oracle-reward reclaim on cancel, a production swap executor, and an emergency pause are still open.