xanoutas/solidity-security-findings huggingface dataset:
Universal Data Key Permissions May Be Abused During Ownership Transfers
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L132-L137
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L282-L288
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L462


# Vulnerability details

## Impact
In LSP6KeyManager, when fetching permissions. we are looking for universal permissions (independent from the owner). If a UP owner transfers ownership to a new owner that uses a key manager, the previously set permissions (like access for a lot controller) remain intact. This can potentially enable the old owner to retain significant control over the UP, which could be abused to destabilize the contract or cause financial harm to the new owner and other participants.

## Proof of Concept
The problem arises from the inability of the smart contract to identify and manage data keys that were set by previous owners. A malicious actor could set certain permissions while they are the owner of the UP, then transfer the ownership to a new owner. The old permissions would remain in effect, allowing the old owner to maintain undue control and possibly 'rug pull' or cause other harmful actions at a later date.

## Tools Used
The issue was identified through manual review of the contract mechanisms and their potential abuse, without the use of specific security tools.


## Recommended Mitigation Steps
To prevent potential abuse through residual permissions, the data keys for permissions should be made owner-specific. The following mitigation steps can be implemented:

- Hash the permission with the owner's address: When setting permissions, they can be hashed with the owner's address. This way, the permissions are specifically associated with a particular owner and do not affect subsequent owners.

- Add a nonce upon ownership transfer: To further ensure the uniqueness and irrelevance of old permissions, a random nonce can be added each time the ownership is transferred. This nonce can be used in conjunction with the address of the LSP6 when retrieving permissions, making any permissions set by old owners irrelevant.



## Assessed type

Rug-Pull
Insufficient Length Check When Verifying Allowed Data Keys
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol#L559; https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol#L679


# Vulnerability details

## Impact
There is an insufficient length check when validating the allowed data keys that can be set by a caller. In particular, if a decoded length in the compact bytes array happens to be 0, the caller will be validated against any data key.

Although a decoded length is not possible when setting allowed data keys via the `LSP6SetDataModule` contract, there is no guarantee that data values before ownership transfer to an LSP6 contract are valid. This allows a scamming opportunity as malicious actors who set-up an ERC725 contract for another can create a backdoor that cannot be easily seen as the allowed data keys will simply have an extra `0x0000`.

When verifying allowed data keys that a caller can set, a length check is done on the first 2 bytes of a compact bytes array to ensure that the length does not exceed a data key's length.

```solidity=559
            if (length > 32)
                revert InvalidEncodedAllowedERC725YDataKeys(
                    allowedERC725YDataKeysCompacted,
                    "couldn't DECODE from storage"
                );
```

This `length` value is used to decide the bit mask when validating data keys.

```solidity=581
            mask =
                bytes32(
                    0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                ) <<
                (8 * (32 - length));
```

In the case that `length == 0`, then `mask == bytes32(0)`.

Then the validation check for all data keys will pass as the validation will be reduced to whether or not `allowedKey & bytes32(0) == inputDataKey & bytes32(0)`, which is always true.

```solidity=600
                allowedKey := and(memoryAt, mask)
            }

            if (allowedKey == (inputDataKey & mask)) return;
```

This allows the caller to set data values for all data keys except those used for LSP1, LSP6, and LSP17 due to the initial checks in `LSP6SetDataModule._getPermissionRequiredToSetDataKey()`. In particular, they would be able to obstruct data values for the following established keys:
- LSP3 keys detailing information about a universal profile
- LSP5 keys detailing information about received assets
- LSP10 keys detailing information about vault ownership

## Proof of Concept
Suppose userA and userB wish to share a universal profile and decide to use an LSP6 key manager to manage the profile. userA is decided to set-up the contracts. However, userA is malicious and does the following:
- Deploys the universal profile contract with userA as the owner
- Sets up permissions and data keys agreed by userA and userB
  - In particular, assume userA has permission to set data for
Calls _mint
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L266


# Vulnerability details

# Note: 
I only reported two issues that were not reported by the winning bot

## Calls _mint
- Severity: Medium
- Confidence: High

### Description
The _mint function is often used to create new tokens in a Solidity smart contract.However, if the function is not implemented correctly, it can introduce vulnerabilities such as integer overflow and underflow, reentrancy, and other types of attacks.To address these issues, the safeMint function was introduced as part of the OpenZeppelin library.The safeMint function includes additional checks to prevent potential attacks, making it a safer alternative to _mint.

<details>

<summary>
There are 2 instances of this issue:

</summary>

###
- File: contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol
```
 
Line: 266          super._mint(to, tokenId, allowNonLSP1Recipient, data)
```
 use safeMint instead.

[https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L266](https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L266)


- File: contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol
```
 
Line: 266          super._mint(to, tokenId, allowNonLSP1Recipient, data)
```
 use safeMint instead.

[https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol#L266](https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol#L266)

 

</details>

# 


## Assessed type

Token-Transfer
The Loop implementation is wrong .  Loop always remove only first operator because  ``address operator = operatorsForTokenId.at(0)`` wrong implementation
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol#L275


# Vulnerability details

## Impact
``address operator = operatorsForTokenId.at(0)`` statement will always return the first operator in the list. So as per current implementation only possible to remove first operator. use ``i`` instead of ``0 `` in loop iterations. When we use ``i `` this will fetch all values and remove all ``operators``. 

## Proof of Concept

```solidity
FILE: Breadcrumbs2023-06-lukso/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol

    function _clearOperators(
        address tokenOwner,
        bytes32 tokenId
    ) internal virtual {
        // here is a good example of why having multiple operators will be expensive.. we
        // need to clear them on token transfer
        //
        // NOTE: this may cause a tx to fail if there is too many operators to clear, in which case
        // the tokenOwner needs to call `revokeOperator` until there is less operators to clear and
        // the desired `transfer` or `burn` call can succeed.
        EnumerableSet.AddressSet storage operatorsForTokenId = _operators[
            tokenId
        ];

        uint256 operatorListLength = operatorsForTokenId.length();
        for (uint256 i = 0; i < operatorListLength; ) {
            // we are emptying the list, always remove from index 0
            address operator = operatorsForTokenId.at(0); //@audit always return first operator in this list . ``i`` should be used instead of ``0``
            _revokeOperator(operator, tokenOwner, tokenId);

            unchecked {
                ++i;
            }
        }
    }

```
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol#L258-L282

## Tools Used
Manual Audit

## Recommended Mitigation Steps
Use ``i`` instead of ``0`` in loop execution 

```solidity

  address operator = operatorsForTokenId.at(i);

```


## Assessed type

Loop
Condition will not revert when block.timestamp is == to the compared variable
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L391-L394


# Vulnerability details

## Impact
The condition does not revert when `block.timestamp` is equal to the compared `>` or `<` variable. For example, if there is a check for `block.timestamp > proposerSignature.expirationTimestamp` then there should be a check for cases where `block.timestamp` is `==` to `proposerSignature.expirationTimestamp`

## Findings
Total: 2

[contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L391-L394](https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L391-L394)
```solidity
391:             if (block.timestamp < startingTimestamp) {
...
394:             if (block.timestamp > endingTimestamp) {
```


## Assessed type

Other
_safeMint() should be used rather than _mint() wherever possible (Addendum)
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L266
https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8CompatibleERC721MintableInitAbstract.sol#L29
https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8CompatibleERC721Mintable.sol#L19
https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol#L266


# Vulnerability details

Note: This risk has been included in the Automated Findings. At that time, the findings given by [M-04](https://gist.github.com/liveactionllama/cb2471f54012df01df5bd06a93e5125b#m04-_safemint-should-be-used-rather-than-_mint-wherever-possible) were not comprehensive.  I'm of the opinion that the subsequent findings should also be categorized under [M-04](https://gist.github.com/liveactionllama/cb2471f54012df01df5bd06a93e5125b#m04-_safemint-should-be-used-rather-than-_mint-wherever-possible) and they share a similar level of risk.

## Impact
`_mint()` is [discouraged](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/d4d8d2ed9798cc3383912a23b5e8d5cb602f7d4b/contracts/token/ERC721/ERC721.sol#L271) in favor of `_safeMint()` which ensures that the recipient is either an EOA or implements IERC721Receiver. Both [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/d4d8d2ed9798cc3383912a23b5e8d5cb602f7d4b/contracts/token/ERC721/ERC721.sol#L238-L250) and [solmate](https://github.com/Rari-Capital/solmate/blob/4eaf6b68202e36f67cab379768ac6be304c8ebde/src/tokens/ERC721.sol#L180) have versions of this function

### Findings
Total: 4

[contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol#L266](https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol#L266)
```solidity
266: super._mint(to, tokenId, allowNonLSP1Recipient, data);
```

[contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L266](https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L266)
```solidity
266: super._mint(to, tokenId, allowNonLSP1Recipient, data);
```

[contracts/LSP8IdentifiableDigitalAsset/presets/LSP8CompatibleERC721MintableInitAbstract.sol#L29](https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8CompatibleERC721MintableInitAbstract.sol#L29)
```solidity
29: _mint(to, tokenId, allowNonLSP1Recipient, data);
```

[contracts/LSP8IdentifiableDigitalAsset/presets/LSP8CompatibleERC721Mintable.sol#L19](https://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8CompatibleERC721Mintable.sol#L19)
```solidity
19: _mint(to, tokenId, allowNonLSP1Recipient, data
LSP6KeyManagerCore.sol#_executeRelayCall: Potential Gas Manipulation by Malicous relayer
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L345


# Vulnerability details

## Impact

This could allow a malicous relayer to manipulate the behavior of the called contract by controlling the gas provided for the transaction.

## Proof of Concept

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L345

The LSP6 protocol allows for relayed calls using supplied signatures. The encoded message is structured as follows:

bytes memory encodedMessage = abi.encodePacked(
   LSP6_VERSION,
   block.chainid,
   nonce,
   validityTimestamps,
   msgValue,
   payload
);

This does not include a specified gas parameter allowing the relayer to determine the gas amount for the transaction. If the provided gas is insufficient, the entire transaction would be reverted, which is expected. 

However, if the contract being called behaves differently based on the gas supplied, a malicious relayer can effectively control that behavior.

## Tools Used

Manual Review

## Recommended Mitigation Steps

The signed message should include a specified gas amount. This would ensure that the relayer cannot arbitrarily set the gas for the transaction. 

Additionally, it would be prudent to check that there is enough gas in the current transaction to cover the specified amount, taking into account the potential for truncation due to the 63/64 rule in EVM.


## Assessed type

DoS
unused-return
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/contracts/LSP1UniversalReceiver/LSP1Utils.sol#L20-L28
https://github.com/code-423n4/2023-06-lukso/contracts/LSP1UniversalReceiver/LSP1Utils.sol#L30-L50


# Vulnerability details

## Impact
Ignoring return value in LSP1Utils.tryNotifyUniversalReceiver:
The function tryNotifyUniversalReceiver attempts to notify a contract about a received asset or vault by calling its universalReceiver function By ignoring the return value, the contract loses the ability to handle any potential errors or messages returned by the universalReceiver function. As well in LSP1Utils.callUniversalReceiverWithCallerInfos:
The function callUniversalReceiverWithCallerInfos calls the universalReceiver function of a specified contract and verifies the result using the Address.verifyCallResult function. 

## Proof of Concept


## Tools Used
Manual analysis
## Recommended Mitigation Steps
It is generally good practice to handle and respond appropriately to return values, especially in cases where the success or failure of a function call can have significant implications for the contract's behavior and security.


## Assessed type

Error
incorrect-equality which can lead to a potential manipulation and subsequently reentrancy.
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol#L136-L176


# Vulnerability details

## Impact
The potential vulnerability in the _whenReceiving() function lies in the strict equality check balance == 0 within the condition if (balance == 0) return "LSP1: balance not updated";. This condition assumes that if the balance is not zero, the keys should not be updated. However, this assumption can be consequential. If the contract implementing the ILSP7DigitalAsset interface does not correctly update the balance when tokens are transferred, the condition balance == 0 may incorrectly evaluate to true. Hence, an attacker could exploit this vulnerability by manipulating the balance update process of the token contract, causing the balance to be incorrect or worse potential reentry.

## Proof of Concept
https://github.com/code-423n4/2023-06-lukso/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol#L170

## Tools Used
Manual analysis
## Recommended Mitigation Steps
To mitigate this vulnerability, it is crucial to ensure that the balance update mechanism in the ILSP7DigitalAsset contract is implemented correctly and consistently reflects the actual balance of the sender.


## Assessed type

Reentrancy
LSP17Extendable._fallbackLSP17Extendable() uses assembly - INLINE ASM
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/contracts/LSP17ContractExtension/LSP17Extendable.sol#L73-L108


# Vulnerability details

## Impact
The potential vulnerability in the _fallbackLSP17Extendable() function lies in the usage of inline assembly. Inline assembly allows direct manipulation of low-level operations in Solidity contracts, bypassing some of the built-in security features. Inline assembly allows for low-level control of contract execution, which can increase the risk of reentrancy attacks. 

## Proof of Concept
https://github.com/code-423n4/2023-06-lukso/contracts/LSP17ContractExtension/LSP17Extendable.sol#L97

## Tools Used
Manual analysis

## Recommended Mitigation Steps
Follow best practices, and consider using higher-level, well-audited libraries or contracts whenever possible


## Assessed type

Reentrancy
Incorrect-equality which can lead to time manipulation attack
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/contracts/LSP14Ownable2Step/LSP14Ownable2Step.sol#L145-L168


# Vulnerability details

## Impact
The use of strict equality in the _renounceOwnership function of the LSP14Ownable2Step contract can introduce a vulnerability known as a "time manipulation attack." Let's understand the potential issue:
The strict equality check _renounceOwnershipStartedAt == 0 is used to determine if the renounceOwnership function is called for the first time. If it is the first time, the function sets the _renounceOwnershipStartedAt variable to the current block number. This condition ensures that the renouncement process can only be initiated once.
By manipulating the block timestamp or block number, an attacker can influence the values used in the strict equality condition. They can set the _renounceOwnershipStartedAt variable to 0 or adjust the current block number to be greater than confirmationPeriodEnd. This manipulation can allow the attacker to bypass the confirmation period and immediately execute the ownership renouncement. 

## Proof of Concept

## Tools Used
Manual analysis

## Recommended Mitigation Steps
Use block timestamp comparisons instead of strict equality checks to allow for some tolerance in the confirmation period.


## Assessed type

Timing
Uninitialize  variables resultTypeIdDelegate and resultDefaultDelegate
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol#L466


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
Not initializing the variables resultTypeIdDelegate and resultDefaultDelegate to default values can potentially lead to unexpected behavior or bugs. When a variable is declared but not initialized, its initial value is the default value of its type. For bytes memory variables, the default value is an empty byte array (bytes memory resultTypeIdDelegate = "";).

In this work, the variables not being initialized, they will have an initial value of bytes memory(0), which represents an empty byte array. Depending on how these variables are used later in the code, this empty byte array may or may not cause issues.

If the uninitialized variables are used in a context where an empty byte array is a valid or expected value, then there may not be any immediate bugs. However, if they are used in a context where a specific value is expected or required, not initializing them could lead to unexpected behavior or errors which can lead to a denial of service.
To ensure code correctness and avoid potential bugs, it's generally recommended to initialize variables with appropriate default values.
## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.

## Tools Used
Manual auditing

## Recommended Mitigation Steps
 If the deployment cost is a concern, you could consider initializing them to a minimum default value that still fulfills the requirements of the code logic.


## Assessed type

Error