Skip to content

Reserve Auction mints wrong canvas#

High Risk

In Minting.sol there is mintReserveAuction function that is used for minting a canvas that was on reserve auction. On line 600 we can see that no mater if canvas is curated or not, the mint function is called on a contract with address canvasOneAddress. However, in case that a canvas is curated, mint should be called on a contract with address canvasOneCuratedAddress. The effect of this is not only that a token is minted in the wrong contract, but also wrong mappings of canvases to their traits, wrong ds.canvasOne and ds.canvasOneCurated mappings of token ID to canvas ID and wrong counters of canvasOne and canvasOneCurated.

uint256 tokenId;
if (ds.canvasSystem[canvasId].isCurated) {
    ds.canvasOneCurated[ds.contractInfo.canvasOneCuratedCounter] = canvasId;
    tokenId = ds.contractInfo.canvasOneCuratedCounter;
    ds.customization[ds.contractInfo.canvasOneCuratedAddress][tokenId].selectedTraits = selectedTraits;
    unchecked { ds.contractInfo.canvasOneCuratedCounter++; }
} else {
    ds.canvasOne[ds.contractInfo.canvasOneCounter] = canvasId;
    tokenId = ds.contractInfo.canvasOneCounter;
    ds.customization[ds.contractInfo.canvasOneAddress][tokenId].selectedTraits = selectedTraits;
    unchecked { ds.contractInfo.canvasOneCounter++; }
}

ds.canvasSystem[canvasId].oneMinted = true;
INFT(ds.contractInfo.canvasOneAddress).mint(msgSender, 1);

Recommendation#

Change the code in a way that calls mint on canvasOneCuratedAddress when canvas is curated and canvasOneAddress when it is not.

uint256 tokenId;
address canvasAddress;
if (ds.canvasSystem[canvasId].isCurated) {
    tokenId = ++ds.contractInfo.canvasOneCuratedCounter;
    canvasAddress = ds.contractInfo.canvasOneCuratedAddress;
    ds.canvasOneCurated[tokenId] = canvasId;
} else {
    tokenId = ++ds.contractInfo.canvasOneCounter;
    canvasAddress = ds.contractInfo.canvasOneAddress;
    ds.canvasOne[tokenId] = canvasId;
}

ds.customization[canvasAddress][tokenId].selectedTraits = selectedTraits;
ds.canvasSystem[canvasId].oneMinted = true;
INFT(canvasAddress).mint(msgSender, 1);

*This example also includes fixes regarding some gas inefficiencies and a bug from Wrong token ID in mintReserveAuction.