HourGlass
Agent DeFi

Provide liquidity

Three single-use delegations that let an agent open one Uniswap v3 position — and an optional mandate that compounds its fees.

Provide liquidity puts idle treasury into a Uniswap v3 pool. The Safe picks the pool and the amounts, signs, and an agent opens the position on the Safe's behalf. The position is minted to the Safe — the agent never owns it.

The deposit plan

Opening a v3 position is three calls: approve each token to the position manager, then mint. HourGlass signs one single-use delegation per call, in that order:

#CallTarget
1approve(address,uint256)token0
2approve(address,uint256)token1
3mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256))Uniswap v3 NonfungiblePositionManager

So the operator signs three times — or four with auto-compound enabled, which adds its mandate to the same run. Each signature is a separate Safe action; the app paces them on your click rather than firing the next one automatically, which would race the Safe confirmation screen.

What bounds each delegation

Every call is known in full at signing time — the pool, the tick range, the exact amounts — so this rail pins the calldata byte for byte rather than bounding an intent. Each of the three delegations carries:

CaveatWhat it fixes
functionCall scopethe exact target contract and the single method selector
exactExecutionthe exact target, value, and calldata — no argument can be changed
limitedCalls(1)the call can be redeemed once
redeemeronly the named agent wallet may redeem it
timestampvalid from signing for one hour, then it expires

The salt is keccak256(callData), binding each signature to its exact action — the same salt = keccak256(terms) convention used everywhere in HourGlass.

The consequence is that the agent has no discretion at all on this rail: not over the target, the method, the arguments, or the amounts. Its only choice is whether and when to submit, within the hour. That is what makes it safe to run unattended.

The one-hour deadline is deliberate: a signed delegation grants a real permission, so the window it stays redeemable is kept short rather than open-ended. If it expires before the agent runs, nothing is lost — re-sign the plan.

Auto-compound (optional)

A position earns fees that sit uncollected. The optional compound mandate is a standing, repeatable delegation that lets the agent harvest those fees and reinvest them into the same position.

Its scope is the Uniswap v3 position manager, restricted to two methods:

  • collect(...) — harvest the accrued fees;
  • increaseLiquidity(...) — add them back to the position.

decreaseLiquidity and burn are not in scope, so the agent cannot withdraw the principal. It can only compound.

Unlike the deposit plan, a compound's amounts are unknown until run time, so this mandate bounds the call surface rather than pinning the bytes — the same means-versus-intent split the limit order uses.

It carries a redeemer caveat locking it to the agent, and — unlike the three deposit delegations — no timestamp caveat. It is a standing authority with no expiry, live until you revoke it.

Two modes:

  • Agent — a gas-aware gate decides when compounding is worth the transaction cost.
  • Manual — a fixed interval in days, carried in the salt-verifiable terms so the agent needs no out-of-band configuration.

Setup it requires

One-time, from the Safe: a standing ERC-20 approval to the position manager for both tokens, so increaseLiquidity can pull the collected fees.

Honest limits

These are real and worth understanding before signing a compound mandate:

  • The position is not pinned. The tokenId does not exist at signing time — the agent mints it afterwards — so the mandate applies to any position the Safe holds in that position manager. Pinning it to one position would need a second signature after the mint.
  • increaseLiquidity amounts are not capped. The agent could add more of the Safe's token balance to the position than just the harvested fees. That is over-allocation into the Safe's own LP position, not theft — the funds stay in a position the Safe owns — but it is not bounded today.
  • collect's recipient is not pinned. Constraining it via calldata bounds would also constrain increaseLiquidity's bytes at the same offset.

The compound mandate is a broader authority than the deposit plan. Sign it only if you accept that it applies to every position the Safe holds in that position manager, and revoke it when the strategy ends.

Chains

Base (8453) and Base Sepolia (84532), where the Uniswap v3 position manager is wired. The APY estimate shown in the app comes from the Uniswap v3 subgraph, which exists for Base only — on Base Sepolia the estimate is simply absent rather than guessed.

Following and stopping a plan

A signed plan appears on Overview — under Agentic DeFi strategies, kept separate from Operations (subscriptions, streams, orders) — and on the Provide liquidity tab, as one card that folds open to show its three delegations and the state of each.

Revoking is per step: disabling a delegation (disableDelegation) makes that step's redeem revert.

A plan is three delegations, so revoking one is not revoking the plan. If you stop a plan after the approvals have been redeemed but before the mint, the remaining step is still live and the agent can still spend it. Revoke every unconsumed step. Revoking a step that was already consumed is harmless — a disableDelegation on a spent delegation is a no-op.

An abandoned plan can also be cleared, which only hides it locally. Clearing is not revoking: the mandate stays signed and redeemable until the deadline passes or you disable it.

The delegations expire on their own an hour after signing, so an untouched plan stops being redeemable by itself.

Revoking the compound mandate stops the harvesting. It has no deadline — it is a standing authority, so it stays live until you disable it. The position itself stays in the Safe, which owns it outright and can manage it directly through Uniswap at any time.

On this page