xanoutas/solidity-security-findings huggingface dataset:
DoS attack possible in mintVault() function
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L278-L291


# Vulnerability details

## Impact
Attacker can push as many mintVault() as he can.
if the governance wants to process the mints after attacker mints, they also need to spend a lot of gas in order to process attacker mints first. So other users can't be able to mint vault because governance needs to process so many mints by attacker first.

## Proof of Concept
- Bob is attacker and want to attack protocol.
- He spends 1 million dollar gas in order to push many mints as he can.
- Governance needs 1 million dollar gas for processing attacker mints.
- If governance doesn't have that much gas, can lead to dos attack.
- So other users cant mint vault. 

## Tools Used
Manual Review

## Recommended Mitigation Steps
Consider implementing logic to avoid this issue like:
every address can mint only one vault. or time limit for each minting.


## Assessed type

DoS
Incorrect validation in `executeTransaction()` could lead to theft of ETH
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/governance/GovernorCharlie.sol#L322-L354


# Vulnerability details


## Impact

Unauthorized extraction of ETH from the contract.

## Proof of Concept

The vulnerability lies within the `executeTransaction` function, since it accepts a `_value` parameter representing the Ethereum value of the transaction. This `_value` is later used in a low-level `call` function to send Ethereum to a `_target` address.

The function, however, does not verify that the provided `_value` matches the `msg.value` sent with the transaction. This means a caller can send a lower amount of Ethereum with the transaction than what they specify in the `_value` parameter, but the contract would still execute the transaction sending the larger `_value` of Ethereum to the `_target` address.
Take a look at [GovernorCharlie.sol#L322-L354](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/governance/GovernorCharlie.sol#L322-L354)

```solidity
  /// @notice Executes a transaction
  /// @param _target Target address for transaction
  /// @param _value Eth value for transaction
  /// @param _signature Function signature for transaction
  /// @param _data Calldata for transaction
  /// @param _eta Timestamp for transaction
  function executeTransaction(
    address _target,
    uint256 _value,
    string memory _signature,
    bytes memory _data,
    uint256 _eta
  ) external payable override {
    if (msg.sender != address(this)) revert GovernorCharlie_NotGovernorCharlie();


    bytes32 _txHash = keccak256(abi.encode(_target, _value, _signature, _data, _eta));
    if (!queuedTransactions[_txHash]) revert GovernorCharlie_ProposalNotQueued();
    if (_getBlockTimestamp() < _eta) revert GovernorCharlie_TimelockNotReached();
    if (_getBlockTimestamp() > _eta + GRACE_PERIOD) revert GovernorCharlie_TransactionStale();


    queuedTransactions[_txHash] = false;


    bytes memory _callData;


    if (bytes(_signature).length == 0) _callData = _data;
    else _callData = abi.encodePacked(bytes4(keccak256(bytes(_signature))), _data);


    // solhint-disable-next-line avoid-low-level-calls
    (bool _success, /*bytes memory returnData*/ ) = _target.call{value: _value}(_callData);
    if (!_success) revert GovernorCharlie_TransactionReverted();


    emit ExecuteTransaction(_txHash, _target, _value, _signature, _data, _eta);
  }
```

With the relevant code in question being:

```solidity
(bool _success, /*bytes memory returnData*/ ) = _target.call{value: _value}(_callData);
if (!_success) revert GovernorCharlie_TransactionReverted();
```

## Tool used

Manual Audit

## Recommended Mitigation Steps

Recommend that a check is introduced to ensure that `msg.value` equals `_value` or less than it. If not, the function should revert the transaction.

A proposed change to the code would be in the lin
permit function allows 0 signature 
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/179384321c36b669f48bc0485bbc1f807fba8fac/core/solidity/contracts/utils/UFragments.sol#L315-L341


# Vulnerability details

## Impact
the permit function in the `Ufragments.sol` allows 0 signature results and its dangerous contract should revert on 0 signature. 
## Proof of Concept 
instances: 
https://github.com/code-423n4/2023-07-amphora/blob/179384321c36b669f48bc0485bbc1f807fba8fac/core/solidity/contracts/utils/UFragments.sol#L315-L341

```solidity 
 function permit(
    address _owner,
    address _spender,
    uint256 _value,
    uint256 _deadline,
    uint8 _v,
    bytes32 _r,
    bytes32 _s
  ) public {
    require(block.timestamp <= _deadline);

    uint256 _ownerNonce = _nonces[_owner];
    bytes32 _permitDataDigest = keccak256(abi.encode(PERMIT_TYPEHASH, _owner, _spender, _value, _ownerNonce, _deadline));
    bytes32 _digest = keccak256(abi.encodePacked('\x19\x01', DOMAIN_SEPARATOR(), _permitDataDigest));

    if (uint256(_s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
      revert UFragments_InvalidSignature();
    }
    require(_owner == ecrecover(_digest, _v, _r, _s));
    if (_owner == address(0x0)) revert UFragments_InvalidSignature();

    _nonces[_owner] = _ownerNonce + 1;

    _allowedFragments[_owner][_spender] = _value;
    emit Approval(_owner, _spender, _value);
  }
}

```
## Tools Used
vs code
## Recommended Mitigation Steps
consider reverting on 0 signature results 


## Assessed type

Invalid Validation
Read-only reentrancy - during liquidation, an attacker can liquidate the vault and borrow USDA without depositing any collateral
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/Vault.sol#L284-L287
https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L684


# Vulnerability details

## Impact
While liquidating a vault, an attacker can use read-only reentrancy to borrow USDA without depositing any collateral

## Proof of Concept

1. Anyone can liquidate an underwater vault, so the liquidator can be the minter of the vault to be liquidated

`attacker = liquidator = minter of vault to be liquidated`

2. The collateral token can be an ERC777 token

3. The attacker attempts to liquidate an underwater vault using [VaultController.sol liquidateVault(...)](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L646)
   
```solidity
    function liquidateVault(
        uint96 _id,
        address _assetAddress,
        uint256 _tokensToLiquidate
    ) external override paysInterest whenNotPaused returns (uint256 _toLiquidate) {
        .
        .
        .
        // decrease the vault's liability
        _vault.modifyLiability(false, (_usdaToRepurchase * 1e18) / interest.factor);

        // decrease the total base liability
        totalBaseLiability -= _safeu192((_usdaToRepurchase * 1e18) / interest.factor);

        // decrease liquidator's USDA balance
        usda.vaultControllerBurn(_msgSender(), _usdaToRepurchase); // liquidators provides usda
        .
        .
        .
        // finally, deliver tokens to liquidator
        _vault.controllerTransfer(_assetAddress, _msgSender(), _tokensToLiquidate - _liquidationFee);
        .
        .
        .
    }
```

4. The `liquidateVault(...)` function
   1. Calculates the amount to liquidate
   2. Decreases the vault's liabilities 
   3. Burns USDA from attacker
   4. Transfers asset from vault to the attacker(liquidator) by calling [Vault.sol controllerTransfer()](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/Vault.sol#L284-L287)
    ```solidity
    function controllerTransfer(address _token, address _to, uint256 _amount) external override onlyVaultController {
        SafeERC20Upgradeable.safeTransfer(IERC20Upgradeable(_token), _to, _amount); // @audit reentrancy
        balances[_token] -= _amount;
    }
    ```
   
5. We can see that in `controllerTransfer()`, the **tokens are transferred before the balance is updated**, which can be a point of **read-only reentrancy** in case of ERC777 tokens
   
6. On receiving the tokens, the attackers calls [VaultController.sol borrowUSDA()](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L476)
   1. This calls [VaultController.sol _borrow(...)](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483
Directly calling BaseRewardPool.getReward locks rewards in Vault
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/Vault.sol#L187-L200


# Vulnerability details

## Impact
A malicious actor can call `IBaseRewardPool.getReward` for any vault address, which will transfer rewards into the vault without a way to get them out.

## Proof of Concept
The function `Vault.claimRewards` contains logic to claim rewards individually:

```js
if (_crvReward != 0) {
  // Claim the CRV reward
  _totalCrvReward += _crvReward;
  //WARDEN: the false-flag prevents extra rewards from being sent to the contract
  _rewardsContract.getReward(address(this), false);
  _totalCvxReward += _calculateCVXReward(_crvReward);
}
...

// Loop and claim all virtual rewards
uint256 _extraRewards = _rewardsContract.extraRewardsLength();
for (uint256 _j; _j < _extraRewards;) {
  IVirtualBalanceRewardPool _virtualReward = _rewardsContract.extraRewards(_j);
  IERC20 _rewardToken = _virtualReward.rewardToken();
  uint256 _earnedReward = _virtualReward.earned(address(this));
  if (_earnedReward != 0) {
    _virtualReward.getReward();
    _rewardToken.transfer(_msgSender(), _earnedReward);
    emit ClaimedReward(address(_rewardToken), _earnedReward);
  }
  unchecked {
    ++_j;
  }
}
```

The issue is that `BaseRewardPool.getReward` is openly accessible and the Vault does not account for that: 

[Link](https://github.com/convex-eth/platform/blob/a5da3f127a321467a97a684c57970d2586520172/contracts/contracts/BaseRewardPool.sol#L263C1-L279C6)

```js
    function getReward(address _account, bool _claimExtras) public updateReward(_account) returns(bool){
        uint256 reward = earned(_account);
        if (reward > 0) {
            rewards[_account] = 0;
            rewardToken.safeTransfer(_account, reward);
            IDeposit(operator).rewardClaimed(pid, _account, reward);
            emit RewardPaid(_account, reward);
        }

        //also get rewards from linked rewards
        if(_claimExtras){
            for(uint i=0; i < extraRewards.length; i++){
                IRewards(extraRewards[i]).getReward(_account);
            }
        }
        return true;
    }
```

So anyone can claim extra rewards for the vault, but the vault only sends them to the minter/owner if the vault has claimed them itself.

## Tools Used

Manual review

## Recommended Mitigation Steps

A possible solution might be to not check for `if (_earnedReward != 0)` but rather send out the balance that the vault has of the extra reward tokens.


## Assessed type

Other
`msg.value ` is not handled properly in `execute` function 
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/governance/GovernorCharlie.sol#L309


# Vulnerability details

## Impact
`msg.value ` is not handled properly in `execute` function  . This can lead to certain scenarios :
1 . Proposals can be executed without the proposer paying anything 
2 . Proposer paying more then amount required but not getting the excess Eth back 
3 . Eth getting stuck in the contract 


## Proof of Concept
The execute function looks like this :
```solidity 
 function execute(uint256 _proposalId) external payable override {//@note why this is payable ??
    if (state(_proposalId) != ProposalState.Queued) revert GovernorCharlie_ProposalNotQueued();
    Proposal storage _proposal = proposals[_proposalId];
    _proposal.executed = true;
    for (uint256 _i = 0; _i < _proposal.targets.length; _i++) {
      this.executeTransaction{value: _proposal.values[_i]}(
        _proposal.targets[_i], _proposal.values[_i], _proposal.signatures[_i], _proposal.calldatas[_i], _proposal.eta
      );
    }
    emit ProposalExecutedIndexed(_proposalId);
    emit ProposalExecuted(_proposalId);
  }
```
But this function doesnot handle the sent ether properly . This may introduce unwanted events .
## Tools Used
manual review 

## Recommended Mitigation Steps 

implement proper logic to track and manage  `msg.value` . 


## Assessed type

Invalid Validation
executeTransaction function is susceptible to signature malleability which allows replay attacks
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/179384321c36b669f48bc0485bbc1f807fba8fac/core/solidity/contracts/governance/GovernorCharlie.sol#L328-L354


# Vulnerability details

## Impact
there is function that is susceptible to signature malleability which allows replay attacks in the contract `GovernorCharlie.sol` especially in `executeTransaction(` which could be very dangerous and lead to unwanted results like replay attacks in executing transactions. 


A signature should never be included into a signed message hash to check if previous messages have been processed by the contract.


## Proof of Concept

See **reference**: https://swcregistry.io/docs/SWC-117

**instances** : https://github.com/code-423n4/2023-07-amphora/blob/179384321c36b669f48bc0485bbc1f807fba8fac/core/solidity/contracts/governance/GovernorCharlie.sol#L328-L354

as you see signature is included in the signed message hash below. 

```solidity
 function executeTransaction(
    address _target,
    uint256 _value,
    string memory _signature,
    bytes memory _data,
    uint256 _eta
  ) external payable override {
    if (msg.sender != address(this)) revert GovernorCharlie_NotGovernorCharlie();

    bytes32 _txHash = keccak256(abi.encode(_target, _value, _signature, _data, _eta));
    if (!queuedTransactions[_txHash]) revert GovernorCharlie_ProposalNotQueued();
    if (_getBlockTimestamp() < _eta) revert GovernorCharlie_TimelockNotReached();
    if (_getBlockTimestamp() > _eta + GRACE_PERIOD) revert GovernorCharlie_TransactionStale();

    queuedTransactions[_txHash] = false;

    bytes memory _callData;

    if (bytes(_signature).length == 0) _callData = _data;
    else _callData = abi.encodePacked(bytes4(keccak256(bytes(_signature))), _data);

    // solhint-disable-next-line avoid-low-level-calls
    (bool _success, /*bytes memory returnData*/ ) = _target.call{value: _value}(_callData);
    if (!_success) revert GovernorCharlie_TransactionReverted();

    emit ExecuteTransaction(_txHash, _target, _value, _signature, _data, _eta);
  }
```

## Tools Used
Manually / VsCode
## Recommended Mitigation Steps
- consider not including the signature in the signed message hash. 


## Assessed type

Governance
Some curve pools have implementations such that Amphora's liquidations always revert.
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/periphery/oracles/EthSafeStableCurveOracle.sol#L36-L44


# Vulnerability details

## Impact
`_updateVirtualPrice` would always revert for some curve pools

## Proof of Concept
In `EthSafeStableCurveOracle.sol`, the `_updateVirtualPrice` function calls `remove_liquidity` with 0 as the amount to lock the curve pool and prevent reentrancy attacks. However, for certain Curve pools like the CRV/ETH pool (0x8301ae4fc9c624d1d396cbdaa1ed877821d7c511, https://curve.fi/#/ethereum/pools/crveth/) calling remove_liquidity(0, [0,0]) always reverts due to an underflow.

## Tools Used
Manual review
## Recommended Mitigation Steps
Use the `claim_admin_fees` function instead of `remove_liquidity`.


## Assessed type

Under/Overflow
The maximum wUSDA supply unchecked.
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/WUSDA.sol#L35
https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/WUSDA.sol#L59-L62
https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/WUSDA.sol#L214-L219


# Vulnerability details

## Impact
In the contract, we have a hardcoded value for the max WUSDA tokens capped at 10M tokens.
This cap is used in the conversion of wrapping and unwrapping of USDA tokens. 
However due to the nature of USDA tokens were by they do not have a fixed total supply, The WUSDA cap would be exceeded and there is no check to prevent this.
## Proof of Concept
When minting WUSDA tokens after deposit, it calculates the amount of total USDA tokens and uses it to divide the product of the amount being deposited  and the cap.
```solidity
  function _usdaToWUSDA(uint256 _usdaAmount, uint256 _totalUsdaSupply) private pure returns (uint256 _wusdaAmount) {
    _wusdaAmount = (_usdaAmount * MAX_wUSDA_SUPPLY) / _totalUsdaSupply;
  }
```
This would be fine except that the totalSUpply of the USDA tokens are never fixed. So if the supply had already minted out all 10 million tokens in the cap, But someone deposits more sUSD into the USDA contract, they can easily mint over the cap of 10_000_000 * 10 **18 used to calculate
This is because in the mint function, there is no check against the cap 
```solidity
  function _deposit(address _from, address _to, uint256 _usdaAmount, uint256 _wusdaAmount) private {
    IERC20(USDA).safeTransferFrom(_from, address(this), _usdaAmount);
    _mint(_to, _wusdaAmount);

    emit Deposit(_from, _to, _usdaAmount, _wusdaAmount);
  }
```
## Tools Used
Manual Review
## Recommended Mitigation Steps
Restrict minting over the cap


## Assessed type

Other
GovernorCharlie.sol#L159 : Blacklisted user can propose proposal and this can be executed due to the mistake in condition check in `propose`
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/governance/GovernorCharlie.sol#L159-L177


# Vulnerability details

## Impact
Malicious proposal which are proposed by the blacklisted user can be executed.
Since the proposal execution is making external call, this would affect the entire protocol. One way could be theft of funds.

## Proof of Concept
```solidity
  function _propose(
    address[] memory _targets,
    uint256[] memory _values,
    string[] memory _signatures,
    bytes[] memory _calldatas,
    string memory _description,
    bool _emergency
  ) internal returns (uint256 _proposalId) {
    // Reject proposals before initiating as Governor
    if (quorumVotes == 0) revert GovernorCharlie_NotActive();
    // Allow addresses above proposal threshold and whitelisted addresses to propose
    if (amph.getPriorVotes(msg.sender, (block.number - 1)) < proposalThreshold && !isWhitelisted(msg.sender)) {---------->>> audit find - check is not correct
      revert GovernorCharlie_VotesBelowThreshold();
    }
    if (
      _targets.length != _values.length || _targets.length != _signatures.length || _targets.length != _calldatas.length
    ) revert GovernorCharlie_ArityMismatch();
    if (_targets.length == 0) revert GovernorCharlie_NoActions();
    if (_targets.length > PROPOSAL_MAX_OPERATIONS) revert GovernorCharlie_TooManyActions();

....
```

The contract `GovernorCharlie` has implementation for executing the proposal which are proposed by the whitelisted user who meet the maximum threshold in the previous block.

when proposing any proposal, there are some check which might be satisfied by the proposal, such has whitelised, meeting the threshold and the proposal is not pending and so.

But there is flaw in the condition check while looking to threshold and blacklisted address.

```solidity
    if (amph.getPriorVotes(msg.sender, (block.number - 1)) < proposalThreshold && !isWhitelisted(msg.sender)) {
      revert GovernorCharlie_VotesBelowThreshold();
    }
```

The above check is incorrect, it is reverting when both conditions met.

There could be another scenario, where the user could be backlisted due to bad actions, but they meet the require threshold.
in above case, the blacklisted user can propose and execute the proposals.

Also, i think the check `amph.getPriorVotes(msg.sender, (block.number - 1)) < proposalThreshold ` is not needed, in certain case, previously proposed proposal may not met the threshold. But the user who want to initiate the proposal can not do so.

## Tools Used

## Recommended Mitigation Steps

Update the check as shown below.

```solidity
    -if (amph.getPriorVotes(msg.sender, (block.number - 1)) < proposalThreshold && !isWhitelisted(msg.sender)) {
     +if (amph.getPriorVotes(msg.sender, (block.number - 1)) < proposalThreshold ||!isWhitelisted(msg.sender)) {
      revert GovernorCharlie_VotesBelowThreshold();
    }
```


## Ass
wusda token can be manipulated
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/WUSDA.sol#L246-L255


# Vulnerability details

## Impact
In mint and burn functions protocol calculate amount with totalUSDASupply/maxWusdaSupply also deposit and withdraw calculate with maxWusdaSupply/totalUSDASupply (maxWusdaSupply is constant). This values can be manipulated with borrow highAmount of Usda because by this way vaultController will mint USDA token and this ratios will be change dramitacally. This vulnarability espacially dangerous because any user can easily make this attack with flashloan (due to this attack can be happen in single transaction.)  
## Proof of Concept
Attacks steps are:
Assume that totalSupply of USDA is x and maxWusdaSupply c.
1)Bob first take flashLoan and deposit to vault.
2) take x/2 Usda with borrow and totalSupply will be 3x/2 so he will have c/3 amount.
3) borrow x/2 amount second time supply is 2x now.
4) burn all wusd which give c/3 *2*x/c =2*x/3.
5) He has 2/3+1/2=7/6*x usda now (initaally x)
6)repay x amount and give colleteral to flashloan and finish transaction with x/6 supply(x was the total supply of Wusd before start exploit)
This attack can be used with loops and all USDA token in Wusda can be taken by this way.
## Tools Used
Manuel review
## Recommended Mitigation Steps


## Assessed type

Invalid Validation