xanoutas/solidity-security-findings huggingface dataset:
Division before multiplication could incur unnecessary precision loss
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/utils/ThreeLines0_100.sol#L86
https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/AMPHClaimer.sol#L196
https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/AMPHClaimer.sol#L241


# Vulnerability details

## Impact
Division before multiplication could incur unnecessary precision loss causing loss of funds.

## Proof of Concept
In the files of the links provided below, division before multiplication were implemented. For example in line 222 of the AMPHClaimer.sol file, in the _calculate() function, the `_amphForThisTurn` is first calculated this way;
```
_amphForThisTurn = ((_rate * _tempAmountReceived) / 1e12) / 1e6;
```
Notice the division by 1e12 and 1e6.
Then on line 241 of the same `_calculate` function, there was a further multiplication of the `amphForThisTurn` variable this way;
```
_amphToMint += (_amphForThisTurn * 1e12); // 1e18 //@audit div before mul
```
Division before multiplication could incur loss.

Instances: 3
Files: 
- https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/utils/ThreeLines0_100.sol#L86
- https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/AMPHClaimer.sol#L196
- https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/AMPHClaimer.sol#L241

## Tools Used
Manual Review

## Recommended Mitigation Steps
Always implement division last when it involves operations with multiplication and division to avoid loss of precision.


## Assessed type

Math
Add Timelock to Sensitive Functions for User Protection
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/VaultController.sol#L319
https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/VaultController.sol#L416
https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/VaultController.sol#L425
https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/VaultController.sol#L383


# Vulnerability details

## Impact
The owner can change any time he wants these functions involving fees without any Timelock modifier to warn users an important change will happen. Add a timelock modifier for to warn the users before any important change happens, it will leave the contract a little more decentralized and predictable.

## Proof of Concept

https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/VaultController.sol#L383C1-L412

```solidity
  function updateRegisteredErc20(
    address _tokenAddress,
    uint256 _ltv,
    address _oracleAddress,
    uint256 _liquidationIncentive,
    uint256 _cap,
    uint256 _poolId
  ) external override onlyOwner {
    CollateralInfo storage _collateral = tokenAddressCollateralInfo[_tokenAddress];
    if (_collateral.tokenId == 0) revert VaultController_TokenNotRegistered();
    // _ltv must be compatible with liquidation incentive
    if (_ltv >= (EXP_SCALE - _liquidationIncentive)) revert VaultController_LTVIncompatible();
    if (_poolId != 0) {
      (address _lpToken,,, address _crvRewards,,) = BOOSTER.poolInfo(_poolId);
      if (_lpToken != _tokenAddress) revert VaultController_TokenAddressDoesNotMatchLpAddress();
      _collateral.collateralType = CollateralType.CurveLPStakedOnConvex;
      _collateral.crvRewardsContract = IBaseRewardPool(_crvRewards);
      _collateral.poolId = _poolId;
    }
    // set the oracle of the token
    _collateral.oracle = IOracleRelay(_oracleAddress);
    // set the ltv of the token
    _collateral.ltv = _ltv;
    // set the liquidation incentive of the token
    _collateral.liquidationIncentive = _liquidationIncentive;
    // set the cap
    _collateral.cap = _cap;

    emit UpdateRegisteredErc20(_tokenAddress, _ltv, _oracleAddress, _liquidationIncentive, _cap, _poolId);
  }
```

It can change important functions immediately without the user being warned, for example in this function above.


## Tools Used
Manual Review

## Recommended Mitigation Steps
Add a timelock modifier to these functions stated and to others the admin thinks it's necessary


## Assessed type

Rug-Pull
[M-05] - Performs multiplication on results of division.
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/AMPHClaimer.sol#L241 https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/utils/ThreeLines0_100.sol#L86


# Vulnerability details

## Impact

Solidity could truncate the results, performing multiplication before division will prevent rounding/truncation in solidity math.

## Tools Used

Slither & Solodit

## Recommended Mitigation Steps

Consider ordering multiplication first.


## Assessed type

Math
`claimRewards()` may run out of gas and revert due to long list of extra rewards
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
Rewards will not be able to be transferred because attempts to do so might revert

## Proof of Concept
The function `claimRewards(address[] memory _tokenAddresses)` will transfer the rewards for each token address in the params. For each of these tokens, CRV and CVX will be transferred along with all the tokens in the list of extra rewards. 

[Vault.sol claimRewards(...)](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/Vault.sol#L186-L200)

```solidity
    // Loop and claim all virtual rewards
    uint256 _extraRewards = _rewardsContract.extraRewardsLength();
    for (uint256 _j; _j < _extraRewards; ) {
        // @audit may run out of gas and revert due to long list of extra rewards
        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 number of extra rewards doesn't have an upper limit, and there is no guarantee that these tokens will be efficient in their use of gas.

Even if not every extra reward token has a balance `if (_earnedReward != 0)`, an attacker can sprinkle each one with dust, forcing a transfer by this function.

So due to these reasons, the gas usage cannot be estimated and the transaction can be reverted.

## Tools Used
Manual review

## Recommended Mitigation Steps
Include an offset and length for claiming the extra rewards


## Assessed type

Loop
The borrower may be liquidated immediately upon resumption of repayments
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

This protocol has a paused state in which repay and liquidate operations are stopped. When not paused, liquidators can go ahead and liquidate users' positions before they have a chance to pay part of the debt to make their position healthy. 
It is likely that the actual oracle prices will go up or down during this pause period. If oracle prices go down, users will not be able to close their positions. 
Although the protocol allows users to add collateral, they may not have the resources to do so.

## Impact
If a user attempts to pay his debt at the same time that repayment is enabled, he may be liquidated due to frontrunning.

## Proof of Concept
Both functions contain the `whenNotPaused` modifier, so they are only usable when the pause is disabled. When this happens after a pause, a user in a liquidation state who wants to make his position healthy by calling one of the repay functions can be instantly liquidated due to frontrun.
```
  function _repay(uint96 _id, uint192 _amountInUSDA, bool _repayAll) internal paysInterest whenNotPaused {
```
https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L584
```
  function liquidateVault(
    uint96 _id,
    address _assetAddress,
    uint256 _tokensToLiquidate
  ) external override paysInterest whenNotPaused returns (uint256 _toLiquidate) {
```
https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L646-L650

## Tools Used
Manual Review

## Recommended Mitigation Steps
When repay is paused and then resumed, put a timer that prevents liquidations for some amount of time after (i.e. 4 hours) so that users can fairly repay their position after repayment has been resumed.


## Assessed type

Context
Possibility of Precision Error 
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/periphery/oracles/UniswapV3OracleRelay.sol#L85


# Vulnerability details

## Impact
Precision error of _e18Amount return in _toBase18(...) function of L84 of UniswapV3OracleRelay.sol contract is possible when _decimal is greater than 18 due to missing validation check of _amount and _decimals parameters. This could have bad effect on the Oracle efficient Contract execution.

## Proof of Concept
https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/periphery/oracles/UniswapV3OracleRelay.sol#L84-L86
```solidity
84. function _toBase18(uint256 _amount, uint8 _decimals) internal pure returns (uint256 _e18Amount) {
85.  _e18Amount = (_decimals > 18) ? _amount / (10 ** (_decimals - 18)) : _amount * (10 ** (18 - _decimals));
86. }
```
from L85 when _decimals is greater than 18 the next calculation (_amount / (10 ** (_decimals - 18))) needs to check if the digits of "_amount" is efficiently more than the digits from the result of (10 ** (_decimals - 18)) before the division takes place to avoid unnecessary decimal numbers which is not allowed in solidity and could result to error. e.g if _amount is 100 and _decimals is 24 then the calculation would be
(100 / (10 ** (24 - 18))) = (100 / (1000000)) = 0.0001 but this result would be written as zero due to precision error
## Tools Used
Solidity, Manual Review
## Recommended Mitigation Steps
A Validation check to confirm _amount digits is greater than (_decimals - 18) or a safeMath library would solve this e.g 
```solidity
84. function _toBase18(uint256 _amount, uint8 _decimals) internal pure returns (uint256 _e18Amount) {
85.  _e18Amount = (_decimals > 18) ? 
        ( _amount.decimalFunc() > (_decimals - 18)? _amount / (10 ** (_decimals - 18)):revert())  :
         _amount * (10 ** (18 - _decimals));
86. }
```




## Assessed type

Error
some tokens cannot be liquadated  if liquadationFee=0
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L435-L441,https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L686,https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/Vault.sol#L285


# Vulnerability details

## Impact
liquidationFee can be set to 0 and there is no prevention for that.(It can be set to 0 for encourage liquidators in future.). However there is some token to revert when 0 transfer. Because of that liquidators cannot liquidate this tokens due to revert to zero amount transfer for liqFee.
## Proof of Concept

## Tools Used
Manuel review
## Recommended Mitigation Steps
Look for amount>0 when transfer for fee. If fee==0 just skip.


## Assessed type

ERC20
If sUSD Crashes Then The Protocol Will Incur Loses
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

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

## Proof of Concept

It's not uncommon for stablecoins to crash/depeg . We saw USDC crashing recently in march where it lost almost 40% of it's value.

Since the protocol assumes a 1:1 relation between USDA and sUSD , consider the case below. We will discuss 2 cases

1.) sUSD crashes , due to this the price of 1 sUSD is 0.5 dollars.

2.) The attacker sees this as an opportunity , and buys a lot of sUSD at lower price.

3.) The attacker calls deposit on the USDA contract here https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L89  , which calls _deposit at L101 and mints himself
the same amount of USDA.

4.) The sUSD recovers , and the attacker has made a good profit by minting USDA worth a lot more than what he bought them for.

Second case can be when user bought a lot of USDA by depositing sUSD into the contract , say it was worth 1M dollars.
When the user withdraws now , he gets sUSD worth a lot less than before due to the crash

But when he withdraws to get the sUSD back it would be worth a lot less

## Tools Used

Manual analysis

## Recommended Mitigation Steps

A possible solution can be to not only have sUSD as the coin backing it up , in case of depeg we can have a logic to use some other stablecoin.


## Assessed type

Context
Attacker Might Grief A repay transaction
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact

Attacker Might Grief A repay transaction which might lead to a vault get liquidated.

## Proof of Concept

Imagine a scenario where a user's vault (vault can be thought as positions , bad/unhealthy position means vault is insolvent and solvent
otherwise) is insolvent or getting close to solvency. 
For simplicity assume the vault is in a debt of 1000 USDA , let's not consider interests for now.

The user decides to reduce the debt to 10 (repaying 990) , calls repay at https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/VaultController.sol#L568 with _amount that would reduce the baseLiability of the vault
by 990.

The attacker sees the transaction inside the mempool and frontruns with a similar repay transaction , but provides an `_amount`
which would reduce the vault's (victim's vault) baseLiabilty by 11.

Now , the total debt is 989 of the victim's vault.

The victim's tx get executed now , but this transaction would revert due to the line L603. This happens because we are repaying 990
while the debt is 989.

Attacker might grief the victim which could lead to the victim's vault  get liquidated since he is not able to repay the poper amount
to maintain solvency.

## Tools Used

Manual analysis

## Recommended Mitigation Steps

A possible solution can be , only let the owner of a vault repay for the same vault.



## Assessed type

Context
updateRegisteredErc20 Does Not Set The Collateral Type To SINGLE If poolId Is 0
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/VaultController.sol#L383-L411


# Vulnerability details

## Impact

updateRegisteredErc20 Does Not Set The Collateral Type To SINGLE If poolId Is 0 , therefore in an update if the poolId is given as 0 to make the collateralType as SINGLE it would not change.

## Proof of Concept

When the owner registers an ERC20 here https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/VaultController.sol#L331 , if the poolId is provided as 0 that means the 
collateralType is Single  (see L350) and if the poolId is  non zero then the collateralType is assigned as the CurveLPStakedOnConvex
(signifying a collateral staked on convex)

But when the owner tries to update the registered token here https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/VaultController.sol#L383 , firstly we check if the poolId is non -zero and if it is
we assign collateralType as CurveLPStakedOnConvex which is correct , but
inside the else clause (the case where poolId is 0) it does not assign the collateralType to Single which it should.

Therefore , assume a scenario where previosly the collateralType was CurveLPStakedOnConvex but it needs to be changed to Single ,
due to the reasons explained above it won't be updated.

## Tools Used

Manual Analysis

## Recommended Mitigation Steps

Assign `_collateral.collateralType` as Single inside the else clause.



## Assessed type

Context
AMPH token allows owner to mint an arbitrary amount of tokens
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact

The AmphoraProtocolToken contract, as it is currently implemented, allows the owner to mint an arbitrary number of AMPH tokens. The project documentation, however, stipulates a maximum supply of 10 billion AMPH tokens. This discrepancy could lead to inflation of the token supply beyond what users have been led to expect, potentially undermining trust in the project and devaluing the token.

## Proof of Concept

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

This mint function, which is accessible only by the contract owner, allows an arbitrary number of tokens to be minted without any checks on the total supply. This contradicts the project documentation, which assert a maximum supply of 10 billion AMPH tokens.

## Tools Used

Manual Review

## Recommended Mitigation Steps:

Implement a maxSupply variable that is checked within the mint function to ensure the total supply of AMPH tokens never exceeds the stated maximum of 10 billion.


## Assessed type

Other
whitelist voting logic error
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact 
In governor protocol look at the proposal's votes and decide is it defeated or succeed after proposal.endBlock. If nonWhitelisted user's proposal's forVote>AgainstVote and forVotes>Quorum then proposal's state will be succeed. Protocol gives extra credit to whitelisters and just needed to againstVote<quorum for succeed. However if proposal take too many vote and forVote>againstVote>quorum happens, then Whitelisted' proposal will be defetad even though it shouldn't. (Because in forVote>againstVote>quorum situation nonwhitelister proposal will be succeed.  
## Proof of Concept

## Tools Used
Manuel review
## Recommended Mitigation Steps
Instead of this 
 (_whitelisted && _proposal.againstVotes > _proposal.quorumVotes) in line 470 @ GovernorCharlie.sol
add this:
(_whitelisted && _proposal.againstVotes > _proposal.quorumVotes &&_proposal.againstVotes>=_proposal.forVotes)


## Assessed type

Invalid Validation
VaultController.sol : `liquidationFee` can be arbitrarily set to any value during contract creation. 
Audit: 2023-07-amphora-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
`liquidationFee` can be set to any arbitrary value during contract creation. This will affects the liquidators negatively till the function [changeLiquidationFee](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L435C12-L435C32) is called.

user might be thinking that the liquidation fee could be well below the 1e18. But it could be some other value.
since this will lead to loss of funds and the value can be changes by calling the function `changeLiquidationFee` setting the severity as medium.

## Proof of Concept.

Vaultcontroller has the set of input parameters which are used during borrow and repay. One of the variable is `liquidationFee` which is used to in the function `getLiquidationFee` in order to calculate the liquation fee during the liquidation.

when we look at the variable `liquidationFee` inside the function [changeLiquidationFee](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/VaultController.sol#L435C12-L440), its value should not go above the `1e18`

```solidity
  function changeLiquidationFee(uint192 _newLiquidationFee) external override onlyOwner {
    if (_newLiquidationFee >= 1e18) revert VaultController_FeeTooLarge(); ---------------->> audit find
    uint192 _oldLiquidationFee = liquidationFee;
    liquidationFee = _newLiquidationFee;


    emit ChangedLiquidationFee(_oldLiquidationFee, _newLiquidationFee);
```

but when we look at the constructor during contract creation,

```solidity
  constructor(
    IVaultController _oldVaultController,
    address[] memory _tokenAddresses,
    IAMPHClaimer _claimerContract,
    IVaultDeployer _vaultDeployer,
    uint192 _initialBorrowingFee,
    address _booster,
    uint192 _liquidationFee
  ) {
    VAULT_DEPLOYER = _vaultDeployer;
    interest = Interest(uint64(block.timestamp), 1 ether);
    protocolFee = 1e14;
    initialBorrowingFee = _initialBorrowingFee;
    liquidationFee = _liquidationFee; ------------->> audit find .. check is missing.


    claimerContract = _claimerContract;


    BOOSTER = IBooster(_booster);


    if (address(_oldVaultController) != address(0)) _migrateCollateralsFrom(_oldVaultController, _tokenAddresses);
  }
```

## Tools Used

Manual review

## Recommended Mitigation Steps

During contract creation, enforce the check that is set inside the function `changeLiquidationFee`. so that the `liquidationFee` is within the range.


## Assessed type

Rug-Pull