Skip to content

Commit

Permalink
Rename to HASCODE
Browse files Browse the repository at this point in the history
  • Loading branch information
pdobacz committed Sep 9, 2024
1 parent 4cae577 commit 762a6eb
Showing 1 changed file with 14 additions and 14 deletions.
28 changes: 14 additions & 14 deletions EIPS/eip-7761.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
eip: 7761
title: ISCONTRACT instruction
description: Introduce ISCONTRACT instruction to replace the EXTCODESIZE > 0 check in EOF
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
Expand All @@ -13,7 +13,7 @@ requires: 3540, 7692

## Abstract

Allow EOF contracts to discriminate between EOAs (Externally Owned Accounts) and contract accounts by introducing an `ISCONTRACT` instruction.
Allow EOF contracts to discriminate between EOAs (Externally Owned Accounts) and contract accounts by introducing an `HASCODE` instruction.

## Motivation

Expand All @@ -22,7 +22,7 @@ EOFv1 as scoped in [EIP-7692](./eip-7692.md) removes code introspection capabili
- `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)

`ISCONTRACT` is aimed to fill this gap and bring back the possibility to easily implement ERC-721 and ERC-1155 standard contracts in EOF.
`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

Expand All @@ -34,21 +34,21 @@ EOFv1 as scoped in [EIP-7692](./eip-7692.md) removes code introspection capabili
| `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`: `ISCONTRACT` (`0xe9`)
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

#### `ISCONTRACT`
#### `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 `ISCONTRACT` 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.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`.

Expand All @@ -64,15 +64,15 @@ There have been other solutions proposed to alleviate the problems related to la
4. `EXT*CALL` setting a new `callstatus` register (+ a new `CALLSTATUS` instruction)
5. Reenable `EXTCODESIZE` in EOF, keeping its behavior same as in legacy

`ISCONTRACT` has been chosen as the most elegant and minimal solution satisfying the requirements at hand and still able to be introduced in EOFv1.
`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 `ISCONTRACT`
### Reuse the `0x3b` (`EXTCODESIZE`) opcode for `HASCODE`

A new opcode is prefered by a general policy to not reuse opcodes. Also `ISCONTRACT` can be rolled out in legacy EVM if desired.
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 `ISCONTRACT` would be an exception from the principle. Without `ISCONTRACT`, ERC-721 and ERC-1155 standard implementations have to resort to either:
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
Expand All @@ -84,19 +84,19 @@ 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 `ISCONTRACT`) 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.
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 `ISCONTRACT` 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.
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

`ISCONTRACT` 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.
`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

Expand Down

0 comments on commit 762a6eb

Please sign in to comment.