xanoutas/solidity-security-findings huggingface dataset:
[H-3] `TraitForgeNft::_incrementGeneration` resets the `generationMintCounts[currentGeneration]` to `0`, causing more than 10000 NFTs of the future generations to be minted
Audit: 2024-07-traitforge-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
As per the contest docs, each generation should have a maximum of 10000 NFTs. NFTs can be created by forging or minting. Since `generationMintCounts[currentGeneration]` is set to 0 when incrementing the `currentGeneration` value, the further generations can have more than 10000 NFTs.

## Proof of Concept
Consider this scenario:

> Let's say 8000 of Gen-1 NFTs are minted.
> These NFTs are then forged and 2000 new Gen-2 NFTs are created by forging.
> When Gen-1 mint count reaches 10000, `_incrementGeneration` will be called for further mints.
> This would first increase `currentGeneration` value from 1 to 2 and then reset `generationMintCounts[currentGeneration]` to 0. After this another 10000 NFTs of Gen-2 can be minted.
> This would be the case for all generations from Gen-2 to Gen-10.

```javascript
  function _incrementGeneration() private {
    require(
      generationMintCounts[currentGeneration] >= maxTokensPerGen,
      'Generation limit not yet reached'
    );
    currentGeneration++;
    generationMintCounts[currentGeneration] = 0;
    priceIncrement = priceIncrement + priceIncrementByGen;
    entropyGenerator.initializeAlphaIndices();
    emit GenerationIncremented(currentGeneration);
  }
```

## Tools Used
Manual Review

## Recommended Mitigation Steps

Simply removing the line `generationMintCounts[currentGeneration] = 0` won't solve the issue.

If this line is removed, consider the following scenario:

> Let's say 8000 of Gen-1 NFTs are minted.
> These NFTs are then forged and all of 10000 new Gen-2 NFTs are created by forging.
> When Gen-1 reaches 10000 NFTs and `mintToken` is called again, inside `_mintInternal` it'll increment the generation to Gen-2, but 10000 of Gen-2 are already created by forging, so it need to increment further however this is not the case.
> This allows 10001 NFTs of Gen-2 to be minted before it moves on to Gen-3.


Probable Fix:
```diff
  function _incrementGeneration() private {
    require(
      generationMintCounts[currentGeneration] >= maxTokensPerGen,
      'Generation limit not yet reached'
    );
    currentGeneration++;
-   generationMintCounts[currentGeneration] = 0;
    priceIncrement = priceIncrement + priceIncrementByGen;
    entropyGenerator.initializeAlphaIndices();
    emit GenerationIncremented(currentGeneration);
  }
```

```diff
  function _mintInternal(address to, uint256 mintPrice) internal {
-   if (generationMintCounts[currentGeneration] >= maxTokensPerGen) {
+   while (generationMintCounts[currentGeneration] >= maxTokensPerGen) {
      _incrementGeneration();
    }
```




## Assessed type

Other
TraitForgeNft:mintToken() will revert if normal users triggers an increase in generation
Audit: 2024-07-traitforge-findings
Severity: HIGH

# Lines of code

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/TraitForgeNft/TraitForgeNft.sol#L353


# Vulnerability details

## Impact
Since TraitForgeNft isn't the owner of EntropyGenerator every `TraitForgeNft:_incrementGeneration()` will revert.

Effectively making the game not-playable after the first generation has ended.

## Proof of Concept
When the `maxTokensPerGen` is reached, `_incrementGeneration()` is called:

```js
function _incrementGeneration() private {
    require(
      generationMintCounts[currentGeneration] >= maxTokensPerGen,
      'Generation limit not yet reached'
    );
    currentGeneration++;
    generationMintCounts[currentGeneration] = 0;
    priceIncrement = priceIncrement + priceIncrementByGen;
    entropyGenerator.initializeAlphaIndices();
    emit GenerationIncremented(currentGeneration);
}
```

Which also calls `EntropyGenerator:initializeAlphaIndices()` which will always revert at this point since `TraitForgeNft` isn't the owner of `EntropyGenerator`.


First change TraitForgeNft:maxTokensPerGen to 10, only for this test to run faster, and then add the following into 'test/TraitForgeNft.test.ts':

```js
it.only('impossible to increment generation', async () => {
    // mint maxTokensPerGen + 1 tokens      
    for(let i = 0; i < 11; i++) {
        await nft.connect(user1).mintToken(merkleInfo.whitelist[1].proof, {
          value: ethers.parseEther('1'),
        });
      }
    })
```

## Tools Used

Manual Review

## Recommended Mitigation Steps

Make `initializeAlphaIndices()` callable by:
- the owner, so it doesn't revert in the constructor
- the allowedCaller, so `TraitForgeNft` can correctly increment generation

```
-function initializeAlphaIndices() public whenNotPaused onlyOwner {
+function initializeAlphaIndices() public whenNotPaused {
+require(msg.sender == owner() || msg.sender == allowedCaller);
```








## Assessed type

Access Control
Access Control Conflict: EntropyGenerator Contract's `onlyOwner` Modifier Conflicts with TraitForgeNft Contract Integration
Audit: 2024-07-traitforge-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntropyGenerator/EntropyGenerator.sol#L36-L39
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/EntropyGenerator/EntropyGenerator.sol#L205-L216
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L345-L355


# Vulnerability details

## Impact
Not setting the owner of the EntropyGenerator contract to the TraitForgeNft contract will result in the `_incrementGeneration` function always reverting, effectively halting the generation increment process. Conversely, setting the owner to TraitForgeNft will restrict future calls to the `setAllowedCaller` function in the EntropyGenerator contract, limiting its flexibility and control.

## Proof of Concept
After deploying the EntropyGenerator contract, the Owner will be the developer's EOA account. According to the deployment script deployTasks, the owner of this contract will not be changed subsequently.

The `initializeAlphaIndices` function of the EntropyGenerator contract has an `onlyOwner` modifier, which means that only the owner of the contract can call it.
```solidity
function initializeAlphaIndices() public whenNotPaused onlyOwner {
    uint256 hashValue = uint256(
        keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp))
    );

    uint256 slotIndexSelection = (hashValue % 258) + 512;
    uint256 numberIndexSelection = hashValue % 13;

    slotIndexSelectionPoint = slotIndexSelection;
    numberIndexSelectionPoint = numberIndexSelection;
}
```

However, this function is also called in the TraitForgeNft contract.
```solidity
function _incrementGeneration() private {
    require(
        generationMintCounts[currentGeneration] >= maxTokensPerGen,
        'Generation limit not yet reached'
    );
    currentGeneration++;
    generationMintCounts[currentGeneration] = 0;
    priceIncrement = priceIncrement + priceIncrementByGen;
    entropyGenerator.initializeAlphaIndices();
    emit GenerationIncremented(currentGeneration);
}
```

This means that if the owner is not set to the TraitForgeNft contract subsequently, the call to its `_incrementGeneration` function will always revert. Conversely, if the owner is set to the TraitForgeNft contract, it will prevent future calls to the `setAllowedCaller` function of the EntropyGenerator contract.

```solidity
  function setAllowedCaller(address _allowedCaller) external onlyOwner {
    allowedCaller = _allowedCaller;
    emit AllowedCallerUpdated(_allowedCaller); // Emit an event for this update.
  }
```

## Tools Used
Manual Review

## Recommended Mitigation Steps
A feasible solution is to modify the access control of the `initializeAlphaIndices` function from `onlyOwner` to `onlyAllowedCaller`, and change the constructor as follows:
```solidity
constructor(address _traitForgetNf
`mintWithBudget` will stop minting for generations 2 and beyond
Audit: 2024-07-traitforge-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Description
There is a bug in `mintWithBudget` which `prevent minting the entire budget` if the end of a generation 1 is reach which seems unexpected and warrant `Medium` severity.

The root cause is due to the fact that the loop is bounded against `_tokenIds < maxTokensPerGen` which will limit the minting to generation 1 (the first 10000 NFT). Afterward, calling this function will not mint any NFT, so just waste gas and refund the player.

```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.');
    }
  }
```  


## Impact
- Player calling `mintWithBudget` once generation 1 is almost all minted, will not have their entire budget spent in minting, as the minting will stop once generation 1 is fully minted.
- Player calling `mintWithBudget` after generation 1 is fully minted will just `waste gas`, as the function will not even enter the loop, hence not minting, and the player will get refunded almost entirely (minus the gas spent in this function).
- Player sending a big amount of ETH will have their transaction `run out of gas` and revert.


## PoC
Add the following changes `TraitForgeNft.test.ts` and run `yarn test`
Modify `TraitForgeNft::maxTokensPerGen` to let say 5 to see the problem faster. You will see that even with a 1 ETH budget, it will only mint 5 NFT, so the first generation only.

```solidity
    it.only('mintWithBudget stop minting at generation 2', async () => {
      // 1)  Allow anyone to mint
      fastForward(24 * 60 * 60 + 1);

      // 2) Pull the data from the contract
      const maxTokensPerGen = await nft.maxTokensPerGen();
      const startPrice = await nft.startPrice();
      const priceIncrement = await nft.priceIncrement();
      const priceIncrementByGen = await nft.priceIncrementByGen();
      const maxGeneration = await nft.maxGeneration();

      console.log(`maxGeneration:        ${maxGeneration}`);
      console.log(`maxTokensPerGen:      ${maxTokensPerGen}`);
      console.log(`startPrice:           ${startPrice}`);
      console.log(`priceIncrement:       ${priceIncrement}`);
      console.log(`priceIncrementByGen:  ${priceIncrementByGen}`);

      // 3) Ensure no NFT has been minted yet
      expect(await nft.curre
Violation of Max Cap Per Generation
Audit: 2024-07-traitforge-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
The [maxCap](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L22) for each nft generation is set to 10K. However that can be violated. 

## Proof of Concept
I'll go through an example to make it more clear by providing the necessary code part. Let's say 100 merger and 100 forger of generation 1 are forged through [forge](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L153) function. In this function the following line of code :
```solidity
 uint256 newGeneration = getTokenGeneration(parent1Id) + 1;
```
shows that the new nft that will be minted has an upper generation.In this case there will be 100 tokens of gen2.After maxCap for generation1 is reached, if [mintToken](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L181) is called, there will be a call to `_mintInternal` function:
```solidity
 function _mintInternal(address to, uint256 mintPrice) internal {
    if (generationMintCounts[currentGeneration] >= maxTokensPerGen) {
      _incrementGeneration();
    }
   //SKIP

  }
```
as it can be seen from the code above,the if check will be  passed (due to fact that gen1 maxcap is reached) and there will be a call to `_incrementGeneration()`:
```solidity
 function _incrementGeneration() private {
    require(
      generationMintCounts[currentGeneration] >= maxTokensPerGen,
      'Generation limit not yet reached'
    );
    currentGeneration++;
    generationMintCounts[currentGeneration] = 0;//@audit-issue  ignores already minted ones
    priceIncrement = priceIncrement + priceIncrementByGen;
    entropyGenerator.initializeAlphaIndices();
    emit GenerationIncremented(currentGeneration);
  }
```
the function initial check will be passed and currentGeneration will be increased to 2. Later generationMintCounts[2] is set to  0, ignoring already minted 100 tokens of gen2 based on the example ı provided above. That will result in over minting and dilute the value of NFTs.
## Tools Used
Vs Code, Manual Review
## Recommended Mitigation Steps
Implement a check that ensures the mint count for the new generation is not reset if it already has minted tokens
```solidity
 function _incrementGeneration() private {
    require(
      generationMintCounts[currentGeneration] >= maxTokensPerGen,
      'Generation limit not yet reached'
    );
    currentGeneration++;

 +++   if (generationMintCounts[currentGeneration] == 0) {
         generationMintCounts[currentGeneration] = 0;
    }
    priceIncrement = priceIncrement + priceIncrementByGen;
    entropyGenerator.initializeAlphaIndices();
    emit GenerationIn
Improper generation increment allows minting more than intended
Audit: 2024-07-traitforge-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

`TraitForgeNft` contract allows users to mint new tokens, with a limit of `maxTokensPerGen` tokens per generation. When the limit for the current generation is reached, the `_incrementGeneration()` function is called to increment the `currentGeneration` and reset the `generationMintCounts` for the new generation.

So, there is an issue in the way the generation is incremented, which allows minting more tokens than intended in a generation. The [_incrementGeneration()](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L345-L355) function is a private function that is called from within the [_mintInternal()](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L280-L309) function.

```solidity
function _mintInternal(address to, uint256 mintPrice) internal {
    if (generationMintCounts[currentGeneration] >= maxTokensPerGen) {
        _incrementGeneration();
    }
    // ...
}
```
The fact that `_incrementGeneration()` can be called multiple times within the same transaction if `_mintInternal()` is called repeatedly. This can happen when a user calls the [mintWithBudget()](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L202-L225) function, which allows minting multiple tokens in a single transaction until the provided budget is exhausted.

As a result, the `currentGeneration` can be incremented by more than 1 in a single transaction, effectively skipping generations and allowing more tokens to be minted in the skipped generations.

## Impact
This issue allows minting more tokens than the intended [maxTokensPerGen](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L22) limit per generation. An attacker can exploit this by calling [mintWithBudget()](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L202-L225) with a large enough budget to trigger multiple generation
`initializeAlphaIndices` uses the wrong modifier and correction for this risks certain protocol functionalities being unavailable.
Audit: 2024-07-traitforge-findings
Severity: HIGH

# Lines of code

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/TraitForgeNft/TraitForgeNft.sol#L353


# Vulnerability details

### Impact

TraitForgeNft.sol doesn't deploy EntropyGenerator.sol and as such is not the owner. Therefore the owner protected functions in EntropyGenerator.sol cannot be directly accessed. Transferring ownership to it however, risks that the ability to pause EntropyGenerator, and set a new allowedCaller will be lost indefinitely.

### Proof of Concept

1. Context

This relies on a bit of speculation.

Important properties of EntropyGenerator.sol to be aware of for this issue.

It's pausable, has an owner and also implements an `onlyAllowedCaller`

```solidity
contract EntropyGenerator is IEntropyGenerator, Ownable, Pausable {
```

```solidity
  modifier onlyAllowedCaller() {
    require(msg.sender == allowedCaller, 'Caller is not allowed');
    _;
  }
```

The allowedCaller can be set, updated or changed by the owner who is the deployer of the contract.

```solidity
  function setAllowedCaller(address _allowedCaller) external onlyOwner {
    allowedCaller = _allowedCaller;
    emit AllowedCallerUpdated(_allowedCaller); // Emit an event for this update.
  }
```
And from the constructor, we discover that the allowedCaller is initially set to the TraitForgeNFT contract.
```solidity
  constructor(address _traitForgetNft) {
    allowedCaller = _traitForgetNft;
    initializeAlphaIndices();
  }
```
And to further cement this, the `onlyAllowedCaller` is used in the `getNextEntropy` function.
```solidity
  function getNextEntropy() public onlyAllowedCaller returns (uint256) {
//...
    return entropy;
  }
```
And in TraitForgeNFT.sol, we can see that the function is called while minting.
```solidity
  function _mintInternal(address to, uint256 mintPrice) internal {
//...
    uint256 entropyValue = entropyGenerator.getNextEntropy();
//...
  }
```

2. Bug Location

In EntropyGenerator.sol, the `initializeAlphaIndices` should be callable by the owner. And since the contract uses [Ownable 4.9.3](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/package.json#L19) which [sets the deployer as the](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/fd81a96f01cc42ef1c9a5399364968d0e07e9e90/contracts/access/Ownable.sol#L28-L31) owner.

```solidity
  function initializeAlphaIndices() public whenNotPaused onlyOwner {
//...
  }
```

But when we look at TraitForgeNFT.sol, there's no function to deploy EntropyGenerator.sol, its only [set](https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L82-L88). So it can be directly inferred that TraitForgeNFT.sol doesn't own EntropyGenerator.sol.

3. Final Effect
mintWithBudget doesn't work with next generation.
Audit: 2024-07-traitforge-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
`mintWithBudget` doesn't work with next generation, only works with the first generation.

## Proof of Concept
In `mintWithBudget`, it requires `_tokenIds < maxTokensPerGen`.

https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/TraitForgeNft/TraitForgeNft.sol#L215-L220
```solidity
    while (budgetLeft >= mintPrice && _tokenIds < maxTokensPerGen) {
      _mintInternal(msg.sender, mintPrice);
      amountMinted++;
      budgetLeft -= mintPrice;
      mintPrice = calculateMintPrice();
    }
```

The problem here is that `tokenId` keeps increasing and does not reset with the generation of a new generation, meaning that if `maxTokensPerGen` is 10, then the first `tokenId` of the second generation will be 10 and will continue to increase, no longer satisfying `tokenId < maxTokensPerGen`.

https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/TraitForgeNft/TraitForgeNft.sol#L285-L287
```solidity
    _tokenIds++;
    uint256 newItemId = _tokenIds;
    _mint(to, newItemId);
```
## Tools Used
vscode
## Recommended Mitigation Steps
I don't know what the intent behind the requirement `_tokenIds < maxTokensPerGen` is. If you only want to limit the tokens to a single generation, you can achieve that by validating `currentGeneration`.


## Assessed type

Error
TRansfering the NFT doesn not transfer the airdrop amount
Audit: 2024-07-traitforge-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
Users can mint NFTs and sell them to others just to farm the airdrop. Selling or transferring these NFTs does not change the airdrop amount they receive.

## Proof of Concept
Airdrop amounts are added when a new `tokenID` is minted:

```solidity
    tokenEntropy[newTokenId] = entropy;
    initialOwners[newTokenId] = newOwner;

    ...
    if (!airdropContract.airdropStarted()) {
        airdropContract.addUserAmount(newOwner, entropy);
    }
```

However, that entropy is removed only when the token is [burned](https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/TraitForgeNft/TraitForgeNft.sol#L141-L151). It is not removed on transfers or sales, enabling airdrop farmers to farm airdrop points by minting NFTs and selling them to active users who actually play the game.

This will lower the value of the game as some users exploit it for quick points and move on when the airdrop ends.

## Tools Used
Manual review

## Recommended Mitigation Steps
In the [_beforeTokenTransfer](https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/TraitForgeNft/TraitForgeNft.sol#L367) function, decrease the airdrop value for `from` and increase it for `to`:

```diff
    }

+   if (!airdropContract.airdropStarted()) {
+       uint256 entropy = getTokenEntropy(tokenId);
+       airdropContract.subUserAmount(initialOwners[tokenId], entropy);
+       initialOwners[tokenId] = to;
+       airdropContract.addUserAmount(initialOwners[tokenId], entropy);
+   }

    require(!paused(), "ERC721Pausable: token transfer while paused");
}
```


## Assessed type

Error