-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
1 changed file
with
96 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
--- | ||
eip: 6913 | ||
title: SETCODE instruction | ||
description: replace code in-place | ||
author: William Morriss (@wjmelements) | ||
discussions-to: https://ethereum-magicians.org/t/eip-6913-setcode-instruction/13898 | ||
status: Draft | ||
type: Standards Track | ||
category: Core | ||
created: 2023-04-20 | ||
--- | ||
|
||
## Abstract | ||
|
||
Introduce the `SETCODE` (`0x49`) instruction, which replaces the code of the current executing address from memory. | ||
Future calls to the modified contract use the new code. | ||
|
||
## 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 owned 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 inside of a `CREATE`-like execution scope that returns new code for the executing address (the account returned by `ADDRESS`), `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. | ||
Code replacement is deferred; the current execution scope and its children proceed before code replacement. | ||
After the current execution scope exits successfully (neither reverting nor aborting), the code in the executing account is replaced. | ||
Like `SSTORE`, this account modification will be reverted if a parent scope reverts or aborts. | ||
Unlike `SELFDESTRUCT`, `SETCODE` does not clear account balance or storage. | ||
|
||
Multiple `SETCODE` operations inside the same execution scope are allowed and replace the pending replacement. | ||
|
||
A `SELFDESTRUCT` operation discards the pending code. | ||
|
||
### 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 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 return data. | ||
|
||
## Backwards Compatibility | ||
|
||
The only prior operation changing code is `SELFDESTRUCT`. | ||
`SELFDESTRUCT` remains compatible by discarding any pending replacement code. | ||
|
||
## Test Cases | ||
|
||
| CodeStart | CallData | CodeResult | Gas | | ||
|----------------------|------------------|----------------------|------| | ||
| 365f5f37365f4900 | 365f5f37365f4900 | 365f5f37365f4900 | 6613 | | ||
| 365f5f37365f4900 | 00 | 00 | 5213 | | ||
| 365f5f37365f4900 | | | 5013 | | ||
| 365f5f37365f49595ffd | 365f5f37365f4900 | 365f5f37365f49595ffd | 6617 | | ||
| 365f5f37365f49fe | 365f5f37365f4900 | 365f5f37365f49fe | 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). |