upgradeExistingContract
will fail to set the new address for upgrades that keep the same name
#755
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
duplicate-742
satisfactory
satisfies C4 submission criteria; eligible for awards
Lines of code
https://github.com/code-423n4/2022-12-gogopool/blob/main/contracts/contract/ProtocolDAO.sol#L209-L216
Vulnerability details
The
upgradeExistingContract
function present in theProtocolDAO
can be used by the guardian of the protocol to upgrade a contract by providing a new implementation address. Under the hood, state is kept in theStorage
contract.upgradeExistingContract
implementation will callregisterContract
andunregisterContract
https://github.com/code-423n4/2022-12-gogopool/blob/main/contracts/contract/ProtocolDAO.sol#L209-L216
registerContract
updates the storage for the new address:https://github.com/code-423n4/2022-12-gogopool/blob/main/contracts/contract/ProtocolDAO.sol#L190-L194
And
unregisterContract
will clear the storage associated with the previous address:https://github.com/code-423n4/2022-12-gogopool/blob/main/contracts/contract/ProtocolDAO.sol#L198-L203
Since the
unregisterContract
call happens after theregisterContract
function, if the upgrade is done using the same contract name, then this will cause the address of the contract to be empty, since it is defined first during theregisterContract
call but immediately deleted in the call tounregisterContract
. This operation should be expected, since throughout the codebase multiple contracts refer to other contracts by getting their addresses indexed by their names (usingBaseAbstract.getContractAddress(name)
).Impact
Upgrading a contract with the same name will result in the contract's address being zero/empty (
address(0)
).Other contracts that refer to the upgraded contract by name will fail, as they will try to call functions on the zero address, likely preventing some parts of the protocol from being executed.
PoC
The following test reproduces the issue. The "Staking" contract is first deployed and registered, and later upgraded to a second deployment by calling
upgradeExistingContract
. After the upgrade, the address for the "Staking" isaddress(0)
.Recommendation
This can be easily fixed by swapping the order of the actions, first unregistering the existing contract before registering the new one.
The text was updated successfully, but these errors were encountered: