OpenZeppelin upgradeable contracts affected by Istanbul hardfork

Executive summary: once the Istanbul hardfork occurs (around early 2020), a very specific interaction with OpenZeppelin/ZeppelinOS upgradeable (proxy) contracts will no longer work (receiving Ether from other contracts via transfer). Nonetheless, all contract functions and the upgrade system itself will remain functional. This concerns less than 1% of all deployed upgradeable contracts: a list with all affected addresses is included at the end of the article.


Much has been discussed about the upcoming Istanbul hardfork (read @fasteater’s overview of the changes to learn more), specially regarding EIP1884, which will cause some EVM operations to be more expensive. This means the set of rules under which smart contracts operate is about to change, potentially breaking some applications. Unfortunately, a subset of the OpenZeppelin SDK (previously ZeppelinOS) upgradeable (proxy) contracts will be affected by this.

The issue

EIP1884 most contentious change is the gas cost increase in SLOAD from 200 to 800 gas. While most contract operations are constrained only by the transaction’s gas (a user-supplied value), Ether transfers between contracts using Solidity’s transfer or Vyper’s send functions forward a fixed amount of gas. This means that a contract that has its gas cost increased by EIP1884 may no longer be able to receive funds in this manner.

transfer and send were originally created as a simple way to mitigate reentrancy vulnerabilities. While they successfully fulfill this purpose, their approach is too heavy-handed, leading to issues such as this one. Consensus in the Ethereum security community is that their usage should be discouraged and replaced with either using the checks-effects-interactions pattern, or custom solutions such as our ReentrancyGuard contract. If you want to learn more, the Consensys Diligence team put together a great writeup on this subject.

How upgradeable contracts are affected

All contract functions, as well as the upgrade system, will continue to work. EIP1884 will only affect:

  1. OpenZeppelin/ZeppelinOS upgradeable (proxy) contracts, e.g. deployed via $ oz create
  2. with a payable fallback function,
  3. that receive Ether from other contracts via transfer or send.

This subset represent less than 1% of all upgradeable contracts currently deployed on mainnet. After Istanbul, these contracts will no longer be able to receive Ether this way (reverting the transaction). Note that sending funds from external accounts, or from other contracts via either payable functions or call will continue to work correctly.

The reason why this affects proxy contracts more than non-upgradeable contracts is because these must perform an extra SLOAD to fetch the underlying implementation address (the very operation that EIP1884 makes more expensive). @chris.whinfrey and @shanefontaine from the Authereum team wrote a great in-depth article on the technical details, along with a list of other upgradability solutions that are also affected by the hardfork. They also kindly reached out to us privately before publishing to make sure we were aware of their findings.

Affected Contracts

We got in contact with the awesome people from the Tenderly team to pinpoint exactly which contracts meet the criteria explained above. They very quickly compiled this list for us, which we expect will help our users prepare for the hardfork and make any necessary adjustments to their applications.

The following upgradeable contracts have received Ether via the methods explained above and will no longer be able to do so come Istanbul. If you control one of these addresses and are unsure of the consequences to your particular contract, get in contact with us! We’ve already identified and contacted the owners of most of them, but some still remain unknown.

0x3e55cbaeaa14765536073c3967f0f990eb4d07f7 // 0xUniverse
0x137ce274199a106b1aa3036241d6757c06968c21 // 0xUniverse
0x2e9a1cfee65b283f5fcfcd84b494c0fc0e0cc486 // 0xUniverse
0xde56eaf3d5a683a386ad9249eb9ea2bc622aae8d // 0xUniverse
0x6d1d7997b2cf32e686ced406e71729d79f2d6419 // Authereum
0x526bdb6bfbb6a5a4e0d73285a7950329d822d95a // Authereum
0xdc4b1f3396325df2cbd853e2bd48acd8d1d7d79b // Authereum
0xc80625a2b9cce29a7eb2c121626ebc0c583294ee
0x7bda753a429502ac7461c9c0de69d50d9940b7a0
0x4206f6463fb047623577c47ec3294f2595ffa0af
0x0f83996b111fd0b317720050a4fa37706edea14b

Best practices moving forward

Istanbul has served as a rude awakening, showing Ethereum developers that having fixed gas allowances at the smart contract level can backfire unexpectedly on protocol upgrades, and is a short-term solution better avoided altogether.

Ways to avoid these sort of issues in the future include:

  • removing the fixed gas limit on Ether transfers (we’re including a helper function for this in the next release of the OpenZeppelin Contracts!)
  • stop sending funds directly altogether and switch to a PullPayment strategy

Regarding our proxies, we’re currently evaluating changing them to be EIP1822-compatible. Among other improvements, this will make them work under EIP1884, but is not a long-term solution, gas costs will be increased again in the future, and contracts should be robust enough to handle these changes.

Issues in other projects

Istanbul will cause issues in multiple contracts across a number of projects. If you want to learn more about these, Hubert Ritzdorf, CTO at ChainSecurity, put together an awesome list of affected contracts that will in some way or another stop working properly once the hardfork occurs.

12 Likes

People interested in this might also be interested in our article about protecting against reentrancy.

1 Like

Hello everyone!

I was wondering if these upgradeable contracts are still affected by Istanbul hardfork, since the Berlin hard fork, and concretely EIP-2929, introduced some changes for SLOAD costs.
For SLOAD, EIP-2929 states that if the contract storage key has never been accessed (cold storage) COLD_SLOAD_COST gas will be charged (which is 2100 gas). On the other hand, if the contract storage key has already been accessed (warm storage), only WARM_STORAGE_READ_COST will be charged (which is 100 gas).

Are the contracts mentioned no longer affected by the Istanbul hardfork due to EIP-2929, or am I missing something?

The contracts are still affected. The cheaper gas cost for warm storage slots may cause them to work as expected in some circumstances.