forked from ethereum/EIPs
-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into 4886-assets-cc0
- Loading branch information
Showing
7 changed files
with
83 additions
and
158 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 |
---|---|---|
@@ -1,63 +1,62 @@ | ||
--- | ||
eip: 2330 | ||
title: EXTSLOAD opcode | ||
description: A new EVM opcode to read external contract storage data. | ||
author: Dominic Letz (@dominicletz), Santiago Palladino (@spalladino) | ||
discussions-to: https://ethereum-magicians.org/t/eip-2330-extsload-and-abi-for-lower-gas-cost-and-off-chain-apps/3733 | ||
status: Stagnant | ||
status: Draft | ||
type: Standards Track | ||
category: Core | ||
created: 2019-10-29 | ||
requires: 2929 | ||
--- | ||
|
||
## Simple Summary | ||
A new `EXTSLOAD <contract> <slot>` EVM opcode to read external contract storage data and corresponding allowing to build registry and token contracts that use less gas. | ||
|
||
## Abstract | ||
While any off-chain application can read all contract storage data of all contracts, this is not possible for deployed smart contracts themselves. These are bound to use contract calls for any interaction including reading data from other contracts. This EIP adds an EVM opcode to directly read external contract storage. | ||
|
||
This proposal adds a new opcode `EXTSLOAD` at `0x5c` which pops two items from the stack: `<account address> <storage key>` and pushes one item: `<storage value>`. The gas cost is sum of account access cost and storage read based on [EIP-2929](./eip-2929.md) Access Lists. | ||
|
||
## Motivation | ||
The gas cost when reading from registry style contract such as ERC-20s, ENS and other data contracts is very high, because they incur cross contract call cost, cost for ABI encoding, decoding and dispatching and finally loading the data. In many cases the underlying storage that is being queried is though just a simple mapping. In these cases a new `EXTSLOAD` call directly accessing the mapping in storage could not only **reduce the gas cost** of the interaction more than 10x, but also it would make the gas cost **predictable** for the reading contract. Furthermore with the use of the existing `EXTCODEHASH` an external contracts implementation can be verified and allows `EXTSLOAD` to make deterministic reads even from third-party smart contracts. | ||
|
||
While any off-chain application can read all contract storage data of all contracts, this is not possible for deployed smart contracts themselves. These are bound to use contract calls for any interaction including reading data from other contracts. This EIP adds an EVM opcode to directly read external contract storage. | ||
|
||
The gas cost when reading from registry style contract such as [EIP-20s](./eip-20.md), ENS and other data contracts is very high, because they incur cross contract call cost, cost for ABI encoding, decoding and dispatching and finally loading the data. In many cases the underlying storage that is being queried is though just a simple mapping. On top of that, the view function may SLOAD many other slots which caller may not be interested in, which further adds to the gas costs. In these cases a new `EXTSLOAD` call directly accessing the mapping in storage could not only **reduce the gas cost** of the interaction more than 10x, but also it would make the gas cost **predictable** for the reading contract. | ||
|
||
## Specification | ||
**Proposal** | ||
|
||
A new EVM instruction `EXTSLOAD (0x5c)` that works like `SLOAD (0x54)` but an additional parameter representing the contract that is to be read from. The gas cost of `EXTSLOAD` would be the sum of the [fee schedule G](https://ethereum.github.io/yellowpaper/paper.pdf) for G\[EXTCODE\](700) + G\[SLOAD\](800) = 1500 gas | ||
A new EVM instruction `EXTSLOAD (0x5c)` that works like `SLOAD (0x54)` but an additional parameter representing the contract that is to be read from. | ||
|
||
``` | ||
```shell | ||
EXTSLOAD (0x5c) | ||
``` | ||
|
||
The `EXTSLOAD` instruction pops 2 values from the stack, first `contract` a contract address and then second `slot` a storage address within `contract`. As result `EXTSLOAD` pushes on the stack the value from the contract storage of `contract` at the storage `slot` address or `0` in case the account `contract` does not exist. | ||
|
||
**Example** | ||
### Gas cost pre-verkle | ||
|
||
An example assuming [further Solidity changes](https://github.com/ethereum/solidity/issues/7593) for illustration: | ||
Gas to be charged before Verkle Tree change is specified as `ACCOUNT_ACCESS_COST + STORAGE_READ_COST` where: | ||
|
||
```solidity | ||
interface MemberList { | ||
public fixed(@5) mapping(address => bool) members; | ||
} | ||
``` | ||
- `ACCOUNT_ACCESS_COST` is `0` if the account address is already in `accessed_addresses` set, otherwise `COLD_ACCOUNT_ACCESS_COST`. | ||
- `STORAGE_READ_COST` is `WARM_STORAGE_READ_COST` if storage key is already in `accessed_storage_keys` set, otherwise `COLD_STORAGE_READ_COST`. | ||
|
||
And a corresponding contract function that uses this member list. Similarly tokens or other registries could be implemented. | ||
### Gas cost post-verkle | ||
|
||
```solidity | ||
function membersOnly(address list, address member) { | ||
MemberList ml = MemberList(list); | ||
if (ml.members[client] == false) revert("Nonmember!"); | ||
} | ||
``` | ||
It is important to consider that post Verkle tree change, `ACCOUNT_ACCESS_COST` will not be needed since a single account's storage would be spread across the entire global trie. Hence gas to be charged post Verkle Tree change is just `STORAGE_READ_COST`, which is as specified in [Gas cost pre-verkle](#gas-cost-pre-verkle). | ||
|
||
The call `ml.members[client]` here could let the Solidity compiler generate the normal map access logic but using the new `EXTSLOAD <contract> <slot>` instructions to read from the `ml` contract storage instead of the local contract storage. | ||
## Rationale | ||
|
||
- Without this EIP, a contract can still opt-in to make their entire state public, by having a method that simply SLOADs and returns the values ([example](../assets/eip-2330/Extsload.sol)). The complexity of the gas cost can be seen as `1`x CALL cost + `N`x SLOAD cost. Hence, the gas cost specified for using EXTSLOAD opcode on an account for `N` times, the charge of `1`x `COLD_ACCOUNT_ACCESS_COST` and `N`x `STORAGE_READ_COST` is hereby justified. | ||
- Without this EIP, a contract can still use internal state of other contracts. An external party can supply a value and proof to a contract, which the contract can verify using `BLOCKHASH`. This is only possible for the previous blocks and not the latest state (since current blockhash cannot be determined before execution). | ||
- This opcode can be seen as breaking object-oriented (OO) model because it allows to read storage of other contracts. In usual systems using OO is net positive, because there is no limit on machine code and it hardly adds any cost to add more methods or use single method to get a ton of data while the caller needs to just a small portion of data. However on EVM, there are visible costs, i.e. about $0.2 per SLOAD (20 gwei and ETHUSD 2000). Also, OO has caused misleading assumptions for developers where variables marked as "private" in smart contracts are encrypted in some way/impossible to read which has resulted bad designs. Hence, this EIP can be beneficial in terms of making smart contract systems more efficient as well as preventing misconceptions as well. | ||
|
||
## Backwards Compatibility | ||
|
||
This change is fully backwards compatible since it adds a new instruction. | ||
|
||
## Test Cases | ||
Not started yet. | ||
## Security Considerations | ||
|
||
## Implementation | ||
[Aleth Pull Request](https://github.com/ethereum/aleth/pull/5805) | ||
- Since the opcode is similar to SLOAD, it should be easy to implement in various clients. | ||
- This opcode allows the callee `A` to re-enter a caller contract `B` and read state of `B` and `B` cannot stop `A` from doing that. Since this does not change any state, it should not be a security issue. Contracts generally use re-entrancy guards, but that is only added to write methods. So even currently without EXTSLOAD, `A` can re-enter `B` and read their state exposed by any view methods and it has not been an issue. | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). |
Oops, something went wrong.