EIP-8360 TCREATE 옵코드 (TCREATE Opcode)

Hegota 포함 검토 (CFI) · EVM·실행 · 원문 상태 Draft · 2026-08-03 작성

한 트랜잭션 안에서만 존재하는 임시 컨트랙트를 만드는 새 EVM 명령어 TCREATE를 추가합니다. 트랜잭션이 끝나면 코드와 논스는 버려지고 잔액만 남습니다.

왜 필요한가

이더리움 앱 가운데는 컨트랙트 코드가 한 트랜잭션 뒤까지 남아 있을 필요가 없는 경우가 많습니다. 상태 채널(state channel) 컨트랙트, 한 번만 쓰는 계정 같은 것들입니다. 지금은 이런 용도에 CREATE나 CREATE2로 컨트랙트를 만들고 SELFDESTRUCT로 지우는 방식을 씁니다. 그런데 SELFDESTRUCT는 EIP-3529 이후 가스를 돌려주지 않고 칸쿤 업그레이드 뒤로는 같은 트랜잭션에서 만든 컨트랙트만 지울 수 있습니다. 앞으로 더 제한될 것으로도 예상됩니다. 그래서 만들고 바로 지우는 방식은 비용 면에서 이점이 없고 오래 믿고 쓸 수도 없습니다. 임시 컨트랙트 전용 명령어가 있으면 비용이 낮아지고 쓸모없는 코드가 상태에 쌓이는 것도 막을 수 있습니다. SELFDESTRUCT에서 단계적으로 벗어나는 길도 열립니다.

무엇이 바뀌나

지금

EIP-8360 이후

누구에게 영향이 있나

심층 설명

주소 계산과 배포자 논스

TCREATE 주소는 keccak256(0xfe || deployer_address || salt || keccak256(init_code))[12:]입니다. deployer_address는 TCREATE를 실행하는 프레임의 ADDRESS 값입니다. CREATE2가 0xff를 쓰는 자리에 0xfe를 두어 두 주소 공간이 겹치지 않게 했습니다. 해시 입력 길이는 CREATE2와 같은 85바이트이고 RLP 첫 바이트 0xfe는 페이로드가 2^48바이트 이상인 리스트를 뜻하므로 23~31바이트 입력에 0xd6~0xde로 시작하는 CREATE 주소와도 겹치지 않습니다. initcode 해시를 넣는 이유는 CREATE2처럼 initcode를 메모리에서 받기 때문입니다. 해시가 없으면 배포 계정이 같은 주소에서 다른 코드를 실행할 수 있습니다. 이 주소는 트랜잭션 사이에 잔액을 유지하므로, 값을 보내는 쪽이 주소만 보고 어떤 코드가 실행될지 확인할 수 있어야 합니다. 배포자 계정의 논스는 주소 충돌, initcode의 REVERT, 예외 중단을 포함한 어떤 결과에서도 올라가지 않습니다. 영구 증가는 임시 배포마다 배포 계정을 바꾸고, 끝에 되돌리는 증가는 나중 트랜잭션의 CREATE와 주소 충돌을 만들기 때문입니다. EIP-2681의 논스 한도는 그대로 적용되어, 배포자 논스가 2^64-1이면 CREATE2처럼 0을 올리고 대상 주소에 접근하지 않습니다. EIP-7702로 위임된 EOA의 코드가 TCREATE를 실행해도 EOA 논스는 바뀌지 않아 대기 중인 트랜잭션을 무효화하지 않습니다.

TCREATE 계정의 범위와 트랜잭션 끝 처리

TCREATE 계정은 현재 트랜잭션에서 TCREATE가 계산한 주소의 계정입니다. initcode 실행이 시작되는 시점부터 트랜잭션이 끝날 때까지 TCREATE 계정이고 생성이 실패하거나 그 TCREATE를 포함한 프레임이 되돌려지면 더는 TCREATE 계정이 아닙니다. 이 EIP의 규칙은 ADDRESS가 TCREATE 계정인 상태로 실행되는 코드에만 적용됩니다. 그 계정의 initcode와 런타임 코드, 그 계정이 DELEGATECALL이나 CALLCODE로 실행하는 코드가 여기에 들어갑니다. 그 계정이 호출하거나 CREATE로 만든 다른 계정의 코드, 다른 계정이 DELEGATECALL, CALLCODE, EIP-7702 위임으로 실행하는 이 계정의 코드는 들어가지 않습니다. 트랜잭션이 끝나면 모든 TCREATE 계정은 논스 0, 코드 없음으로 확정되고 잔액만 보존됩니다. SLOAD와 SSTORE가 멈추므로 저장소는 없습니다. 트랜잭션 전에도 이 주소는 논스 0, 코드 없음이어야 했으므로(아니면 EIP-684로 실패) 트랜잭션 전후 상태는 잔액만 다릅니다. 확정 과정이 상태에서 코드나 저장소를 지우는 일은 없고 잔액까지 0인 빈 계정만 EIP-161에 따라 제거됩니다. 이 EIP는 새 옵코드를 더할 뿐 기존 컨트랙트의 동작은 바꾸지 않습니다.

SLOAD·SSTORE·CREATE2는 멈추고 CREATE·TCREATE는 허용

TCREATE 계정 컨텍스트에서 SLOAD와 SSTORE는 현재 프레임을 예외 중단시킵니다. 슬롯에 접근하지 않고 BAL 항목도 만들지 않습니다. EIP-1153의 TLOAD와 TSTORE는 그대로 쓸 수 있습니다. 지금 쓰이는 임시 컨트랙트(입금 포워더, 인텐트 실행기, CREATE3 프록시)는 저장소를 쓰지 않는다는 것이 근거입니다. CREATE는 허용되고 기존 의미를 따릅니다. 만들어진 컨트랙트는 TCREATE 계정이 아니며 트랜잭션 뒤에도 남습니다. TCREATE 계정의 논스는 initcode 시작 때 1이고 트랜잭션 끝에 0으로 돌아가므로, 같은 계정을 나중에 다시 만들면 같은 논스의 CREATE는 같은 주소를 냅니다. 그 주소에 논스나 코드가 있으면 EIP-684대로 실패하고 TCREATE 계정의 논스는 그래도 올라갑니다. 잔액만 있는 경우는 실패하지 않습니다. 영구 프록시와 SELFDESTRUCT 없이 CREATE3 성질을 얻는 방법입니다. CREATE2는 전송 금액, 논스, 호출 깊이와 무관하게 예외 중단합니다. 0을 올리지 않고 새 주소에 접근하지 않으며 BAL 항목도 없습니다. 새 기능을 더하지 않고 쓰이는 패턴도 없어 미래 호환성을 위해 막았다는 설명입니다. 대가로 Solidity의 new C{salt: s}()와 클론·CREATE3 라이브러리 코드가 이 컨텍스트에서 멈추고 컴파일러는 이를 미리 알 수 없습니다. TCREATE는 중첩이 허용되고 그렇게 만든 계정도 TCREATE 계정입니다.

SELFDESTRUCT 처리

TCREATE 계정 컨텍스트의 SELFDESTRUCT는 EIP-6780이 현재 트랜잭션에서 만들어지지 않은 계정에 정한 대로 동작합니다. 잔액 전부를 대상에게 보내고 현재 프레임을 멈춥니다. 계정은 삭제 대상으로 표시되지 않고 EIP-7928의 관점에서도 파괴된 것으로 취급하지 않습니다. 계정 제거는 이 EIP의 트랜잭션 끝 확정이 맡습니다. 잔액 변화는 이 EIP의 가스 규칙으로 계산하고 EIP-8037의 SELFDESTRUCT 리필 규칙은 적용하지 않습니다. 전송이 대상 계정을 새로 만들 때의 상태 가스와 EIP-7708의 전송 로그 등 나머지 규칙은 그대로입니다. TCREATE 계정이 CREATE로 만든 컨트랙트의 SELFDESTRUCT는 평소처럼 EIP-6780을 따릅니다. 규칙을 따로 두지 않으면 EIP-6780의 삭제, EIP-8037의 리필 없음, EIP-7928의 읽기 기록, 이 EIP의 잔액 리필이 겹치게 됩니다. 이렇게 정하면 SELFDESTRUCT로 끝나는 기존 임시 컨트랙트 코드가 그대로 돌아갑니다. 금지도 검토했지만 값을 보내는 호출은 대상 코드를 실행하고 대상이 되돌리면 실패하므로 같은 대체물이 아니라고 봤습니다. EIP-5920의 PAY라면 대체가 가능합니다.

가스 계산

TCREATE 실행마다 BASE_OPCODE_COST 100과 CREATE2에 보통 붙는 실행 가스(initcode 실행, jumpdest 분석, 메모리 확장, 복사 비용)를 냅니다. CREATE2의 계정 생성 비용인 GAS_NEW_ACCOUNT와 EIP-8037의 코드 저장 상태 가스(배포 코드 1바이트당 CPSB 1530)는 내지 않습니다. 코드 해시 비용 6 × ceil(L / 32)는 CREATE2와 같이 냅니다(L은 배포 코드 길이). 계정 접근 비용은 EIP-8038을 따르며 차가운 계정 접근은 COLD_ACCOUNT_ACCESS 3000, 따뜻한 접근은 WARM_ACCESS 100입니다. 잔액을 바꾸는 연산은 다른 계정과 같이 ACCOUNT_WRITE 9000을 연산마다 내고 환불은 없습니다. 상태 가스는 이 EIP가 따로 정합니다. 계정 생성 자체가 아니라 트랜잭션 끝까지 되돌릴 수 없는 상태 변화에만 매기고 같은 트랜잭션 안에서 되돌려지면 리필합니다. TCREATE 대상 계정의 잔액을 바꾸는 모든 연산(초기화 중 포함)에 적용됩니다. 원래 잔액 0에서 처음 양수가 되면 STATE_BYTES_PER_NEW_ACCOUNT × CPSB를 내고 원래 잔액이 0이었던 계정이 다시 0이 되면 같은 양을 리필합니다. 그 외의 잔액 변경은 상태 가스 조정이 없습니다. 선불 생성 비용이 없는 것은 클라이언트가 TCREATE 실행 시점에 이 계정의 코드와 논스가 상태에 쓰이지 않는다는 것을 알기 때문입니다.

BAL(블록 접근 목록) 기록

TCREATE 계정은 SLOAD와 SSTORE가 멈추므로 EIP-7928의 BAL에 저장소 항목이 없습니다. 트랜잭션 끝 확정은 BAL의 트랜잭션 후 값을 정하기 전에 적용해야 합니다. 그래서 TCREATE 계정은 그 트랜잭션에 nonce_changes나 code_changes 항목이 있을 수 없습니다. CREATE를 실행해 논스가 올라갔던 경우도 같습니다. 주소 자체는 EIP-7928이 CREATE2 대상 주소에 정한 규칙대로 BAL에 들어가고 잔액 변화는 EIP-7928에 따라 기록합니다. TCREATE 자체는 실행 계정에 nonce_changes 항목을 만들지 않습니다. TCREATE 계정 컨텍스트에서 CREATE로 만든 컨트랙트는 다른 배포 컨트랙트와 같이 기록합니다. 예외 중단하는 CREATE2는 어떤 BAL 항목도 더하지 않습니다.

보안 고려사항

TCREATE 주소는 deployer_address, salt, initcode 해시에만 의존하고 트랜잭션 뒤에는 잔액 외의 상태가 남지 않으므로, 같은 주소에 나중 트랜잭션에서 다시 배포할 수 있습니다. NUMBER나 ORIGIN처럼 실행 맥락에 의존하는 런타임 코드는 배포마다 다르게 동작할 수도 있습니다. TCREATE 계정의 CREATE는 만들어지는 트랜잭션마다 같은 주소 순서를 내는데, 이 주소들은 TCREATE initcode에는 묶이지만 CREATE에 넘기는 initcode에는 묶이지 않습니다. 임의 호출자를 위해 TCREATE를 실행하는 컨트랙트는 지금의 CREATE3 팩토리처럼 호출자 주소를 salt에 넣고 TCREATE 계정은 배포한 계정의 CREATE 요청만 받아야 합니다. 그렇지 않으면 누구든 다른 사용자가 기대하는 주소에 임의 코드를 배포할 수 있습니다. 트랜잭션 끝 확정은 다른 계정이 TCREATE 주소에 대해 가진 소유자, 허용량, 허용 목록 같은 상태를 지우지 않습니다. 배포 계정은 나중에 같은 salt와 initcode로 계정을 다시 만들어 그 권한을 다시 쓸 수 있고 initcode는 매번 다른 런타임 코드를 돌려줄 수도 있습니다. 따라서 TCREATE 주소에 지속되는 권한을 주면 안 되고 그 계정이 만든 컨트랙트는 권한 주소를 initcode 인자로 명시해 받아야 합니다. EIP-7702 위임을 TCREATE 주소로 두는 것도 같은 문제입니다. 트랜잭션 사이에 그 주소에는 코드가 없어 호출이 빈 코드로 성공하고 코드는 배포 계정이 같은 트랜잭션에서 계정을 만든 뒤에만 쓸 수 있습니다. 계정은 TCREATE 주소로 위임하지 않아야 합니다.

상태와 포크 논의

원문 상태는 Draft이고 2026-08-03에 만들어졌습니다. TCREATE 옵코드 번호는 TBD로 비어 있습니다. 명세, 가스 수치, 금지 옵코드 목록 모두 아직 바뀔 수 있습니다. 코어 개발자 콜에서는 이렇게 다뤄졌습니다. 08.13 ACDE #243에서는 챔피언이 콜에 없어 후보로 접수되지 않았습니다(DFI). 08.27 ACDE #244에서는 SELFDESTRUCT 환급을 대체할 해법의 자리표시자로 후보에 남았습니다(PFI). 글램스테르담이 일회용 컨트랙트의 가스 환급을 없애면서 생긴 EIP-8037 논쟁의 해법을 헤고타에서 찾겠다는 뜻입니다. 09.10 ACDE #245에서는 논의만 있었습니다. 09.24 ACDE #246에서는 셀프디스트럭트 폐기 논의와 함께 정하기로 하고 결정을 미뤘습니다(보류). 10.08 ACDE #247에서 EIP-8360과 EIP-4758(SELFDESTRUCT 비활성화)을 묶어 헤고타 검토 대상(CFI)에 올렸습니다. 10.12 ACDT #100에서도 논의만 있었고 결정은 없었습니다.

EIP 원문 · ← EIPs