xanoutas/solidity-security-findings huggingface dataset:
A malicous user can drain all ETH from the contract 
Audit: 2022-11-non-fungible-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L209


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
A malicious user can drain all the ETH from the contract. Some ETH might be stuck in the contract due to line L209: 1) it does not check the return value of the underlying low-level ETH transfer call; 2) the caller might be a contract and might forget to include a fallback/receive function to receive ETH. 


## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
Suppose there are 20 ETH in the contract. Alice can create bulk orders and then call function ``bulkExecute()``, since the contract does not account for the ETH balance for each trader, when line ``_returnDust()`` is called, all the remaining ETH In the contract will be returned to Alice. Alice just drained all the ETH from the contract, possibly those left by a previous user Bob due to his failure to setting up fallback/receive function for his trading contract.  
Note that Alice can bypass the check in line 215 by sending a nominal eth to the contract when she calls ``bulkExecute``.


## Tools Used
Remix

## Recommended Mitigation Steps
Keep track of the ETH balance of each trader so that a trader can only return eth ETH from his balance.
Anybody can increase the nonce of a trader
Audit: 2022-11-non-fungible-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L315


# Vulnerability details

## Impact
Detailed description of the impact of this finding.

## 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

## Recommended Mitigation Steps
EVERY TIME ONCE _execute FUNCTION COMPLETED NEED TO SET isOpen  TO 0. OTHERWISE WE CAN CALL EXECUTE FUNCTIONS MULTIMPLE TIMES.
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L234-L283


# Vulnerability details

## Impact
IN THIS WAY WE CAN CALL AND EXECUTE FUNCTIONS MULTIPLE TIMES . EVERY TIME BEFORE CALL EXECUTE NEED TO CALL INITIALIZE FUNCTIONS.

## Proof of Concept
function _execute(Input calldata sell, Input calldata buy)
        public
        payable
        reentrancyGuard
        internalCall
    {
        require(sell.order.side == Side.Sell);

        bytes32 sellHash = _hashOrder(sell.order, nonces[sell.order.trader]);
        bytes32 buyHash = _hashOrder(buy.order, nonces[buy.order.trader]);

        require(_validateSignatures(sell, sellHash), "Sell failed authorization");
        require(_validateSignatures(buy, buyHash), "Buy failed authorization");

        require(_validateOrderParameters(sell.order, sellHash), "Sell has invalid parameters");
        require(_validateOrderParameters(buy.order, buyHash), "Buy has invalid parameters");

        (uint256 price, uint256 tokenId, uint256 amount, AssetType assetType) = _canMatchOrders(sell.order, buy.order);

        /* Mark orders as filled. */
        cancelledOrFilled[sellHash] = true;
        cancelledOrFilled[buyHash] = true;

        _executeFundsTransfer(
            sell.order.trader,
            buy.order.trader,
            sell.order.paymentToken,
            sell.order.fees,
            price
        );
        _executeTokenTransfer(
            sell.order.collection,
            sell.order.trader,
            buy.order.trader,
            tokenId,
            amount,
            assetType
        );

        emit OrdersMatched(
            sell.order.listingTime <= buy.order.listingTime ? sell.order.trader : buy.order.trader,
            sell.order.listingTime > buy.order.listingTime ? sell.order.trader : buy.order.trader,
            sell.order,
            sellHash,
            buy.order,
            buyHash
        );

        // return (price);
    }

## MANUALLY fOUND

## Recommended Mitigation Steps

JUST SET isOpen to 0 once _execute function execution is completed
Exchange owner can consume all orders at arbitrary price
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L543


# Vulnerability details

## Impact
The choice of policy to use for a transaction is determined by the listingTime. The listingTime can be supplied by the caller of execute()/bulkExecute() and can be arbitrary as along as it passes validation. And the policy of a given order is used to determine the transaction price when the order is matched with another order. The owner of the Exchange can change the policyManager, which determines which policies are whitelisted, at any time (or they can change which policies are whitelisted by the manager).

A malicious exchange operator could set a policy manager that allows arbitrary policies, then create a policy that allows payment at low prices, and finally supply a series of orders at low price, with this policy manager, and an early but valid listingTime set. This would allow purchasing offered tokens at low prices for example.

## Proof of Concept
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L543
This is my first code4rena contest and unfortunately I did not have time to develop a poc.

## Tools Used

## Recommended Mitigation Steps
Increase validation of listingTime and add a timelock when changing the policy manager or changing which policies are whitelisted by the policy manager.
Theft of ETH that was not used for the successful execution of orders
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Exchange.sol#L168
https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Exchange.sol#L154
https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Exchange.sol#L179
https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Exchange.sol#L209
https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Exchange.sol#L216
https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Exchange.sol#L219


# Vulnerability details

## Description

There are `execute` and `bulkExecute` functions in `Exchange` smart contract. There is the refund of any ETH that was unused (for example that was left due to the unsuccessful order execution) at the end of its execution flow:

```solidity=
_returnDust();
```

`_returnDust` function is the following:

```solidity=
function `_returnDust`() private {
    uint256 _remainingETH = remainingETH;
    assembly {
        if gt(_remainingETH, 0) {
            let callStatus := call(
                gas(),
                caller(),
                selfbalance(),
                0,
                0,
                0,
                0
            )
        }
    }
}
```

Please, note the call result `callStatus` is not enforced to be true.

Let's remember the [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md) 63/64 rule. The 63/64 rule says that call opcode can consume at most 63/64 gas of parent call, in other words, the child call can consume "all but one 64th" of the gas, and parent calls will have at least 1/64 of gas to continue the execution.

So, `_returnDust` can make a call with gas that is not enough to successfully end the execution of the transfer, but the parent call will still have some gas and can successfully end the execution. As result, the remaining ETH will not be refunded but the execution will succeed.

After that, the attacker can withdraw the remaining ETH by calling `execute` or `bulkExecute` function with any valid input (the attacker will receive the remaining ETH in the same way that the honest user (actually he is the attacker's target) expected to receive it).

### Attack scenario

A honest user calls `bulkExecute` function with a nonzero ETH value.

Some of the orders fail and a situation described in `Description` section of this document happens ("according to EIP-150 rule ETH that should be refunded to the user will remain on the exchange contract but the execution of the overall call will succeed"). That can happen if the attacker (for example using MEV logic) front-runs such a transaction and changes the state in an appropriate way (changes some storage slots/executes some orders by himself/makes some of the orders available/etc.). Also, it is possible if the user is represented by a smart contract and the call of a fallback function fails due to its internal logic.

In the next transaction, the attacker calls the` bu
Counterparty-exchange owner may alter policy manager in execution callback, altering the price of subsequent order matching
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L332


# Vulnerability details

## Impact
In the context of bulkExecute(), with a sqeuence of executions requested, transferring ETH, ERC721 or ERC1155 may result in a hook/callback to a counterparty on receipt of ETH or one of these tokens. If this counterparty is also the exchange owner, or is colluding with the exchange owner (for example able to perform actions as the exchange owner if the owner is a contract), then within an asset transfer callback the counterparty may alter the exchange's policy manager, which is responsible for permitting which policies can determe the price at which orders are matched. If several subsequent transactions had been requested in bulkExecute(), the new policy manager could ensure that all ETH was used in the first of these succeeding executions, for example, and not available for the remaining transactions. The bulkExecute() would still succeed because it allows some executions to fail.

Note that in this scenario the caller to bulkExecute() would need to supply a signed counterparty order containing the malicious policy. However, the caller may not have validated the policies on all orders, instead assuming that the Exchange's policy manager is legitimate and will not change during the transaction.

## Proof of Concept
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L332
This is function I referenced. This is my first code4rena contest and unfortunately I did not have time to write a POC before the deadline.

## Tools Used

## Recommended Mitigation Steps
Use a reentrancy guard for setPolicyManager()
RETURN STATEMENT OF THE transferFrom FUNCTION ALWAYS RETURN TRUE EVEN THE TRANSFER IS FAILED . IF RETURN TRUE FOR ALL TRANSACTIONS IT WILL CAUSE A PROBLEM AND LOSE OF AMOUNT
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

 https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Pool.sol#L58-L68


# Vulnerability details

## Impact
When ever we calling transfer from function it will return true even the transfer failed. So as per function we think the transfer is success. But in real that transfer may or may not be failed. We don't get the exact status of the transfer 

## Proof of Concept

function transferFrom(address from, address to, uint256 amount)
        public
        returns (bool)
    {
        if (msg.sender != EXCHANGE && msg.sender != SWAP) {
            revert('Caller is not authorized to transfer');
        }
        _transfer(from, to, amount);

        return true;
    }

 there is no checks for return statement. if we call  transferFrom function with correct parameter values and  if the msg.sender is not a EXCHANGE and not SWAP condition true it will returns true always .

## Manually Found

## Recommended Mitigation Steps

NEED TO CHECK THE TRANFER STATUS THEN DECIDE THE RETURN VALUE IS TRUE OR FALSE
Counterparty can cancel subsequent orders within ETH or token transfer callback.
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L289; https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L306; https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L315


# Vulnerability details

## Impact
The scenario is when a caller uses bulkExecute() to request a sequence of executions on the Exchange. The caller will generally expect that all orders valid prior to calling bulkExecute() will be valid during the execution of bulkExecute(). However, a counterparty offering orders may receive callbacks when a transfer occurs in the course of completing the order (for example, on receiving ETH, ERC721 or ERC1155) and can use the functions cancelOrder(), cancelOrders(), or incrementNonce() to cancel other of their orders that the original caller may intend to execute. This allows a counterparty to selectively and opportunistically withdraw orders depending on the set of orders requested by the original caller, a capability the caller to bulkExecute() would not ordinarily expect.

## Proof of Concept
The functions I have referenced are:
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L289
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L306
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L315
This is the first code4rena contest I have participated in, and unfortunately I did not have time to develop a proof of concept.

## Tools Used

## Recommended Mitigation Steps
cancelOrder(), cancelOrders(), and incrementNonce() should utilize reentrancyGuard. Potentially add an isAtomic option to bulkExecute() so the caller may ensure all executions either succeed or fail.
deposit and withdraw emit the same event than mint and burn in ERC20 and can affect to Dapps
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Pool.sol#L37
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Pool.sol#L49


# Vulnerability details

## Impact
Deposit and Withdraw emit the same event than burn and mint than ERC20 so it's not possible to distinguish in a DAPP than deposit and withdraw are not mint or burn and could affect to the DAPP logics. For example, cointracking.info could understand in a bad way this events to pay taxes.

## Tools Used
Manual reviewed 

## Recommended Mitigation Steps
Modify de event for deposit and withdraw
_returnDust doesn't check the return value after call
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L216


# Vulnerability details

## Impact
_returnDust doesn't check that the call has been sucesfully. For example, if the buyer is a contract could fail during the reception but due to _returnDust doesn't check the return value to revert the transaction in case of failure the tokens could be missed.

## Tools Used
Manual reviewed

## Recommended Mitigation Steps
Check the return value callStatus
Exchange's _returnDust() does not validate return value of call() to send excess ETH to sender.
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L216


# Vulnerability details

## Impact
When a caller to Exchange's execute() or bulkExecute() includes more ETH than is required to complete the transaction(s), _returnDust is intended to return this excess back to the caller. However, _returnDust() does not validate that the call() it performs to return this ETH succeeds. Returning the ETH may fail silently for example when the caller is a contract not implementing a function to receive ETH, or reaching out of gas, etc. The excess ETH will remain in the Exchange contract and can be taken by any other caller to the Exchange who sends excess ETH, triggers _returnDust() again, and receives the ETH left in the Exchange by the earlier caller who failed to receive it.

The danger is in a caller to Exchange expecting that any excess ETH provided (perhaps an upper bound of ETH expected for an unfamiliar transaction policy) will be returned. When in fact, the excess may not be returned in some cases.

## Proof of Concept
The call I referred to is here:
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L216
This is the first code4rena contest I have participated in, and unfortunately I did not have time to create a demonstration Proof of Concept.

## Tools Used

## Recommended Mitigation Steps
Validate the status returned by the call() in _returnDust()
Unintended code path execution by modifying user controlled input
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Exchange.sol#L543


# Vulnerability details

## Impact
Unintended code path execution by modifying user controlled input. The deal maker gets to pick if buyer or seller matching policy are executed. The actual impact of this vulnerability would depend on the matching policy. Any where from wasted gas to loss of NFTs.

## Proof of Concept
In `Exchange.sol`, the function `_canMatchOrders()` splits into two branches, a "seller is maker" or "buyer is maker" branch. The branch path execution is decided by comparison of `sell.listingTime` with `buy.listingTime`. As the deal maker can set the order's listingTime, they can choice which branch of code gets executed. 

The branch decision is based on the listingTime of the orders. The deal maker can set listingTime for their order (either sell or buy side). By changing listingTime, they can enter branch #1 or branch #2.

``` solidity
        if (sell.listingTime <= buy.listingTime) {
            /* Seller is maker. */   <-branch #1
        ....
        } else {
            /* Buyer is maker. */   <-branch #2

```
ref: https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Exchange.sol#L543

The branch decides if the buyer or seller matching policy are to be executed. The deal maker gets to pick if buyer or seller matching policy are executed by changing listingTime.

## Recommended Mitigation Steps

Instead of comparing listingTimes to determine deal maker, compare buy.order.trade or sell.order.trader to msg.sender to determine the deal maker.
unconventional reentrant structure can result in reentrance into _returnDust
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L168


# Vulnerability details

## Impact
unconventional nonreentrant code structure allows for reentrance from _returnDust()

## Proof of Concept
Once `_execute` finishes execution, the reentrancy guard is reset to be not in effect, and the flow goes into _returnDust(). Now caller()'s receive function can call into `execute`/`bulkExecute` again. 

## Tools Used

## Recommended Mitigation Steps
adopt more conventional code structure with reentrancyGuard:
```
function execute(Input calldata sell, Input calldata buy)
        external
        payable
        reentrancyGuard
    {...}
function bulkExecute(Execution[] calldata executions)
        external
        payable
        reentrancyGuard
    {...}
function _execute(Input calldata sell, Input calldata buy)
        internal
    {...}
```
Pool is not initialized correctly
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Pool.sol#L13


# Vulnerability details

## Impact
Pool has no owner and will be un-upgradeable.

## Proof of Concept

Pool does not provide an initialize interface to initialize the owner, so the owner will never be set.

Pool as a UUPSUpgradeable can not be upgraded without a valid owner.

## Tools Used
n/a

## Recommended Mitigation Steps

Implement the initialize function to set the owner just like [Exchange.sol#L112-L118](https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L112-L118).
Tx should revert when the call in _returnDust failed
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L216-L224


# Vulnerability details

## Impact
User may lose remaining ETH of the transaction

## Proof of Concept

As the returned status of the call in `_returnDust` is ignored, the tx will success even if the call failed, which means the caller does not get his ETH back.

## Tools Used
n/a

## Recommended Mitigation Steps

Revert the whole transaction when the call failed (returns 0).
[H-01] `owner` not set in Pool.sol
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Pool.sol#L15


# Vulnerability details

The pool.sol contract here ([https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Pool.sol](https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Pool.sol)) is an `UUPSUpgradeable` contract. But there is no initialize function where `__Ownable_init` is called , due to which `owner` is `0x0`.

It would be impossible to call `_authorizeUpgrade` or change ownership of the contract.

### POC

Adding the following line on line: 626 of `execution.test.ts` will show that the owner is `0x0`.

```solidity
console.log(await pool.owner());
```

### Recommendations

Add an initialize function and call `__Ownable_init` in the function.
`_returnDust` does not revert ether transfer failure
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L212


# Vulnerability details

## Impact

In function `_returnDust` the return value of call is not checked for success. If a user had sent excess ether or if an order in a bulk order had failed, and if the call fails ether will remain in the contract. Users who execute orders later will be able to receive the ether

## Proof of Concept

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L206

```solidity
    let result := delegatecall(gas(), address(), memPointer, add(size, 0x04), 0, 0) 
```

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L212

```solidity
    function _returnDust() private {
        uint256 _remainingETH = remainingETH;
        assembly {
            if gt(_remainingETH, 0) {
                let callStatus := call(
                    gas(),
                    caller(),
                    selfbalance(),
                    0,
                    0,
                    0,
                    0
                )   
            }
        }
    }
```

## Tools Used

Manual Analysis

## Recommended Mitigation Steps

Add return value checks 

```solidity
require(!callStatus, "transfer failed")
```