--- eip: 8360 title: TCREATE Opcode description: Introduce a new opcode for creating contracts that exist only for the duration of a single transaction author: Helkomine (@Helkomine), abc-123-c (@abc-123-c), Milos (@milonite), Peter Phillips (@PeterMPhillips) discussions-to: https://ethereum-magicians.org/t/eip-8360-tcreate-opcode/29258 status: Draft type: Standards Track category: Core created: 2026-08-03 requires: 161, 684, 1014, 1153, 3529, 7928, 8037, 8038 --- ## 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. ## Motivation Many Ethereum applications do not require deployed code to persist beyond a single transaction. Examples include state-channel contracts, single-use accounts, and other ephemeral execution environments. Today, such patterns rely on a combination of `CREATE`/`CREATE2` and `SELFDESTRUCT`. However, `SELFDESTRUCT` has no longer provided gas refunds since [EIP-3529](./eip-3529.md), can only delete contracts created within the same transaction since the Cancun upgrade, and is expected to undergo further semantic restrictions in future protocol upgrades. As a result, the deploy-and-self-destruct pattern is no longer economically attractive, nor can its long-term behavior be relied upon. Providing a dedicated EVM opcode for temporary contract deployment offers a lower-cost alternative while improving state management by preventing unnecessary long-term code accumulation. This proposal also provides a gradual migration path away from `SELFDESTRUCT`. The proposal is fully compatible with account abstraction. Existing account semantics remain unchanged, while accounts may deploy transient contracts to implement extended execution logic entirely through calldata, for example, hook-based execution. Such hooks may execute dedicated logic or serve as reusable code templates that are invoked through `DELEGATECALL`. ## Specification ### Parameters | Parameter| Description| Value | Source | | --- | --- | --- | --- | | `TCREATE` | New opcode | TBD | This EIP | | `BASE_OPCODE_COST` | Base opcode cost | 100 | This EIP | | `CPSB` | State gas price per byte | 1530 | [EIP-8037](./eip-8037.md) | | `STATE_BYTES_PER_NEW_ACCOUNT`| State bytes created per account| 120 | [EIP-8037](./eip-8037.md) | | `WARM_ACCESS` | Touch of an already warm account or storage slot| 100 | [EIP-8038](./eip-8038.md) | | `COLD_ACCOUNT_ACCESS` | Cold touch of an account | 3000 | [EIP-8038](./eip-8038.md) | | `ACCOUNT_WRITE` | Surcharge applied when an account leaf is modified for the first time | 9000 | [EIP-8038](./eip-8038.md) | ### Semantics The behavior of `CREATE2` is defined in [EIP-1014](./eip-1014.md). `TCREATE` behaves identically to `CREATE2` except for the following changes: - The address is computed as `keccak256(0xfe || deployer_address || salt || keccak256(init_code))[12:]` where `||` denotes byte concatenation. - At the end of the transaction, all code, nonce, and storage created during transaction execution are removed from the target account. The account balance is preserved. An account that becomes empty is removed from the state trie at the end of the transaction in accordance with [EIP-161](./eip-161.md). The semantics are clarified further [here](#state-transition-handling). - Code deployment rules and collision semantics are identical to `CREATE2`. A target account is considered non-empty during the transaction, and address collisions therefore revert execution in accordance with [EIP-684](./eip-684.md). The semantics are clarified further [here](#state-transition-handling). ### State transition handling At the end of the transaction, the account state of every contract created by `TCREATE` is finalized as follows: - The account nonce is reset to 0. - The account code is removed. - All storage associated with the account is removed. - The account balance is preserved. `TCREATE` does not increment the nonce of the executing account. ### Opcode Behavior Changes #### `SSTORE` and `SLOAD` handling Within a `TCREATE`-created account, `SSTORE` and `SLOAD` MUST behave as `TSTORE` and `TLOAD` ([EIP-1153](./eip-1153.md)): they operate on storage that is scoped to the transaction and discarded when it completes, together with the rest of the account's transient state. Writes performed through `SSTORE` are never committed to the persistent storage trie, and subsequent transactions observe the account's storage as empty. Whether clients implement this by sharing the [EIP-1153](./eip-1153.md) transient storage or by keeping a separate ephemeral storage is an implementation detail and is not observable by contracts. #### BAL handling Storage accesses performed by `SLOAD` and `SSTORE` within a `TCREATE` account MUST NOT be recorded in the block-level Block Access List (BAL) defined by [EIP-7928](./eip-7928.md). Although these operations may read from or modify the ephemeral storage of the `TCREATE` account during transaction execution, none of these storage changes can affect the persistent state after the transaction completes. Excluding them from the BAL therefore avoids recording state accesses that have no persistent state effect and reduces the size of the block access list. This exclusion applies to both `SLOAD` and `SSTORE`. A `SLOAD` performed by a `TCREATE` account MUST NOT create a BAL entry for the accessed storage slot, and an `SSTORE` performed by a `TCREATE` account MUST NOT create or update a BAL entry for the modified storage slot. #### `CREATE` and `CREATE2` handling Within a `TCREATE`-created account, `CREATE` is permitted and follows its existing semantics. Because the account nonce is 1 when initcode execution begins and is reset to 0 at the end of the transaction, the first `CREATE` executed by the account in each transaction derives its address from nonce 1. The resulting contract is persistent; only the `TCREATE`-created account is ephemeral. If the account is created again by `TCREATE` in a later transaction and executes `CREATE`, the derived address is the same as in the earlier transaction. If that address is non-empty, the creation fails in accordance with [EIP-684](./eip-684.md). Within a `TCREATE`-created account, `CREATE2` MUST result in an exceptional halt of the current execution frame. This restriction applies only to code executing in the context of the `TCREATE`-created account, including code reached through `DELEGATECALL` or `CALLCODE` from that account. It does not apply to other accounts called from it. ### Gas Accounting Each execution of `TCREATE` is charged `BASE_OPCODE_COST` together with the execution-gas costs that normally apply to `CREATE2`, including initcode execution, jumpdest analysis, memory expansion, copying costs, and other execution-related charges. `TCREATE` does not incur the account-creation charges associated with `CREATE2`, such as `GAS_NEW_ACCOUNT` or code-deposit costs. Account access costs continue to follow [EIP-8038](./eip-8038.md). In particular, accesses to cold accounts are charged `COLD_ACCOUNT_ACCESS` as appropriate. State-gas accounting is defined separately by this EIP. Rather than charging for account creation itself, state-gas is charged only for state changes that cannot be reasonably reclaimed by the end of the transaction, and refilled when those state changes are reverted within the same transaction. Any operation that modifies the balance of the target account of a `TCREATE` operation, including during contract initialization, performs state-gas accounting according to the following table. | Original balance | Current balance | New balance | Description | State-gas charges/refills | | --- | --- | ---- | --- | --- | | 0 | x | 0 | Balance restored to zero when the initial transaction balance was zero | `STATE_BYTES_PER_NEW_ACCOUNT × CPSB` refilled | | 0 | 0 | x | First balance written to the account | `STATE_BYTES_PER_NEW_ACCOUNT × CPSB` charged | | 0 or x | y | z | Existing account balance updated | No state-gas adjustment | Execution-gas accounting for account updates (following the principles introduced in [EIP-8038](./eip-8038.md)) is defined as follows. | Original balance | Current balance | New balance | Description | Regular-gas charges/refills | | --- | --- | --- | --- | --- | | x | y | x | Balance restored to its value at the beginning of the transaction | `ACCOUNT_WRITE` refunded | | x | x | y | First balance modification | `ACCOUNT_WRITE` charged | | 0 or x | y | z | Subsequent balance modification | No regular-gas adjustment | Additionally, the gas costs of `SSTORE` and `SLOAD` are reduced to match those of `TSTORE` and `TLOAD`, respectively, since they operate exclusively on transient storage within `TCREATE` execution. ## Rationale ### Lower Deployment and Execution Costs Today, combining `CREATE` with `SELFDESTRUCT` is the only mechanism for implementing temporary contracts. This approach is relatively expensive and no longer benefits from gas refunds, reducing incentives for efficient state management. By making the cost of temporary contracts comparable to that of a regular `CALL`, this proposal encourages experimentation with transient execution models while avoiding unnecessary long-term state growth. ### Address Prefix Selection The `0xfe` prefix is chosen to ensure that the address derivation scheme used by `TCREATE` cannot collide with that of `CREATE2`, which uses the `0xff` prefix as specified in [EIP-1014](./eip-1014.md). Selecting the adjacent value `0xfe` preserves the existing address derivation structure while providing a distinct domain separator. This choice also remains outside the range of prefixes that can be generated by RLP encoding, whose maximum representable payload size is many orders of magnitude larger (up to petabyte-scale objects). Consequently, no ambiguity is introduced with existing contract address derivation mechanisms. ### Temporary Nonce Semantics Although `TCREATE` creates only transient account state, its execution temporarily follows the existing nonce semantics of `CREATE2`. This avoids introducing additional exceptional rules for address collision handling during contract creation. In particular, the target account becomes non-empty during execution by virtue of its temporary nonce, preventing multiple initialization frames from executing simultaneously at the same address before code deposition. Resetting the nonce of transient accounts at the end of the transaction preserves the stateless nature of `TCREATE` while allowing implementations to reuse existing contract creation logic with minimal modifications. The nonce of the executing account is not incremented. The `TCREATE` address does not depend on it, so an increment would serve only convention. Incrementing it and restoring it at the end of the transaction would cause collisions: a `CREATE` executed after `TCREATE` in the same transaction would use the incremented nonce, and after the restore a `CREATE` in a later transaction would derive the same address again. For EOAs delegated through [EIP-7702](./eip-7702.md), this also keeps the sender's nonce independent of transient deployments, which simplifies transaction simulation and mempool analysis. ### `SSTORE` and `SLOAD` handling Mapping `SLOAD` and `SSTORE` to ephemeral storage preserves compatibility with existing contract code that assumes the availability of state storage while preventing persistent state growth. Prohibiting these opcodes entirely would introduce unnecessary incompatibilities, whereas allowing writes to persistent storage would conflict with the ephemeral nature of `TCREATE` accounts and the requirement that no storage root remains after transaction completion. The distinction between ephemeral storage used by `SLOAD` and `SSTORE` and the transient storage defined by [EIP-1153](./eip-1153.md) is intentionally invisible to contracts. It exists solely to simplify client implementations while preserving the expected semantics of both storage models. ### State-Gas Accounting for Balance Transfers Removing balance accounting entirely would simplify gas accounting but would reintroduce a special case that [EIP-8246](./eip-8246.md) sought to eliminate. Preserving balance semantics while accounting only for temporary state changes provides a more consistent design. This decision may be revisited if native balance-burning mechanisms are introduced in the future. ### Extended state accounting method Unlike `CREATE2`, whose state-gas accounting is tied to permanent account creation, `TCREATE` accounts are ephemeral. Therefore, charging for account creation itself would overestimate the persistent state introduced by the opcode. Instead, this EIP generalizes the state-accounting model of [EIP-8037](./eip-8037.md) by charging only for state that remains after transaction execution and refilling charges when transient state is completely eliminated. ### State creation gas is not upfront The absence of upfront account-creation and code-deposit charges is possible because the client knows from the execution of `TCREATE` that the target account is temporary. Unlike `CREATE2`, whose resulting account may persist after the transaction, a `TCREATE` account is guaranteed by the protocol to have its code, nonce, and storage removed at the end of the transaction. The client therefore does not need to reserve gas in advance for persistent account state that cannot survive the transaction. This does not make account creation or code execution free. The execution costs required to initialize and execute the account are still charged normally, and state-gas is charged whenever execution creates state that may persist beyond the temporary lifetime of the account. In particular, a non-zero balance transferred to a `TCREATE` account is charged as account state because the balance is preserved at the end of the transaction. If that balance is subsequently transferred out in full during the same transaction, the corresponding state-gas charge is refilled because the state no longer needs to be preserved. ### `CREATE` and `CREATE2` handling `CREATE` from a `TCREATE`-created account yields a contract address that depends only on the deployer, the salt, and the `TCREATE` initcode, and not on the bytecode of the created contract. This is the "`CREATE3`" deployment pattern currently implemented with a persistent or self-destructing proxy. With `TCREATE`, the proxy leaves no account in the state. The collision on repeated creation gives each address a single deployment, which is the expected behavior of this pattern. `CREATE2` from a `TCREATE`-created account provides no capability that the deploying account cannot obtain by executing `CREATE2` directly. Its address includes the hash of the initcode, so it does not offer the property above. Because the `TCREATE` account can be created again with the same address, a repeated `CREATE2` with the same salt and initcode collides with the contract created earlier. Prohibiting it removes this case from the specification. ## Backwards Compatibility ### Contract Execution Flow Deployment workflows for temporary-use contracts remain unchanged except that no deployed bytecode is retained after the transaction completes. Applications requiring persistent code or storage should continue to use `CREATE` or `CREATE2`. ## Security Considerations ### Repeated Contract Deployment Because target addresses are derived using the same rules as `CREATE2`, while all account state except balance is removed after transaction completion, such accounts become valid deployment targets again under [EIP-684](./eip-684.md). Contracts whose runtime code depends on execution context (for example, using `NUMBER`, `ORIGIN`, or similar opcodes) may exhibit different behavior across deployments if appropriate safeguards are not implemented. ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md).