You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Feature request: optional, opt-in ship lifecycle hooks — beforeShip / 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:
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.
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.
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.
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.
Summary
Feature request: optional, opt-in ship lifecycle hooks —
beforeShip/afterShipcallbacks 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/dockas pure bookkeeping: balances are stored in a hash-keyed mapping and the only signal is theShippedevent. 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 (
beforeSwapno-ops the core AMM via return-delta custom accounting, then settles viapush/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:ship(worse UX, easy to forget — the position exists but earns nothing), orShipped(app == hook)and registering permissionlessly (works, but adds infrastructure every Aqua app with this need must duplicate).An
afterShipcallback removes both: ship-and-register becomes one atomic transaction. BecauseafterShipruns after balances are stored, the app can validate the strategy viasafeBalancesinside the callback. ThebeforeShipvariant (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:
HOOK_NONE / HOOK_BEFORE / HOOK_AFTER / HOOK_BOTH; no ERC-165 probing; apps document which flags they support.shipas an overload delegating toship(..., 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.dockhooks — 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.shiphooks 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):
shipgains a transient reentrancy guard, so a hook cannot re-entership/dock; view probes likesafeBalancesstill work insideafterShip. 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
IShipHook, flags, reentrancy guard,AquaHooks.t.soltest suite); needs a rebase and the overload amendment above.afterShipconsumer implementation on request.