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

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.