---
eip: 6913
title: SETCODE instruction
description: new instruction to replace code in-place
author: William Morriss (@wjmelements)
discussions-to: https://ethereum-magicians.org/t/eip-6913-setcode-instruction/13898
status: Withdrawn
type: Standards Track
category: Core
created: 2023-04-20
withdrawal-reason: The author prefers EIP-7702
---

## Abstract

Introduce the `SETCODE` (`0xfc`) instruction, which replaces the code of the executing account from memory.

## Motivation

Many contracts are upgradeable in order to facilitate improvement or defer decisions without migrating to a new address.
Contracts presently do this in several ways:

The oldest method uses `CALL`.
The limitation of this method is that internal state must be modifiable by all future implementations.

Second, `DELEGATECALL` can proxy the implementation.
Some proxies are minimal while others branch to many separate implementation accounts.
This method can also bypass account code size limits.

A third method uses `SELFDESTRUCT` and `CREATE2` to replace code in-place.
This method improves upon the prior methods by removing the need to call into external contracts.
One limitation of this method is that any internal state is removed by `SELFDESTRUCT`.
Another limitation is that `SELFDESTRUCT` does not remove code until the end of the transaction, sacrificing availability until `CREATE2` can complete the upgrade.

Given the upcoming deprecation of `SELFDESTRUCT`, `SETCODE` introduces a better method for replacing code in-place.

## Specification

When within a read-only execution scope like the recursive kind created by `STATICCALL`, `SETCODE` causes an exceptional abort.

When the currently executing code does not equal the code of the executing account, such as can happen inside of `DELEGATECALL` or `CREATE`, `SETCODE` causes an exceptional abort.

Otherwise, `SETCODE` consumes two words from the stack: offset and length.
These specify a range of memory containing the new code.
Any validations that would be performed on the result of `CREATE` or `CREATE2` occur immediately, potentially causing failure with exceptional abort.
The operations `EXTCODESIZE` and `EXTCODECOPY` now query the updated code, and message-calls such as `DELEGATECALL`, `CALLCODE`, `CALL`, and `STATICCALL` now execute the updated code.
Any execution scopes already executing replaced code, including the one that `SETCODE`, will continue executing the prior code.
Inside such scopes, `CODESIZE` and `CODECOPY` continue to query the executing code.

Like `SSTORE`, this account modification will be reverted if the current scope or any parent scope reverts or aborts.

Unlike `SELFDESTRUCT`, `SETCODE` does not clear account balance, nonce, or storage.

### Gas

The gas cost of this operation is the sum of `Gselfdestruct` and the product of `Gcodedeposit` and the number of bytes in the new code.

## Rationale

The behavior of `CODECOPY`, `CODESIZE`, `EXTCODESIZE`, and `EXTCODECOPY` match the behavior of `DELEGATECALL` and `CREATE`, where it is also possible for executing code to differ from the code of the executing account.

The gas cost of `SETCODE` is comparable to `CREATE` but excludes `Gcreate` because no execution context is created, nor any new account.
Other account modification costs are accounted for outside of execution gas.

Unlike `SELFDESTRUCT`, execution proceeds normally after `SETCODE` in order to allow validation and return data.
Post-update validation can undo a `SETCODE` operation with `REVERT`, or with a recursive `SETCODE`, but `REVERT` uses less gas.

Preventing `SETCODE` within most `DELEGATECALL` allows static analysis to easily identify mutable code.
Account code not containing the `SETCODE` operation can be safely assumed to be immutable.
Code observed in a non-reverting context to be immutable will remain immutable, allowing on-chain static analysis for immutability.

## Backwards Compatibility

The only prior operation changing code is `SELFDESTRUCT`.
As code modification via `SELFDESTRUCT` is deferred until the end of the transaction, its interactions with `SETCODE` are well-defined.

## Test Cases

| CodeStart            | CallData         | CodeResult           | Gas  |
|----------------------|------------------|----------------------|------|
| 365f5f37365ffc00     | 365f5f37365ffc00 | 365f5f37365ffc00     | 6613 |
| 365f5f37365ffc00     | 00               | 00                   | 5213 |
| 365f5f37365ffc00     |                  |                      | 5013 |
| 365f5f37365ffc595ffd | 365f5f37365ffc00 | 365f5f37365ffc595ffd | 6617 |
| 365f5f37365ffcfe     | 365f5f37365ffc00 | 365f5f37365ffcfe     |  all |

## Security Considerations

Risks related to `SETCODE` similarly apply to other upgrade patterns.

Most contracts should never be replaced and should not be upgradeable.
Any upgrade mechanism can risk permanent failure.
The possibility of upgrade perpetuates such risk.

Access to upgrade operations should be restricted.
Upgrades should never be performed in a hurry or when tired.
Upgrades should be tested under as similar conditions to production as possible; discrepancies are sources of unexpected results.
When possible, multiple engineers should preview and independently verify pending upgrade procedures.

Block explorers, wallets, and other interfaces should flag upgradeable code.
Client software should warn against approving [ERC-20](./eip-20.md) or [ERC-721](./eip-721.md) tokens for upgradeable accounts.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
