xanoutas/solidity-security-findings huggingface dataset:
Function collision between extension functions and account functions
Audit: 2023-06-lukso-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol#L151


# Vulnerability details

## Impact
Users or owner can't use extensions because of collision between extension functions and account functions
## Proof of Concept
Whenever someone calls account it will check for functions inside it, if there isn't function it goes to fallback to check extensions.
As mentioned in docs: 
[https://docs.lukso.tech/standards/universal-profile/lsp6-key-manager](https://docs.lukso.tech/standards/universal-profile/lsp6-key-manager)
“when the account is called with a function that does not exist natively in its public interface. The fallback function of the linked ERC725Account will handle the call to the extension set for the function selector being called.”
so if someone wants to use an extension if that extension has collision with existing functions, he cannot use.
## Tools Used
manual
## Recommended Mitigation Steps
save all function selectors and add check before adding extension, for checking function collision .


## Assessed type

Other
LSP8CompatibleERC721._checkOnERC721Received return value is incorrect
Audit: 2023-06-lukso-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L297-L339
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L180-L191


# Vulnerability details

## Impact

Can be transferred to EOA through safeTransferFrom

## Proof of Concept
### problematic code
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L297-L339

### call path
safeTransferFrom->_safeTransfer->_checkOnERC721Received
#### safeTransferFrom annotate
    /**
     * @inheritdoc ILSP8CompatibleERC721
     * @dev Compatible with ERC721 safeTransferFrom (without optional data).
     * Using allowNonLSP1Recipient=false so that no EOA and only contracts supporting LSP1 interface may receive the tokenId.
     */
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L180-L191


## Tools Used

manual review

## Recommended Mitigation Steps

should return false




















## Assessed type

Error
LSP8CompatibleERC721InitAbstract._checkOnERC721Received return value is incorrect
Audit: 2023-06-lukso-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol#L337
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol#L193-L204


# Vulnerability details

## Impact

Can be transferred to EOA through safeTransferFrom

## Proof of Concept
### problematic code
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol#L297-L339

### call path
safeTransferFrom->_safeTransfer->_checkOnERC721Received
#### safeTransferFrom annotate
    /**
     * @inheritdoc ILSP8CompatibleERC721
     * @dev Compatible with ERC721 safeTransferFrom (without optional data).
     * Using allowNonLSP1Recipient=false so that no EOA and only contracts supporting LSP1 interface may receive the tokenId.
     */
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol#L193-L204


## Tools Used

manual review

## Recommended Mitigation Steps

should return false











## Assessed type

Error
Incorrect modification authorization amount
Audit: 2023-06-lukso-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol#L76-L103


# Vulnerability details

## Impact

In a specific scenario, the authorized transfer amount from N->M (M>0, N>0) will cause the user to lose M+N money. This solution is to first change the authorized amount to N->0 and then to 0->M. This is not the best solution suggested by the article, and it is more complicated to implement, requiring 2 transactions to complete, and a deep understanding of the operating principle of the blockchain is required. A better solution is to directly change it to N->M as suggested by the author. When modifying, judge whether the current authorized amount is equal to N. If not, roll back the operation


## Proof of Concept

### problematic code
https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol#L76-L103

### recommended solution
https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit



## Tools Used

manual review

## Recommended Mitigation Steps
Add the following function to modify the authorized amount
    /**
     * If current allowance for operator is equal to currentAmount,
     * then overwrite it with amount, otherwise revert.
     */
    function modifiyAuthorizeOperator( 
        address operator, 
        uint256 currentAmount, 
        uint256 amount) public virtual {
        uint256 currentAllowance = authorizedAmountFor(operator, msg.sender);
        if (currentAllowance != currentAmount) {
            revert("amount has been changed");
        }
        _updateOperator(msg.sender, operator, amount);
    }












## Assessed type

Token-Transfer
ERC721 onERC721Received() reentrancy
Audit: 2023-06-lukso-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol?plain=1#L246-L257
https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721.sol?plain=1#L307-L339
https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol?plain=1#L246-L257
https://github.com/code-423n4/2023-06-lukso/blob/main/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CompatibleERC721InitAbstract.sol?plain=1#L307-L339


# Vulnerability details

## Impact
Reentrancy is an attack that can occur when a bug in a contract may allow a malicious contract to reenter the contract unexpectedly during execution of the original function. This can be used to drain funds from a smart contract if used maliciously. Reentrancy is likely the single most impactful vulnerability in terms of total loss of funds by smart contract hacks, and should be considered accordingly. [List of reentrancy attacks](https://github.com/pcaversaccio/reentrancy-attacks)

The most common NFT standards are ERC-721 and ERC-1155. OpenZeppelin has implemented corresponding template contracts that are commonly used by the community. These contracts incorporate functions such as _safeTransfer, _safeMint, _mint, _safeTransferFrom, _mintBatch and _safeBatchTransferFrom that will invoke the receiver contract through the callback functions onERC721Received, onERC1155Received, and onERC1155BatchReceived to ensure that the tokens can be received by the receiver. However, this can potentially create a security loophole. An attacker can perform a reentrancy call inside the onERC721Received, onERC1155Received, or onERC1155BatchReceived callback.


If malicious code is included in onERC721Received() or onERC1155Received in the target contract of the transfer, a reentrancy attack may be conducted.

Using a safe function does not guarantee a safe contract

Confusingly enough, the word “safe” means it is checking if the receiving address is a smart contract, then attempting to call the “onERC721Received” function. The transferFrom and _mint functions don’t do this, so you don’t have to worry about re-entrancy.

This doesn’t mean you shouldn’t use safeTransferFrom or _safeMint methods, it means you should use the check-effects pattern or reentrancy guards to prevent re-entrancy if you use it.


# Resources

https://github.com/kadenzipfel/smart-contract-vulnerabilities/blob/master/vulnerabilities/reentrancy.md#safemint

https://samczsun.com/the-dangers-of-surprising-code/

https://twitter.com/Beosin_com/status/1565180106682671104?lang=en

## Proof of Concept
I noticed that the safeTransferFrom() function used in line 197 calls the _safeTransfer function in line 246, as seen below, has a special callback mechanism embedded, which could be exploited to hijack the control flow. 
```
function _safeTransfer(
stealth of funds
Audit: 2023-06-lukso-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP0ERC725Account/LSP0ERC725Account.sol#L41
https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol#L225
https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol#L283


# Vulnerability details

# [CRITICAL]
## Impact
The `LSP0ERC725Account` contract executes calls to specified targets (provided in the arguments), the contract can receive native coins using the payable functions or directly transfered since the contract implements a `receive` function. However, the way the contract handles the `execute` function allows any user to steal all available native coins inside the contract.

## Proof of Concept
consider the following scenario.
1. The `LSP0ERC725Account` contract has a balance of 100 ETH
2. A malicious user calls the `execute()` function with a `target` to which the address of a receiver contract ownend by the malicious user is assigned and a `value` argument equals `LSP0ERC725Account.balance()` and a msg.value = 0.
3. The `LSP0ERC725Account` proceeds to call the attacker's receiver contract `fallback()` function with value specified in the arguments which in our case msg.value equals the value specified in the args as the `ERC725x` specifies (NOTE the msg.value sent by the attacker is 0 however the one sent by the contract is the one provided in the arguments).
4. Since the `fallback()` function is payable it will transfer all available funds inside the `LSP0ERC725Account` contract to the attacker's receiver contract
## Tools Used
manual analysis
## Recommended Mitigation Steps
it is recommended to use the following code instead on line 244 inside `LSP0ERC725Account`
```
bytes memory result = ERC725XCore._execute(
            operationType,
            target,
            msg.value,
            data
        );
```
and not take it from the arguments as the current `execute()` function does


## Assessed type

call/delegatecall
LSP6KeyManagerCore reentrancy vulnerability
Audit: 2023-06-lukso-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L83
https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L518-L520
https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L527-L544


# Vulnerability details

## Impact

Both LSP6KeyManager and LSP6KeyManagerInit inherit from LSP6KeyManagerCore. Consider our previous 3 contracts as A, B and C. We write a contract D, call the A.execute method, and let it execute D.execute. When executing D.execute, we can also execute B.execute, and the execute methods of A and B are inherited from C.execute. C.execute can be executed 2 times in one transaction

## Proof of Concept

The inheritance relationship is as follows：

https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManager.sol#L13

https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManagerInit.sol#L12

https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManagerInitAbstract.sol#L16


## Tools Used

manual review

## Recommended Mitigation Steps

Set a global anti-reentrancy, set _reentrancyStatus in ERC725YCore._store, you can prevent reentrancy across contracts


## Assessed type

Reentrancy
Reentry restrictions are not properly released
Audit: 2023-06-lukso-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L338
https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L404


# Vulnerability details

## Impact

After LSP6KeyManagerCore._execute or LSP6KeyManagerCore._executeRelayCall is executed, non-isSetData methods that call these two methods without re-entry permission cannot be called normally

## Proof of Concept
https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L338

https://github.com/code-423n4/2023-06-lukso/blob/bd49f57c32a522563fc42feeee23c83c8b373405/contracts/LSP6KeyManager/LSP6KeyManagerCore.sol#L404

## Tools Used

manual review

## Recommended Mitigation Steps
If (!isReentrantCall && !isSetData) is changed to if (isReentrantCall && !isSetData)





## Assessed type

Error
Potential Ownership Issues Due to External Calls in LSP0ERC725AccountCore's execute and executeBatch Functions
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol#L252-L254
https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol#L316-L321


# Vulnerability details

## Impact
In the LSP0ERC725AccountCore contract, the `execute` and `executeBatch` functions use the `LSP20CallVerification` standard. In some cases, you may need to use `verifyCallAfter`. However, because an external call is made between `verifyCall` and `verifyCallAfter`, this can lead to potential issues if the call interacts with a contract that has permissions over the Universal Profile (UP) and follows a logic where it first transfers and then accepts ownership.

The LSP20 standard intends for the `verifyAfterCall` to be performed on the owner of the UP, but if the ownership changes in the interim due to the external call, the verification process may not be accurate. This could cause incorrect permissions to be granted, impacting the security of the contract and potentially enabling unauthorized actions.


## Proof of Concept
Consider a scenario where the `execute` or `executeBatch` function calls an external contract that has permissions over the UP. The external contract, upon receiving the call, first transfers the ownership of the UP to a new owner and then accepts the ownership. In this case, when the `execute` or `executeBatch` function proceeds to `verifyCallAfter`, it verifies the original owner, not considering the change in ownership made by the external contract.

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

## Recommended Mitigation Steps

-Restrict the ability to change ownership in the middle of function execution: Consider implementing a mechanism to prevent ownership transfer during the execution of certain sensitive functions. This could be achieved by introducing a lock state variable that prevents ownership changes when set, and is only unset at the conclusion of such functions.


## Assessed type

Other
A Storage Write Removal Bug in contracts
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP17ContractExtension/LSP17Extendable.sol#L86-L128


# Vulnerability details

## Summary
In _fallbackLSP17Extendable(), Calling functions that conditionally terminate the external EVM call using the assembly statements ``return(...)`` may result in incorrect removals of prior storage writes.

## Impact
In LSP17Extendable.sol, _fallbackLSP17Extendable() is given as below. The contract is affected by the bug called **Storage Write Removal Bug** which was introduced in solidity version 0.8.13 and it has been fixed on Solidity version 0.8.17.

```Solidity
File: contracts/LSP17ContractExtension/LSP17Extendable.sol

86    function _fallbackLSP17Extendable() internal virtual {
        // If there is a function selector
        address extension = _getExtension(msg.sig);

        // if no extension was found, revert
        if (extension == address(0))
            revert NoExtensionFoundForFunctionSelector(msg.sig);

        // solhint-disable no-inline-assembly
        // if the extension was found, call the extension with the msg.data
        // appended with bytes20(address) and bytes32(msg.value)
        assembly {
            calldatacopy(0, 0, calldatasize())

            // The msg.sender address is shifted to the left by 12 bytes to remove the padding
            // Then the address without padding is stored right after the calldata
            mstore(calldatasize(), shl(96, caller()))

            // The msg.value is stored right after the calldata + msg.sender
            mstore(add(calldatasize(), 20), callvalue())

            // Add 52 bytes for the msg.sender and msg.value appended at the end of the calldata
            let success := call(
                gas(),
                extension,
                0,
                0,
                add(calldatasize(), 52),
                0,
                0
            )

            // Copy the returned data
            returndatacopy(0, 0, returndatasize())

            switch success
            // call returns 0 on failed calls
            case 0 {
                revert(0, returndatasize())
            }
            default {
127                return(0, returndatasize())
            }
        }
130    }
```

At L-127, the _fallbackLSP17Extendable() has used the inbuilt inline assembly return(...) in an inline assembly block which is the prerrequiste of this bug. Such an inline assembly call will not return from the current function, but instead result in an early successful (i.e. non-reverting) termination of the entire external EVM call.

**Further bug description:**
A call to a Yul function that conditionally terminates the external EVM call could result in prior storage writes being incorrectly removed by the Yul optimizer. This used to happen in cases in which it would have been valid to remove the store, if the Yul function in question never actually terminated the ex
No validation check for whether the msg.value is not less than the value parameter in the execute function
Audit: 2023-06-lukso-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-06-lukso/blob/9dbc96410b3052fc0fd9d423249d1fa42958cae8/contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol#L228


# Vulnerability details

## Impact
Users can send `msg.value` lesser than the supplied `value` parameter leading to incorrect accounting.

## Proof of Concept
There is no check for whether `msg.value >= value` in the `execute` function of the LSP0ERC725AccountCore contract. 
LSP0ERC725Account is in scope and inherits from LSP0ERC725AccountCore.

```
function execute(
        uint256 operationType,
        address target,
        uint256 value,
        bytes memory data
    ) public payable virtual override returns (bytes memory) {
        if (msg.value != 0) {
            emit ValueReceived(msg.sender, msg.value);
        }
//@audit no validation to check if msg.value >=value.
        address _owner = owner();

        // If the caller is the owner perform execute directly
        if (msg.sender == _owner) {
            return ERC725XCore._execute(operationType, target, value, data);
        }

        // If the caller is not the owner, call {lsp20VerifyCall} on the owner
        // Depending on the magicValue returned, a second call is done after execution
        bool verifyAfter = LSP20CallVerification._verifyCall(_owner);

        // Perform the execution
        bytes memory result = ERC725XCore._execute(
            operationType,
            target,
            value,
            data
        );

...

}
```

Also, the `executeBatch`  of the same LSP0ERC725AccountCore did not validate that the `msg.value` is not less than the `values` parameter. This can be fixed by the way it is validated in the `executeBatch` function of the LSP6KeyManagerCore.sol contract.


## Tools Used
Manual Review 

## Recommended Mitigation Steps
Add validation to check that `msg.value >= value` in the `execute` function.


## Assessed type

ETH-Transfer
In `LSP6SetDataModule.sol`, Infinite loop in `_verifyAllowedERC725YDataKeys()`  
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#L726-L734


# Vulnerability details

## Impact
In `_verifyAllowedERC725YDataKeys() ` there is a great possibility of an Infinite loop. This is because `++ii` is an increment inside `if` condition. This can lead to excessive gas consumption, causing the Ethereum transaction to fail due to the gas limit

## Proof of Concept
In the loop of the `_verifyAllowedERC725YDataKeys()`  method, the position of ++i is wrong, which may lead to a infinite loop
```
File: LSP6SetDataModule.sol
622:    function _verifyAllowedERC725YDataKeys(
----
726:            for (uint256 ii; ii < inputKeysLength; ) {
727:                // if the input data key has been marked as allowed previously,
728:                // SKIP it and move to the next input data key.
729:                if (validatedInputKeysList[ii]) {
730:                    unchecked {
731:                        ++ii; // @audit possibility of an Infinite loop
732:                    }
733:                    continue;
734:                }
```
In the above code, when `!validatedInputKeysList[ii] `, `ii` is not incremented, resulting in a infinite loop.


## Tools Used
Manual Review
## Recommended Mitigation Steps
To avoid this potential infinite loop, move the unchecked box outside the `if` condition.


## Assessed type

DoS