Closed code423n4 closed 2 years ago
Invalid. This is a misunderstanding of immutable
variables in upgradeable/proxy contracts.
Both parts of this statement are false, "Upgradeable contracts cannot use neither constructors nor use immutable variables":
Since the immutable variables are in the bytecode, they are accessible as expected when called via a proxy.
Yes, I had the same misconception before XD
Immutable variables can be used in constructors to be read by proxies because they're written directly into the bytecode.
Lines of code
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTCollectionFactory.sol#L104 https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTCollectionFactory.sol#L181-L185 https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/shared/ContractFactory.sol#L19 https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/shared/ContractFactory.sol#L30-L33 https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTDropCollection.sol#L101-L103 https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTCollection.sol#L95-L97
Vulnerability details
Impact
Admin functions in
NFTCollectionFactor.sol
are unusable through a proxyProof of Concept
Upgradeable contracts cannot use neither constructors nor use immutable variables. The reason for that is they work behind a proxy which calls them using
delegatecall
so the real variables are stored in the proxy contract. Note that all contracts in OpenZeppelin do not have any constructor.
Issue in
NFTCollectionFactory.sol
In
NFTCollectionFactory
the variablerolesContract
which is where admin is consulted is immutable.The result is that it cannot be seen from proxy and all
onlyAdmin
unable to use or produce unexpected behavior.Issue in
ContractFactory.sol
(inheritedNFTDropCollection.sol
andNFTCollection.sol
)Same problem in this contract
Recommended Mitigation Steps
1) Remove
immutable
keyword from variables mentioned 2) Remove constructors . 3) Move the constructor code toinitialize()
function.4) Be sure you call
initialize()
for every parentA good suggestion to avoid confusions is to add
Upgradeable
at the end of the name of every contract. For exampleContractFactory
could be renamedContractFactoryUpgradeable
.