A based rollup could automatically (implicitly) use the previous L1 block hash as the latest known L1 block hash. If the L1 and L2 block proposers are identical, then the previous L1 block hash is known to the block builder, and L2 block inclusion is guaranteed.
My concern would be in these two cases:
Permissionless fallback: L1 proposer did not opt in to propose the next L2 block so someone else needs to propose it, inclusion in the next L1 block is not guaranteed.
L1 reorgs automatically lead to L2 reorgs.
In these cases, the ālatest known L1 block hashā is either not known in advance or might change, which can invalidate preconfs.
That makes sense, at first sight I donāt see any issue here.
And that shows that L1STATICCALL has better composability than L1SLOAD. With L1SLOAD on an L3, you might need different precompiles for reading from L1 and L2.
Indeed, the latency for each UserOp would add up which might lead to timeout.
The solution you suggested is backward-compatible in its format, but I assume weād need different pricing / gas discounts for preloading L1 slots. That said, I donāt think itās a very invasive change, we can consider adding it to the RIP.
Thatās not necessarily the case. With EIP-7702 you could delegate to a contract, let it write to your accountās storage, then revoke the delegation.
Developers should think of L1SLOAD as eth_getStorageAt, but accessible from within the EVM and reading from the base chain.
Just a thought ā thereās a possible future where many chains are able to communicate with one another with no delay ā full composability.
Restricting an opcode this useful to just one chain (the layer below) could be a mistake, would it not be better to include a chain id as part of the stack arguments consumed for this opcode?
For the base case of calling down a layer (L3 ā L2, L2 ā L1, etc.), it would largely work the same, however there is additional overhead of the additional chain ID stack argument, though performance in that area is not currently the major concern, and rollups have more lax performance requirements.
Which chain IDs are allowed to be called/loaded from is a choice that the rollup themselves would make, if an invalid chain ID is provided, the call frame could simply revert. Currently that would look like restricting the allowed chain IDs list to simply the ID of layer below.
Right now, this probably isnāt a game changer, but rollups using based sequencing or infrastructure such as Optimismās Superchain could benefit immensely, if the chain is able to achieve synchronous composability with one or many chains.
In short, its a small change now that could be useless, but the downsides are very low, and the potential upside and future proofing could unlock massive possibilities.
Thanks for the suggestion. I agree there seems to be not much overhead. But I think this might be premature generalization, this RIP was not meant to be a general-purpose interop solution.
I feel like L1SLOAD might not be the right tool for chains that synchronously compose with each other. They could easily use more sophisticated interop primitives, like cross-chain calls.
Iām curious to learn more about this. So the sequencer of one of the L2s in the Superchain would help dapps fetch storage entries from other L2s. Are all these chains settled on L1 in lockstep, so that the corresponding storage proofs can also easily be verified? (Verified by a full node, a fraud proof game, and later using a validity proof.)
I agree SLOAD is probably not the right case for such a generalization ā there was some discussion on L1STATICCALL earlier in the thread which is what I was intending should be generalized, apologies for not clarifying.
L1CALL is also another option, so we could in theory write between chains, but that has some really weird semantics with how ordering works ā which chain runs first, two chains writing to each other in sync, etc.
I also have an inkling that cross chain SLOAD (L1 or otherwise) could lead to some weird possible security concerns? In the standard EVM, contracts cannot directly query another contracts internal state. This may be an absolute nothing-burger, after all nodes can directly query storage, but just a thought I had.
Yep thats correct, Iām less certain on the long term & technical plans for Optimismās Superchain, but the long term goal with based rollups is that the proposer / builder will do all the processing for them in one bundle, so they would all be settled/committed to in lockstep, allowing cross chain calls to happen extremely seamlessly.
Verification for how that all works I would imagine is outside the scope of the RIP, its up to the rollup themselves to implement security measures, the point (in my opinion) of the RIP is to standardize an opcode/precompile for cross-chain calls, not conceive how many different types of rollups could secure the cross-chain call.
I definitely share the performance concerns with making RPCs a synchronous part of the L2 EVM - but this has already been covered several times so I wonāt rehash it here.
My following thoughts are mainly from the perspective of making smart contract accounts (SCA) more chain agnostic via keystores.
Will this cause any violations on AA validation rules (ERC-7562)? In other words, will this be compliant with the current canonical UserOp mempool or will it require an alternative mempool?
Given that there will be some lag to prevent finality risk, do we expect any security concerns due to a significant delay for key rotations to take effect on all chains?
Does this enforce SCAs to be deployed to L1 in order to get the interop benefits or just the keystore contract? On a similar note, is a L1SLOAD also a pre-requisite to achieving a minimal keystore rollup?
If keystores go all in on L1SLOAD, does this lock out non-rollup networks (e.g. Polygon PoS, BSC, Avalanche C-Chain, etc) from getting the interop benefits?
Iām aware that some of these questions could be out of scope for this particular RIP discussion, but I think its worth calling out given the expectation that keystores are a major potential use case for this opcode.
The L1SLOAD will need a special rule in erc-7562, to white-list its address.
But still, it can be treated like storage access and thus accessing its data is an āassociated storageā and thus allowed in account validation.
Yes, there going to be a time-window that some networks use one key and others use a different key.
Donāt think of it as a āimmediate kill switchā, but more like a maintainanace key rotation, and as such, there is no security concern.
I think it will only require users that makes complex cross-chain operations wait a little until it is fully propagated.
For propagation to L2s, only the keystore needs to be installed on L1. For key modification, it either trust L2 [canonical] bridges, or require the account on L1.
I canāt see how you can permissionlessly trust L1 change on another L1. e.g if you had L1 block hashes, you could create a merkle proof for the account key, but that is expensive to check - and still depend on some trusted oracle to post L1 block hash on this alt L1
This is a pretty good idea, and I like it a lot, though Iām not sure if extending the accessList this way is the best approach.
I understand the benefit is backward compatibility, but TBH, this feels too hacky.
The only other approach that comes to my mind is the new transaction type, which is not without its own set of issues.
Still, I think it will work better here, especially if we batch and pre-fetch L1SLOADs before EVEM execution, as you suggested. We could have a new TX Pool specific to these L1SLOAD transactions, in which we pre-fetch the L1 state, completely removing the need for RPC calls during the EVM execution (AFAIK op-stack does smth. similar for their interop txs).
The main downside of the new TX type, in my view, would be the additional burden on the fronted (user-facing libraries, wallets, etc.). Still, even the proposed accessList requires the changes