SettleLab
전체 코스
DeFi · LESSON 06

Uniswap v4 Hooks, Flash Accounting, MEV

DeFiDeFi risk surface심화1시간근거 3
AreaDeFi
TopicDeFi risk surface
Evidence layerCONTRACT / OPS
Connected areasStablecoin

학습 결과

  • hook이 pool lifecycle을 확장하는 지점과 위험을 설명한다.
  • flash accounting을 "공짜 자금"이 아니라 transaction-level net settlement로 이해한다.
  • MEV, JIT liquidity, dynamic fee hook을 release gate로 검토한다.

선행 조건

  • concentrated-liquidity-ticks
  • liquidation-oracle-engine

완료 기준

  • beforeSwap, afterSwap, liquidity hook 중 최소 3개 지점의 위험을 설명했다.
  • hook allowlist, fee bounds, invariant check를 포함한 release gate를 작성했다.

Uniswap v4 Hooks, Flash Accounting, MEV

도입

Uniswap v4 hook은 AMM을 더 유연하게 만든다. pool lifecycle의 특정 지점에 외부 contract가 붙어 dynamic fee, custom accounting, liquidity rule, oracle update 같은 동작을 넣을 수 있다. 하지만 확장성이 커진 만큼 audit surface도 커진다.

hook을 "새 기능을 붙이는 플러그인"으로만 보면 위험하다. hook은 swap 전후, liquidity 변경 전후 같은 민감한 지점에서 실행된다. 잘못된 hook은 가격 계산, fee, reserve accounting, 사용자 minOut을 흔들 수 있다. flash accounting도 같은 transaction 안의 net settlement를 전제로 하므로 invariant가 끝에서 맞아야 한다.

학습 목표

  • hook이 pool lifecycle을 확장하는 지점과 위험을 설명한다.
  • flash accounting을 "공짜 자금"이 아니라 transaction-level net settlement로 이해한다.
  • MEV, JIT liquidity, dynamic fee hook을 release gate로 검토한다.

개념 설명

위험 매트릭스가로 스크롤 · 크게 보기 지원
v4 hook 출시 위험 매트릭스hook이 실행되는 lifecycle 지점마다 가격, fee, accounting, routing 위험을 분리해 release gate로 바꾼다.
Impact highLikelihood medium

beforeSwap price guard

완화 장치를 정의한다.

Impact criticalLikelihood medium

afterSwap accounting drift

완화 장치를 정의한다.

Impact mediumLikelihood medium

JIT liquidity capture

완화 장치를 정의한다.

Impact mediumLikelihood high

routing exclusion

완화 장치를 정의한다.

크게 보기
Impact highLikelihood medium

beforeSwap price guard

완화 장치를 정의한다.

Impact criticalLikelihood medium

afterSwap accounting drift

완화 장치를 정의한다.

Impact mediumLikelihood medium

JIT liquidity capture

완화 장치를 정의한다.

Impact mediumLikelihood high

routing exclusion

완화 장치를 정의한다.

표 자료가로 스크롤 · 크게 보기 지원
Hook 지점가능한 기능주요 위험검증 증거
beforeSwapdynamic fee, allowlistquote 변경과 minOut 훼손fee bounds
afterSwaprebate, custom accountingbalance driftnet settlement invariant
beforeAddLiquidityKYC, vault ruleLP censorshippolicy event
afterRemoveLiquidityfee accountingwithdrawal mismatchposition diff
크게 보기
Hook 지점가능한 기능주요 위험검증 증거
beforeSwapdynamic fee, allowlistquote 변경과 minOut 훼손fee bounds
afterSwaprebate, custom accountingbalance driftnet settlement invariant
beforeAddLiquidityKYC, vault ruleLP censorshippolicy event
afterRemoveLiquidityfee accountingwithdrawal mismatchposition diff

코드로 확인하기

CODE SURFACEtypescript
export function boundedDynamicFee({  volatilityBps,  depthUsd,  baseFeeBps}: {  volatilityBps: number;  depthUsd: number;  baseFeeBps: number;}) {  const volatilityPremium = Math.min(50, Math.floor(volatilityBps / 20));  const depthPenalty = depthUsd < 1_000_000 ? 30 : depthUsd < 5_000_000 ? 10 : 0;  return Math.min(100, Math.max(baseFeeBps, baseFeeBps + volatilityPremium + depthPenalty));}
CODE SURFACEsolidity
// SPDX-License-Identifier: MITpragma solidity ^0.8.24;contract HookReleaseGate {    uint16 public constant MAX_FEE_BPS = 100;    mapping(address => bool) public approvedHook;    function assertHook(address hook, uint16 feeBps) external view {        require(approvedHook[hook], "hook not approved");        require(feeBps <= MAX_FEE_BPS, "fee too high");    }}

두 예시는 hook 자체 구현이 아니라 release guard다. 교육의 핵심은 "hook을 만들 수 있다"보다 "어떤 hook을 pool에 붙여도 되는가"다. dynamic fee는 volatility와 depth를 반영할 수 있지만, 상한과 event logging이 없으면 사용자 quote를 예측하기 어렵게 만든다.

강의 포인트

표 자료가로 스크롤 · 크게 보기 지원
관점확인할 질문증거로 남길 것
Lifecyclehook은 어느 지점에서 실행되는가before/after 함수 목록
Permission어떤 pool에 붙을 수 있는가hook allowlist
Accountingtransaction 끝의 net balance가 맞는가invariant test
Routing사용자가 실제로 접근 가능한가frontend route support
크게 보기
관점확인할 질문증거로 남길 것
Lifecyclehook은 어느 지점에서 실행되는가before/after 함수 목록
Permission어떤 pool에 붙을 수 있는가hook allowlist
Accountingtransaction 끝의 net balance가 맞는가invariant test
Routing사용자가 실제로 접근 가능한가frontend route support

실무 예시

컨트랙트[OPS] 어떤 팀이 volatility가 높을 때 fee를 올리는 hook pool을 출시하려 한다. 제품 문구는 "LP 보호"라고 말하지만, 사용자는 swap 직전에 fee가 바뀌는 경험을 할 수 있다. 따라서 quote에는 current fee, max fee, fee update reason이 보여야 한다. backend는 hook address allowlist와 fee bounds를 관리해야 한다.

MEV 측면에서는 JIT liquidity도 봐야 한다. 특정 bot이 큰 swap 직전에 liquidity를 넣고 직후 제거하면 일반 LP의 fee capture가 낮아질 수 있다. hook이 이를 막을 수도 있지만, 잘못된 hook은 더 큰 privilege surface가 된다.

흔한 오해와 실패 시나리오

표 자료가로 스크롤 · 크게 보기 지원
오해실패 시나리오교정 방식
hook은 앱 플러그인이다swap accounting을 직접 흔든다lifecycle별 invariant를 둔다
dynamic fee는 항상 LP에게 좋다사용자의 quote 예측 가능성을 낮춘다max fee와 사유를 노출한다
flash accounting은 flash loan이다transaction 끝 net settlement가 핵심인데 중간 balance를 오해한다final balance invariant를 테스트한다
hook pool은 자동으로 route된다frontend나 aggregator가 배제할 수 있다route support를 출시 조건에 넣는다
크게 보기
오해실패 시나리오교정 방식
hook은 앱 플러그인이다swap accounting을 직접 흔든다lifecycle별 invariant를 둔다
dynamic fee는 항상 LP에게 좋다사용자의 quote 예측 가능성을 낮춘다max fee와 사유를 노출한다
flash accounting은 flash loan이다transaction 끝 net settlement가 핵심인데 중간 balance를 오해한다final balance invariant를 테스트한다
hook pool은 자동으로 route된다frontend나 aggregator가 배제할 수 있다route support를 출시 조건에 넣는다

실습 과제

  1. Hook 위험 매트릭스 만들기: beforeSwap, afterSwap, addLiquidity, removeLiquidity hook별 권한과 실패 상태를 표로 작성한다.
  2. Dynamic fee guard 작성하기: volatilityBps와 poolDepthUsd를 받아 허용 가능한 feeBps를 제한하는 함수를 작성한다.

완료 기준

  1. beforeSwap, afterSwap, liquidity hook 중 최소 3개 지점의 위험을 설명했다.
  2. hook allowlist, fee bounds, invariant check를 포함한 release gate를 작성했다.

근거 자료

  • 03 DEX and AMM
  • Uniswap v4 Hooks
  • Uniswap v4 Flash Accounting
Final checkpoint

읽기를 마쳤다면 여기서 기록한다

아래 버튼은 읽기 진도를 저장한다. 체크리스트, 과제, 랩 산출물은 위 Workbook에서 따로 관리한다.

  • beforeSwap, afterSwap, liquidity hook 중 최소 3개 지점의 위험을 설명했다.
  • hook allowlist, fee bounds, invariant check를 포함한 release gate를 작성했다.

학습 자료 근거

03 DEX and AMM
v4 hooks, MEV, JIT liquidity 설명 재구성
내부 참고 문서
Uniswap v4 Hooks
https://developers.uniswap.org/docs/protocols/v4/concepts/hooks
Uniswap v4 Flash Accounting
https://developers.uniswap.org/docs/protocols/v4/concepts/flash-accounting