EIP-8298 SETCODEFROM 코드 재사용 명령어 (SETCODEFROM Code Reuse Instruction)
Hegota 포함 검토 (CFI) · EVM·실행 · 원문 상태 Draft · 2026-06-11 작성
이미 배포된 컨트랙트의 코드 해시를 현재 계정에 복사하는 EVM 명령어 SETCODEFROM을 추가합니다. 같은 코드를 다시 배포하는 비용을 없애고 일반 계정이 ECDSA 키 없이 코드로만 움직이게 바꾸는 길도 엽니다.
왜 필요한가
지금 이더리움에서 코드가 같은 컨트랙트를 여러 개 배포하면, 배포할 때마다 똑같은 코드를 다시 저장하는 값을 냅니다. 토큰 발행기처럼 같은 코드를 반복해서 찍어내는 경우 이 비용이 그대로 쌓입니다. 컨트랙트 배포 가격을 상태 증가에 맞춰 다시 매기는 EIP-8037 같은 제안이 들어오면 부담은 더 커집니다. 일반 계정(EOA)의 통제권도 문제입니다. 지금 EOA는 ECDSA 서명으로만 거래를 시작할 수 있고 EIP-7702로 코드를 위임해도 위임 표시만 붙을 뿐이어서 원래 키로 서명한 거래가 계속 유효합니다. 양자내성(PQ) 지갑처럼 다른 방식으로 계정을 지키려면 ECDSA 거래 권한을 끊을 길이 있어야 하는데, 지금은 그런 길이 없습니다. SETCODEFROM은 이 두 문제를 한 명령어로 풉니다. 계정별 저장 값을 먼저 쓰고 그 다음 이미 배포된 공용 코드를 자기 코드로 채택하는 방식입니다.
무엇이 바뀌나
지금
- 같은 런타임 코드를 배포할 때마다 코드 저장(code deposit) 가스를 전부 다시 냅니다.
- EOA는 ECDSA 서명 거래 권한을 영구히 끊을 방법이 없고 EIP-7702 위임 뒤에도 원래 키가 살아 있습니다.
- 블록 접근 목록(BAL)의 코드 변경 항목은 새 바이트코드 자체만 기록합니다.
- 계정 코드는 컨트랙트 생성 때 또는 EIP-7702 위임으로만 바뀝니다.
EIP-8298 이후
- 초기화 코드가 저장 값을 쓴 뒤 SETCODEFROM으로 공용 코드를 채택하면 코드 저장 가스를 내지 않습니다.
- EOA가 일반 코드를 채택하면 ECDSA 거래가 EIP-3607에 따라 무효가 되고 EIP-7702 재위임도 막힙니다.
- SETCODEFROM으로 바뀐 코드는 BAL에 바이트코드 대신 32바이트 코드 해시로 기록됩니다.
- 배포된 코드가 실행 중에 자기 계정의 코드 해시를 다른 계정의 것으로 바꿀 수 있습니다.
누구에게 영향이 있나
- 지갑·앱 개발자: 클론 팩토리와 프록시 업그레이드를 코드 저장 비용 없이 구현할 수 있습니다. 대신 채택 경로를 신뢰된 권한으로 묶고 채택 직전에 소스의 코드 해시를 확인해야 합니다.
- EOA 사용자: 지갑 코드를 채택하면 원래 키가 은퇴하고 되돌릴 수 없습니다. 이후 계정은 채택한 코드로만 움직이며 ETH나 토큰을 받을 때도 그 코드가 실행됩니다.
- 클라이언트 팀: 새 opcode 구현과 함께 EIP-7928 BAL 인코딩 변경, 멤풀 축출 규칙, 실행 중인 코드와 계정 코드의 분리를 처리해야 합니다.
- 계정 추상화 인프라(ERC-4337·EIP-8141): 검증 단계에서 SETCODEFROM 실행을 막고 이 명령어를 담은 컨트랙트를 변경 가능한 코드로 다뤄야 합니다.
심층 설명
명령어 정의: 주소 하나를 받아 코드 해시를 복사합니다
SETCODEFROM은 opcode 0xA7로 정의됩니다. 스택에서 항목 하나를 꺼내 하위 160비트를 source 주소로 해석하고 실행 뒤 success를 밀어 넣습니다. source가 유효하면 1, 아니면 0입니다. 입력은 원시 코드 해시가 아니라 주소이며 합의 상태에 살아 있는 계정의 source.codeHash를 읽어 옵니다. 바뀌는 쪽은 현재 실행 환경 계정입니다. ADDRESS가 돌려주는 주소이자 SSTORE가 저장소를 건드리는 바로 그 계정입니다. 실행 중인 코드가 EIP-7702 위임처럼 다른 계정에서 불러온 것이어도 코드 출처 계정이 아니라 실행 환경 계정의 코드 해시가 바뀝니다. 성공하면 이후 source가 어떻게 바뀌어도 현재 계정의 codeHash와 그 해시가 가리키는 바이트코드의 가용성에는 영향이 없어야 합니다. 상태 변경은 일반 EVM 되돌림 규칙을 따릅니다. 프레임이나 거래가 되돌려지면 코드 변경도 함께 되돌려집니다.
유효한 소스 조건과 예외 중단
source가 유효하려면 네 조건을 모두 만족해야 합니다. 상태에 존재하는 계정이고 source.codeHash가 EMPTYCODEHASH(0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470)가 아니며 source.code가 활성 포크에서 유효한 일반 배포 코드여야 합니다. 즉 EIP-3541이 예약하고 EIP-7702 위임 표시가 쓰는 0xEF로 시작하면 안 됩니다. 마지막으로 현재 거래에서 생성된 계정이 아니어야 합니다. 생성 여부는 EIP-6780이 SELFDESTRUCT로 삭제를 허용하는 경우와 정확히 같습니다. 이 제한은 source에만 걸리고 현재 계정은 자기 초기화 코드 안에서 생성되는 중이어도 됩니다. 정적 컨텍스트에서 실행되거나 현재 계정이 시스템 컨트랙트이면 예외 중단합니다. 시스템 컨트랙트는 블록 처리 중 프로토콜이 SYSTEM_ADDRESS(0xfffffffffffffffffffffffffffffffffffffffe)에서 호출하는 계정이며 로그만 읽히는 EIP-6110 예치 컨트랙트는 해당하지 않습니다. 두 중단은 SETCODEFROM_SOURCE_GAS 청구 전에 일어나 source에 접근하지 않습니다. 소스가 무효이면 0을 밀고 상태를 바꾸지 않습니다. 노드마다 로컬 코드 DB 내용이 다를 수 있어 입력은 주소로 받습니다. 존재 조건을 따로 둔 이유는 없는 계정의 codeHash를 0으로 표현하는 구현이 코드 없는 해시를 설치하는 일을 막기 위해서입니다. 현재 거래에서 생성된 소스는 거부합니다. 그 코드가 거래 끝 전에 삭제되거나 바뀔 수 있어 바이트코드가 블록 전 상태에도 BAL에도 남지 않을 수 있기 때문입니다. 그 대가로 템플릿은 배포한 거래 안에서는 채택할 수 없습니다.
실행 중인 코드와 보이는 코드의 분리, 생성 중 채택
배포된 코드 실행 중에 SETCODEFROM이 성공하면 현재 실행 컨텍스트 계정의 코드 해시가 바뀌지만 현재 프레임은 이미 불러온 코드를 계속 실행합니다. 그 프레임의 CODESIZE와 CODECOPY는 기존 코드를 가리키고 현재 계정에 대한 EXTCODESIZE, EXTCODEHASH, EXTCODECOPY는 새 코드 해시를 봅니다. 같은 거래 안에서 같은 계정을 다시 호출하면 새 코드가 실행됩니다. 초기화 코드 실행 중에도 허용됩니다. 생성 거래, CREATE, CREATE2 모두에서 생성 중인 계정이 현재 계정이 되고 갱신은 즉시 반영되며 생성 프레임은 기존 초기화 코드를 계속 실행합니다. 초기화 코드가 정상 종료되면 두 갈래로 나뉩니다. 계정의 codeHash가 EMPTYCODEHASH이면 반환 데이터를 검증하고 코드 저장 가스를 청구해 설치합니다. 아니면 반환 데이터를 빈 것으로 취급해 검증, 해시, 설치, 코드 저장 가스 청구를 모두 생략하고 채택된 codeHash를 그대로 둡니다. 이때 배포된 코드는 되돌려지지 않은 마지막 성공 SETCODEFROM의 코드이며 실행 추적이나 eth_call 결과도 그 코드를 보고합니다. 성공한 CREATE와 CREATE2는 EIP-211대로 호출자의 반환 데이터 버퍼를 비워 둡니다. 새 계정 리프를 추가하는 계정 생성 상태 가스는 그대로 들지만 채택한 코드에 대한 코드 저장 상태 가스와 실행 가스는 들지 않습니다. 생성 중 채택을 허용한 이유는 설치 규칙을 하나로 두기 위해서입니다. 생성은 초기화 코드가 반환한 바이트 또는 채택된 코드 해시 중 하나만 설치하며 초기화 코드 종료 시점의 codeHash가 어느 쪽인지 정합니다.
가스 비용
가스 매개변수는 다섯 개입니다. SOURCE_ACCOUNT_ACCESS_COST는 source가 차가우면 COLD_ACCOUNT_ACCESS, 따뜻하면 WARM_ACCESS입니다. SETCODEFROM_SOURCE_GAS는 SOURCE_ACCOUNT_ACCESS_COST + WARM_ACCESS, SETCODEFROM_CURRENT_ACCESS_GAS는 WARM_ACCESS, SETCODEFROM_WRITE_GAS는 ACCOUNT_WRITE, SETCODEFROM_STATE_GAS는 0입니다. 실행 시도마다 먼저 SETCODEFROM_SOURCE_GAS를 청구합니다. 소스 계정 리프 로딩(SOURCE_ACCOUNT_ACCESS_COST)과 소스 코드 검증(WARM_ACCESS, 바이트코드를 들여다볼 때 필요한 코드 저장소 접근을 덮는 고정 비용)을 합친 값입니다. 이 청구가 끝나면 유효 여부와 관계없이 source가 EIP-2929의 accessed_addresses에 들어갑니다. 검증은 source 자신의 코드만 읽고 EIP-7702 위임을 따라가지 않으므로 위임 대상은 접근, 청구, 예열되지 않습니다. source가 유효하면 SETCODEFROM_CURRENT_ACCESS_GAS를 청구한 뒤 두 코드 해시를 비교하고 다르면 SETCODEFROM_WRITE_GAS를 청구하고 갱신합니다. 쓰기 비용은 EIP-8038의 ACCOUNT_WRITE를 따릅니다. 현재 EIP-8038 값(ACCOUNT_WRITE 9000, COLD_ACCOUNT_ACCESS 3000, WARM_ACCESS 100) 기준으로 무효 소스는 차가울 때 3100, 따뜻할 때 200이고 유효하지만 해시가 같으면 3200과 300, 실제로 갱신되면 12200과 9300입니다. 코드 저장 작업이 없으므로 비용은 소스 코드 크기와 무관하며 초기화 코드 안에서 실행해도 같습니다. 생성 자체의 계정 리프 추가 상태 가스는 별도로 들 수 있습니다.
ECDSA 거래 권한 종료와 공개 멤풀 규칙
SETCODEFROM이 일반 배포 코드를 설치하면 계정은 그 코드로만 통제됩니다. EIP-7702 위임 표시가 있었다면 채택한 코드가 대체합니다. 코드가 비어 있지 않으므로 복구된 발신자가 그 계정인 ECDSA 거래는 EIP-3607에 따라 무효가 되고 EIP-7702 권한 처리는 빈 코드나 기존 위임 표시만 받아들이므로 재위임도 막힙니다. 아래 멤풀 규칙은 합의에 영향을 주지 않는 권고입니다. 채택 시점에 이미 대기 중인 ECDSA 거래도 무효가 되므로 노드는 새 블록을 처리할 때 이를 축출하고 새 거래를 거부해야 합니다. 은퇴하는 것은 키이고 계정이 아니어서 계정은 자기 코드가 승인하는 EIP-8141 프레임 거래의 발신자로 계속 거래하고 다른 거래가 호출할 때도 동작합니다. EOA는 EIP-7702 위임 코드를 실행해야만 코드를 채택할 수 있으므로 채택이 무효화하는 거래는 위임 코드가 이미 무효화할 수 있는 범위를 넘지 않고 위임된 EOA당 대기 거래 하나라는 EIP-7702 권고가 그대로 적용됩니다. ERC-7562 사용자 작업 검증은 SELFDESTRUCT처럼 SETCODEFROM을 막아야 합니다. EIP-8141 프레임 거래에서는 검증 접두 실행 중 SETCODEFROM을 금지합니다. 검증 접두에서 CALL*이나 EXTCODE*로 도달한 컨트랙트 코드에 SETCODEFROM 명령어가 있으면(PUSH 데이터 등 즉시값 제외) EIP-7702 위임 표시가 있는 계정처럼 변경 가능한 코드로 다룹니다. 대신 DELEGATECALL이나 CALLCODE가 있으면 위임 코드로 SETCODEFROM에 닿을 수 있으므로 그 코드 해시를 검증 의존성으로 추적하고 거기에 기대는 대기 거래 수를 제한합니다. 프록시 기반 계정을 계속 쓸 수 있게 하기 위한 조치입니다.
블록 접근 목록(BAL) 인코딩 변경
EIP-7928의 CodeChange에 선택적 꼬리 요소 new_code_hash를 추가합니다. 생성이나 EIP-7702로 설치된 코드는 기존처럼 [block_access_index, new_code] 두 요소로 적고 SETCODEFROM으로 채택된 코드는 [block_access_index, b"", new_code_hash] 세 요소로 적습니다. 거래 안에서 계정의 코드 해시가 바뀌었고 거래 끝 값이 SETCODEFROM으로 정해졌다면 반드시 세 요소 형식을 써야 하며 다른 방식으로 기록한 BAL은 무효입니다. new_code_hash 뒤의 바이트코드는 블록 전 상태 또는 블록 접근 인덱스가 더 낮은 code_changes 항목의 new_code에 있어야 하고 같거나 높은 인덱스를 참조하는 항목은 없습니다. SETCODEFROM_SOURCE_GAS가 청구된 순간부터 source는 유효 여부와 관계없이 BAL에 포함되어야 하며 다른 변경이 없으면 빈 변경 목록으로 들어갑니다. 청구에 실패하면 포함하지 않습니다. EIP-7928의 상태 접근 전 가스 검증에서 SETCODEFROM의 사전 상태 검증 비용은 SETCODEFROM_SOURCE_GAS입니다. 바이트코드 대신 해시를 기록하는 이유는 바이트코드가 이미 있기 때문입니다. 따뜻한 소스 기준 9300 가스로 최대 코드 크기까지 BAL에 넣을 수 있다면 바이트당 1 가스에도 못 미쳐 EIP-7928 bal_items 한도의 가정이 깨집니다. 해시를 별도 요소로 둔 이유는 32바이트 new_code 값이 32바이트 런타임 코드와 구별되지 않기 때문입니다. 항목 형식이 출처를 드러내고 크기가 고정되므로 EIP-8279 같은 바이트 하한 방식으로 계량할 수 있습니다.
보안 고려 사항
SETCODEFROM은 거래가 되돌려지지 않으면 계정 동작을 영구히 바꾸므로, 이 명령어를 노출하는 컨트랙트는 신뢰된 통제 경로로 접근을 제한해야 합니다. 유효한 소스는 자기 코드 해시를 바꿀 수 있고 채택이 승인된 시점과 실행 시점 사이에도 바뀔 수 있습니다. 서명이나 제안으로 미리 승인하는 채택은 소스 주소뿐 아니라 기대하는 코드 해시를 명시하고 채택 코드는 SETCODEFROM 직전에 외부 호출 없이 EXTCODEHASH(source)를 그 해시와 비교해야 합니다. EIP-6913과 달리 이 EIP는 위임 실행이 호출자의 계정 코드를 바꾸는 것을 허용합니다. 기존 프록시 업그레이드 패턴을 보존하기 위해서이며 지갑은 그런 모듈을 업그레이드 권한이 있는 코드로 취급하고 delegatecall 대상을 제한해야 합니다. SETCODEFROM에 닿을 수 있는 계정에 EIP-7702로 위임하면 그 계정이 앞으로 채택할 모든 코드를 신뢰하는 셈이며 이제 EOA도 여기에 들어갑니다. 일반 코드를 채택한 EOA는 되돌릴 수 없습니다. ECDSA 거래를 시작할 수 없고 7702 재위임도 안 되며 빈 코드로 되돌리는 명령어도 없습니다. ecRecover로 직접 서명을 검증하는 컨트랙트(permit 등)는 여전히 그 주소를 복구하므로 EIP-8151 같은 동반 변경이 필요하고 8151이 있으면 자기 주소에 대한 ecRecover 인증은 영구히 실패합니다. 초기화되지 않은 상태에만 의존하는 인증은 계정을 잠글 수 있으므로 초기화는 채택 거래 안에서 끝내야 하고 누구나 할 수 있는 초기화는 선점당할 수 있습니다. 채택 뒤에는 CALL로 들어오는 ETH나 수신 훅이 있는 토큰 전송도 채택한 코드를 실행합니다. EIP-8141이 없는 체인에서는 계정이 호출될 때만 동작하므로 ERC-4337 진입점 같은 중계 경로가 없는 코드는 발이 묶입니다. 초기화 코드가 끝나기 전 콜백으로 호출되면 이미 채택된 코드가 미완성 저장소 위에서 실행되므로 채택 전에 초기화를 끝내야 합니다.
현재 상태와 포크 논의
이 EIP는 2026-06-11에 만들어진 Draft 상태이고 Test Cases 절은 아직 비어 있습니다(TODO). 새 명령어를 추가하므로 하드포크가 필요하고 이미 배포된 컨트랙트 중 이 opcode를 쓰는 것은 동작이 바뀔 수 있습니다. EIP-7928만 구현한 클라이언트는 new_code_hash를 쓴 블록을 거부하고 반대도 같습니다. 0xEF로 시작하는 메인넷 컨트랙트 세 개는 소스에서 제외되지만 0xEF가 정의되지 않은 명령어라 실행 가능한 코드가 아니어서 실질적 손실은 없습니다. 코어 개발자 콜에서는 07.02 ACDE #240에서 헤고타(Hegota) 후보(PFI)로 접수했습니다. 09.16 AMA #15와 09.24 ACDE #246에서 논의했으나 결정은 없었습니다. 10.08 ACDE #247에서 EIP-8151(ecRecover 제한)과 한 쌍으로 묶어 검토 대상(CFI)으로 올렸습니다. 일반 계정이 ECDSA에 기대지 않고 양자내성으로 이주할 경로를 여는 조합이라는 이유였습니다. 10.22 ACDE #248에서 bogota-devnet-2 범위를 EIP-8253, EIP-4758, EIP-8298, EIP-8151 네 개로 확정하고 다음 주 Nethermind, Geth, ethrex 세 클라이언트로 출시한다고 했습니다. 헤고타 후보 EIP를 실제 네트워크에서 돌려보는 실험망입니다. Draft 상태이므로 opcode 값, 가스 수치, BAL 인코딩 같은 세부 내용은 아직 바뀔 수 있습니다.