discussions-to for EIP-7907: Meter Contract Code Size And Increase Limit
(original PR: Add EIP: Meter Contract Code Size And Increase Limit by charles-cooper · Pull Request #9483 · ethereum/EIPs · GitHub)
discussions-to for EIP-7907: Meter Contract Code Size And Increase Limit
(original PR: Add EIP: Meter Contract Code Size And Increase Limit by charles-cooper · Pull Request #9483 · ethereum/EIPs · GitHub)
I performed jumpdest analysis benchmarks for eip 7903, which are relevant here.
Twitter is cheering up.
But this incentivises tha lazy inclusion of libraries and goes against the principle of maximum reuse of what is already deployed on chain.
Ofc, the question is whether there is even a common agreement on such a principle of deployed code reusability.
If the account is warm, no change to the gas schedule occurs.
The account being warm doesn’t mean the code is loaded:
EXTCODEHASH
also warms the account but doesn’t load the codeOther actions loading the code are not included in the pricing:
EXTCODESIZE
loads the codeDo you need to add all these to pricing, or add as second “warm” list that records if code is loaded?
Hmm, interesting. What do you think is the cleanest way in the spec to specify that the cost is only incurred on the first load of the code?
It doesn’t have to btw, the EIP specifies that clients should keep an out-of-band index for codesize –
Clients should add an efficient way to determine the code size without loading the entire code, e.g. storing it in a separate table keyed by code hash. This way, they can charge for the access cost before physically loading the code. Otherwise, a client may load a contract, even when there is not enough gas left to pay for the code load.
So should loading from this new table incur the cost of an SLOAD?
Making EXTCODESIZE
cost warm account
(get hasd) + 2100
gas (get data) rather than 20
gas?
How does this work for statelessness and zk; since it is an unwitnessed data with no root, how is it proved to be correct?
It’s witnessed by codehash, but I’m not sure where and when in the protocol the proof would be provided.
Actually I’m checking go-ethereum and calling EXTCODESIZE
triggers addition of the full code to the witness. Suggesting that yes, EXTCODESIZE should also trigger the per-byte cost in the EIP.
Nice catch! I think we should introduce an additional warm state for the code so that
WARM_STORAGE_READ_COST = 100
vs 2600
for the first 24KB of the code. If the code size > 24KB, then we charge 2 gas per byte as in EIP-7907 and put the account as code warm;WARM_STORAGE_READ_COST = 100
gas.Yes, this makes sense to me. It looks inelegant at first to have two different warm states, but it makes sense bc code is stored in an auxiliary table separate from accounts.
Yeah is a bit ugly; but EXTCODESIZE
etc has been a pain point in many scenarios; so it is a pragmatic fix
I spoke a bit about the EXTCODESIZE
issue offline with @matt, and here are my thoughts –
As a user of the EVM, it’s a bit of a gotcha for EXTCODESIZE to be priced differently from other account querying opcodes, e.g. EXTCODEHASH. It is also uniquely determined by codehash (up to hash collision resistance), so if there are any tricks that the implementation can pull to make this happen, I think it would be good for users.
However, I recognize this might not be copacetic with how implementations actually work. For example, for stateless clients, they probably need the full code in order to prove codesize, even though it is “witnessed” (uniquely determined) by codehash.
I think there are basically three options:
I prefer 2, 1 and then 3, in that order. I don’t think an additional cost needs to be added for the codesize query on top of account loading cost, since it can be prefetched in parallel with the other account data (or simply added into the db entry for an account, just without affecting the state root).
All that being said, this issue probably doesn’t matter too much in the big picture, since EXTCODESIZE usually happens near a CALL as part of the contract existence check. So the code is typically going to be loaded, anyways!
Meanwhile, option 1 seems most friendly for stateless clients. I think it would also be fine to ship option 1 instead of option 2, and figure out how to bring the gas cost down for EXTCODESIZE down later (since intuitively it looks like it should be cheap).
Paging @matt, @qizhou, @jochem-brouwer as well who have also been very helpful with feedback to see what their thoughts are here. I’d also like everybody to be on the same page so there aren’t surprise disagreements in the spec later.
My preference order is also 2,1,3. My argument is that the gas pricing for stateful, statelessness, and zk may be completely different - not only for EXTCODESIZE but almost all other OP codes and precompiles. For example, statelessness needs full code to prove codesize, while zk can prove the relationship between codehash => codesize with a much smaller prove size. Given our priority is for the current stateful EVM upgrade in Fukasa, I would choose 2 considering the negligible cost of the parallel lookup of codehash => codesize in stateful DB as Charles explained.
One of the Shanghai DoS attacks was EXTCODESIZE
,POP
; so while this is a fair assumption for well meaning code; it isn’t for intentional attacks
Ah, I meant for the user – as in the typical user won’t experience a large change in pricing depending on the two schemes.
An early draft implementing EIP-7907 in Geth can be found here add EIP-7903 by qizhou · Pull Request #1 · qizhou/go-ethereum · GitHub
The EIP does not reference 7702 delegations. Might be a good idea to explicitly clarify the access costs for delegated accounts.
Change the gas schedule for opcodes which load code. Specifically, the
CALL
,STATICCALL
,DELEGATECALL
,CALLCODE
andEXTCODECOPY
opcodes are modified so thatceil32(excess_contract_size) * 2 // 32
gas is added to the cold access cost, whereexcess_contract_size = max(0, contract_size - 0x6000)
. (Cf. initcode metering: EELS). If the account is warm, no change to the gas schedule occurs.
It is a bit unclear if the value of 2 used in the formula ceil32(excess_contract_size) * 2 // 32
is the same as the INITCODE_WORD_COST
that is defined in EIP-3860 or if this EIP wishes to define a new constant with the same value. Explicitly clarifying this will help avoid ambiguity in case of future changes/updates.
Good point. It should be the same as INITCODE_WORD_COST
. I’ll update the EIP