EIP-7702 EOA에 코드 설정하기 (Set Code for EOAs)

최종 확정 · 계정 추상화 · 원문 상태 Final · 2024-05-07 작성

외부 소유 계정(EOA)이 자기 계정에 특정 컨트랙트 코드를 가리키는 위임 표시를 영구히 설정할 수 있는 새 트랜잭션 유형을 추가합니다. 기존 주소를 그대로 쓰면서 스마트 컨트랙트 지갑처럼 동작할 수 있습니다.

왜 필요한가

EOA는 개인키로 서명한 호출 하나만 보낼 수 있는 가장 단순한 계정입니다. 그래서 토큰 사용을 승인하고 바로 쓰는 흔한 작업도 오늘날 트랜잭션 두 개로 나눠야 하고 수수료를 다른 계정이 대신 내 줄 방법이 없으며 개인키가 곧 전체 권한이라 일부 권한만 떼어 줄 수도 없습니다. 원문은 스마트 컨트랙트 지갑 생태계가 크게 발전했는데도 EOA가 발목을 잡아 이런 사용성 개선이 애플리케이션 전반으로 퍼지지 못했다고 진단합니다. 이 EIP는 EOA가 서명한 권한 증명을 트랜잭션에 실어 계정 코드 자리에 위임 지시자를 기록하게 합니다. 이후 그 계정을 호출하면 지시자가 가리키는 주소의 코드가 그 계정 맥락에서 실행됩니다. 주소를 바꾸지 않고도 배칭(batching), 수수료 대납(sponsorship), 권한 축소(privilege de-escalation)를 쓸 수 있게 하는 것이 목표입니다.

무엇이 바뀌나

지금

EIP-7702 이후

누구에게 영향이 있나

심층 설명

새 트랜잭션 유형과 authorization_list

TransactionType이 SET_CODE_TX_TYPE(0x04)인 EIP-2718 트랜잭션을 추가합니다. 페이로드는 rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, value, data, access_list, authorization_list, signature_y_parity, signature_r, signature_s])이고 외부 필드의 의미는 EIP-4844와 같아 destination이 null인 생성 트랜잭션은 허용되지 않습니다. authorization_list는 [chain_id, address, nonce, y_parity, r, s] 튜플의 목록이며 길이가 0이면 트랜잭션 자체가 무효입니다. 유형 4를 범용 트랜잭션 포맷으로 쓰는 것을 막기 위한 설계입니다. 각 필드에는 chain_id < 2**256, nonce < 2**64, 주소 길이 20바이트 같은 범위 검사가 적용됩니다. 블롭 운반과 컨트랙트 생성은 의도적으로 제외했습니다.

권한 튜플 처리 절차

authorization_list는 발신자 논스를 올린 뒤, 실행부가 시작되기 전에 처리합니다. 튜플마다 (1) 체인 ID가 0이거나 현재 체인인지, (2) nonce < 2**64 - 1인지 확인하고 (3) msg = keccak(MAGIC || rlp([chain_id, address, nonce]))에 대해 ecrecover로 authority를 복원합니다(s는 EIP-2에 따라 secp256k1n/2 이하). 이어 (4) authority를 accessed_addresses에 넣고 (5) 코드가 비어 있거나 이미 위임 상태인지, (6) 논스가 일치하는지 검증한 뒤, (8) 코드 자리에 0xef0100 || address를 쓰고 (9) 논스를 1 올립니다. address가 0x0이면 지시자를 쓰지 않고 코드해시를 빈 코드해시로 되돌려 계정을 순수 EOA로 복원합니다. 어느 단계든 실패하면 그 튜플만 건너뛰고 다음 튜플로 넘어가며 같은 authority의 튜플이 여럿이면 마지막 유효 튜플의 주소가 적용됩니다. 트랜잭션 실행이 실패해도 이미 처리된 위임 지시자는 되돌리지 않습니다.

위임 지시자와 opcode별 동작

위임 지시자는 EIP-3541에서 금지된 0xef 프리픽스를 써서 일반 코드와 구별합니다. CALL, CALLCODE, DELEGATECALL, STATICCALL, 그리고 destination이 위임 계정인 트랜잭션은 모두 포인터를 따라가 address의 코드를 authority 맥락에서 실행합니다. 코드 읽기 중에는 CODESIZE와 CODECOPY만 위임된 실제 코드를 기준으로 동작하고 EXTCODESIZE는 지시자 자체 크기인 23을 돌려줍니다. EXTCODEHASH 등도 지시자를 그대로 읽는데, 위임을 따라가면 계정이 특정 코드해시를 가진 것처럼 위장할 수 있어 코드해시를 행동 보증으로 쓰는 기존 컨트랙트가 깨지기 때문입니다. 프리컴파일 주소로 위임하면 코드가 빈 것으로 간주되어 호출이 아무 실행 없이 성공합니다. 위임이 또 다른 위임을 가리키면 클라이언트는 첫 번째 코드만 가져오고 체인 추적을 멈춥니다.

가스 비용과 선불 과금

고유 비용은 EIP-2930을 물려받아 21000 + 16 * 非제로 calldata 바이트 + 4 * 제로 바이트 + 1900 * 접근 목록 스토리지 키 수 + 2400 * 접근 목록 주소 수이고, 여기에 PER_EMPTY_ACCOUNT_COST(25000) * 권한 목록 길이를 더합니다. 발신자는 튜플의 유효성이나 중복과 무관하게 전부에 대해 지불합니다. 처리 중 authority 계정이 이미 존재하면 PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST(12500)만큼 환불 카운터에 더합니다. 최악 비용을 먼저 받고 나중에 환불하는 이 구조는 고유 가스 계산 시점에 권한별 상태 조회를 피하고 발신자 계정 조회만으로 유효성을 빠르게 판단하기 위한 것입니다. 위임 코드를 해석하다 콜드 계정을 건드리면 COLD_ACCOUNT_READ_COST 2600가스를 추가로 물리고 웜 상태면 100가스입니다. PER_AUTH_BASE_COST 12500은 calldata 운반, 주소 복원, 상태 읽기, 코드 기록 등 영향 기반으로 산정한 12016가스를 올림한 값입니다.

깨지는 불변식과 tx.origin 문제

이 EIP는 세 가지 불변식을 깹니다. 첫째, 계정 잔액은 그 계정이 보낸 트랜잭션으로만 줄어든다는 보장이 사라집니다. 위임된 계정은 누가 호출해도 잔액이 줄 수 있습니다. 둘째, EOA 논스는 실행 중에 늘지 않는다는 보장이 사라집니다. 위임 코드가 생성 연산을 부를 수 있기 때문입니다. 셋째, tx.origin == msg.sender는 최상위 프레임에서만 참이라는 보장이 사라집니다. 원문은 이 검사의 세 용도 중 EOA 여부 확인은 영향이 없고 원자적 샌드위치(플래시론 류) 방어는 깨지며 재진입 방지 용도는 실제 사례를 찾지 못했다고 분석합니다(탐색은 비망라적). 또 EIP-3607의 제한을 수정해 코드가 유효한 위임 지시자인 EOA만 트랜잭션을 발신할 수 있게 합니다.

위임 컨트랙트와 지갑의 보안 책임

부실한 위임 컨트랙트는 공격자에게 서명자 EOA에 대한 거의 완전한 통제권을 줄 수 있습니다. 원문은 위임 컨트랙트가 계정 주인의 서명에 재사용 방지 장치(논스), value, gas, target/calldata를 포함해야 한다고 명시합니다. 빠지면 서명 재사용, 악의적 대납자의 가스 고갈 유발, 임의 컨트랙트 호출이 가능해집니다. 위임은 실행 없이 코드만 설정하므로 초기화를 관찰자가 선점할 수 있는데, 이를 막으려면 초기 설정 calldata가 EOA 키로 서명됐는지 ecrecover로 검증해야 합니다. 위임 대상을 바꿀 때는 스토리지 충돌을 피해야 하며 ERC-7201처럼 고유 식별자 기반 슬롯에 레이아웃을 두는 방식을 예로 듭니다. 지갑 측 원칙도 있습니다. 앱이 사용자에게 위임 서명을 제안하도록 두는 안전한 인터페이스는 존재하지 않으므로, 지갑이 그런 인터페이스를 제공하지 않아야 하고 위임 코드는 지갑이 면밀히 감사해야 합니다.

트랜잭션 전파와 대기열 관리

지금까지 EOA는 값 전송만 할 수 있어 노드가 계정별 대기 트랜잭션의 유효성을 정적으로 판단할 수 있었습니다. 위임 이후에는 그 계정의 코드를 누구나 트랜잭션 중간에 호출할 수 있어 잔액이 쓸려 나갔는지 정적으로 알 수 없고 한 트랜잭션이 다른 계정들의 대기 트랜잭션을 무효화할 수 있습니다. 원문은 위임 지시자가 있는 EOA에 대해 클라이언트가 대기 트랜잭션을 1개까지만 받으라고 권고합니다. 대안으로 트랜잭션에 '하이드레이트'할 계정 목록을 명시하는 확장도 언급합니다. 논스가 한 트랜잭션에서 여러 번 오를 수 있다는 점도 전파 설계에서 고려해야 합니다. 대납 중계자는 권한 무효화(논스 증가)나 자산 인출로 가스만 쓰고 보상을 못 받을 수 있어 보증금이나 평판 시스템을 고려해야 합니다.

상태와 최근 논의

이 EIP는 최종 확정(Final) 상태입니다. 콜 기록으로는 08.13 ACDE #243과 08.29 AMA #14에서 논의됐으나 결정은 없었습니다. 최근 바이낸스 해킹을 두고 논쟁이 있었습니다. 계정 추상화 기여자 decentrek은 EIP-7702 자체는 깨지지 않았지만 배칭 기능이 해커가 ETH와 USDT 등 64종 토큰을 한 트랜잭션에 빼내 피해를 키우도록 도운 것은 사실이라며 운영 관행을 개선하고 EIP-8141 프레임 트랜잭션(frame transaction) 같은 엔드게임 계정 추상화로 전환하자고 촉구했습니다. 반면 FigoETH, AzianMike, ETH_MAXER 등은 7702는 안전하고 중립적인 UX 도구이며 문제는 개인키 유출과 바이낸스의 허술함이라고 반박했습니다.

EIP 원문 · ← EIPs