Open code423n4 opened 1 year ago
berndartmueller marked the issue as primary issue
This is considered more of a Medium risk and a solution would be to have the ERC-721 contract manage the sequential IDs and have the sales contracts simply request minting of the next token ID
mehtaculous marked the issue as sponsor disputed
mehtaculous marked the issue as disagree with severity
Due to the external requirement of this finding, I'm downgrading it to Medium severity.
berndartmueller changed the severity to 2 (Med Risk)
berndartmueller marked the issue as selected for report
Lines of code
https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/FixedPrice.sol#L66 https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/OpenEdition.sol#L67 https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/LPDA.sol#L74
Vulnerability details
In all of the three sale types of contracts, the
buy
function will mint tokens with sequential ids starting at a given configurable value.If an external entity mints any of the token ids involved in the sale, then the buy procedure will fail since it will try to mint an already existing id. This can be the creator manually minting a token or another similar contract that creates a sale.
Taking the
FixedPrice
contract as the example, if any of the token ids betweensale.currentId + 1
andsale.finalId
is minted by an external entity, then thebuy
process will be bricked since it will try to mint an existing token id. This happens in lines 65-67:https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/FixedPrice.sol#L65-L67
The implementation of the
mint
function (OZ contracts) requires that the token id doesn't exist:https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/token/ERC721/ERC721Upgradeable.sol#L293
Impact
If any of the scenarios previously described happens, then the contract will be bricked since it will try to mint an already existing token and will revert the transaction. There is no way to update the token ids in an ongoing sale, which means that the buy function will always fail for any call.
This will also cause a loss of funds in the case of the
FixedPrice
andLPDA
contracts since those two require that all token ids are sold before funds can be withdrawn.PoC
The following test reproduces the issue using the
FixedPrice
sale contract type.Recommendation
The quick solution would be to mint the tokens to the sale contract, but that will require a potentially high gas usage if the sale involves a large amount of tokens.
Other alternatives would be to "reserve" a range of tokens to a particular minter (and validate that each one mints over their own range) or to have a single minter role at a given time, so there's just a single entity that can mint tokens at a given time.