xanoutas/solidity-security-findings huggingface dataset:
Miss slippage protection for amountMinted in mintWithBudget.
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/TraitForgeNft/TraitForgeNft.sol#L202-L225


# Vulnerability details

## Impact
Miss slippage protection for `amountMinted` in `mintWithBudget`.

User may get less amount than they expected.

## Proof of Concept
In `mintWithBudget`, only the total payment amount `msg.value` is specified, and the desired mint quantity is not specified.

https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/TraitForgeNft/TraitForgeNft.sol#L202-L225
```solidity
  function mintWithBudget(
    bytes32[] calldata proof
  )
    public
    payable
    whenNotPaused
    nonReentrant
    onlyWhitelisted(proof, keccak256(abi.encodePacked(msg.sender)))
  {
    uint256 mintPrice = calculateMintPrice();
    uint256 amountMinted = 0;
    uint256 budgetLeft = msg.value;

    while (budgetLeft >= mintPrice && _tokenIds < maxTokensPerGen) {
      _mintInternal(msg.sender, mintPrice);
      amountMinted++;
      budgetLeft -= mintPrice;
      mintPrice = calculateMintPrice();
    }
    if (budgetLeft > 0) {
      (bool refundSuccess, ) = msg.sender.call{ value: budgetLeft }('');
      require(refundSuccess, 'Refund failed.');
    }
  }
```

Due to the constantly rising price of mint, the same `msg.value` executed at different times may result in receiving different quantities of NFTs.

For example, at the beginning when it was cheap, 1 ETH could buy 5 NFT, but later as the mint price rose, 1 ETH could only buy 2 NFT. The user cannot know how much the mint price will rise before their transaction is executed. If the user cannot set the expected number to be obtained, he may end up spending the same amount of money to buy fewer NFTs than expected.

## Tools Used
vscode
## Recommended Mitigation Steps
Add `minAmountMinted` in `mintWithBudget` and check with `amountMinted`.


## Assessed type

Invalid Validation
Lack of Slippage Protection in Dynamic Pricing Mint Function
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L202-L225


# Vulnerability details

## Impact
The mintWithBudget function uses a dynamic pricing mechanism without implementing slippage protection. Given the specific pricing parameters, this can lead to users paying more than anticipated for their NFTs, especially for larger mints or mints occurring later in a generation. Specific impacts include:

* Unexpected cost increases for users, particularly for multi-NFT mints.
* Potential for users to receive fewer NFTs than expected if prices rise during minting.
* Possible transaction failures if the price increases beyond the user's budget, wasting gas.


## Proof of Concept
The current implementation calculates the mint price for each NFT individually within the minting loop:

```function mintWithBudget(bytes32[] calldata proof) public payable whenNotPaused nonReentrant onlyWhitelisted(proof, keccak256(abi.encodePacked(msg.sender))) {
    uint256 mintPrice = calculateMintPrice();
    uint256 amountMinted = 0;
    uint256 budgetLeft = msg.value;

    while (budgetLeft >= mintPrice && _tokenIds < maxTokensPerGen) {
      _mintInternal(msg.sender, mintPrice);
      amountMinted++;
      budgetLeft -= mintPrice;
      mintPrice = calculateMintPrice();  // Price recalculated for each mint
    }
    // ...
}

function calculateMintPrice() public view returns (uint256) {
    uint256 currentGenMintCount = generationMintCounts[currentGeneration];
    uint256 priceIncrease = priceIncrement * currentGenMintCount;
    uint256 price = startPrice + priceIncrease;
    return price;
}
```

Consider the following scenario:

User calculates that they can mint 100 NFTs with a budget of 12.75 ETH when 5000 NFTs have been minted in the current generation.
* Initial price: 0.005 + (0.0000245 * 5000) = 0.1275 ETH per NFT
* Expected total: 100 * 0.1275 = 12.75 ETH
* Before the user's transaction is processed, another person mints 50 NFTs.
* When the user's transaction is processed, the new starting price is:
* 0.005 + (0.0000245 * 5050) = 0.128725 ETH
* The user attempts to mint with their 12.75 ETH budget:

They can now only mint 99 NFTs (12.75 / 0.128725 ≈ 99.04)
Total cost for 99 NFTs: approximately 12.74 ETH
Remaining 0.01 ETH is refunded


Actual outcome:

User receives 99 NFTs instead of the expected 100
The average price paid per NFT is higher than initially calculated



This scenario demonstrates how the lack of slippage protection in the dynamic pricing mechanism can lead to users receiving fewer NFTs than they anticipated or paying more per NFT than expected, due to price increases caused by other users' minting activities between the time of calculation and the transaction being processed.
## Tools Used
manual view
## Recommended Mitigation Steps
add slippage protection


## Assessed type

Context
Upgraded Q -> 2 from #191 [1724083427475]
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

Judge has assessed an item in Issue #191 as 2 risk. The relevant finding follows:

 Impact
Cannot pause the contract in an emergency situation.

Proof of Concept
The DevFund, EntityTrading, Airdrop, EntityForging, EntropyGenerator, NukeFund, and TraitForgeNft contracts inherit Pausable and use the whenNotPaused modifier. However, they do not have a public function that calls Pausable._pause. Therefore, it is practically impossible to pause these contracts.

Tools Used
Manual Review

Recommended Mitigation Steps
Create a public function in the contracts using Pausable that calls Pausable._pause so that the administrator can pause the contract.
Upgraded Q -> 2 from #201 [1724083404790]
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

Judge has assessed an item in Issue #201 as 2 risk. The relevant finding follows:

 If the forge() mints the last tokenId in the gen, next user could receive the tokenId in the gen+1 with the significant less price, which lead to the protocol money loose.
Impact
The problem here is that if the mintEntity will be minted exactly at the end of the generation, the next user could mint an NFT without paying a full price for it, only the base price. Once the gen will be updated, the generationMintCounts will be set to 0. https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L345-L354 After, the user will invoke the mintToken function and the price will be multiplied by 0, which will lead to more favorable price the user can buy a token https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L181 ##Recommended Mitigation Steps Ensure that the price for the first token minted will not be multiplied by 0
Upgraded Q -> 2 from #1013 [1724082675544]
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

Judge has assessed an item in Issue #1013 as 2 risk. The relevant finding follows:

 [L-02] NFT.mint lack slippage protection
Description
    function calculateMintPrice() public view returns (uint256) {
        uint256 currentGenMintCount = generationMintCounts[currentGeneration];
        uint256 priceIncrease = priceIncrement * currentGenMintCount;
        uint256 price = startPrice + priceIncrease;
        return price;
    }
The price of NFT increases gradually with the number of minted coins. The user’s transaction may be delayed, resulting in the minting cost exceeding the user’s expectations. In particular, mintWithBudget allows users to mint in batches, which may cause financial losses.

Recommendations
The mintWithBudget function should add slippage protection for single minting price
Upgraded Q -> 2 from #1022 [1724081741665]
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

Judge has assessed an item in Issue #1022 as 2 risk. The relevant finding follows:

 [L-01] Pause/Unpause functionalities are not implemented in many pausable contracts
In the current implementation of the protocol’s contracts, which are intended to be pausable by design (as they inherit from the Pausable contract provided by OpenZeppelin), there is a critical oversight. While these contracts do include internal functions _pause and _unpause since they inherit from pausable, they lack the necessary public or external functions that allow a contract manager or administrator to actually trigger these pause and unpause operations.

contract NukeFund is INukeFund, ReentrancyGuard, Ownable, Pausable {}
contract EntityForging is IEntityForging, ReentrancyGuard, Ownable, Pausable{}
contract EntityTrading is IEntityTrading, ReentrancyGuard, Ownable, Pausable{}
contract TraitForgeNft is ITraitForgeNft, ERC721Enumerable, ReentrancyGuard, Ownable, Pausable{}

As it is shown above all the contracts are meant to be pausable but because those functions in the pausable are internal, the contract must implement two other public/external pause and unpause functions to allow the manager to pause and unpause the contracts when necessary. None of the aforementioned contracts implement those functions, which means even if those contracts are supposed to be pausable (and have the pause/unpause functionalities), none of them can be paused. without the corresponding public or external functions to expose these internal mechanisms, the contracts remain permanently in their operational state and cannot be paused when necessary.

Recommended Mitigation Steps
Add public/external pause and unpause functions in the aforementioned contracts to allow them to be pausable, this can be done as in the UserWithdrawalManager contract. For example:

/**
 * @dev Triggers stopped state.
 * Contract must not be paused
 */
function pause() external {
    UtilLib.onlyManagerRole(msg.sender, staderConfig);
    _pause();
}

/**
 * @dev Returns to normal state.
 * Contract must be paused
 */
function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {
    _unpause();
}
Upgraded Q -> 2 from #1027 [1724081366853]
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

Judge has assessed an item in Issue #1027 as 2 risk. The relevant finding follows:

 [QA-1] Contract inherits from Pausable but does not expose pausing/unpausing functionality
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/DevFund/DevFund.sol#L6 https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityForging/EntityForging.sol#L6 https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityTrading/EntityTrading.sol#L7 https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntropyGenerator/EntropyGenerator.sol#L5 The TraitForge smart contracts inherits from OpenZeppelin’s Pausable contract, but the _pause and _unpause methods are not exposed externally to be callable This shows that Pausable was used incorrectly and is possible to give out a false sense of security when actually contract is not pausable at all.
Pause/unpause functionalities not implemented in many pausable contracts
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/Airdrop/Airdrop.sol#L1-L75
https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/DevFund/DevFund.sol#L1-L93
https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/EntityForging/EntityForging.sol#L1-L208
https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/EntityTrading/EntityTrading.sol#L1-L118
https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/EntropyGenerator/EntropyGenerator.sol#L1-L217
https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/NukeFund/NukeFund.sol#L1-L195
https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/Trait/Trait.sol#L1-L28
https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/TraitForgeNft/TraitForgeNft.sol#L1-L396


# Vulnerability details

The Airdrop, DevFund, EntityForging, EntityTrading, NukeFund, Trait and TraitForgeNft are supposed to be pausable (they inherit from Pauseable, and ERC20Pausable) but they don't implement the external pause/unpause functionalities which means it will never be possible to pause them.

## **Proof of Concept**

All the following contracts Airdrop, DevFund, EntityForging, NukeFund, Trait and TraitForgeNft inherit from the openzeppelin Pausable extension which means that they contain internal functions _pause and _unpause. Because those functions are internal, the contract must implement two other public/external pause and unpause functions to allow the owner to pause and unpause the contracts when necessary. None of the aforementioned contracts implement those functions, which means even if those contracts are supposed to be pausable (and have the pause/unpause functionalities), none of them can be paused.

## **Recommended Mitigation Steps**

Add public/external pause and unpause functions in the aforementioned contracts to allow them to be pausable. For example:

```
/**
 * @dev Triggers stopped state.
 * Contract must not be paused
 */
function pause() external onlyOwner {
    _pause();
}

/**
 * @dev Returns to normal state.
 * Contract must be paused
 */
function unpause() external onlyOwner {
    _unpause();
}

```


## Assessed type

Access Control
`pause/unpause` functionality isn't implemented.
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityForging/EntityForging.sol#L10
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/DevFund/DevFund.sol#L9
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityTrading/EntityTrading.sol#L11
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntropyGenerator/EntropyGenerator.sol#L9
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/NukeFund/NukeFund.sol#L11
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L14


# Vulnerability details

## Impact
The following contracts: `EntityForging`, `DevFund`, `EntityTrading`, `EntropyGenerator`, `NukeFund`, `TraitForgeNft` are supposed to be pausable (as they all inherit from `Pausable`), but they don't implement the external pause/unpause functionalities which means it will never be possible to pause them.

## Proof of Concept
All the following contracts inherit from the openzeppelin Pausable extension which means that they contain internal functions _pause and _unpause.

Because those functions are internal, the contract must implement two other public/external pause and unpause functions to allow the manager to pause and unpause the contracts when necessary. None of the aforementioned contracts implement those functions, which means even if those contracts are supposed to be pausable (and have the pause/unpause functionalities), none of them can be paused.

## Tools Used
Manual review.

## Recommended Mitigation Steps
Add public/external pause and unpause functions in the aforementioned contracts to allow them to be pausable. For example:
```solidity
function pause() external onlyOwner {
    _pause();
}

function unpause() external onlyOwner {
    _unpause();
}
```


## Assessed type

Access Control
TraitForgeNft and various other contracts are expected to be Pauseable, but can never be paused.
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L19
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L96
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L141
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L158
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L186
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L207
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L394


# Vulnerability details

## Impact
The [TraitForgeNft contract inherits OpenZeppelin's Pausable](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L19), and defines various functions which cannot be called while the contract is paused (for example: [this](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L141), and [this](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L394)). Yet it does not define a function that can actually trigger the pausing of the contract (by calling the _pause function available from the OpenZeppelin Pausable inherited). This means the contract can never be paused, and the entire logic for pausing the contract can never be reached - so in an emergency, or cases when the owner would find it appropriate or necessary to pause the contract, it will be impossible to do so.

Note that I have mentioned here only the instances where pausablity is expected in TraitForgeNft, but the same issue exists also in Airdrop, DevFund, EntityForging, EntityTrading, EntropyGenerator, NukeFund, and Trait (the latter inherits ERC20Pausable which inherits Pauseable, but none have a externally exposed function that could trigger the paused state of the contract).

## Proof of Concept
You can see that there is no function that changes the state of the defined _paused state variable, except the _pause and _unpause functions defined by OpenZeppelin, but these are internal and not used in the contract, so cannot be used by the owner (or anyone for that matter).

## Tools Used
Code review

## Recommended Mitigation Steps
Add externally callable pause() and unpause() functions which have an onlyOwner modifier for their access control, like so:

```
function pause() external onlyOwner {
  _pause();
}

f
Many pausable contract is not pausable because the external 'pause/unpause' function is not implemented
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityTrading/EntityTrading.sol#L38-L41
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityTrading/EntityTrading.sol#L63
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityTrading/EntityTrading.sol#L94
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L96
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L141
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L153-L158
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L181-L187
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L202-L209
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L394
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/NukeFund/NukeFund.sol#L153
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityForging/EntityForging.sol#L67-L70
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityForging/EntityForging.sol#L102-L105
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityForging/EntityForging.sol#L177-L179
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntropyGenerator/EntropyGenerator.sol#L206
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/DevFund/DevFund.sol#L61


# Vulnerability details

## Impact
The following contracts: EntityTrading, TraitForgeNft, NukeFund, EntityForging, EntropyGenerator and DevFund (in scope), and Airdrop (not in scope) are supposed to be pausable (as they all inherit from Pausable contract, and use the `whenNotPaused` modifier in some functions), but they don't implement the external `pause/unpause` function which means it will never be possible to pause them. And the modifier `whenNotPaused` will also not work.

## Proof of Concept
All the following contracts: EntityTrading, TraitForgeNft, NukeFund, EntityForging, EntropyGenerator and DevFund inherit from the openzeppelin's Pausable contract which means that they contain internal functions `_pause` and `_unpause` and some functions and modifiers regarding the pause funcionality.

```solidity
    function _pause()
Contracts are meant to be pausable but it is impossible in practice
Audit: 2024-07-traitforge-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntityTrading/EntityTrading.sol#L11


# Vulnerability details

## Impact
The owner is unable to pause the contracts.

## Proof of Concept
All of the in-scope contracts inherits from OZ Pausable but none of them provides any public methods for pausing/unpausing the contract.

## Tools Used
Manual review

## Recommended Mitigation Steps
Add public/external pause and unpause functions to all the contracts:

```js
function pause() external onlyOwner{
    _pause();
}

function unpause() external onlyOwner {
    _unpause();
}
```


## Assessed type

Context