EIP-8360 TCREATE opcode

Hegota Considered for Inclusion · EVM & execution · EIP status Draft · created 2026-08-03

Adds TCREATE, a new EVM instruction that creates a temporary contract that exists only within a single transaction. When the transaction ends, the code and nonce are discarded and only the balance remains.

Why it is needed

Many Ethereum apps do not need contract code to remain after a single transaction. Examples are state channel contracts and one-time-use accounts. Today, these use cases create a contract with CREATE or CREATE2 and delete it with SELFDESTRUCT. However, since EIP-3529 SELFDESTRUCT no longer refunds gas, and since the Cancun upgrade it can only delete contracts created in the same transaction. It is also expected to be restricted further. So the create-and-delete approach offers no cost advantage and cannot be relied on for long. A dedicated instruction for temporary contracts would lower costs and prevent useless code from accumulating in state. It also opens a path to phase out SELFDESTRUCT gradually.

What changes

Today

After EIP-8360

Who is affected

In depth

Address computation and deployer nonce

The TCREATE address is keccak256(0xfe || deployer_address || salt || keccak256(init_code))[12:]. deployer_address is the ADDRESS value of the frame executing TCREATE. 0xfe is placed where CREATE2 uses 0xff so that the two address spaces do not overlap. The hash input length is 85 bytes, the same as CREATE2, and since the RLP first byte 0xfe denotes a list with a payload of 2^48 bytes or more, it also does not collide with CREATE addresses, whose 23 to 31 byte inputs start with 0xd6 to 0xde. The initcode hash is included because, as with CREATE2, the initcode is taken from memory. Without the hash, the deploying account could run different code at the same address. Because this address keeps its balance between transactions, the party sending value must be able to verify from the address alone what code will run. The deployer account's nonce does not increase under any outcome, including address collision, initcode REVERT, and exceptional halt. A permanent increment would change the deploying account for each temporary deployment, and an increment reverted at the end would cause address collisions with later CREATEs in subsequent transactions. The nonce limit of EIP-2681 still applies: if the deployer nonce is 2^64-1, it pushes 0 like CREATE2 and does not access the target address. Even when code of an EOA delegated through EIP-7702 executes TCREATE, the EOA nonce does not change, so pending transactions are not invalidated.

Scope of TCREATE accounts and end-of-transaction handling

A TCREATE account is the account at the address computed by TCREATE in the current transaction. It is a TCREATE account from the moment initcode execution starts until the transaction ends, and it stops being one if creation fails or the frame containing that TCREATE is reverted. The rules of this EIP apply only to code executing with ADDRESS being a TCREATE account. This includes that account's initcode and runtime code, and code that the account executes through DELEGATECALL or CALLCODE. It does not include the code of other accounts that the account calls or creates with CREATE, nor this account's code executed by other accounts through DELEGATECALL, CALLCODE, or EIP-7702 delegation. When the transaction ends, every TCREATE account is finalized with nonce 0 and no code, and only the balance is preserved. Since SLOAD and SSTORE halt, there is no storage. The address was already required to have nonce 0 and no code before the transaction (otherwise it fails under EIP-684), so the only difference between the state before and after the transaction is the balance. Finalization never deletes code or storage from state, and only empty accounts whose balance is also 0 are removed under EIP-161. This EIP only adds a new opcode and does not change the behavior of existing contracts.

SLOAD, SSTORE, and CREATE2 halt, while CREATE and TCREATE are allowed

In a TCREATE account context, SLOAD and SSTORE cause the current frame to halt exceptionally. They do not access the slot and do not create a BAL entry. TLOAD and TSTORE from EIP-1153 can still be used. The rationale is that the temporary contracts in use today (deposit forwarders, intent executors, CREATE3 proxies) do not use storage. CREATE is allowed and follows its existing semantics. The created contract is not a TCREATE account and remains after the transaction. The TCREATE account's nonce is 1 at the start of initcode and returns to 0 at the end of the transaction, so if the same account is created again later, a CREATE with the same nonce yields the same address. If the nonce or code exists at that address, it fails under EIP-684, and the TCREATE account's nonce still increases. A balance-only address does not cause failure. This is a way to get CREATE3 properties without a permanent proxy and without SELFDESTRUCT. CREATE2 halts exceptionally regardless of transfer amount, nonce, or call depth. It does not push 0 and does not access the new address, and there is no BAL entry. The explanation is that it was blocked for future compatibility, since it adds no new capability and no pattern in use depends on it. The cost is that Solidity's new C{salt: s}() and clone and CREATE3 library code halt in this context, and the compiler cannot know this in advance. TCREATE may be nested, and accounts created that way are also TCREATE accounts.

SELFDESTRUCT handling

SELFDESTRUCT in a TCREATE account context behaves as EIP-6780 specifies for an account not created in the current transaction. It sends the entire balance to the target and halts the current frame. The account is not marked for deletion, and EIP-7928 does not treat it as destroyed. Account removal is handled by this EIP's end-of-transaction finalization. The balance change is priced under this EIP's gas rules, and EIP-8037's SELFDESTRUCT refill rule does not apply. The remaining rules stay as they are, including the state gas when the transfer creates a new target account and the EIP-7708 transfer log. SELFDESTRUCT in a contract that a TCREATE account created with CREATE follows EIP-6780 as usual. Without a separate rule, EIP-6780's deletion, EIP-8037's absence of a refill, EIP-7928's read record, and this EIP's balance refill would overlap. With this rule, existing temporary contract code that ends in SELFDESTRUCT keeps working unchanged. A ban was also considered, but a value-sending call executes the target's code and fails if the target reverts, so it was judged not to be an equivalent substitute. With EIP-5920's PAY, a substitution would be possible.

Gas accounting

Each TCREATE execution pays BASE_OPCODE_COST of 100 and the execution gas that normally accompanies CREATE2 (initcode execution, jumpdest analysis, memory expansion, copy costs). It does not pay CREATE2's account creation cost GAS_NEW_ACCOUNT or EIP-8037's code storage state gas (CPSB of 1530 per byte of deployed code). The code hash cost 6 × ceil(L / 32) is paid as in CREATE2 (L is the deployed code length). Account access costs follow EIP-8038: a cold account access costs COLD_ACCOUNT_ACCESS 3000 and a warm access costs WARM_ACCESS 100. An operation that changes a balance pays ACCOUNT_WRITE 9000 per operation, as with other accounts, and there is no refund. This EIP sets the state gas separately. It is charged not for account creation itself but only for state changes that cannot be reverted by the end of the transaction, and it is refilled if the change is reverted within the same transaction. It applies to every operation that changes the balance of a TCREATE target account, including during initialization. When the balance first becomes positive from an original balance of 0, it pays STATE_BYTES_PER_NEW_ACCOUNT × CPSB, and when an account whose original balance was 0 returns to 0, the same amount is refilled. Other balance changes have no state gas adjustment. There is no upfront creation cost because the client knows, at the time TCREATE executes, that this account's code and nonce will not be written to state.

BAL (Block Access List) recording

A TCREATE account halts SLOAD and SSTORE, so it has no storage entries in the EIP-7928 BAL. The end-of-transaction finalization must be applied before the BAL's post-transaction values are determined. Therefore a TCREATE account cannot have nonce_changes or code_changes entries for that transaction. The same holds if a CREATE was executed and raised the nonce. The address itself enters the BAL under the rule EIP-7928 sets for CREATE2 target addresses, and balance changes are recorded according to EIP-7928. TCREATE itself does not create a nonce_changes entry for the executing account. A contract created with CREATE in a TCREATE account context is recorded like any other deployed contract. A CREATE2 that aborts with an exception adds no BAL entry.

Security considerations

A TCREATE address depends only on deployer_address, salt, and the initcode hash, and no state other than the balance remains after the transaction, so it can be deployed again at the same address in a later transaction. Runtime code that depends on execution context, such as NUMBER or ORIGIN, may behave differently on each deployment. CREATE in a TCREATE account yields the same address sequence in each transaction in which it is created. These addresses are bound to the TCREATE initcode but not to the initcode passed to CREATE. A contract that runs TCREATE for arbitrary callers should put the caller address in the salt, as today's CREATE3 factories do, and the TCREATE account should accept CREATE requests only from the account that deployed it. Otherwise anyone could deploy arbitrary code at an address another user expects. The end-of-transaction finalization does not clear state that other accounts hold about a TCREATE address, such as owners, allowances, and allowlists. The deploying account can later recreate the account with the same salt and initcode and reuse those permissions, and the initcode may return different runtime code each time. Therefore persistent permissions must not be granted to a TCREATE address, and contracts created by that account must receive the privileged address explicitly as an initcode argument. Setting an EIP-7702 delegation to a TCREATE address has the same problem. Between transactions, that address has no code, so a call succeeds with empty code, and the code can be used only after the deploying account creates the account in the same transaction. An account must not delegate to a TCREATE address.

Status and fork discussion

The source status is Draft and it was created on 2026-08-03. The TCREATE opcode number is left empty as TBD. The specification, the gas figures, and the list of banned opcodes can all still change. It was handled as follows on the core developer calls. At ACDE #243 on 08.13, the champion was not on the call, so it was not accepted as a candidate (DFI). At ACDE #244 on 08.27, it stayed as a candidate, as a placeholder for a solution to replace the SELFDESTRUCT refund (PFI). This means Hegotá will look for the solution to the EIP-8037 dispute that arose when Glamsterdam removed the gas refund for single-use contracts. At ACDE #245 on 09.10, there was only discussion. At ACDE #246 on 09.24, it was decided to settle it together with the discussion on deprecating SELFDESTRUCT, and the decision was postponed (on hold). At ACDE #247 on 10.08, it was bundled with EIP-8360 and EIP-4758 (disabling SELFDESTRUCT) and placed under consideration for Hegotá (CFI). At ACDT #100 on 10.12, there was again only discussion and no decision.

Original EIP · ← EIPs