01. Relevant GitHub Links
02. Summary
RAACNFT Contract's mint function uses an incorrect comparison operator for the amount entered by the user, causing nft mint to fail even if the user tries to pay the correct amount of money for the nft they want to mint.
03. Vulnerability Details
In the RAACNFT::mint
function, the amount of tokens the user paid to purchase the _tokenId
NFT is provided as the _amount
argument. If you set the _amount
argument to a value that exactly matches the price of the token you want to mint, the condition price > _amount
will be true, causing a revert.
function mint(uint256 _tokenId, uint256 _amount) public override {
uint256 price = raac_hp.tokenToHousePrice(_tokenId);
if(price == 0) { revert RAACNFT__HousePrice(); }
@> if(price > _amount) { revert RAACNFT__InsufficientFundsMint(); }
token.safeTransferFrom(msg.sender, address(this), _amount);
_safeMint(msg.sender, _tokenId);
if (_amount > price) {
uint256 refundAmount = _amount - price;
token.safeTransfer(msg.sender, refundAmount);
}
emit NFTMinted(msg.sender, _tokenId, price);
}
04. Impact
05. Tools Used
Manual Code Review and Foundry
07. Recommended Mitigation
function mint(uint256 _tokenId, uint256 _amount) public override {
uint256 price = raac_hp.tokenToHousePrice(_tokenId);
if(price == 0) { revert RAACNFT__HousePrice(); }
- if(price > _amount) { revert RAACNFT__InsufficientFundsMint(); }
+ if(price >= _amount) { revert RAACNFT__InsufficientFundsMint(); }
// transfer erc20 from user to contract - requires pre-approval from user
token.safeTransferFrom(msg.sender, address(this), _amount);
// mint tokenId to user
_safeMint(msg.sender, _tokenId);
// If user approved more than necessary, refund the difference
if (_amount > price) {
uint256 refundAmount = _amount - price;
token.safeTransfer(msg.sender, refundAmount);
}
emit NFTMinted(msg.sender, _tokenId, price);
}