ERC-8167 모듈형 디스패치 프록시 (Modular Dispatch Proxies)
Final · 기타 · 2026-02-16 작성
함수 호출을 앞 4바이트 선택자(selector)에 따라 서로 다른 로직 모듈로 나눠 보내는 프록시 컨트랙트의 표준입니다. 도구가 이런 프록시의 함수 목록과 각 함수의 구현 주소를 조회할 수 있게 합니다.
왜 필요한가
이더리움에서 널리 쓰이는 프록시(proxy) 컨트랙트는 보통 모든 호출을 구현 컨트랙트 하나로 넘깁니다. 이런 단일 구조는 컨트랙트 코드 크기 제한에 부딪히기 쉽고 업그레이드할 때 구현 전체를 한 번에 갈아끼워야 해서 관련 없는 기능까지 깨뜨릴 위험이 있으며 테스트와 검증도 어렵습니다. 기능을 여러 모듈로 쪼갠 프록시는 이런 문제를 피할 수 있지만 표준 조회 방법이 없으면 지갑이나 블록 탐색기 같은 도구가 이 프록시에 어떤 함수가 있고 각 함수가 어느 컨트랙트에 구현돼 있는지 알아낼 방법이 없습니다. 이 표준은 그 조회 방법을 최소한의 인터페이스로 통일합니다.
구현해야 하는 것
event SelectorDelegated(bytes4 indexed selector, address indexed delegate);: 어떤 선택자에 델리게이트 로직 모듈을 배정할 때 발생하는 이벤트입니다. delegate가 address(0)이면 제거를 뜻합니다.function implementation(bytes4 selector) external view returns (address);: 해당 선택자를 처리하는 델리게이트 주소를 돌려줍니다. 함수가 없으면 address(0)을 돌려줍니다.function selectors() external view returns (bytes4[] memory);: 프록시의 ABI를 드러내는 함수로, 구현이 있는 모든 함수 선택자를 돌려주어야 합니다.error FunctionNotFound(bytes4 selector);: 선택자에 델리게이트가 설정돼 있지 않을 때 프록시가 이 오류로 되돌리는(revert) 것이 권장됩니다.
심층 설명
디스패치 규칙
모듈형 디스패치 프록시는 호출 데이터(calldata)의 첫 4바이트에 해당하는 델리게이트로 호출 데이터 전체를 delegatecall로 전달해야 합니다(MUST). 4바이트 선택자를 쓰는 이유는 가장 널리 지원되는 ABI가 솔리디티의 4바이트 ABI이기 때문이며 프록시도 같은 4바이트로 함수를 배분합니다. IERC8167 함수들은 프록시 본체가 아니라 델리게이트로 구현하는 것이 권장되고(SHOULD), 생성자는 최소 한 개의 델리게이트를 설정하는 것이 권장됩니다.
implementation(bytes4)의 설계
구현 주소는 eth_getStorageAt으로도 찾을 수 있지만 공통 인터페이스가 있으면 어떤 저장소 배치와 구현 방식을 쓰든 같은 방법으로 조회할 수 있습니다. 함수 이름은 기존 단일 구현 프록시의 관례와 일치시키되 선택자 매개변수를 더한 형태입니다. 함수를 찾지 못하면 address(0)을 돌려줍니다.
selectors()로 ABI 복원하기
도구는 세 단계로 프록시의 ABI를 만듭니다. 첫째, selectors()의 각 선택자에 대해 implementation(selector)를 조회합니다. 둘째, 고유한 구현마다 코드가 검증됐는지 확인하고 검증됐으면 ABI를 가져오고 아니면 사용자가 ABI를 보충하게 합니다. 셋째, 선택자를 구현의 ABI와 맞춰 프록시가 지원하는 함수를 식별합니다. 선택자는 SelectorDelegated 이벤트로도 얻을 수 있지만 selectors() 함수는 로그 접근 없이 같은 정보를 제공합니다. 로그 조회는 데이터베이스 인덱스가 없으면 느릴 수 있습니다. 압축 인코딩이 메모리 할당을 줄일 수는 있지만 bytes4 배열이 도구가 해석하기에 가장 단순합니다.
업그레이드와 저장소 배치는 범위 밖
이 표준은 업그레이드 함수를 규정하지 않습니다. 원자적 일괄 업그레이드를 위한 버전 관리 체계는 다른 표준이 이 표준을 확장해 정의할 수 있습니다. 저장소 배치도 규정하지 않으며 저장소 충돌 등 실수를 막는 패턴 역시 다른 표준이 제안할 수 있습니다. 참조 구현에는 인터페이스, 네임스페이스 기반 저장소 배치, 점검·관리용 델리게이트를 갖춘 프록시 구현 세 파일이 포함돼 있습니다.
ERC-2535(다이아몬드)와의 관계
이 표준은 ERC-2535를 세 가지 면에서 개선합니다. 다이아몬드 용어를 없앴습니다. 조회 함수는 더 적고 단순하며 업그레이드 이벤트도 더 단순합니다. 기존 모듈형 프록시는 조회 함수를 추가하고 선택적으로 설치된 모든 함수에 대해 SelectorDelegated 이벤트를 발생시키면 이 표준으로 이행할 수 있습니다.
단일 구현 프록시의 이행 경로
기존 업그레이드 가능한 단일 구현 프록시는 세 단계로 이행합니다. 첫째, 선택자-델리게이트 매핑을 채우는 메서드가 있는 구현으로 업그레이드합니다. 둘째, ABI의 모든 메서드와 조회 함수에 대해 매핑을 채웁니다. 셋째, 채워진 매핑을 쓰는 디스패치 프록시를 구현으로 설정합니다.
쓸 때 주의할 점
- 업그레이드 함수의 접근 통제: 업그레이드 함수에는 어떤 형태로든 접근 통제가 있어야 합니다. 접근 통제 설계 자체는 이 표준의 범위 밖입니다.
- 델리게이트의 self-destruct 금지: 델리게이트는 self-destruct를 해서는 안 됩니다. 델리게이트가 스스로 소멸할 수 있으면 그것을 쓰는 프록시들이 망가질 수 있습니다.
- 저장소 배치 충돌 주의: 프록시 업그레이드는 저장소 인덱스를 밀어내지 않도록 주의해야 합니다. 밀리면 컨트랙트 데이터가 손상됩니다. 델리게이트 간 저장소 겹침을 막는 방법은 두 가지가 알려져 있습니다. 모든 델리게이트가 상속하는 공통 상위 클래스에 단일 공유 저장소 배치를 정의하고 하위 클래스는 저장소를 추가 선언하지 않는 방법과, ERC-7201이나 ERC-8042 같은 저장소 네임스페이스를 쓰는 방법입니다. 후자는 공유 라이브러리에 적합합니다.