xanoutas/solidity-security-findings huggingface dataset:
Yul `call` return value not checked
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-L227


# Vulnerability details

### Author: rotcivegaf

### Impact

The Yul `call` return value on function `_returnDust` is not checked, which could leads to the `sender` lose funds

### Proof of Concept

The caller of the functions `bulkExecute` and `execute` could be a contract who may not implement the `fallback` or `receive` functions or reject the `call`, when a call to it with value sent in the function `_returnDust`, it will revert, thus it would fail to receive the `dust` ether

Proof: 
 - A contract use `bulkExecute`
 - One of the executions fails
 - The `Exchange` contract send the `dust`(Exchange balance) back to the contract 
 - This one for any reason reject the call
 - The `dust` stay in the `Exchange` contract
 - In the next call of `bulkExecute` or `execute` the balance of the `Exchange` contract(including the old `dust`) will send to the new caller
 - The second sender will get the funds of the first contract

### Tools Used

Review

### Recommended Mitigation Steps

```diff
+    error ReturnDustFail();
+
     function _returnDust() private {
         uint256 _remainingETH = remainingETH;
+        bool success;
         assembly {
             if gt(_remainingETH, 0) {
-                let callStatus := call(
+                success := call(
                     gas(),
                     caller(),
                     selfbalance(),
                     0,
                     0,
                     0,
                     0
                 )
             }
         }
+        if (!success) revert ReturnDustFail();
     }
```
Buyers/Sellers cannot reinput the same order after order is cancelled via `cancelOrder` because nonce is not updated
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#L242-L243
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L298


# Vulnerability details

When buyer/seller wants to cancel their order, they cannot fill in the same order again, which causes slight inconvenience to either party.

## Impact

Creates inconvenience to buyers/sellers

## Proof of Concept

Anytime an order is executed, the order is hashed via [`_hashOrder`](https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L242-L243). _hashOrder takes in a nonce and the Input struct of either the sell/buy order and hashes in. The hash will be changed completely should any parameters change slightly due to the Avalanche effect.

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

Afterwards, the cancelledOrFilled[] mapping is [marked as true.](https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L254-L255)

        cancelledOrFilled[sellHash] = true;
        cancelledOrFilled[buyHash] = true;

Before execution, if a buyer/seller wants to cancel their order, they can call [cancelOrder](https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L289) which will cancel their order by changing cancelledOrFilled to true. 

        bytes32 hash = _hashOrder(order, nonces[order.trader]);


        require(!cancelledOrFilled[hash], "Order already cancelled or filled");


        /* Mark order as cancelled, preventing it from being matched. */
        cancelledOrFilled[hash] = true;

If a buyer/seller wants to use the same order again, they won't be able to do so because the order has already been cancelled and the _validateOrderParameters check will fail.

Example: 
1. Alice wants to sell an NFT for $500 USDC
2. Alice decides to cancel the NFT an arbitrary period of time after listing and before expiration. 
3. Alice calls cancelOrder, cancelledOrFilled[hash] = true
4. Alice wants to sell the same NFT for $500 again, but she cannot because the Order will fail the [_validateOrderParameters check](https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L366-L379)

## Tools Used

VSCode

## Recommended Mitigation Steps

Update the nonce every time an order is cancelled, so traders can still use the same order despite cancelling the order at first because the nonce will always be different.

    function cancelOrder(Order calldata order) public {
        /* Assert sender is authorized to cancel order. */
        require(msg.sender == order.trader);


        bytes32 hash = _hashOrder(order, nonces[ord
A single point of failure is not acceptable for this project
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#L6


# Vulnerability details


## Impact

The `owner` role has a single point of failure and `onlyOwner` can use critical a few functions.

`owner` role in the project:
Owner is not behind a multisig and changes are not behind a timelock.

Even if protocol admins/developers are not malicious there is still a chance for Owner keys to be stolen. In such a case, the attacker can cause serious damage to the project due to important functions. In such a case, users who have invested in project will suffer high financial losses.


```solidity
8 results - 2 files



contracts/Exchange.sol:
   56:     function open() external onlyOwner {

   60:     function close() external onlyOwner {

   66:     function _authorizeUpgrade(address) internal override onlyOwner {}

  324      function setExecutionDelegate(IExecutionDelegate _executionDelegate) onlyOwner

  334:     function setPolicyManager(IPolicyManager _policyManager) onlyOwner

  342      function setOracle(address _oracle) onlyOwner

  352:     function setBlockRange(uint256 _blockRange)

contracts/Pool.sol:
  15:     function _authorizeUpgrade(address) internal override onlyOwner {}

```

This increases the risk of ```A single point of failure```


See this example where a similar finding ;
https://github.com/code-423n4/2021-08-realitycards-findings/issues/73

Similar vulnerability;
Private keys stolen:

Hackers have stolen cryptocurrency worth around €552 million from a blockchain project linked to the popular online game Axie Infinity, in one of the largest cryptocurrency heists on record. Security issue : PrivateKey of the project officer was stolen:
https://www.euronews.com/next/2022/03/30/blockchain-network-ronin-hit-by-552-million-crypto-heist




## Tools Used
Manuel Code Review


## Recommended Mitigation Steps
Add a time lock to  critical functions. Admin-only functions that change critical parameters should emit events and have timelocks. 

Events allow capturing the changed parameters so that off-chain tools/interfaces can register such changes with timelocks that allow users to evaluate them and consider if they would like to engage/exit based on how they perceive the changes as affecting the trustworthiness of the protocol or profitability of the implemented financial services.

Allow only multi-signature wallets to call the function to reduce the likelihood of an attack.

https://twitter.com/danielvf/status/1572963475101556738?s=20&t=V1kvzfJlsx-D2hfnG0OmuQ

Also detail them in documentation and NatSpec comments
Silent fail of `_returnDust()` can lead to user losing refund.
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
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L44


# Vulnerability details

The `execute` function refunds the unused `ETH` back to the `msg.sender` through `_returnDust()`. This internal function uses a low-level call to transfer the ETH.

The issue is that the return value of the call is not checked. As per the Solidity documentation

```
Exceptions to this rule are send and the low-level functions call, delegatecall and staticcall:
they return false as their first return value in case of an exception
```

Two cases here:

- the `msg.sender` is a smart contract that has a `receive()` function performing some logic and can revert in certain conditions.

- There is [not enough gas](https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L217) for the low-level call to succeed, but enough [for the `execute()` call to finish](https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L161) - which is possible due to the 64th gas not being passed to sub-calls [as per EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md)

Both cases would lead to [the call](https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L216) failing silently, and the `msg.sender` would not retrieve the extra `ETH` passed during `execute()`.

On top of that, because `remainingETH` is set to `0` at [the end of the call](https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L44) due to the `setupExecution` modifier, that amount would be lost forever.


## Impact

Medium

## Tools Used

Manual Analysis

## Mitigation

Check the return value of the call, and revert if it is not `true`.

```diff
    function returnDust() private {
        uint256 remainingETH = remainingETH;
        assembly {
            if gt(remainingETH, 0) {
                let callStatus := call(
                    gas(),
                    caller(),
                    selfbalance(),
                    0,
                    0,
                    0,
                    0
                )
            }
        }
+        if (!callStatus) revert();
    }
```
`withdraw` function architecture is incorrect
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#L44-L50


# Vulnerability details




### Impact

`Pool.sol` allows user to predeposit ETH so that it can be used when a seller takes their bid. However, some parts are wrong;

1 - The `withdraw` function is a function that allows the sender to receive the Ether incoming in the contract. The registration of incoming Ethers in the contract is done with the `deposit()` in the `receive()` function.
However, receive is not the only method of sending a contract to Ether,
Ether can come into the contract with `selfdesctruct()`
The problem here is that Ether, which comes in a different way, is stuck in the contract.

2- `withdraw` function emits `Transfer(address(0), msg.sender, amount)` after sending Ether, accordingly it is recorded that there is an Ether transfer from 0 addresses, this is incorrect information, the correct information is `Transfer(address) It should be (this), msg.sender, amount)`
Even-Emits are critical information areas for websites and analytics dapps like Graph, causing them to report incorrectly.

3- Add Re-Entrancy guard to `withdraw` function



[Pool.sol#L44-L50](https://github.com/code-423n4/2022-11-non-fungible/blob/main/contracts/Pool.sol#L44-L50)

```solidity

contracts/Pool.sol:
  43       */
  44:     function withdraw(uint256 amount) public {
  45:         require(_balances[msg.sender] >= amount);
  46:         _balances[msg.sender] -= amount;
  47:         (bool success,) = payable(msg.sender).call{value: amount}("");
  48:         require(success);
  49:         emit Transfer(address(0), msg.sender, amount);
  50:     }

```

### Proof of Concept

As can be seen in the test below, when ETH is sent to a contract with selfdesctruct, no record can be kept.

```js

pragma solidity ^0.8.13;

contract selfdestructContract  {

    fallback() external payable {}

    function checkbalance(address payable check) public  {
        selfdestruct(check);
    }

}


pragma solidity ^0.8.13;

contract Test  {

    mapping(address  => uint ) public balance;

    receive() external payable {
        balance[msg.sender] = msg.value;
    }

    function balanceOf (address check) public view returns(uint256 ) {
        return balance[check];
    }
}
```


### Tools Used
Manuel Review

### Recommended Mitigation Steps

```diff

contracts/Pool.sol:
  43       */
  44:     function withdraw(uint256 amount) public {
  45:         require(_balances[msg.sender] >= amount);
  46:         _balances[msg.sender] -= amount;
  47:         (bool success,) = payable(msg.sender).call{value: amount}("");
  48:         require(success);
emit Transfer(address(0), msg.sender, amount);
+     emit Transfer(address(this), msg.sender, amount);
  50:     }

+           function withdrawOnlyOwner(uint256 amount) public  onlyOwner{
+                (bool success,) = payable(msg.sender).call{value: amount}("");
+                require(success);
+                emit
Trade execution functions should not be callable by anyone
Audit: 2022-11-non-fungible-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
Currently, the `Exchange.execute` ([https://github.com/code-423n4/2022-11-non-fungible/blob/e9451f78069999cfd8fdd126b87241eb94e93078/contracts/Exchange.sol#L154](https://github.com/code-423n4/2022-11-non-fungible/blob/e9451f78069999cfd8fdd126b87241eb94e93078/contracts/Exchange.sol#L154)) and `Exchange.bulkExecute` ([https://github.com/code-423n4/2022-11-non-fungible/blob/e9451f78069999cfd8fdd126b87241eb94e93078/contracts/Exchange.sol#L168](https://github.com/code-423n4/2022-11-non-fungible/blob/e9451f78069999cfd8fdd126b87241eb94e93078/contracts/Exchange.sol#L168)) functions can be called by anyone.  

In the contest details it is stated that "Although the protocol can be called and used by anyone, we maintain the main orderbook for valid orders.".  

You should either maintain an order book for all valid orders and disallow users from calling the above functions directly or add additional safety measures for when users call these functions.  

This is because allowing users to call the functions directly leads to a number of problems that can interfere with the availability of certain functionality and encourages bad behavior in the market participants.  



## Proof of Concept
I will explain the scenarios that I think pose a risk to the protocol and its users.

### Race for execution
1. A Seller A and Buyer B agree on a trade and one of them sends the sell and buy order to the execute function.  
2. Alice sees the transaction in the mempool and finds the conditions of the sell order attractive. She sends her own buy order with the sell order and a higher Gas price.
3. Alice's order will be executed, leaving Buyer B's order unfilled.

This means users are incentivized to steal orders from each other's trades.  
And orders that are sent with a valid counterpart order might not get executed.  

### Deny a user the ability to execute orders
From the above scenario it follows that a determined attacker can deny a user the ability to execute orders.  

The attacker must do the following:  
Whenever he sees a transaction with the user's order in the mempool, he must create his own transaction and execute the order that the user wants to execute with.  

### Deny order cancellation
1. Bob sends an order for execution that fails to execute
2. Market conditions might have changed now and Bob wants to cancel the order by calling `Exchange.cancelOrder` or `Exchange.incrementNonce`
3. Alice sees the transaction in the mempool and sends Bob's initial order with a matching order of her own in a transaction with a higher Gas price
4. Bob's order will be executed

Taking this scenario a step futher it becomes clear that a determined attacker can deny a large range
reentrancy
Audit: 2022-12-tigris-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/Lock.sol#L1


# Vulnerability details

## Impact
If an attacker were able to successfully exploit a reentrancy vulnerability in this contract, they could potentially cause the contract to enter an infinite loop, consuming all available gas and rendering it unusable. This could result in financial losses for users of the contract and damage the reputation of the contract and its developers.

## Proof of Concept
To demonstrate the potential impact of a reentrancy attack, an attacker could create a malicious contract that calls the vulnerable contract's functions in a way that triggers the reentrancy vulnerability. For example, the attacker's contract could call IERC20.transferFrom and then call another function in the vulnerable contract before the transferFrom function has completed, potentially causing the vulnerable contract to enter an infinite loop.

## Tools Used

## Recommended Mitigation Steps
To mitigate the risk of a reentrancy attack, the contract should use the ReentrancyGuard pattern to ensure that external calls are completed before executing any other actions. This can be implemented by setting a flag before making the external call, and then checking the flag before executing any other actions in the contract. This will ensure that the contract is not vulnerable to reentrancy attacks.
integer overflow or underflow
Audit: 2022-12-tigris-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/Lock.sol#L18


# Vulnerability details

## Impact
If an integer overflow or underflow occurs in the contract, it could lead to incorrect calculations and potentially unintended consequences, such as the transfer of incorrect amounts of tokens or the allocation of incorrect amounts of rewards. This could have financial impacts for users of the contract and could potentially undermine the integrity of the platform.
## Proof of Concept
Suppose the contract has a mapping called totalLocked, which tracks the total amount of a specific token that has been locked up by users.
An attacker creates a bond with a lock period of 365 days and locks up 1,000,000 of a specific token.
The attacker then extends the lock period by an additional 365 days, but this time they lock up 2,000,000 of the same token.
The contract updates the totalLocked mapping to reflect the additional locked amount.
However, because the contract is using a uint type to store the totalLocked value, if the value exceeds the maximum uint value (2^256 - 1), it will wrap around to the minimum uint value (0).
As a result, the totalLocked value will be set to 0, even though the attacker has locked up a total of 3,000,000 of the token
## Tools Used
Mythril

## Recommended Mitigation Steps
To mitigate the risks of integer overflow and underflow in the contract, we recommend implementing the following measures:

Use the SafeMath library, which provides functions for performing arithmetic operations that automatically check for overflow and underflow conditions.
Use the uint256 type (available in Solidity 0.9.0 and higher) to store and manipulate values that may exceed the maximum uint value.
Carefully review and test your code to ensure that arithmetic operations are performed correctly and that the contract handles overflow and underflow conditions appropriately.
Not enough margin pulled or burned from user when adding to a position
Audit: 2022-12-tigris-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/Trading.sol#L275-L282


# Vulnerability details

## Impact
When adding to a position, the amount of margin pulled from the user is not as much as it should be, which leaks value from the protocol and lowering the collateralization ratio of `tigAsset`.

## Proof of Concept
In `Trading.addToPosition` the `_handleDeposit` function is called like this:

```js
_handleDeposit(
    _trade.tigAsset,
    _marginAsset,
    _addMargin - _fee,
    _stableVault,
    _permitData,
    _trader
);
```

The third parameter with the value of `_addMargin - _fee` is the amount pulled (or burned in the case of using `tigAsset`) from the user. The `_fee` value is calculated as part of the position size like this: 

```js
uint _fee = _handleOpenFees(_trade.asset, _addMargin*_trade.leverage/1e18, _trader, _trade.tigAsset, false);
```

The `_handleOpenFees` function mints `_tigAsset` to the referrer, to the `msg.sender` (if called by a function meant to be executed by bots) and to the protocol itself. Those minted tokens are supposed to be part of the `_addMargin` value paid by the user. Hence using `_addMargin - _fee` as the third parameter to `_handleDeposit` is going to pull or burn less margin than what was accounted for.

An example for correct usage can be seen in `initiateMarketOrder`:

```js
uint256 _marginAfterFees = _tradeInfo.margin - _handleOpenFees(_tradeInfo.asset, _tradeInfo.margin*_tradeInfo.leverage/1e18, _trader, _tigAsset, false);
uint256 _positionSize = _marginAfterFees * _tradeInfo.leverage / 1e18;
_handleDeposit(_tigAsset, _tradeInfo.marginAsset, _tradeInfo.margin, _tradeInfo.stableVault, _permitData, _trader);
```

Here the third parameter to `_handleDeposit` is not `_marginAfterFees` but `_tradeInfo.margin` which is what the user has input and is supposed to pay.


## Tools Used

Manual Review

## Recommended Mitigation Steps

In `Trading.addToPosition` call the `_handleDeposit` function without subtracting the `_fee` value:

```js
_handleDeposit(
    _trade.tigAsset,
    _marginAsset,
    _addMargin,
    _stableVault,
    _permitData,
    _trader
);
```
Might lose manager forever
Audit: 2022-12-tigris-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/BondNFT.sol#L366


# Vulnerability details

## Impact
If project sets new manager with a typo, might lose manager forever

## Proof of Concept
``` 
    function setManager(
        address _manager
    ) public onlyOwner() {
        manager = _manager;
    }
```
https://twitter.com/realgmhacker/status/1603362870699429889?s=20&t=vm4wY1ITefLhCW8BDa0oig

## Recommended Mitigation Steps
implement pending() function to check and validate manager.