The tree proxy architecture, designed to facilitate the upgrade of multiple branches in the same release version, faces a critical compatibility issue with OpenZeppelin's Initializable
design. This problem will arise in future upgrades because of the shared INITIALIZABLE_STORAGE
slot. This incompatibility results in failed upgrades, making the pattern unsuitable for current use with the OpenZeppelin Initializable library.
The root cause of the vulnerability is the misuse of the Initializable
library, where multiple initializables are expected while ONLY one INITIALIZABLE_STORAGE
slot is used.
Let us walk through the issue with the following scenario:
Alice, a developer, implements the tree proxy pattern using OpenZeppelin's Initializable
library for managing upgradeable contracts.
After the initial deployment, Alice has freshly developed more branches and attempts to add those in the same release version using the initialize
function.
Since the RootProxy
manages all branches with the same slot of INITIALIZABLE_STORAGE
, it is impossible to call initialize
on them outside of construction because the INITIALIZABLE_STORAGE._initialed
state has been set to 1
after the initial deployment of the RootProxy
and address(RootProxy).code.length
is not 0
anymore which makes both initialSetup
and construction
below not being met. This will cause Alice's call to upgrade
to fail with InvalidInitialization
error.
Alice tries to workaround the issue by calling the reinitialize(version)
function but still fails due to this version condition as it strictly requires the version
input has to be incremented after each calls. Which means each new/upgraded branch version has to be unique even if they belong to the same release.
Incrementing the version for each new branch contradicts versioning semantics, making upgrades infeasible.
Add following code to 2024-07-zaros/test/integration/tree-proxy/upgrade-branch/upgrade/upgradeBranch_initializables.t.sol
and run with forge test -vvv --mt test_addNewInitializables
The PASS result will confirm the upgradability issue.
This vulnerability has a Medium severity because it fundamentally breaks the upgrade process in the tree proxy pattern. The inability to (re)initialize branches with the same version prevents seamless upgrades, potentially leading to significant operational disruptions and increased complexity in version management. This will also reduce the number of potential adaptations of the Tree Proxy architecture.
Foundry test
To mitigate this critical issue, consider customizing the Initializable
library to make the INITIALIZABLE_STORAGE
slot unique for each new initializable branch, ensuring the Root does not use a conflicted slot. Alternatively, develop a new Initializable
pattern compatible with the Tree Proxy pattern.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.