EIP-8360: TCREATE Opcode

Discussion topic for EIP-8360

Abstract

This EIP introduces a new EVM opcode, TCREATE, where T stands for transient, providing an official, gas-efficient, and state-aware mechanism for deploying temporary contracts.

1 Like

Can a contract deployed via TCREATE execute a regular CREATE?

As written, it seems yes, since all other opcodes retain normal behavior. In that case, the transient contract’s nonce would increase during execution, but be deleted at the end of the transaction.

This creates a problem across transactions:

  1. TCREATE deploys contract A with nonce 0.

  2. A uses CREATE, deploying child B from nonce 0.

  3. A’s nonce is removed at transaction end.

  4. A is deployed again later and starts from nonce 0.

  5. Its next CREATE derives B’s address again and collides under EIP-684.

This would make persistent CREATE deployments from a reusable transient address unreliable. Should CREATE/CREATE2 be prohibited inside TCREATE contracts, or should their children also be transient?

That has been considered. In fact, TCREATE is the cost-effective version of the CREATE2/SELFDESTRUCT combination, and its issues are expected to be similar. Deploying to a target address already has code forbidden by EIP-684 means there is no risk if CREATE deployments are made via temporary contracts. If you use the TCREATE/CREATE combination for contract deployment, it is essentially the CREATE3 model currently in use.

I will go over this EIP as of commit Add EIP: TCREATE Opcode · ethereum/EIPs@a9031bd · GitHub (initial commit creating this EIP).

The EIP depends on EIP-7610, which was (likely) correct at the time of writing, but this should be changed to EIP-684 as this is the current collission check. EIP-7610 got removed from Glamsterdam.

In Specification:

When transaction execution completes, the deployer’s nonce is restored to original_nonce + permanent_nonce_increments, where permanent_nonce_increments excludes nonce increments introduced solely by TCREATE.

How does this work if we also invoke CREATE or CREATE2? What if we TCREATE, then CREATE? To which nonce should we roll back? Would it not be easier to state that TCREATE simply does not increase the nonce? (the address calculation of TCREATE (or CREATE2) does not depend on nonce). This would directly remove this conflict. Is there a pattern necessary where TCREATE temporarily bumps the nonce?

SSTORE and SLOAD

Could this be renamed that SSTORE and SLOAD behalve like TSTORE and TLOAD in an TCREATE-created account? I belive this part makes this EIP more complex to implement. I do not have the full context, likely this is because some L2s do not support EIP-1153 and there might also be some reasoning regarding TSTORE/TLOAD not ending up in written values. For instance in frame transactions or via storage introspection we might want to use these features from the S family of opcodes (although this is currently not possible on Mainnet EVM yet)? What about block access lists? Do these S opcodes get added to the list?

Gas accounting section:

TCREATE does not incur the account-creation charges associated with CREATE2, such as GAS_NEW_ACCOUNT or code-deposit costs.

What if we send value using TCREATE? Then it clearly creates an account. I also feel like for DoS reasons we need to charge the code-deposit costs, otherwise deploying code is “free”. This gets refunded at the end of the transaction. It seems in the table later this is changed though, but this sentence reads like it never charges account creation costs.

(I need to thorougly check the tables)

2 Likes

Thank you to everyone who has contributed so far particularly for raising the cross-transaction CREATE collision question and for the thorough review of the initial commit.

Current design consensus:

The core semantics appear to have converged:

• TCREATE creates an ephemeral account (code, nonce, and storage are discarded at the end of the transaction; balance is preserved).

• Address derivation uses the 0xfe prefix (distinct from CREATE2’s 0xff).

• TCREATE does not increment the caller’s nonce.

• Inside a TCREATE-created account:

• CREATE is allowed and produces a persistent child (protected by EIP-684 on subsequent reuse of the same transient address).

• CREATE2 causes an exceptional halt.

• SSTORE / SLOAD behave as TSTORE / TLOAD (ephemeral only).

• Storage accesses performed by those opcodes inside a TCREATE account are excluded from the Block Access List (EIP-7928).

This cleanly supports the useful “CREATE3-style” pattern while keeping the factory itself strictly transient and free of persistent state growth.

Open points:

The outstanding items are mainly around precise wording, gas tables, and client implementation cost. Proposed resolutions:

1. Nonce handling

The earlier “restore original_nonce + permanent_nonce_increments” language has been replaced by the simpler rule:

TCREATE never increments the executing account’s nonce.

This removes the ambiguity when mixed with ordinary CREATE/CREATE2 and matches the suggestion in the review.

2. SSTORE / SLOAD mapping

The mapping to ephemeral behaviour is intentional for backward compatibility (existing contracts that use ordinary storage variables continue to work).

Implementation may share the EIP-1153 transient-storage map or use a separate ephemeral map the choice is not observable.

BAL exclusion is already normative.

Welcome feedback from client teams on whether the dual-path handling introduces meaningful complexity.

3. Gas accounting

• No permanent GAS_NEW_ACCOUNT or code-deposit costs are charged (the account and its code are guaranteed to disappear).

• Execution gas (initcode, jumpdest analysis, memory expansion, etc.) is charged normally.

• Balance changes are metered via the existing state-gas / regular-gas tables with refill semantics.

The “code-deposit is free” design is deliberate to avoid re-introducing refund complexity. If client implementers believe a refundable code-deposit charge is still required for DoS resistance, revisit the tables.

Proposed next steps:

1. A focused clarifying PR against the EIP text that:

• Confirms the simplified nonce rule,

• Strengthens the SSTORE/SLOAD and BAL wording,

• Adds a short explicit note on the intentional omission of permanent account-creation / code-deposit costs and the associated reasoning.

2. Request for client-team feedback (Geth, Nethermind, Reth, Erigon, Besu, etc.) on:

• Implementation cost of the SSTORE → ephemeral mapping,

• Whether any additional gas or BAL edge cases need coverage,

• Preference on the code-deposit charging question.

3. Once the above is settled, moving to test-vector expansion and readiness for further PFI / inclusion discussion.

Please reply with any remaining concerns, alternative preferences, or implementation observations. Concrete wording suggestions or test cases are especially welcome.

Looking forward to closing these last points cleanly.

1 Like

Most of the updates have been made here and are currently awaiting review for merging:

Thank you for the quick update and for pointing to the PR.

It’s excellent to see that the majority of the feedback from this thread (nonce simplification, TCREATE account context, opcode rules for CREATE/CREATE2 and SSTORE/SLOAD, BAL exclusion, and gas alignment including the intentional omission of permanent account-creation/code-deposit costs) has already been incorporated into:

PR #12370 – Update EIP-8360: Define TCREATE account context, opcode rules, and gas alignment.

To help move this forward cleanly, it would be very useful to hear from client teams (Geth, Nethermind, Reth, Erigon, Besu, and others) on the following points once they have looked at the PR:

1. Implementation complexity of the SSTORE/SLOAD → ephemeral mapping under the new TCREATE account context definition.

2. Whether the current gas alignment (no permanent account-creation or code-deposit charges) is acceptable, or if a refundable charge is still preferred for DoS resistance.

3. Any remaining edge cases related to BAL (EIP-7928) or state-gas metering.

Once PR #12370 has been reviewed and merged, the remaining work should mainly be expanding test vectors and preparing for further PFI / inclusion discussion.

2 Likes

A TCREATE address is a stable deployment-capability identity, not a stable runtime-code identity. Persistent authority MUST NOT be inferred solely from equality of TCREATE address across transactions.

For every successful transaction and every successfully created TCREATE address A, ordinary EVM execution applies until transaction finalization. At finalization, A is projected into successor state as nonce = 0, code = ∅, storage = ∅, and balance = final_balance. Every effect on other accounts, every persistent child created with CREATE, and every log, transfer, or ordinary state transition survives or reverts according to normal EVM rules. TCREATE membership itself is transaction-scoped, journaled, and rolls back with the frame that introduced it.

That single invariant resolves state-lifetime ambiguity. “Transient” no longer means “whatever the implementation thinks temporary means.” It identifies exactly which state loses authority at the crossing and which consequences survive. Then the gas rule becomes equally simple:

Charge work. Do not charge persistent state that does not survive.

We should also create an explicit rule to solve a deeper authority problem for PR #12370: the same TCREATE address can be recreated in a later transaction with different runtime code, because the address commits to the initcode, not necessarily the runtime code it eventually returns. Persistent external state–an allowance, owner slot, allowlist entry, EIP-7702 delegation–can therefore survive while the code exercising that authority changes.

That should be stated as an actual identity boundary:

A TCREATE address is a stable deployment-capability identity, not a stable runtime-code identity. Persistent authority MUST NOT be inferred solely from equality of TCREATE address across transactions. If we eventually want TCREATE addresses to be safe long-lived authority principals, that is a separate extension: bind an expected runtime-code hash into creation identity and reject deployment if the returned runtime code does not match.

If i’m missing anything feel free to let me know.

1 Like

This is similar to the current CREATE[2].

Yes. CREATE2 is the precedent. The difference is CREATE2 normally leaves deployed code occupying the address, while TCREATE deliberately returns the address to a re-creatable state at every transaction boundary. That makes the identity/authority distinction a recurring property of the primitive rather than an exceptional lifecycle case. Which is why I think it is worth stating explicitly for TCREATE: address continuity across transactions does not imply runtime-code continuity or inherited authority. The precedent exists and TCREATE makes the boundary first-class.

1 Like

I have noted that risk in the Security Considerations section, but I will clarify it further.