Scarcity and uniqueness arguably the core philosophy of NFTs. This bug allows NFT creators(CoreProxy owners) to re-initialize the CoreProxy contract anytime, effectively breaking all promises on scarcity and uniqueness granted upon contract creation. It also allows changing of other fields such as fees for minting, uri for minted NFTs, thus putting buyers at the mercy of contract owner.
Proof of Concept
For proxy contracts, the backing implementation often provides an initialize function to help proxy populate initial state. Since the function is intended for initialization, it is expected to be called just once(just like constructors should only be called once for normal contracts).
However, in the case of CoreCollection.initialize, no modifiers that check whether the contract has already been initialized is used, thus allowing contract owners to re-initialize the contract states whenever they want.
Re-initialize allows re-setting several critical fields, including _baseUri, mineFee and maxSupply, just to name a few. This violates the common guideline of NFTs, and should be mitigated before actual contract deployment.
Lines of code
https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/CoreCollection.sol#L87
Vulnerability details
Impact
Scarcity and uniqueness arguably the core philosophy of NFTs. This bug allows NFT creators(CoreProxy owners) to re-initialize the CoreProxy contract anytime, effectively breaking all promises on scarcity and uniqueness granted upon contract creation. It also allows changing of other fields such as fees for minting, uri for minted NFTs, thus putting buyers at the mercy of contract owner.
Proof of Concept
For proxy contracts, the backing implementation often provides an
initialize
function to help proxy populate initial state. Since the function is intended for initialization, it is expected to be called just once(just like constructors should only be called once for normal contracts).However, in the case of
CoreCollection.initialize
, no modifiers that check whether the contract has already been initialized is used, thus allowing contract owners to re-initialize the contract states whenever they want.Re-initialize allows re-setting several critical fields, including
_baseUri
,mineFee
andmaxSupply
, just to name a few. This violates the common guideline of NFTs, and should be mitigated before actual contract deployment.Tools Used
vim, ganache-cli
Recommended Mitigation Steps
Add the
onlyUnInitialized
modifier toinitialize
.