xanoutas/solidity-security-findings huggingface dataset:
Amphora tokens max supply is not set causing unlimited minting of tokens
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
AmphoraProtocolToken.sol is Amphora Token contract. The AMPH token is the core governance token of the Amphora Protocol. The issue here is about the supply of AMPH token. Per the contract functions,

```Solidity
File: core/solidity/contracts/governance/AmphoraProtocolToken.sol

contract AmphoraProtocolToken is IAmphoraProtocolToken, ERC20VotesComp, Ownable {
  constructor(
    address _account,
    uint256 _initialSupply
  ) ERC20('Amphora Protocol', 'AMPH') ERC20Permit('Amphora Protocol') {
    if (_account == address(0)) revert AmphoraProtocolToken_InvalidAddress();
    if (_initialSupply <= 0) revert AmphoraProtocolToken_InvalidSupply();

    _mint(_account, _initialSupply);
  }

  /// @notice Mint a specified amount of tokens to a specified address
  function mint(address _dst, uint256 _rawAmount) public onlyOwner {
    _mint(_dst, _rawAmount);
  }
```
Here, there is no maximum supply limit is mentioned. However as per the Amphora Protocol documentation,

**"There will be a max of 10B Amphora tokens minted over time."**

Documentation reference: https://amphora-protocol.gitbook.io/amphora-protocol/tokens/the-amph-token

With current implementation, unlimited AMPH tokens can be minted as Amphora tokens are only generated when the protocol earns CRV tokens. 

Therefore, the code does not comply the technical documentation and giving an edge to owner to mint unlimited tokens. The end users will falsely believe the 10B Max supply per documentation however as per code it is not true. Therefore, Max supply limit should be introduced and mint logic should be corrected.

## Proof of Concept
https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/governance/AmphoraProtocolToken.sol#L8-L22

## Tools Used
Manual review

## Recommended Mitigation Steps
Add MaxTokenSupply variable and re-work in token minting logic. Ensure the AMPH token supply should not be more than 10B.


## Assessed type

Other
The first WUSDA minter can take tremendous improper profit
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
The first WUSDA minter can mint almost 10 million WUSDA with a small amount of USDA.
As more users mint USDA, `USDA.totalSupply` increases and the price to mint WUSDA also goes up.
As a result, the first minter can take multiples of his cost in USDA just by minting WUSDA early and burning it.
If the purpose of WUSDA is similar with [wstETH](https://etherscan.io/token/0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0),
the ratio of `USDA / WUSDA` may increase due to accrued interests, but should not change when a user mints USDA.

## Proof of Concept
Add `testMonopolyByAndy` in E2EUSDA as below in https://github.com/code-423n4/2023-07-amphora/blob/5d1cea9410db5448760c834f001af04a72edf3e0/core/solidity/test/e2e/WUSDA.t.sol#L15.
Then run `forge test --mt testMonopolyByAndy`. Note that the test name is `E2EUSDA` but the file name is `WUSDA.t.sol`.
I explain the steps to exploit in comments. Especially, `WUSDA.totaSupply()` is able to exceed `MAX_wUSDA_SUPPLY`.

```solidity
contract E2EUSDA is CommonE2EBase {
  uint256 public susdAmount = 500 ether;
  uint256 public maxwUSDASupply;

  function setUp() public override {
    super.setUp();
    maxwUSDASupply = wusda.MAX_wUSDA_SUPPLY(); // 10Me18
  }
    
  // @audit Add this test
  function testMonopolyByAndy() public {
    // @audit 1. Andy deposits SUSD
    _depositSUSD(andy, andySUSDBalance);
    uint256 _andyUSDABalance = usdaToken.balanceOf(andy);
    console.log('andyUSDABalance', _andyUSDABalance);  // 100e18

    // Check the total usda supply
    uint256 _totalUSDASupply = usdaToken.totalSupply();
    console.log("_totalUSDASupply", _totalUSDASupply); // 101e18 (1e18 is the initial supply)

    // @audit 2. Andy deposits usda to wusda
    vm.startPrank(andy);
    usdaToken.approve(address(wusda), _andyUSDABalance);
    wusda.deposit(_andyUSDABalance);
    uint256 _andyWUSDABalance = wusda.balanceOf(andy); // 9900990099009900990099009 i.e. 9_900_990e18 wusda
    console.log("_andyWUSDABalance", _andyWUSDABalance);
    vm.stopPrank();

    // @audit 3. Bob Deposits SUSD
    _depositSUSD(bob, bobSUSDBalance);
    uint256 _bobUSDABalance = usdaToken.balanceOf(bob);
    console.log("_bobUSDABalance", _bobUSDABalance); // 1000e18

    // @audit 4. Bob deposits usda to wusda. The totalSupply becomes larger than `maxwUSDASupply`.
    vm.startPrank(bob);
    usdaToken.approve(address(wusda), _bobUSDABalance);
    wusda.deposit(_bobUSDABalance);
    uint256 _bobWUSDABalance = wusda.balanceOf(bob);
    console.log("_bobWUSDABalance", _bobWUSDABalance); // 9_082_652.134423251589464123e18
    vm.stopPrank();

    // @audit 5. Andy now withdraw all usda and it will take the most of USDA deposite
`WUSDA.mint` can be done for free.
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/5d1cea9410db5448760c834f001af04a72edf3e0/core/solidity/contracts/core/WUSDA.sol#L59-L62
https://github.com/code-423n4/2023-07-amphora/blob/5d1cea9410db5448760c834f001af04a72edf3e0/core/solidity/contracts/core/WUSDA.sol#L255


# Vulnerability details

## Impact
A user can mint WUSDA without paying usda from the deployment until `usdaTotalSupply >= wusdaMaxSupply`.

## Proof of Concept
Add `testMintWithoutDecreasingUserUSDABalance` as below in https://github.com/code-423n4/2023-07-amphora/blob/5d1cea9410db5448760c834f001af04a72edf3e0/core/solidity/test/unit/WUSDA.t.sol#L68.
Then run `forge test --mt testMintWithoutDecreasingUserUSDABalance`
I explain the steps to exploit in comments.
```solidity
contract UnitWUSDAMint is Base {
    // @audit Add this test
    function testMintWithoutDecreasingUserUSDABalance() public {
        // @audit UFragments.INITIAL_FRAGMENTS_SUPPLY is 1e18
        uint256 INITIAL_FRAGMENTS_SUPPLY = 1e18;
        usdaTotalSupply = INITIAL_FRAGMENTS_SUPPLY;
        vm.mockCall(usdaToken, abi.encodeWithSelector(IERC20.totalSupply.selector), abi.encode(usdaTotalSupply));

        uint256 mintAmount = 9_999_999;
        // @audit minting cost is 0 because (9_999_999 * 1e18) / (10_000_000 * 1e18) = 0
        uint256 _expectedCost = (mintAmount * usdaTotalSupply) / wusdaMaxSupply;
        assertEq(_expectedCost, 0);

        // @audit the caller mints 9_999_999 wusda by paying 0 usda
        vm.expectCall(usdaToken, abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(wusda), 0));
        wusda.mint(mintAmount);
        assertEq(wusda.balanceOf(address(this)), mintAmount);

        // @audit the caller keeps minting without paying any usda.
        //        This is possible until usdaTotalSupply >= wusdaMaxSupply
        vm.expectCall(usdaToken, abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(wusda), 0));
        wusda.mint(mintAmount);
        assertEq(wusda.balanceOf(address(this)), mintAmount * 2);
    }
```

## Tools Used
Manual review

## Recommended Mitigation Steps

Round up when calculating the cost of users and keep rounding down when calculating the cost of the protocol. `Math.ceilDiv` is useful.
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/Math.sol#L107-L115

I suggest a fix as below.
```solidity
  function mint(uint256 _wusdaAmount) external override returns (uint256 _usdaAmount) {
    // @audit change _wUSDAToUSDA to __wUSDAToUSDACeil
    _usdaAmount = _wUSDAToUSDACeil(_wusdaAmount, _usdaSupply());
    _deposit(_msgSender(), _msgSender(), _usdaAmount, _wusdaAmount);
  }
```

```diff
  function _wUSDAToUSDACeil(uint256 _wusdaAmount, uint256 _totalUsdaSupply) private pure returns (uint256 _usdaAmount) {
    - _usdaAmount = (_wusdaAmount * _totalUsdaSupply) / MAX_wUSDA_SUPPLY;
    + _usdaAmount = Math.ceilDiv(_wusdaAmount * _totalUsdaSupply, MAX_wUSDA_SUPPLY);
when `withdrawAndUnwrap` inside Vault operations is called, it cause extra rewards to be stuck
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#L297
https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/Vault.sol#L120


# Vulnerability details

## Impact
`withdrawAndUnwrap` call to reward pool will always withdraw `extraRewards`. However, it doesn't considered in Vault operations and cause the rewards to stuck.

## Proof of Concept

Inside Convex reward pool, when `withdrawAndUnwrap` is called, it will always claim `extraRewards` if exist : 

https://github.com/convex-eth/platform/blob/main/contracts/contracts/BaseRewardPool.sol#L240-L243

```solidity
    function withdrawAndUnwrap(uint256 amount, bool claim) public updateReward(msg.sender) returns(bool){

        //also withdraw from linked rewards
        for(uint i=0; i < extraRewards.length; i++){
            IRewards(extraRewards[i]).withdraw(msg.sender, amount);
        }
        
        _totalSupply = _totalSupply.sub(amount);
        _balances[msg.sender] = _balances[msg.sender].sub(amount);

        //tell operator to withdraw from here directly to user
        IDeposit(operator).withdrawTo(pid,amount,msg.sender);
        emit Withdrawn(msg.sender, amount);

        //get rewards too
        if(claim){
            getReward(msg.sender,true);
        }
        return true;
    }
```

However, inside all operations that incorporate `withdrawAndUnwrap` inside Vault, this extra rewards are not considered :

https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/Vault.sol#L293-L298
https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/Vault.sol#L117-L133

There is no functions that allow Vault to collect this extra rewards and can cause this rewards to be stuck.


## Tools Used

Manual review

## Recommended Mitigation Steps

Consider this extra rewards in the operations, or add functionality to sweep tokens that is outside of Vault `balances` accounting.





## Assessed type

Error
Wrong consideration of block period in GovernorCharlie.sol
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#L35-L103


# Vulnerability details

## Impact
In GovernorCharlie.sol contract, There is wrong calculation in [votingPeriod](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/governance/GovernorCharlie.sol#L90),  [votingDelay](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/governance/GovernorCharlie.sol#L91) and other voting related variables which are calculated in the number of blocks because of incorrect consideration of block formation period. Constructor is used to pass these voting related variables which is given as below,

```Solidity
File: core/solidity/contracts/governance/GovernorCharlie.sol

88  constructor(address _amph) {
89    amph = IAMPH(_amph);
90    votingPeriod = 40_320;
91    votingDelay = 13_140;
92    proposalThreshold = 1_000_000_000_000_000_000_000_000;
93    proposalTimelockDelay = 172_800;
94    proposalCount = 0;
95    quorumVotes = 10_000_000_000_000_000_000_000_000;
96    emergencyQuorumVotes = 40_000_000_000_000_000_000_000_000;
97    emergencyVotingPeriod = 6570;
98    emergencyTimelockDelay = 43_200;
99
100    optimisticQuorumVotes = 2_000_000_000_000_000_000_000_000;
101    optimisticVotingDelay = 25_600;
102    maxWhitelistPeriod = 31_536_000;
103  }
```

Per the sponsor discussion, The contracts will be deployed on Ethereum mainnet Chain only and in a Ethereum mainnet chain, the blocks are made every 12 seconds but [votingPeriod](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/governance/GovernorCharlie.sol#L90),  [votingDelay](https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/governance/GovernorCharlie.sol#L91) and other voting related variables has used 15 seconds while calculating their values.

To be noted here, 13 to 15 seconds was an average block formation time before Ethereum merge i.e before september, 2022.

**BEFORE merge Ethereum block time reference with chart: [Click this link](https://drive.google.com/file/d/149MUn_1C7lgWHASBNZFwMbvqqOtSdBP1/view?usp=drive_link)**

**However, Ethereum block formation happens on every 12 seconds and it is confirmed from below sources,**
[Ethereum official Reference-01](https://ethereum.org/en/developers/docs/blocks/#:~:text=In%20Ethereum%2C%20time%20is%20divided,the%20block%20time%20is%2012s)
[chainstack Reference-02](https://chainstack.com/protocols/ethereum/#Performance)
[ycharts Reference-03](https://ycharts.com/indicators/ethereum_average_block_time)

**AFTER merge Ethereum block time reference with chart: [Click this link](https://drive.google.com/file/d/1rW7DKdZO4nvNPaLIbINxG0s73bdBTQHE/view?usp=drive_link)**

To examine the differenc
Reentrancy issue with the 'withdraw' method of USDC. All tokens could be drained.
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/USDA.sol#L147-L157
https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/USDA.sol#L114


# Vulnerability details


## Impact

High: All USDC tokens could be drained from the protocol.

## Proof of Concept

There is a reentrancy issue with the 'withdraw' methods of USDC.

A user could call either of the external withdraw functions: `withdraw` or `withdrawTo`

which further calls `_withdraw();` which basically burns the user's token and transfers user the `_susdAmount`. The exchange is 1 to 1.


```solidity
function withdraw(uint256 _susdAmount) external override {
    _withdraw(_susdAmount, _msgSender());
}
```


```solidity
  function _withdraw(uint256 _susdAmount, address _target) internal paysInterest whenNotPaused {
    if (reserveAmount == 0) revert USDA_EmptyReserve();
    if (_susdAmount == 0) revert USDA_ZeroAmount();
    if (_susdAmount > this.balanceOf(_msgSender())) revert USDA_InsufficientFunds();
    // Account for the susd withdrawn
    reserveAmount -= _susdAmount;
    sUSD.transfer(_target, _susdAmount);
    _burn(_msgSender(), _susdAmount);

    emit Withdraw(_target, _susdAmount);
  }
```

The issue is that the `_withdraw()` function does not follow the CEI pattern and fails to update the state (burning token in this case) before the token transfer.

```solidity
sUSD.transfer(_target   , _susdAmount);
_burn(_msgSender(), _susdAmount);
```

It is possible to re-enter the function `USDC.withdraw()` from the malicious attack contract's fallback function as soon as it recieves the transfered amount.

This will again hit the attacker contract's fallback function (with the withdrawn token amount) and repeat the flow until USDA tokens from contract are completely drained.

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

## Tools Used

Manual

## Recommended Mitigation Steps

This could be prevented by first burning the user's tokens or using a Mutex / Re-entrancy guard from OpenZeppelin lib.



## Assessed type

Reentrancy
crvRewardsContract `getReward` can be called directly, breaking vaults `claimRewards` functionallity
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#L164-L229


# Vulnerability details

## Impact
crvRewardsContract of convex can be called by anyone on behalf of Vault, this will allow malicious users to call `getReward` and break the Vault `claimRewards` functionality.

## Proof of Concept

Convex rewarded allow anyone to call `getReward` on behalf of any users : 

https://github.com/convex-eth/platform/blob/main/contracts/contracts/BaseRewardPool.sol#L263-L279

This will break Vault `claimRewards` functionality that depends on this ``getReward` : 

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

```solidity
  function claimRewards(address[] memory _tokenAddresses) external override onlyMinter {
    uint256 _totalCrvReward;
    uint256 _totalCvxReward;

    IAMPHClaimer _amphClaimer = CONTROLLER.claimerContract();
    for (uint256 _i; _i < _tokenAddresses.length;) {
      IVaultController.CollateralInfo memory _collateralInfo = CONTROLLER.tokenCollateralInfo(_tokenAddresses[_i]);
      if (_collateralInfo.tokenId == 0) revert Vault_TokenNotRegistered();
      if (_collateralInfo.collateralType != IVaultController.CollateralType.CurveLPStakedOnConvex) {
        revert Vault_TokenNotCurveLP();
      }

      IBaseRewardPool _rewardsContract = _collateralInfo.crvRewardsContract;
      uint256 _crvReward = _rewardsContract.earned(address(this));

      if (_crvReward != 0) {
        // Claim the CRV reward
        _totalCrvReward += _crvReward;
        _rewardsContract.getReward(address(this), false);
        _totalCvxReward += _calculateCVXReward(_crvReward);
      }

   ...
  }
```

This will allow malicious users to call `getReward` on behalf of Vaults, and basically prevent them to mint get the rewards and get the deserved AMPH tokens.

## Tools Used

Manual review.

## Recommended Mitigation Steps

Create another functionality inside Vault that similar to `claimRewards`, but used CVX, CRV balance inside the contract, to perform the AMPH claim and claim the rewards.





## Assessed type

Other
Token minting does not have a upper cap limit since MAX_wUSDA_SUPPLY constant is ignored. 
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#L216


# Vulnerability details

## Impact

Token minting does not have a upper cap limit since MAX_wUSDA_SUPPLY constant is ignored. 

## Proof of Concept

The `WUSDA._deposit()` ignores the uppercap (`MAX_wUSDA_SUPPLY`) value and mints token `_wusdaAmount` amount of tokens.

This is clearly not what the protocol intends to do and could lowers the token market value and thus does not align with the expected functionality it provides.

```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);
}
```

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

## Tools Used

Manual

## Recommended Mitigation Steps

Add:

```solidity
require(_wusdaAmount <= MAX_wUSDA_SUPPLY, "Amount exceeds max supply")
```


## Assessed type

ERC20
Whitelisting status of proposer might changed after the vote is completed affecting the voting result
Audit: 2023-07-amphora-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
Within the GovernorCharlie contract, each proposal can exist in different states, which can be queried using the `state()` function. However, the state of a proposal depends on the whitelisting status of the proposer, and this status could change or expire at any point in time. As a result, unexpected behavior may occur, such as the voting result changing after the voting period has ended.

```solidity
function state(uint256 _proposalId) public view override returns (ProposalState _state) {
  if (proposalCount < _proposalId || _proposalId <= initialProposalId) revert GovernorCharlie_InvalidProposalId();
  Proposal storage _proposal = proposals[_proposalId];
    
  // @audit The whitelisting state of the proposer might change/expire
  bool _whitelisted = isWhitelisted(_proposal.proposer); 
  if (_proposal.canceled) return ProposalState.Canceled;
  else if (block.number <= _proposal.startBlock) return ProposalState.Pending;
  else if (block.number <= _proposal.endBlock) return ProposalState.Active;
  else if (
    (_whitelisted && _proposal.againstVotes > _proposal.quorumVotes)
      || (!_whitelisted && _proposal.forVotes <= _proposal.againstVotes)
      || (!_whitelisted && _proposal.forVotes < _proposal.quorumVotes)
  ) return ProposalState.Defeated;
  else if (_proposal.eta == 0) return ProposalState.Succeeded;
  else if (_proposal.executed) return ProposalState.Executed;
  else if (block.timestamp >= (_proposal.eta + GRACE_PERIOD)) return ProposalState.Expired;
  _state = ProposalState.Queued;
}
```


## Proof of Concept
Consider the scenario:
1. A whitelisted proposer creates a proposal, and the voting result is as follows:
```shell
quorumVotes = 1000
againstVotes = 500
forVotes = 900
```
2. Since the proposal is whitelisted and `againstVotes < quorumVotes`, the proposal is considered succeeded, even though `forVotes` did not reach the quorum votes. At this point, the state of the proposal is `Succeeded`.
3. However, after the voting process is completed, the whitelist status of the proposer expires. Now, the proposal is no longer whitelisted, and because `forVotes < quorumVotes`, the state of the proposal changes to `Defeated`, even though the voting process had already concluded.

In another scenario, where the proposer is whitelisted after the voting process had already concluded, the state of the proposal could also change from `Defeated -> Succeeded`.

## Tools Used

Manual Review

## Recommended Mitigation Steps
Consider recording the whitelist status of the proposer at the moment the proposal is created.



## Assessed type

Other
`executeTransaction()` function could render proposals unusable
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#L309-L354


# Vulnerability details

## Impact
 Proposals could be rendered unusable and stuck.

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

The smart contract contains a proposal mechanism that allows multiple transactions to be bundled together and executed sequentially through the `execute()` function. The proposal can be queued for execution and anyone can execute it by calling `execute()` function which goes through each individual transaction in the proposal and calls `executeTransaction()` on it.
The problem arises when an attacker executes a single transaction using `executeTransaction()`,which is an external function, from the proposal. This causes subsequent `execute()` calls on the proposal to fail and revert because the already executed transaction fails the queued check. Consequently, the entire proposal becomes unusable and gets stuck.

## Tools Used
Manual Analysis
## Recommended Mitigation Steps
Change the visibility of the `executeTransaction()` function from external to internal.


## Assessed type

Governance