Repricing for trie-size-dependent opcodes
EIP-1884 proposes to reprice trie-size-dependent opcodes in order to address the issue of denial-of-service attacks that have shown that these opcodes are under-priced relative to other opcodes. The concern is that such opcodes will be the easiest known mechanism to degrade network performance via transaction spam. The EIP increases the cost of storage reading opcodes to target a limit of 8 MB of data that needs to be read in order to process a block. The costs have been derived from an updated version of the calculation table used to generate the 1.0 gas costs. The EIP adds a flat penalty of 300 gas on top of the costs calculated in this table to account for the cost of loading the code. The risks associated with this change can be mitigated by the existence of an accessed_addresses and accessed_storage_keys map, which makes some cases recoverable. Another possibility is to add a POKE precompile, which would allow transactions that attempt to "rescue" stuck contracts by pre-poking all of the storage slots that they will access. EIP-2930 is another option that would have a similar effect to POKE but is more general.
Video
Original
Simple Summary
This EIP proposes repricing certain opcodes, to obtain a good balance between gas expenditure and resource consumption.
Abstract
The growth of the Ethereum state has caused certain opcodes to be more resource-intensive at this point than
they were previously. This EIP proposes to raise the gasCost
for those opcodes.
Motivation
An imbalance between the price of an operation and the resource consumption (CPU time, memory etc) has several drawbacks:
- It could be used for attacks, by filling blocks with underpriced operations which causes excessive block processing time.
- Underpriced opcodes cause a skewed block gas limit, where sometimes blocks finish quickly but other blocks with similar gas use finish slowly.
If operations are well-balanced, we can maximise the block gaslimit and have a more stable processing time.
Specification
At block N
,
- The
SLOAD
(0x54
) operation changes from200
to800
gas, - The
BALANCE
(0x31
) operation changes from400
to700
gas, - The
EXTCODEHASH
(0x3F
) operation changes from400
to700
gas, - A new opcode,
SELFBALANCE
is introduced at0x47
.SELFBALANCE
pops0
arguments off the stack,SELFBALANCE
pushes thebalance
of the current address to the stack,SELFBALANCE
is priced asGasFastStep
, at5
gas.
Rationale
Here are two charts, taken from a full sync using Geth. The execution time was measured for every opcode, and aggregated for 10K blocks. These bar charts show the top 25 'heavy' opcodes in the ranges 5M to 6M and 6M to 7M:
Note: It can also be seen that the SLOAD
moves towards the top position. The GASPRICE
(0x3a
) opcode has position one which I believe can be optimized away within the client -- which is not the case with SLOAD
/BALANCE
.
Here is another chart, showing a full sync with Geth. It represents the blocks 0
to 5.7M
, and highlights what the block processing time is spent on.
It can be seen that storage_reads
and account_reads
are the two most significant factors contributing to the block processing time.
SLOAD
SLOAD
was repriced at EIP-150, from 50
to 200
.
The following graph shows a go-ethereum full sync, where each data point represents
10K blocks. During those 10K blocks, the execution time for the opcode was aggregated.
It can be seen that the repricing at EIP-150 caused a steep drop, from around 67
to 23
.
Around block 5M
, it started reaching pre-EIP-150 levels, and at block 7M
it was averaging on around 150
- more than double pre-eip-150 levels.
Increasing the cost of SLOAD
by 4
would bring it back down to around 40
.
It is to be expected that it will rise again in the future, and may need future repricing, unless
state clearing efforts are implemented before that happens.
BALANCE
BALANCE
(a.k.a EXTBALANCE
) is an operation which fetches data from the state trie. It was repriced at EIP-150 from 20
to 400
.
It is comparable to EXTCODESIZE
and EXTCODEHASH
, which are priced at 700
already.
It has a built-in high variance, since it is often used for checking the balance of this
,
which is a inherently cheap operation, however, it can be used to lookup the balance of arbitrary account which often require trie (disk) access.
In hindsight, it might have been a better choice to have two
opcodes: EXTBALANCE(address)
and SELFBALANCE
, and have two different prices.
- This EIP proposes to extend the current opcode set.
- Unfortunately, the opcode span
0x3X
is already full, hence the suggestion to placeSELFBALANCE
in the0x4X
range. - As for why it is priced at
5
(GasFastStep
) instead of2
(GasQuickStep
), like other similar operations: the EVM execution engine still needs a lookup into the (cached) trie, andbalance
, unlikegasPrice
ortimeStamp
, is not constant during the execution, so it has a bit more inherent overhead.
- Unfortunately, the opcode span
EXTCODEHASH
EXTCODEHASH
was introduced in Constantinople, with EIP-1052. It was priced at 400
with the reasoning:
The gas cost is the same as the gas cost for the
BALANCE
opcode because the execution of theEXTCODEHASH
requires the same account lookup as inBALANCE
.
Ergo, if we increase BALANCE
, we should also increase EXTCODEHASH
Backwards Compatibility
The changes require a hardfork. The changes have the following consequences:
- Certain calls will become more expensive.
- Default-functions which access the storage and may in some cases require more than
2300
gas (the minimum gas that is always available in calls). - Contracts that assume a certain fixed gas cost for calls (or internal sections) may cease to function.
- A fixed gas cost is specified in ERC-165 and implementations of this interface do use the affected opcodes.
- The ERC-165 method
supportsInterface
must return abool
and use at most30,000
gas. - The two example implementations from the EIP were, at the time of writing
586
gas for any input, and236
gas, but increases linearly with a higher number of supported interfaces
- The ERC-165 method
- It is unlikely that any ERC-165
supportsInterface
implementation will go above30.000
gas. That would require that the second variant is used, and thirty:ish interfaces are supported. - However, these operations have already been repriced earlier, so there is a historical precedent that 'the gascost for these operations may change', which should have prevented such fixed-gas-cost assumptions from being implemented.
- A fixed gas cost is specified in ERC-165 and implementations of this interface do use the affected opcodes.
I expect that certain patterns will be less used, for example the use of multiple modifiers which SLOAD
s the same opcode will be merged into one. It may also lead to less log
operations containing SLOAD
ed values that are not strictly necessary.
Test Cases
Testcases that should be implemented:
- Test that
selfbalance == balance(address)
, - Test that
balance(this)
costs as before, - Test that
selfbalance
does not pop from stack - Gascost verification of
SLOAD
,EXTCODEHASH
andSELFBALANCE
- Verify that
SELFBALANCE
is invalid before Istanbul
Some testcases have been implemented as statetests at https://github.com/holiman/IstanbulTests/tree/master/GeneralStateTests
Implementation
This EIP has not yet been implemented in any client. Both these opcodes have been repriced before, and the client internals for managing reprices are already in place.
SELFBALANCE
This is the implementation for the new opcode in go-ethereum:
func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { stack.push(interpreter.intPool.get().Set(interpreter.evm.StateDB.GetBalance(contract.Address()) return nil, nil }
Security considerations
- See backwards compatibility section.
- There are no special edgecases regarding
SELFBALANCE
, if we define it asBALANCE
withaddress
instead of popping an address from the stack -- sinceBALANCE
is already well-defined. - It should be investigated if Solidity contains any hardcoded expectations on the gas cost of these operations.
- In many cases, a recipient of
ether
from aCALL
will want to issue aLOG
. TheLOG
operation costs375
plus375
per topic. If theLOG
also wants to do anSLOAD
, this change may make some such transfers fail.
Copyright
Copyright and related rights waived via CC0.
Adopted by projects
Not miss a beat of EIPs' update?
Subscribe EIPs Fun to receive the latest updates of EIPs Good for Buidlers to follow up.
View all