Mandate execution
Once a proposal isApproved, the pre-committed calls run directly on the vault:
- Anyone calls
executeProposal(proposalId)on the governor; no arguments beyond the id. - The governor checks, in order: the state is
Approved(ProposalNotApproved); no other strategy is live (StrategyAlreadyActive); the owner stake is live (OwnerBondNotLive); the tier and coverage have not regressed since propose (TierRegressed,CoverageRegressed);maxCapitalstill fitstotalAssets() × maxCapitalBps / 10_000(MaxCapitalCeilingRegressed). There is no cooldown check at execute; the cooldown is enforced at propose. - It stamps
executedAt, records the active proposal, starts the management-fee clock on the whole fund’stotalAssets(), and asks the exposure ledger for the coverage guardians actually booked. A partial book scalesmaxCapitaland every per-call cap by the same ratio (EffectiveMaxCapitalSet); an empty book revertsInsufficientApproveCoverage. See Coverage. - The governor calls
vault.executeGovernorBatch(executeCalls, effectiveCallCaps, effectiveMaxCapital), the vault’s governor-only entrypoint. All positions now live on the vault address.
The liquidity lock is a pull-check, not a stored flag.
redemptionsLocked() and depositsLocked() both read governor.openProposalCount() != 0 live on every access. The lock is on from propose (a Draft counts) until the proposal reaches a terminal state, not only while a strategy is executing. Nothing on the vault sets or clears it, so the vault and governor can never disagree about whether a proposal is open.deposit / mint / withdraw / redeem and the owner rescue functions are closed. Depositors use the async queue: requestRedeem / requestDeposit escrow in the withdrawal queue, settlement stamps one realized price for redeems, and anyone claims after unlock.
Batch guards
executeGovernorBatch(calls, callCaps, maxNetOutflow) is the only path by which calldata reaches vault capital. It is onlyGovernor nonReentrant whenNotPaused, and it enforces:
Two clocks
- Execution window (
executionWindow, 24 h at launch): time to start executing after approval. Miss it and the proposal isExpired. - Strategy duration (
strategyDuration, 1 h – 30 d): time the position runs before anyone may settle.
Settlement paths
A live strategy runs for its committed duration, then settles by replaying the pre-committedsettlementCalls. Because the exact onchain state at settlement can’t be predicted (slippage, interest accrual, pool drift), those calls can revert. The protocol provides the standard path plus a bonded, guardian-gated emergency split for stuck strategies.
Every settlement path runs the unwind batch with a net egress budget of zero: vault float may leave inside the batch only if at least as much comes back before it ends, so a settlement can repay a debt the vault fronts but cannot drain the fund.
- Standard settle
- unstick (owner, pre-committed calls)
- emergencySettleWithCalls (guardian-reviewed)
The proposer can settle from 1 hour after execution (
MIN_STRATEGY_DURATION_BEFORE_SELF_SETTLE), the early-close incentive, since the agent has the most context and only earns carry on profit. Once the full strategyDuration has elapsed, anyone can settle (StrategyDurationNotElapsed before then), so a disappearing agent never traps capital. After the batch, two checks guard the result:StrategyNotSettled(strategy)if the strategy clone still reportsexecuted() == true: the unwind did not finish.SettlePriceBelowFloorif price per share fell belowppsAtExecute × (10_000 − min(maxDrawdownBps, 9_000)) / 10_000, the drawdown floor the proposal declared.
unstick needs no new calldata, and any custom calldata is bonded and guardian-gated.
Fees can’t brick settlement. Every fee transfer is wrapped so that a failure (a recipient the token has blacklisted, a paused token) escrows the owed amount against that recipient instead of reverting the settlement (
FeeTransferFailed). The recipient pulls it later with claimUnclaimedFees(vault, token), keyed to the origin vault and to msg.sender; nobody else can push it, and the pull waits while that vault has an active proposal (VaultProposalActive).Cooldown
Every terminal transition — settle, cancel, veto, reject, expire — stampscooldownEndsAt = now + cooldownPeriod (1 h at launch; bounds 1 h – 30 d). The next propose on that vault reverts CooldownNotElapsed until then; executeProposal does not check it. As soon as no proposal is open, instant deposits and redemptions re-open, so the cooldown is the deliberate exit window between strategies: if depositors don’t like what’s next, they get out first.
P&L and the two fees
Only one strategy runs per vault at a time, so P&L is a balance snapshot: the vault’s asset balance at settlement minus the baseline snapshotted at execution. Any non-asset dust the strategy failed to unwind counts as that much loss; strategies must fully return the underlying before settling. Settlement charges exactly two fees, at rates and splits snapshotted at propose. The management fee is charged on every settlement — profit, flat, or loss. The performance fee is charged only above the fund’s previous peak price per share. They are taken in a fixed order:ProtocolConfig: management 60/20/20 across agent, protocol and guardians; performance 50/15/25/10 across agent, protocol, guardians and the fund owner. There is no sequential waterfall of compounding haircuts. The guardian slice routes onchain to a fee-recipient multisig in the fund’s asset, then distributes to individual guardians off-chain, weekly, via Merkl. See Economics for the bounds and the loss-case disclosure.
Full lifecycle in the call arrays
The proposal commits the complete lifecycle upfront: opening calls inexecuteCalls, closing calls in settlementCalls. A Portfolio-strategy proposal against a USDG-denominated fund is two calls each way, because the strategy clone does the swapping:
rescueERC20, which can move them only to a strategy clone of the same vault. Because the unwind is a prediction of future state, agents should leave slippage room; if the standard settle reverts, the owner uses unstick or the guardian-reviewed emergency path.
The onchain track record is the
ProposalSettled(proposalId, vault, pnl, performanceFee, duration) event emitted at settlement, which indexers aggregate into per-agent history. A richer EAS-based attestation is planned but not shipped.