code-423n4 / 2023-03-canto-identity-findings

1 stars 1 forks source link

Anybody can mint trays during prelaunch phase #19

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-03-canto-identity/blob/main/canto-namespace-protocol/src/Tray.sol#L150-L168 https://github.com/code-423n4/2023-03-canto-identity/blob/main/canto-namespace-protocol/src/Tray.sol#L154

Vulnerability details

Impact

During pre-launch phase, only owner of contract can mint trays using buy().

Currently, anybody can call the external function buy() and mint trays during pre-launch phase as long as it does not exceed the maximum number of trays that can be minted pre-launch.

Proof of Concept

Tray.sol#L150-L168 Tray.sol#L154

/Tray.sol
150:    function buy(uint256 _amount) external {
151:        uint256 startingTrayId = _nextTokenId();
152:        if (prelaunchMinted == type(uint256).max) {
153:            // Still in prelaunch phase
154:            if (msg.sender != owner) revert OnlyOwnerCanMintPreLaunch();
155:            if (startingTrayId + _amount - 1 > PRE_LAUNCH_MINT_CAP) revert MintExceedsPreLaunchAmount(); 
156:        } else {
157:            SafeTransferLib.safeTransferFrom(note, msg.sender, revenueAddress, _amount * trayPrice);
158:        }
159:        for (uint256 i; i < _amount; ++i) {
160:            TileData[TILES_PER_TRAY] memory trayTiledata;
161:            for (uint256 j; j < TILES_PER_TRAY; ++j) {
162:                lastHash = keccak256(abi.encode(lastHash));
163:                trayTiledata[j] = _drawing(uint256(lastHash));
164:            }
165:            tiles[startingTrayId + i] = trayTiledata;
166:        }
167:        _mint(msg.sender, _amount); // We do not use _safeMint on purpose here to disallow callbacks and save gas
168:    }
154: if (msg.sender != owner) revert OnlyOwnerCanMintPreLaunch();

In the function buy, the owner variable is not set and check on buyer can be bypassed even though buyer is not the owner during prelaunch phase.

This means that anybody can call the external function buy and mint trays during pre-launch phase as long as it does not exceed the maximum number of trays that can be minted pre-launch. This is unintended as only the owner is allowed to mint trays during pre-launch.

Tools Used

Manual Review

Recommendation

Consider declaring owner variable and setting owner address in constructor

address public immutable owner;

constructor(
bytes32 _initHash,
uint256 _trayPrice,
address _revenueAddress,
address _note,
address _namespaceNFT,
address _owner
) ERC721A("Namespace Tray", "NSTRAY") Owned(msg.sender) {
    lastHash = _initHash;
    trayPrice = _trayPrice;
    revenueAddress = _revenueAddress;
    note = ERC20(_note);
    namespaceNFT = _namespaceNFT;
    owner = _owner;
    if (block.chainid == 7700) {
        // Register CSR on Canto mainnnet
        Turnstile turnstile = Turnstile(0xEcf044C5B4b867CFda001101c617eCd347095B44);
        turnstile.register(tx.origin);
    }
}
code423n4 commented 1 year ago

Withdrawn by 0xnev