EIP-4758 SELFDESTRUCT 비활성화 (Deactivate SELFDESTRUCT)
Hegota 포함 검토 (CFI) · EVM·실행 · 원문 상태 Stagnant · 2022-02-03 작성
컨트랙트를 지우는 명령어 SELFDESTRUCT를 SENDALL로 바꿉니다. 계정의 이더를 모두 보내는 기능만 남기고 코드와 저장 공간은 지우지 않으며 관련 가스 환불도 없앱니다.
왜 필요한가
지금 SELFDESTRUCT 명령어는 컨트랙트 계정의 코드와 저장 공간(storage)을 통째로 지우고 남은 이더를 지정한 주소로 보냅니다. 계정 상태(state)를 크게 바꾸는 작업입니다. 이더리움은 앞으로 상태를 버클 트리(Verkle tree)라는 새 자료구조에 담으려 합니다. 버클 트리에서는 한 계정의 데이터가 여러 키에 흩어져 저장되고 그 키들이 어느 계정에 속하는지 겉으로 드러나지 않습니다. 그래서 계정 하나를 통째로 지우는 일이 사실상 불가능해집니다. 원문은 이 명령어를 없애는 것이 노드가 전체 상태를 들고 있지 않아도 되는 무상태성(statelessness)의 필요조건이라고 설명합니다. 반면 지금 SELFDESTRUCT를 꼭 써야 할 강한 이유는 없고 자금 회수 용도로만 쓰는 앱은 바뀐 뒤에도 그대로 동작합니다. 그래서 명령어를 없애는 대신 이더만 보내는 단순한 동작으로 바꾸자는 제안입니다.
무엇이 바뀌나
지금
- SELFDESTRUCT는 계정의 코드와 저장 공간을 모두 지우고 이더를 지정한 주소로 보냅니다
- SELFDESTRUCT와 묶인 가스 환불(refund) 규칙이 있습니다
- 지운 자리에 CREATE2로 같은 주소에 새 컨트랙트를 다시 배포할 수 있습니다
EIP-4758 이후
- 이름이 SENDALL로 바뀌고 계정의 이더만 지정한 주소로 보냅니다
- 코드, 저장 공간, 논스(nonce)는 그대로 남고 관련 환불은 모두 없어집니다
- 같은 주소에 컨트랙트를 다시 배포하는 방식은 이제 동작하지 않습니다
누구에게 영향이 있나
- 사용자: 대부분 체감 변화가 없습니다. 자금 회수 용도로만 SELFDESTRUCT를 쓰는 앱은 바뀐 뒤에도 그대로 동작합니다.
- 지갑·앱 개발자: CREATE2로 같은 주소에 재배포하거나 업그레이드 수단으로 SELFDESTRUCT를 쓰는 컨트랙트는 깨집니다. 업그레이드는 위임(delegate) 방식으로 바꿔야 합니다.
- 클라이언트 팀: 합의 규칙을 바꾸므로 하드포크가 필요합니다. 콜 기록상 bogota-devnet-2 범위에 포함돼 Nethermind, Geth, ethrex 세 클라이언트가 구현합니다.
- 노드 운영자·검증자: 원문은 이 변경이 무상태성(statelessness)의 필요조건이라고 적습니다. 버클 트리 전환과 맞물린 변경입니다.
심층 설명
명령어 이름과 동작 변경
SELFDESTRUCT 명령어의 이름을 SENDALL로 바꿉니다. 새 동작은 계정에 있는 모든 ETH를 즉시 대상(target)으로 옮기는 것뿐입니다. 코드와 저장 공간(storage)을 파괴하지 않고 논스(nonce)도 바꾸지 않습니다. 즉 실행 뒤에도 컨트랙트는 같은 주소에 코드와 상태를 그대로 둔 채 남아 있고 잔액만 0이 됩니다. 한 가지 짚어 둘 점이 있습니다. 원문 머리말의 description은 자금을 호출자(caller)에게 돌려준다고 적고 Specification 절은 대상(target)에게 보낸다고 적습니다. 원문이 두 표현을 함께 쓰므로 구현할 때는 논의 스레드에서 의도를 확인할 필요가 있습니다.
환불 제거
SELFDESTRUCT 관련 환불(refund)을 모두 제거합니다. 환불 제거는 명령어 이름 변경과 함께 Specification 절의 두 항목 중 하나입니다. 원문 명세는 이 한 줄만 적고 어떤 환불이 얼마였는지, 새 가스 비용이 얼마인지는 따로 제시하지 않습니다. SENDALL은 코드와 저장 공간을 지우지 않으므로 상태를 줄인 대가로 가스를 돌려줄 근거가 없다는 뜻으로 읽힙니다. 명령어의 가스 비용 자체를 바꾼다는 내용은 원문에 없습니다.
버클 트리와 무상태성
SELFDESTRUCT는 계정의 코드와 저장 공간을 모두 제거하는 큰 상태 변경을 요구합니다. 버클 트리(Verkle tree)에서는 각 계정이 여러 계정 키(account key)에 나뉘어 저장되고 이 키들이 루트 계정과 명확히 연결되지 않습니다. 따라서 계정 하나를 통째로 지우는 작업은 앞으로 불가능해집니다. Rationale 절은 SELFDESTRUCT 제거가 과거에도 검토됐고 지금 이를 써야 할 강한 이유가 없으며 비활성화가 무상태성(statelessness)의 필요조건이라고 적습니다. 자금 회수 용도로만 SELFDESTRUCT를 쓰는 앱은 바뀐 뒤에도 동작합니다.
하위 호환성: CREATE2 재배포가 깨집니다
합의 규칙을 바꾸므로 하드포크가 필요합니다. 원문은 이 변경에 영향받는 앱이 적다고 적습니다. 깨지는 유일한 용례는 SELFDESTRUCT 뒤에 CREATE2로 같은 주소에 컨트랙트를 다시 만드는 방식입니다. CREATE2는 배포 주소를 미리 정할 수 있어서 컨트랙트를 지운 다음 같은 자리에 다른 코드를 올리는 패턴에 쓰였습니다. SENDALL은 코드를 지우지 않으므로 그 주소에 코드가 계속 남고 같은 자리에 다시 배포할 수 없습니다. 자금 회수만을 위해 SELFDESTRUCT를 쓰던 앱은 그대로 동작합니다.
보안 고려사항: 안전하지 않게 되는 두 가지 용례
원문은 더 이상 안전하지 않은 용례를 두 가지로 정리합니다. 첫째, 컨트랙트 안에서 EIP-20 같은 ETH가 아닌 토큰 잔액을 태우는(burn) 용도로 SELFDESTRUCT를 쓰는 경우입니다. 저자들은 이런 용례를 알지 못하며 소각 주소로 보내면 쉽게 되므로 이렇게 쓸 가능성은 낮다고 봅니다. 둘째, CREATE2로 같은 자리에 컨트랙트를 재배포하는 경우입니다. 여기에는 두 갈래가 있습니다. 하나는 특정 맥락 밖에서 컨트랙트를 쓰지 못하게 막으려고 작업 끝에 SELFDESTRUCT를 호출하는 패턴입니다. 예를 들어 누구나 자금을 인출할 수 있는 컨트랙트에서 다른 이의 인출을 막는 데 씁니다. 원문은 이 패턴이 SELFDESTRUCT에 의존하지 않도록 쉽게 고칠 수 있다고 적습니다. 다른 하나는 컨트랙트 업그레이드 수단으로 SELFDESTRUCT를 쓰는 경우입니다. 이제는 지원되지 않으며 위임(delegate) 방식을 써야 합니다.
원문 상태와 코어 개발자 콜 결정
원문 상태는 Stagnant(정체)입니다. 2022년 2월 3일에 만들어졌고 저자는 Guillaume Ballet, Vitalik Buterin, Dankrad Feist입니다. 최종 확정(Final)된 명세가 아니므로 내용은 아직 바뀔 수 있습니다. 코어 개발자 콜에서는 다시 다뤄지고 있습니다. 10.08 ACDE #247에서 EIP-8360(TCREATE)과 EIP-4758(SELFDESTRUCT 비활성화)을 묶어 헤고타(Hegota) 검토 대상(CFI)으로 올렸고 글램스테르담에서 도입된 문제를 고치는 수정이라고 설명했습니다. 10.22 ACDE #248에서는 bogota-devnet-2 범위를 EIP-8253, EIP-4758, EIP-8298, EIP-8151 네 개로 확정하고 다음 주 Nethermind, Geth, ethrex 세 클라이언트로 출시하기로 했습니다. bogota-devnet-2는 헤고타 후보 EIP를 실제 네트워크에서 돌려보는 실험망입니다.