Uniswap v4 Hooks와 결제/리스크 실험
도입
Uniswap v4 hooks는 swap route를 단순한 AMM 가격 계산에서 programmable market behavior로 바꾼다. 공식 문서 기준 hooks는 pool에 붙는 외부 smart contract이며, pool lifecycle의 특정 지점에서 실행 흐름을 가로채거나 확장할 수 있다. stablecoin 제품 관점에서는 이것이 기회이자 리스크다. dynamic fee, TWAMM, compliance rule 같은 실험이 가능하지만, route에 들어온 pool의 behavior가 hook logic에 따라 달라진다.
이 레슨에서는 hook을 직접 작성하는 방법보다 결제 route에 hook pool이 들어왔을 때 무엇을 확인해야 하는지 배운다. checkout은 "swap output이 충분한가"만 보지 않고, hook이 어디서 실행되고 어떤 revert/accounting 변화를 만들 수 있는지 확인해야 한다.
학습 목표
- Uniswap v4 hook이 pool behavior를 확장하는 방식을 설명한다.
- 결제, fee, risk control 실험의 안전 경계를 세운다.
개념 설명
핵심 가정 오류
hook pool을 route에 넣기 전 simulation, audit, pool allowlist 근거를 확인한다.
운영 상태 누락
hook revert, fee mismatch, accounting delta를 checkout 상태와 rollback 조건으로 연결한다.
학습 산출물 미흡
Uniswap v4 Hooks와 결제/리스크 실험 이해 점검
hook은 pool-specific extension point다
Uniswap v4는 pool별로 하나의 hook contract를 붙일 수 있고, hook은 initialize, liquidity modification, swap, donate 같은 lifecycle point에 대응하는 함수를 구현할 수 있다. hook permission은 contract address에 인코딩되고, PoolManager는 pool key와 permission을 기준으로 어떤 hook function을 호출할지 판단한다.
| lifecycle | hook point | stablecoin route 영향 |
|---|---|---|
| Pool initialize | beforeInitialize, afterInitialize | pool 생성 조건과 초기 설정 확인 |
| Liquidity add/remove | beforeAddLiquidity, afterAddLiquidity, beforeRemoveLiquidity, afterRemoveLiquidity | liquidity depth와 LP policy 변화 |
| Swap | beforeSwap, afterSwap | fee, allowlist, custom accounting, revert condition |
| Donate | beforeDonate, afterDonate | LP reward나 pool accounting 변화 |
stablecoin 결제에서 왜 관찰해야 하나
merchant가 USDC를 받더라도 실제 route는 USDC, PYUSD, USDS, USDe, L2 asset, fiat rail 사이를 오갈 수 있다. v4 hook pool이 route에 포함되면 price, fee, revert, accounting이 hook logic에 따라 달라진다.
| 활용 가능성 | 설명 | product 질문 |
|---|---|---|
| Dynamic fee | volatility/liquidity에 따라 fee 조정 | depeg 구간에서 fee가 어떻게 변하는가 |
| TWAMM | 큰 주문을 시간 분할 | treasury rebalance와 checkout을 분리했는가 |
| Limit order | pool 안에서 조건부 체결 | partial fill과 expiry를 어떻게 처리하는가 |
| Custom accounting | pool별 정산 logic | ledger가 hook output을 읽을 수 있는가 |
| Compliance hook | swap 조건 제한 | allowlist 실패를 사용자에게 어떻게 설명하는가 |
hook route 상태 흐름
beforeSwap에서 막히는 실패와 afterSwap에서 accounting이 달라지는 실패는 운영 대응이 다르다. 전자는 결제 전 실패로 사용자에게 다른 route를 제시할 수 있지만, 후자는 settlement evidence를 더 꼼꼼히 저장해야 한다.
코드로 확인하기
Uniswap v4 hook은 swap lifecycle에 코드를 꽂는 방식이다. 안정적인 결제 시스템에서는 hook을 "수수료를 마음대로 바꾸는 장치"가 아니라 정책을 사전에 검증하고 이벤트로 남기는 경계로 읽는다.
컨트랙트beforeSwap에서 정책 확인
function beforeSwap( address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata hookData) external returns (bytes4) { if (msg.sender != address(poolManager)) revert OnlyPoolManager(); if (!approvedRouters[sender]) revert RouterNotApproved(sender); if (params.amountSpecified == 0) revert ZeroSwapAmount(); bytes32 paymentId = abi.decode(hookData, (bytes32)); emit CheckoutSwapStarted(paymentId, key.currency0, key.currency1); return this.beforeSwap.selector;}hook은 pool manager가 호출하는 lifecycle 함수다. 따라서 caller 검증과 hookData 검증이 없으면 결제 id와 swap 결과를 연결할 수 없다.
백엔드hook 이벤트와 checkout invoice 연결
type HookEvent = { paymentId: string; inputCurrency: string; outputCurrency: string; txHash: string;};function reconcileHookSwap(event: HookEvent, invoiceCurrency: string) { if (event.outputCurrency !== invoiceCurrency) { return { status: "mismatch", reason: "wrong_output_currency" }; } return { status: "matched", txHash: event.txHash };}capstone에서는 hook 이벤트가 invoice, settlement, risk dashboard로 이어지는지 본다. hook 자체보다 hook이 남긴 증거를 회계 흐름에 연결하는 것이 더 중요하다.
강의 포인트
Hook을 쓰는 route는 allowlist와 simulation이 필요하다. router가 자동으로 hook pool을 선택한다면 app은 hook address, permission, audit 상태, supported wallet/router, fallback route를 확인해야 한다. OpenZeppelin의 hooks library 같은 도구가 등장해도, 문서는 backward compatibility나 guarantee가 제한될 수 있음을 명시한다. 라이브러리 존재는 검토 시작점이지 production 승인 근거가 아니다.
강의에서 강조할 기준은 다음과 같다.
| 기준 | 체크 질문 |
|---|---|
| Hook identity | 어떤 hook contract가 pool에 연결되어 있는가 |
| Permission | 어떤 lifecycle point에서 실행되는가 |
| Route compatibility | 우리 router, wallet, indexer가 해당 route를 처리하는가 |
| Failure handling | revert, custom fee, custom accounting을 상태 머신에 반영했는가 |
| MEV policy | hook이 있어도 sandwich와 adverse execution 방어가 있는가 |
실무 예시
스테이블코인 swap 결제에서 hook route와 non-hook route를 비교한다.
| 항목 | non-hook route | hook route |
|---|---|---|
| 검증 대상 | token pair, fee tier, liquidity, slippage | hook address, permission, audit, route support 추가 |
| 실패 원인 | slippage, liquidity 부족, deadline | hook revert, extra accounting, unsupported router |
| ledger field | amountIn, amountOut, pool, tx signature | hookAddress, hookPermissions, hookResult 추가 |
| fallback | 다른 pool 또는 RFQ | non-hook pool, RFQ, manual review |
| 채택 판단 | liquidity와 price 중심 | behavior 검토가 끝난 hook pool만 allowlist |
이 비교가 없으면 router가 더 좋은 가격을 찾았다는 이유만으로 미검증 hook pool을 선택할 수 있다. compliance-critical route에서는 가격보다 behavior predictability가 우선이다.
흔한 오해와 실패 시나리오
| 오해 | 실패 장면 | 바로잡는 기준 |
|---|---|---|
| hook은 pool의 부가 기능일 뿐이다. | beforeSwap에서 route가 revert되어 checkout이 실패한다. | hook lifecycle point를 상태 머신에 반영한다. |
| 공식 v4 기능이면 모든 router가 안전하게 처리한다. | wallet/router가 hook pool을 표시하거나 simulation하는 방식이 부족하다. | router/wallet compatibility를 별도 체크한다. |
| hook이 MEV 문제를 해결한다. | route는 여전히 public mempool에 노출되고 sandwich risk가 남는다. | slippage, private route, RFQ 정책을 함께 둔다. |
| hook library를 쓰면 audit이 끝난 것이다. | library 조합과 owner-controlled parameter가 product risk를 만든다. | deployed hook address와 permission, owner authority를 검토한다. |
실습 과제
- Uniswap v4 Hooks와 결제/리스크 실험 이해 점검: hook lifecycle과 호출 지점을 표시하고, route가
beforeSwap과afterSwap에서 각각 실패할 때 checkout 상태를 정의한다. - Uniswap v4 Hooks와 결제/리스크 실험 적용 과제: stablecoin swap route에서 hook pool을 허용하는 allowlist 정책을 작성한다. hook address, permission, audit/source, router support, fallback route, ledger field를 포함한다.
완료 기준
- hook 실행 지점과 pool behavior 확장 방식을 설명했다.
- router/wallet/indexer compatibility 위험을 정리했다.
- hook route가 실패할 때 non-hook pool, RFQ, manual review로 전환하는 fallback 설계를 만들었다.
근거 자료
- Uniswap v4 Hooks: 09-기술레이더/Uniswap-v4-Hooks.md
- Uniswap v4 Hooks Documentation: https://docs.uniswap.org/contracts/v4/concepts/hooks
- OpenZeppelin Uniswap Hooks Documentation: https://docs.openzeppelin.com/uniswap-hooks