EIP-7779 상호운용 가능한 위임 계정 (Interoperable Delegated Accounts)
콜 결정 없음 · 계정 추상화 · 원문 상태 Draft · 2024-10-02 작성
EIP-7702로 스마트 계정에 위임된 EOA가 지갑을 옮길 때 스토리지 충돌 없이 재위임할 수 있도록, 계정 정보와 스토리지 베이스를 조회하고 떠나기 전 정리하는 표준 인터페이스를 정의합니다.
왜 필요한가
EIP-7702가 적용되면 기존 EOA(외부 소유 계정)가 스마트 계정 구현에 자신을 위임해 일괄 실행, 가스 대납 같은 기능을 쓸 수 있게 됩니다. 위임된 계정이 자기 주소에 묶인 스토리지를 쓴다는 게 문제입니다. 사용자가 지갑을 바꿔 다른 구현으로 다시 위임하면 이전 지갑이 쓰던 스토리지는 그대로 남고 새 구현이 같은 자리를 쓰면 충돌이 생겨 계정 잠김이나 보안 취약점 같은 예기치 않은 동작으로 이어질 수 있습니다. 지금까지 EOA는 암호 키 쌍만으로 동작해 지갑 사이를 자유롭게 오갔고 사용자에게 지갑 이동은 이미 익숙한 일입니다. 위임 이후에도 이 자유를 지키려면 계정이 어떤 스토리지 자리를 써 왔는지 표준 방식으로 확인하고 옮기기 전에 정리할 수 있는 공통 약속이 필요합니다.
무엇이 바뀌나
지금
- EOA는 키 쌍만으로 동작해 지갑을 바꿔도 옮겨야 할 온체인 상태가 없습니다
- 7702 위임 계정은 구현마다 고유한 스토리지 자리를 쓰지만 이를 조회할 표준 방법이 없습니다
- 재위임할 때 충돌이 없기를 해시 확률에만 기대야 합니다
EIP-7779 이후
- accountStorageBases()로 계정이 지금까지 써 온 스토리지 베이스 전체 이력을 조회할 수 있습니다
- accountId()로 현재 위임된 구현의 이름과 버전 같은 정보를 확인할 수 있습니다
- 선택 기능인 onRedelegation()으로 재위임 전에 기존 스토리지를 최대한 정리할 수 있습니다
누구에게 영향이 있나
- 사용자: 7702 위임 후에도 스토리지 충돌 걱정 없이 지갑을 자유롭게 옮길 수 있습니다
- 지갑 개발자: 다른 지갑이 위임해 둔 계정을 받아올 때 표준 인터페이스로 스토리지를 검증하고 정리를 요청할 수 있습니다
- 스마트 계정 구현 팀: 표준 준수를 위해 두 인터페이스 구현과 keccak256 기반 스토리지 베이스 계산, 초기화 시 베이스 기록을 반영해야 합니다
심층 설명
accountId(): 계정 네임스페이스 조회
계정의 네임스페이스를 문자열로 돌려주는 view 함수입니다. 네임스페이스에는 계정 버전, 계정 이름, 지갑 벤더 이름 등이 들어갈 수 있고 원문 예시는 "v0.1.2.7702Account.WalletProjectA"입니다. 이 표준은 네임스페이스의 형식 자체는 표준화하지 않습니다. 활용 예로 재위임 과정에서 지갑이 "Wallet A → Wallet B로 옮기시겠습니까" 같은 안내를 띄울 때 Wallet A 쪽 정보를 이 함수에서 얻는 경우를 듭니다. accountId()와 accountStorageBases()를 담은 IInteroperableDelegatedAccount 인터페이스는 표준 준수를 위해 반드시(MUST) 구현해야 합니다.
accountStorageBases(): 스토리지 베이스 이력 조회
계정이 써 온 베이스 스토리지 슬롯 목록을 돌려줍니다. 충돌을 줄이기 위해 슬롯 계산에는 반드시 keccak256()을 써야 하며 해시의 원본 값(이름, 버전 또는 그 조합)은 계정 재량입니다. 이 목록은 bytes32[] 타입으로 keccak(keccak('InteroperableDelegatedAccount.ERC.Storage')-1) & ~0xff 슬롯에 저장합니다. 덧붙이기만 하는(append-only) 배열이므로 새로 위임된 계정은 기존 값을 덮어쓰지 않고 자기 베이스를 추가해야 합니다. 추가는 계정 초기화 단계에서 하며 동일한 항목이 이미 있으면 생략할 수 있습니다. 외부 스토리지 컨트랙트를 쓰는 계정은 ERC 번호를 앞에 반복해 붙이고 스토리지 컨트랙트 주소를 이어 붙인 값을 돌려줍니다. 주소가 0xAAAA...AAAA라면 0x777977797779777977797779AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA가 됩니다. 충돌하는 베이스가 발견되면 계정은 온체인 또는 오프체인에서 추가 검증을 한 뒤 위임 여부를 정할 수 있고 충돌 지점에 사용자를 노리는 의심스러운 값(섀도 서명자 등)이 있으면 지갑이 위임을 되돌릴 수 있습니다.
onRedelegation(): 재위임 전 정리 훅
다른 구현으로 위임을 바꾸기 전에 호출되는 함수로, IRedelegableDelegatedAccount 인터페이스에 담겨 있으며 구현은 선택(MAY)입니다. 이미 위임된 EOA를 넘겨받으려는 새 지갑이 호출을 유도할 수 있고 기존 계정은 필요한 스토리지를 초기화 전 상태로 되돌리는 등 지갑별 준비 로직을 실행합니다. 호출자가 정당한 소유자인지 msg.sender로 검증해야 하고 자체 검증 방식을 쓰는 계정이라면 자기 호출(self-call)로 처리할 수도 있습니다. 표준은 구체적인 동작을 강제하지 않으며, 스토리지를 완전히 지우라고 의무화하지도 않습니다. 매핑처럼 비우기 어려운 자료형을 많이 쓰는 계정도 있기 때문에, 새 지갑이 쓸 수 있도록 가능한 한 깨끗한 상태를 남기는 최선 노력(best effort) 함수로 설계됐습니다.
설계 근거: 해시 확률에 기대지 않는 스토리지 검증
지갑마다 다른 베이스 슬롯을 쓰면 해시 특성상 충돌 확률이 충분히 낮으니 검사가 불필요하다는 시각도 있지만 이 표준은 반대 입장을 취합니다. 다이아몬드 패턴(ERC-2535)에서 개발자가 해시 확률에만 기대지 않고 퍼싯(Facet)의 스토리지를 직접 검증하는 것처럼, 위임 전에 계정 스토리지를, 적어도 새 구현이 쓸 영역만큼은 훑어보는 편이 낫다고 봅니다. 그래서 accountStorageBases()는 현재 구현의 베이스만이 아니라 계정이 써 온 스토리지 슬롯의 전체 이력을 돌려주도록 설계됐고 이 이력이 위임 전 스토리지 스캔에 쓸 재료가 됩니다.
보안 고려 사항
onRedelegation() 호출에는 소유자를 제대로 인증하는 보안 장치가 있어야 합니다. 또 이 함수는 리플레이 보호(재사용 방지) 값을 초기화해서는 안 됩니다. 서명 재사용 공격 같은 취약점이 생길 수 있기 때문입니다. 스토리지를 비운 뒤에는 임의의 주체가 초기화 함수를 다시 호출할 수 없도록 막아야 합니다. 그리고 이 표준은 ERC이므로 규칙을 강제해도 실제 구현이 따르지 않을 수도 있습니다. 표준을 지원하는 척하는 계정이 있을 수 있으니, 알려진 안전한 구현인지 검증하는 것이 권장되며 필요하면 오프체인 방식으로 정보의 진위를 확인할 수 있습니다.
진행 상태: Draft, 콜에서는 논의만
이 제안은 Draft(초안) 상태라 인터페이스와 세부 규칙이 앞으로 바뀔 수 있습니다. 코어 개발자 쪽에서는 08.29 AMA #14에서 논의됐지만 결정은 없었습니다. ERC이므로 하드포크에 포함되는 방식이 아니라 지갑과 계정 구현들이 채택하면서 자리 잡는 표준입니다.