Architecture
Two safes, two delegations — how a treasury enforces an on-chain per-period budget for an agent that swaps.
A swap cannot be bounded "per period" on-chain: the period enforcers only accept a
literal transfer, and revert on a swap (see Strategies).
The way around it is two safes and two delegations: the treasury enforces the
per-period budget with a transfer delegation to a dedicated DCA safe, and the
agent swaps out of that DCA safe under a balance-change delegation. The DCA safe's
balance becomes the real, on-chain per-period cap.
The two-safe model
┌──────────────────┐
│ Treasury safe │ the real funds
└──────────────────┘
│
│ Delegation 1 — periodic transfer (erc20PeriodTransfer)
│ "at most 50 USDC per week → the DCA safe"
│ Enforced on-chain: it's a transfer, so the period cap holds.
▼
┌──────────────────┐
│ DCA safe │ the strategy envelope — holds only the released budget
└──────────────────┘
│
│ Delegation 2 — the strategy mandate (erc20BalanceChange)
│ "swap the DCA safe's balance, ≤ cap and ≤ max price per swap"
│ Enforced on-chain: the balance-change bounds hold on a swap.
▼
┌──────────────────┐
│ Uniswap │
└──────────────────┘Why this unlocks the per-period cap
- Delegation 1 is a transfer, so
erc20PeriodTransferaccepts it and enforces "≤ 50 USDC per week" on-chain. This is exactly what could not be done directly on a swap. - The DCA safe can only ever hold what the treasury released this period. Even if the agent swaps the entire DCA safe balance, it cannot exceed the weekly budget — because the treasury only lets that much through. The temporal cap becomes real.
- Delegation 2 bounds each swap (max spend + max price) via
erc20BalanceChange, as before. The agent still holds nothing; it only redeems.
So the temporal budget (Delegation 1) and the per-swap safety (Delegation 2) are both enforced on-chain, split across the two safes.
Who owns what
- The DCA safe is created by the DAO itself (via the standard Safe interface), with the same owners as the treasury. It is an envelope of the same entity — one per strategy — not a third party. Hourglass does not create it.
- Each safe enables the DeleGator module (the app does this on the safe it runs in), then signs its delegation from there.
What it unlocks
This composes into a real system, not a single feature:
- Multiple strategies — one DCA safe per strategy, each with its own periodic budget and its own bounds. A DAO runs several in parallel without them touching each other.
- Per-strategy agents — a distinct agent assigned to each DCA safe, each with its own enforcers. Compromising one agent bounds the loss to that one DCA safe's budget, never the treasury.
- A clear separation — the treasury is the single source; the DCA safes are bounded envelopes; the agents are replaceable executors.
Critical: sign delegations under the FINAL owner set
A Safe delegation is an EIP-1271 signature that the DelegationManager re-checks at
every redeem against the Safe's current owners and threshold (verified in
Safe.checkNSignatures, which reads threshold from storage and requires each
signer to be a current owner). So changing a Safe's owners or threshold after
signing invalidates every delegation it signed — a delegation signed while 1-of-1
reverts (GS020 / GS026 → InvalidERC1271Signature) once the threshold is raised.
What is and isn't sensitive to an owner change:
| Action | Re-checked at redeem? | Consequence |
|---|---|---|
| Enable the DeleGator module | No — a one-shot on-chain tx (enableModule) | Can be done by a single signer; survives later owner changes |
| Sign a delegation (periodic transfer, strategy mandate) | Yes — EIP-1271 re-run every redeem | Must be signed under the final owner set; a later owner change bricks it |
Rule: put each safe in its final multisig configuration before signing any delegation from it. Installing the module first as 1-of-1 (simple, zero-fund, zero risk) is fine — just reach the final owner set before the delegation signatures.
The operator flow
- Set up the agent — install the Hourglass agent skill; it creates the agent wallet and returns its address.
- Create the DCA safe — the DAO creates a new Safe (same owners as the treasury) for this strategy's budget. Enable the DeleGator module (a 1-of-1 setup is fine here — it survives later owner changes), then bring the DCA safe to its final multisig owner set before signing anything.
- Sign Delegation 2 (from the DCA safe, now at its final owners) — the strategy mandate to the agent (the per-swap bounds).
- Sign Delegation 1 (from the treasury) — the periodic-transfer delegation to the DCA safe (the per-period budget, enforced on-chain).
- Fund the treasury path last — with both delegations signed under their final owner sets, let the periodic budget flow. Test the whole wiring at zero funds first if you like; the budget only moves once Delegation 1 is live.
- Hand the recap to the agent — the strategy context (target, amount, cadence) the agent pairs with the mandates it discovers.
Honest limits
- The DCA safe transiently holds the released budget. This is not fully non-custodial like a single-swap mandate — but the custody sits in a DAO-owned Safe (same owners), bounded per period, never in the agent.
- Per-swap spacing ("once per day") is still off-chain. The period cap bounds the amount released per period, not the number of swaps or their spacing. The cadence remains the agent's responsibility.