-
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.
Merged by EIP-Bot.
- Loading branch information
Showing
1 changed file
with
107 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,107 @@ | ||
--- | ||
eip: 7761 | ||
title: HASCODE instruction | ||
description: Introduce HASCODE instruction to replace the EXTCODESIZE > 0 check in EOF | ||
author: Andrei Maiboroda (@gumb0), Piotr Dobaczewski (@pdobacz), Danno Ferrin (@shemnon) | ||
discussions-to: https://ethereum-magicians.org/t/eip-7761-is-contract-instruction/20936 | ||
status: Draft | ||
type: Standards Track | ||
category: Core | ||
created: 2024-09-01 | ||
requires: 3540, 7692 | ||
--- | ||
|
||
## Abstract | ||
|
||
Allow EOF contracts to discriminate between EOAs (Externally Owned Accounts) and contract accounts by introducing an `HASCODE` instruction. | ||
|
||
## Motivation | ||
|
||
EOFv1 as scoped in [EIP-7692](./eip-7692.md) removes code introspection capabilities from the EVM, including the `EXTCODESIZE` instruction. This makes it hard for [ERC-721](./eip-721.md) and [ERC-1155](./eip-1155.md) standard contracts to be implemented, as they rely on discovering whether a token's `safeTransfer` call target was an EOA or a contract account: | ||
|
||
- `safeTransfers` to EOAs succeed | ||
- `safeTransfers` to contract accounts call an `onERC721Received` (`onERC1155Received`) on them and expect to get a special magic return value, otherwise the transfer reverts (on the assumption that such a receipient may not be able to interact with the token) | ||
|
||
`HASCODE` is aimed to fill this gap and bring back the possibility to easily implement ERC-721 and ERC-1155 standard contracts in EOF. | ||
|
||
## Specification | ||
|
||
### Parameters | ||
|
||
| Constant | Value | | ||
| - | - | | ||
| `FORK_BLKNUM` | tbd | | ||
| `GAS_COLD_ACCOUNT_ACCESS` | Defined as `2600` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/fcd12750edd4443a91f138728689a1d0a503a7c1/src/ethereum/cancun/vm/gas.py#L64) | | ||
| `GAS_WARM_ACCESS` | Defined as `100` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/fcd12750edd4443a91f138728689a1d0a503a7c1/src/ethereum/cancun/vm/gas.py#L65) | | ||
|
||
We introduce a new EOFv1 instruction on the block number `FORK_BLKNUM`: `HASCODE` (`0xe9`) | ||
|
||
EOF code which contains this instruction before `FORK_BLKNUM` is considered invalid. Beginning with block `FORK_BLKNUM` `0xe9` is added to the set of valid EOFv1 instructions. | ||
|
||
### Execution Semantics | ||
|
||
#### `HASCODE` | ||
|
||
- deduct `GAS_WARM_ACCESS` gas | ||
- pop 1 argument `target_address` from the stack | ||
- if `target_address` has any of the high 12 bytes set to a non-zero value (i.e. it does not contain a 20-byte address), then halt with an exceptional failure | ||
- deduct `GAS_COLD_ACCOUNT_ACCESS - GAS_WARM_ACCESS` if `target_address` is not in `accessed_addresses` and add `target_address` to `accessed_addresses` | ||
- push `1` onto the stack if `target_address.code` is not empty, `0` otherwise | ||
|
||
If `target_address.code` contains an [EIP-7702](./eip-7702.md) delegation, the result of `HASCODE` should follow the delegation and return a result according to the delegation designator account. Additional gas costs and rules concering `accessed_addresses` apply as specified in EIP-7702 for code reading instructions like `EXTCODESIZE`. | ||
|
||
If `target_address` points to an account with a contract mid-creation, it behaves aligned with similar instructions like `EXTCODESIZE` and returns `0`. | ||
|
||
## Rationale | ||
|
||
### Alternative solutions | ||
|
||
There have been other solutions proposed to alleviate the problems related to lack of code introspection required for ERC-721 and ERC-1155 standards: | ||
|
||
1. Extra status code for `EXT*CALL` instruction - allowing to discriminate a result coming from calling an EOA | ||
2. Extra argument for `EXT*CALL` (a "fail if EOA" flag) | ||
3. Two return values from `EXT*CALL` (status code + whether it was EOA) | ||
4. `EXT*CALL` setting a new `callstatus` register (+ a new `CALLSTATUS` instruction) | ||
5. Reenable `EXTCODESIZE` in EOF, keeping its behavior same as in legacy | ||
|
||
`HASCODE` has been chosen as the most elegant and minimal solution satisfying the requirements at hand and still able to be introduced in EOFv1. | ||
|
||
### Reuse the `0x3b` (`EXTCODESIZE`) opcode for `HASCODE` | ||
|
||
A new opcode is prefered by a general policy to not reuse opcodes. Also `HASCODE` can be rolled out in legacy EVM if desired. | ||
|
||
### Keep code introspection banned | ||
|
||
Removing code introspection is one of the tenets of EOF and `HASCODE` would be an exception from the principle. Without `HASCODE`, ERC-721 and ERC-1155 standard implementations have to resort to either: | ||
|
||
1. Leveraging a "booster contract" which would be legacy and would call `EXTCODESIZE` for them. This has been deemed inelegant and inconvenient from the point of view of library implementers, requiring them to hard code an address of such a contract (with the usual address-related problems arising on different EVM chains) | ||
2. Continuing to use legacy EVM themselves. This is sub-optimal, since EVM compilers are likely to at some point deprecate legacy EVM as compilation target | ||
3. Updating the standards to not rely on code introspection (`safeTransfer` safe guards) patterns, also unlikely to happen as ERC-721 and ERC-1155 are Final and adopted in practice. | ||
|
||
### "Endgame Account Abstraction" issues | ||
|
||
TBD - can someone verbalize it? <!-- TODO --> | ||
|
||
### Relation to [EIP-7702](./eip-7702.md) "Set EOA account code" | ||
|
||
After [EIP-7702](./eip-7702.md) is activated, the discrimination between EOAs and contract accounts using `EXTCODESIZE` (or `HASCODE`) has an edge case: Whenever an EOA sets its code to a contract account which does not respond as expected to an `onERC721Received` (`onERC1155Received`) callback, transfers to it will revert, despite the recipient being able to interact with the token. This has been deemed unlikely to be a problem, as for the intended real-world uses of EIP-7702, those callbacks will be implemented by designator codes. | ||
|
||
### Including safe guarding against proxy bricking | ||
|
||
In parallel to the ERC-721 / ERC-1155 problem, another potential risk has been brought to attention. Since EOFv1 prohibits `EXTDELEGATECALL` targetting legacy contracts, there exists a scenario where an EOF proxy contract accidentally upgrades its implementation to a legacy EVM one. Since reverting this or upgrading again (using current proxy standards) requires the implementation contract to be called, it would effectively render the contract unusable. | ||
|
||
One potential solution to this would be to have a generalized `CONTRACT_KIND` instruction instead of `HASCODE` which would further discriminate the account into legacy or EOFv1 with a `0` / `1` / `2` return value, thereby providing means for an additional safeguard against such a scenario. | ||
|
||
This problem is potentially solvable on the application layer (proxy upgrade would include a direct check of the implementation contract being `EXTDELEGATECALL`-able) or even by re-enabling `EXTDELEGATECALL` to a legacy target in a future EVM upgrade. | ||
|
||
## Backwards Compatibility | ||
|
||
`HASCODE` at `0xe9` can be introduced in a backwards compatible manner into EOFv1 (no bump to version), because `0xe9` has been rejected by EOF validation before `FORK_BLKNUM` and there are no EOF contracts on-chain with a `0xe9` which would have their behavior altered. | ||
|
||
## Security Considerations | ||
|
||
Needs discussion <!-- TODO --> | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). |