Singleton Design

김현학·2024년 9월 23일
0

Uniswap v4 Hook

목록 보기
3/6
post-thumbnail

Singleton Design은 v4에서 가장 핵심이 되는 개념이다. 기존 v3 프로토콜은 파편화된 컨트랙트 간의 상호작용으로 많은 양의 가스가 연산에 소요되었다면, v4는 구조의 개선을 통해 이를 멋지게 개선했다. 아직 개발 단계이지만, 새로운 Pool 배포에 소요되는 가스비는 약 99% 절감되는 것으로 밝혀졌다.

1. Singleton의 개념

  • 디자인 패턴에서 Singleton은 어떤 객체의 인스턴스가 유일하도록 관리하는 방법이다.
  • Uniswap v3가 다양한 컨트랙트 간의 상호 작용(external function call; 이하 extcall)을 기반으로 동작했다면, v4는 hook, router 등의 peripheral contract 이외의 모든 상호작용을 poolManager 내부에서 처리한다.
    • 컨트랙트 크기 제한이 있음에도 이러한 구현이 가능한 이유는 library의 사용 덕분이다. 라이브러리는 배포된 외부 코드를 컨트랙트 내부에서 참조하여 사용할 수 있는 기능이다.

2. 이는 이전 버전의 어떤 결핍을 해소하는가?

v3는 UniswapV3Factory를 기반으로 각각의 pool이 하나의 컨트랙트로 구현되었다.

  • 새로운 pool의 생성은 컨트랙트 배포를 포함하고, 따라서 매우 비싼 연산이 되었다.
  • 이에 따라 다양한 pool 간의 교환을 의미하는 multi-hop swap도 많은 extcall을 필요로 하게 되므로, 자연스럽게 비싼 연산이 된다.

    상호작용하려는 각각의 모든 컨트랙트에 대해 CALL을 통한 컨택스트 변경과, 많은 변수에 대한 SLOAD, 최종적으로 상호작용 결과를 SSTORE로 모두 갱신한다. 연산을 위해서는 많은 양의 가스가 필요할 수 밖에 없다.

3. 이는 이전 버전의 결핍을 어떻게 해소하는가?

  • 높은 가스비를 야기한 v3의 구조는, 각각의 pool이 독립적인 컨트랙트로서 각자의 스토리지에 상태를 관리하는 순간 예정된 수순이었다. 문제의 핵심은 다음과 같다.

    1. 잦은 외부 함수 호출 (CALL)
    2. 잦은 스토리지 읽기 (SLOAD)
    3. 잦은 스토리지 쓰기 (SSTORE)
  • PoolManager가 모든 로직의 수행을 내부적으로 처리한다.

  • PoolManager는 내부에 mapping으로 모든 pool의 상태를 관리한다.


    사진을 클릭하여 GitHub Permalink로 이동하면, 직접 구현 코드를 살펴볼 수 있다.

3-1. Singleton으로 외부 호출 감소했지만, 여전히 스토리지 참조하지 않나?

  • 정확하다. 하지만 Cancun 업데이트에 도입된 transient storage를 사용하기에 더 효율적이다. 해당 스토리지 값은 현재 트랜잭션에서만 유효하고, 항상 종료 시에 0으로 초기화한다.
  • 이를 통해 구현한 Flash Accounting을 활용하면, 풀 생성에 소요되는 가스비는 99% 감소시킬 수 있다.

Flash Accounting은 별도의 🚧작성 예정에서 다룬다.

0개의 댓글