Because both the GlobalConfigurationBranch
and the UpgradeBranch
inherit the functions of OwnableUpgradeable
, they both have the same function selector. Since the selectorToBranch
mapping in the PerpsEngine
can only hold one branch per function selector, trying to add the second branch will revert and therefore the deployment of the PerpsEngine will revert.
The PerpsEngine
contract uses the Tree Proxy Pattern. A RootProxy and multiple branches store the smart contract functions. Each branch holds a set of functions with the corresponding function selectors. When calling the PerpsEngine
, the fallback function is activated and the call is delegated to the corresponding branch based on the provided function selector. To determine which branch to delegate the call to, the RootProxy utilizes the selectorToBranch
mapping, which maps a function selector to the corresponding branch address. This mapping is initialized during deployment.
The issue arises from the fact that both GlobalConfigurationBranch
and the UpgradeBranch
inherit external functions from the OwnableUpgradeable
contract and therefore share the same function selectors, for example transferOwnership(address)
. Since in the selectorToBranch
mapping only one branch can be mapped to a specific branch, adding the second branch will revert resulting in a failed deployment of the PerpsEngine
.
To ensure the full functionality of the inherited OwnableUpgradeable
contract for both the GlobalConfigurationBranch
and the UpgradeBranch
, consider adding additional functions to the branch contracts which call the duplicate functions. Only add the function selectors of those new functions to the selectorToBranch
mapping.
For example, add a transferOwnershipGlobalConf
function to the GlobalConfigurationBranch
which calls the transferOwnership
function:
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.