Skip to content

Feature request: opt-in ship lifecycle hooks (beforeShip/afterShip) for app-side discovery and native ETH — extends PR #39 #134

Description

@deacix

Summary

Feature request: optional, opt-in ship lifecycle hooksbeforeShip / afterShip callbacks on the app — so Aqua apps can react atomically when a strategy is shipped to them. A working implementation with tests already exists in PR #39; this issue frames the broader motivation (app-side discovery) and the design constraints we believe make the extension safe to accept.

Motivation: apps have no on-chain discovery

Aqua deliberately keeps ship/dock as pure bookkeeping: balances are stored in a hash-keyed mapping and the only signal is the Shipped event. That is great for custody and gas, but it means an app cannot know, on-chain, which strategies were shipped to it.

Concrete integration where this bites: we built a Uniswap v4 hook that acts as an Aqua app — v4 swaps are filled from Aqua maker strategies (beforeSwap no-ops the core AMM via return-delta custom accounting, then settles via push/pull; strategies are priced as XYCSwap-style constant-product or XYCConcentrate-style concentrated curves). The hook must know which strategies back a token pair at swap time, so it keeps a small on-chain registry. Today populating that registry requires either:

  • a second transaction from the maker after ship (worse UX, easy to forget — the position exists but earns nothing), or
  • an off-chain keeper watching Shipped(app == hook) and registering permissionlessly (works, but adds infrastructure every Aqua app with this need must duplicate).

An afterShip callback removes both: ship-and-register becomes one atomic transaction. Because afterShip runs after balances are stored, the app can validate the strategy via safeBalances inside the callback. The beforeShip variant (payable) additionally enables native-ETH flows (wrap-to-WETH on ship), as PR #39 demonstrates.

Proposal

Adopt the shape of PR #39, with two amendments to make it strictly additive:

  1. Opt-in flags, zero cost to non-users (as in PR feat: add beforeShip hook for native ETH wrapping #39): HOOK_NONE / HOOK_BEFORE / HOOK_AFTER / HOOK_BOTH; no ERC-165 probing; apps document which flags they support.
  2. Keep the existing 4-param ship as an overload delegating to ship(..., HOOK_NONE) — the current PR replaces the signature, which would break live integrators; an overload keeps the extension backward-compatible on all deployed chains' tooling.
  3. Ship-only, no dock hooks — by design. A dock callback would place app code on the maker's exit path; a reverting app could block withdrawal, violating Aqua's custody promise. ship hooks have no such issue: the maker opts in per call and can always re-ship without flags. (Apps handle docking lazily — a docked strategy simply stops quoting.)

Security posture (already in PR #39): ship gains a transient reentrancy guard, so a hook cannot re-enter ship/dock; view probes like safeBalances still work inside afterShip. The callback target is the app the maker explicitly shipped to — no new trust surface beyond what shipping already grants.

Secondary ask

Please confirm that the Shipped(maker, app, strategyHash, strategy) event — specifically the full strategy bytes in the event payload — is a stable, committed interface. Off-chain indexers and the keeper fallback described above depend on decoding it; a written stability guarantee de-risks every app that builds on it.

References

  • PR feat: add beforeShip hook for native ETH wrapping #39 — working implementation (IShipHook, flags, reentrancy guard, AquaHooks.t.sol test suite); needs a rebase and the overload amendment above.
  • Motivating integration: Uniswap v4 hook proxying v4 swap flow to Aqua maker strategies (constant-product + concentrated curves, multi-maker splitting, quote==execution parity verified on a mainnet fork against the deployed Aqua registry). Happy to share design details, test vectors, or the afterShip consumer implementation on request.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions