Skip to content

Commit 4cc5dea

Browse files
authored
Merge branch 'ethereum:master' into master
2 parents aad332f + 6b3e816 commit 4cc5dea

23 files changed

Lines changed: 1733 additions & 406 deletions

EIPS/eip-4788.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def get():
117117

118118
root_idx = timestamp_idx + HISTORY_BUFFER_LENGTH
119119
root = storage.get(root_idx)
120-
120+
121121
evm.return(root)
122122

123123
def set():
@@ -240,14 +240,11 @@ If this EIP is active in a genesis block, the genesis header's `parent_beacon_bl
240240

241241
## Rationale
242242

243-
### Gas cost of precompile
244-
245-
The suggested gas cost reflects a cold `SLOAD` analogous to the operation(s) performed while executing the precompile's logic.
246-
247243
### Why not repurpose `BLOCKHASH`?
248244

249245
The `BLOCKHASH` opcode could be repurposed to provide the beacon root instead of some execution block hash.
250-
To minimize code change, avoid breaking changes to smart contracts, and simplify deployment to mainnet, this EIP suggests leaving `BLOCKHASH` alone and adding a new precompile with the desired semantics.
246+
To minimize code change, avoid breaking changes to smart contracts, and simplify deployment to mainnet, this EIP suggests leaving `BLOCKHASH` alone and adding new
247+
functionality with the desired semantics.
251248

252249
### Beacon block root instead of state root
253250

@@ -261,7 +258,7 @@ e.g. with a singleton state root contract that caches the proof per slot).
261258
### Why two ring buffers?
262259

263260
The first ring buffer only tracks `HISTORY_BUFFER_LENGTH` worth of roots and so for all possible timestamp values would consume a constant amount of storage.
264-
However, this design opens the precompile to an attack where a skipped slot that has the same value modulo the ring buffer length would return an old root value,
261+
However, this design opens the contract to an attack where a skipped slot that has the same value modulo the ring buffer length would return an old root value,
265262
rather than the most recent one.
266263

267264
To nullify this attack while retaining a fixed memory footprint, this EIP keeps track of the pair of data `(parent_beacon_block_root, timestamp)` for each index into the

EIPS/eip-5725.md

Lines changed: 108 additions & 62 deletions
Large diffs are not rendered by default.

EIPS/eip-6120.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,13 @@ interface IUniversalTokenRouter {
177177
}
178178
```
179179

180-
See [Discard Payment](#discard-payment-1) in **Security Considerations** for an important security note.
180+
Please refer to the [Discard Payment](#discard-payment-1) section in the **Security Considerations** for an important security note.
181+
182+
### Native Token Tranfer
183+
184+
The `UTR` SHOULD have a `receive()` function for user execution logic that requires transferring ETH in. The `msg.value` transferred into the router can be spent in multiple inputs across different actions. While the caller takes full responsibility for the movement of `ETH` in and out of the router, the `exec` function SHOULD refund any remaining `ETH` before the function ends.
185+
186+
Please refer to the [Reentrancy](#reentrancy) section in the **Security Considerations** for information on reentrancy risks and mitigation.
181187

182188
### Usage Examples
183189

EIPS/eip-6493.md

Lines changed: 322 additions & 99 deletions
Large diffs are not rendered by default.

EIPS/eip-7201.md

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,35 @@ created: 2023-06-20
1212

1313
## Abstract
1414

15-
We define a formula to derive a location in storage, that is suitable for structs of arbitrary size, from an identifier. The formula is chosen to be safe against collisions with the standard Solidity storage layout. We define a convention to document this location in Solidity source code.
15+
We define a formula to derive a location in storage, that is suitable for structs of arbitrary size, from an identifier. The formula is chosen to be safe against collisions with the storage layouts used by Solidity and Vyper. We define a convention to document this location in Solidity source code.
1616

1717
## Motivation
1818

19-
The default Solidity storage layout is linear: all state variables are assigned sequential locations starting from storage slot 0. This is sufficient for most contracts. However, various design patterns used in smart contract development can benefit from a non-linear storage layout. One example is a modular design where using `DELEGATECALL` a contract executes code from multiple contracts, all of which share the same storage space, and which have to carefully coordinate on how to use it. Another example is upgradeable contracts, where it can be difficult to add state variables in an upgrade given that they may affect the assigned storage location for the preexisting variables.
19+
Smart contract languages such as Solidity and Vyper rely on tree-shaped storage layout. This tree starts at slot 0 and is composed of sequential chunks for consecutive variables. Hashes are used to ensure the chunks containing values of mappings and dynamic arrays do not collide. This is sufficient for most contracts. However, it presents a challenge for various design patterns used in smart contract development. One example is a modular design where using `DELEGATECALL` a contract executes code from multiple contracts, all of which share the same storage space, and which have to carefully coordinate on how to use it. Another example is upgradeable contracts, where it can be difficult to add state variables in an upgrade given that they may affect the assigned storage location for the preexisting variables.
2020

21-
In a non-linear storage layout, instead of being assigned sequential locations starting from slot 0, state variables are spread out across the storage space, usually at pseudorandom locations obtained by hashing. Each value may be placed in an entirely different location, but more frequently values that are used together are put in a Solidity struct and co-located in storage.
21+
Rather than using this default storage layout, these patterns can benefit from laying out state variables across the storage space, usually at pseudorandom locations obtained by hashing. Each value may be placed in an entirely different location, but more frequently values that are used together are put in a Solidity struct and co-located in storage. These pseudorandom locations can be the root of new storage trees that follow the same rules as the default one. Provided that this pseudorandom root is constructed so that it is not part of the default tree, this should result in the definition of independent spaces that do not collide with one another or with the default one.
2222

23-
These storage usage patterns are invisible to the Solidity compiler because they are not represented as Solidity state variables. Smart contract tools like static analyzers or blockchain explorers often need to know the storage location of contract data. Standardizing the location for non-linear storage layouts will allow these tools to correctly interpret contracts where these design patterns are used.
23+
These storage usage patterns are invisible to the Solidity and Vyper compilers because they are not represented as Solidity state variables. Smart contract tools like static analyzers or blockchain explorers often need to know the storage location of contract data. Standardizing the location for storage layouts will allow these tools to correctly interpret contracts where these design patterns are used.
2424

2525
## Specification
2626

27-
A _namespace_ consists of a set of variables that are placed contiguous in the storage layout of a contract. It should be implemented as a struct.
27+
A _namespace_ consists of a set of ordered variables, some of which may be dynamic arrays or mappings, with its values laid out following the same rules as the default storage layout but rooted in some location that is not necessarily slot 0. It should be implemented as a struct.
2828

2929
A _namespace id_ is a string that uniquely identifies a namespace in a contract. It should not contain any whitespace characters.
3030

31-
The storage location for a namespace is defined as `ns_loc(id: string) = keccak256(abi.encode(uint256(keccak256(id)) - 1))`.
31+
The storage location for a namespace is defined as `ns_loc(id: string) = keccak256(keccak256(id) - 1) & ~0xff`.
3232

33-
A Solidity contract using namespaced storage can annotate a struct with the NatSpec tag `@custom:storage-location erc7201:<NAMESPACE_ID>` to identify it as a namespace with id `<NAMESPACE_ID>`. _(Note: The Solidity compiler includes this annotation in the AST since v0.8.20, so this is recommended as the minimum compiler version when using this pattern.)_
33+
A Solidity contract using namespaced storage can annotate a struct with the NatSpec tag `@custom:storage-location erc7201:<NAMESPACE_ID>` to identify it as a namespace with id `<NAMESPACE_ID>`. _(Note: The Solidity compiler includes this annotation in the AST since v0.8.20, so this is recommended as the minimum compiler version when using this pattern.)_ Structs with this annotation found outside of contracts are not considered to be namespaces for any contract in the source code.
3434

3535
## Rationale
3636

37-
A requirement for the location is that it shouldn't overlap with any storage location that would be used by the standard Solidity layout. This is in case namespaced storage is used alongside standard linear storage, either deliberately or accidentally.
37+
The tree-shaped storage layout used by Solidity and Vyper follows the following grammar (with root=0):
3838

39-
First, note that a namespace may be larger than a single storage slot, so a variable in a namespace will be placed in a slot `ns_loc(id) + k`. If we assume collision resistance of Keccak-256, the chosen `ns_loc` function has the desired property with very high probability, because the cases in which a Solidity variable receives a location of the form `keccak256(x)` are:
39+
$L_{root} := \mathit{root} \mid L_{root} + n \mid \texttt{keccak256}(L_{root}) \mid \texttt{keccak256}(H(k) \oplus L_{root}) \mid \texttt{keccak256}(L_{root} \oplus H(k))$
4040

41-
1. Dynamic Arrays:
42-
1. If the array is at the top level and is assigned to storage slot `n`, the location of the `k`th item in the array will be `keccak256(n) + k`, but `n` will be a number much smaller than `uint256(keccak256(id)) - 1`.
43-
2. If the array is within another array or mapping, it will be in some location `keccak256(x) + j`, and the `k`th item will be at `keccak256(keccak256(x) + j) + k`. For this to equal `ns_loc(x) + k` we would need `j = -1`, but `j` will always be a non-negative number in standard Solidity layout.
44-
2. Mappings: The value for key `q` in a mapping will be at location `keccak256(h(q) . x)` where `x` is the location of the mapping itself, and `h` is as defined in the Solidity documentation (section "Layout of State Variables in Storage"). Note that `h(q)` can be any number of bytes. If it is a non-zero number of bytes, it is distinct from any `ns_loc(id) + k`. If it is zero bytes, it can be that `ns_loc(id) = keccak256(x)` if `x = keccak256(id) - 1`, but we know that `x` is the location of the mapping and (as mentioned for arrays above) a variable will be at `keccak256(y) + j` for a non-negative number `j`.
41+
A requirement for the root is that it shouldn't overlap with any storage location that would be part of the standard storage tree used by Solidity and Vyper (root = 0), nor should it be part of the storage tree derived from any other namespace (another root). This is so that multiple namespaces may be used alongside each other and alongside the standard storage layout, either deliberately or accidentally, without colliding. The term `keccak256(id) - 1` in the formula is chosen as a location that is unused by Solidity, but this is not used as the final location because namespaces can be larger than 1 slot and would extend into `keccak256(id) + n`, which is potentially used by Solidity. A second hash is added to prevent this and guarantee that namespaces are completely disjoint from standard storage, assuming keccak256 collision resistance and that arrays are not unreasonably large.
42+
43+
Additionally, namespace locations are aligned to 256 as a potential optimization, in anticipation of gas schedule changes after the Verkle state tree migration, which may cause groups of 256 storage slots to become warm all at once.
4544

4645
### Naming
4746

@@ -63,9 +62,9 @@ contract Example {
6362
uint256 y;
6463
}
6564
66-
// keccak256(abi.encode(uint256(keccak256("example.main")) - 1));
65+
// keccak256(abi.encode(uint256(keccak256("example.main")) - 1)) & ~bytes32(uint256(0xff));
6766
bytes32 private constant MAIN_STORAGE_LOCATION =
68-
0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab5da;
67+
0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500;
6968
7069
function _getMainStorage() private pure returns (MainStorage storage $) {
7170
assembly {

EIPS/eip-7412.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ error OracleDataRequired(address oracleContract, bytes oracleQuery)
3939
```solidity
4040
interface IERC7412 {
4141
function oracleId() view external returns (bytes32 oracleId);
42-
function fulfillOracleData(bytes oracleQuery, bytes signedOffchainData) payable external;
42+
function fulfillOracleQuery(bytes oracleQuery, bytes signedOffchainData) payable external;
4343
}
4444
```
4545

@@ -48,12 +48,12 @@ interface IERC7412 {
4848
The contract implementing the `IOracleContract` interface MUST revert with the following error message if it requires payment to fulfill the oracle data query:
4949

5050
```solidity
51-
error OracleFeeRequired(uint feeAmount)
51+
error FeeRequired(uint amount)
5252
```
5353

54-
`feeAmount` specifies the amount of native gas tokens required to execute the `fulfillOracleData` function, denominated in wei. This error MUST be resolved if the caller provides sufficient `msg.value` such that the fee amount can be collected by the oracle contract. The contract MAY NOT return gas tokens if they are provided in excess of the `feeAmount`. In practice, we would expect the fee amount to remain relatively stable, if not constant.
54+
`amount` specifies the amount of native gas tokens required to execute the `fulfillOracleQuery` function, denominated in wei. This error MUST be resolved if the caller provides sufficient `msg.value` such that the fee amount can be collected by the oracle contract. The contract MAY NOT return gas tokens if they are provided in excess of the `amount`. In practice, we would expect the fee amount to remain relatively stable, if not constant.
5555

56-
It is the responsibility of the client to decide how to construct the multicall, where necessary the `fulfillOracleData` functions are being called before the intended function call in an atomic transaction. Wallets that support account abstraction (per [ERC-4337](./eip-4337.md)) should already have the ability to generate atomic multi-operations. For EOA support, protocols could implement [ERC-2771](./eip-2771.md). A standard multicall contract can only be used to construct multicalls including functions which do not reference `msg.sender` or `msg.data`.
56+
It is the responsibility of the client to decide how to construct the multicall, where necessary the `fulfillOracleQuery` functions are being called before the intended function call in an atomic transaction. Wallets that support account abstraction (per [ERC-4337](./eip-4337.md)) should already have the ability to generate atomic multi-operations. For EOA support, protocols could implement [ERC-2771](./eip-2771.md). A standard multicall contract can only be used to construct multicalls including functions which do not reference `msg.sender` or `msg.data`.
5757

5858
To prevent data becoming too stale for a request between the simulation and a call's execution, ideally a contract could also emit the following event: `event OracleDataUsed(address oracleContract, bytes oracleQuery, uint expirationTime)` Here, `expirationTime` is the time after which the `OracleDataRequired` error would be thrown by the contract. (This would typically be a calculation involving a staleness tolerance and `block.timestamp`). Client applications that implement this standard would be able to recognize this event during simulation and estimate if an additional update will still be necessary, taking into account the speed of the chain. For example, the oracle query may request the latest quote available for a particular price feed and the expiration time may signal that the price cannot be older than three seconds prior to the current timestamp recognized by the blockchain. This has been omitted from the standard because there isn't a practical way to retrieve event data during transaction simulations on most JSON-RPC APIs at this time.
5959

@@ -111,7 +111,7 @@ contract OracleContract is IERC7412 {
111111
return bytes32(abi.encodePacked("MY_ORACLE_ID"));
112112
}
113113
114-
function fulfillOracleData(bytes calldata oracleQuery, bytes calldata signedOffchainData) payable external {
114+
function fulfillOracleQuery(bytes calldata oracleQuery, bytes calldata signedOffchainData) payable external {
115115
_verify(signedOffchainData);
116116
latestVerifiedData[keccak256(oracleQuery)] = signedOffchainData;
117117
}
@@ -129,7 +129,7 @@ contract OracleContract is IERC7412 {
129129
130130
function _verify(bytes memory signedOffchainData) payable internal {
131131
// Insert verification code here
132-
// This may revert with error OracleFeeRequired(uint feeAmount)
132+
// This may revert with error FeeRequired(uint amount)
133133
}
134134
135135
}

assets/eip-5725/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# EIP-5725: Transferrable Vesting NFT - Reference Implementation
2+
23
This repository serves as a reference implementation for **EIP-5725 Transferrable Vesting NFT Standard**. A Non-Fungible Token (NFT) standard used to vest ERC-20 tokens over a vesting release curve.
34

45
## Contents
6+
57
- [EIP-5725 Specification](./contracts/IERC5725.sol): Interface and definitions for the EIP-5725 specification.
6-
- [ERC-5725 Implementation (abstract)](./contracts/ERC5725.sol): ERC-5725 contract which can be extended to implement the specification.
8+
- [ERC-5725 Implementation (abstract)](./contracts/ERC5725.sol): ERC-5725 contract which can be extended to implement the specification.
79
- [VestingNFT Implementation](./contracts/reference/LinearVestingNFT.sol): Full ERC-5725 implementation using cliff vesting curve.
8-
- [LinearVestingNFT Implementation](./contracts/reference/VestingNFT.sol): Full ERC-5725 implementation using linear vesting curve.
10+
- [LinearVestingNFT Implementation](./contracts/reference/VestingNFT.sol): Full ERC-5725 implementation using linear vesting curve.

0 commit comments

Comments
 (0)