xanoutas/solidity-security-findings huggingface dataset:
Caller will receive excess rewards intended for curators
Audit: 2024-08-phi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/reward/CuratorRewardsDistributor.sol#L120
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/reward/CuratorRewardsDistributor.sol#L77-L130


# Vulnerability details

In [CuratorRewardsDistributor.sol:120](https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/reward/CuratorRewardsDistributor.sol#L120), the excess balance after distributing rewards to curators is transferred back to the caller:
```solidity
_msgSender().safeTransferETH(royaltyfee + distributeAmount - actualDistributeAmount);
```
This is a mistake because the excess balance should be kept in the contract for future distributions, rather than being sent back to the caller.

[CuratorRewardsDistributor#distribute](https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/reward/CuratorRewardsDistributor.sol#L77-L130)
```solidity
function distribute(uint256 credId) external {
    // ...

    uint256 royaltyfee = (totalBalance * withdrawRoyalty) / RATIO_BASE;
    uint256 distributeAmount = totalBalance - royaltyfee;

    // ...

    _msgSender().safeTransferETH(royaltyfee + distributeAmount - actualDistributeAmount);

    // ...
}
```
The issue is that the contract sends back the remaining balance (`royaltyfee + distributeAmount - actualDistributeAmount`) to the caller (`_msgSender()`) instead of keeping it in the contract for future distributions.

## Impact
The curators suffer a loss of the excess rewards that are incorrectly sent to the caller. The caller gains this excess amount without being entitled to it.

## Proof of Concept
**Internal pre-conditions:**

* The `CuratorRewardsDistributor` contract needs to have a balance greater than zero for a specific `credId`.

**Attack Path:**

* The caller calls the `distribute` function with a `credId` that has a balance greater than zero.
* The contract calculates the `royaltyfee` and `distributeAmount` based on the total balance and the `withdrawRoyalty` percentage.
* The contract calculates the rewards for each curator based on their share of the total shares.
* The `actualDistributeAmount` is calculated by summing up the rewards for each curator.
* The contract sends the excess balance (`royaltyfee + distributeAmount - actualDistributeAmount`) back to the caller, instead of keeping it in the contract for future distributions.

## Tools Used
Manual review

## Recommended Mitigation Steps
Remove [the line](https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/reward/CuratorRewardsDistributor.sol#L120) that sends the excess balance back to the caller:
```diff
- _msgSender().safeTransferETH(royaltyfee + distributeAmount - actualDistributeAmount);
```
Instead, the excess balance should be kept in the contract for future distributions. This can be achieved by updating the `balanceOf` mappi
Function returns excess ETH to incorrect address
Audit: 2024-08-phi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/art/PhiNFT1155.sol#L152


# Vulnerability details

## Impact

The `PhiNFT1155` contract has logic that handles excess ETH return and sends it back to `msg.sender`. However, the problem is that the `msg.sender` in this case will be `PhiFactory`, due to the `onlyPhiFactory` modifier. This behavior was not intended, as `PhiFactory` does not have `fallback` or `receive` functions, leading to a revert if the user sends more than the `artFee`.

## Proof of Concept

Vulnerable function:

```solidity
function createArtFromFactory(uint256 artId_) external payable onlyPhiFactory whenNotPaused returns (uint256) {
        _artIdToTokenId[artId_] = tokenIdCounter;
        _tokenIdToArtId[tokenIdCounter] = artId_;

        uint256 artFee = phiFactoryContract.artCreateFee();

        protocolFeeDestination.safeTransferETH(artFee);
        emit ArtCreated(artId_, tokenIdCounter);
        uint256 createdTokenId = tokenIdCounter;

        unchecked {
            tokenIdCounter += 1;
        }
        if ((msg.value - artFee) > 0) {
     @==>  _msgSender().safeTransferETH(msg.value - artFee);
        }

        return createdTokenId;
    }

```

PoC (Insert in PhiFactory.t.sol):

```solidity
    function testSendingMoreThanRequiredBug() public {
        string memory artIdUrl_ = "random-url";
        bytes memory credData = abi.encode(1, owner, "SIGNATURE", 31_337, bytes32(0));
        bytes memory signCreateData = abi.encode(expiresIn, artIdUrl_, credData);
        bytes32 createMsgHash = keccak256(signCreateData);
        bytes32 createDigest = ECDSA.toEthSignedMessageHash(createMsgHash);
        (uint8 cv, bytes32 cr, bytes32 cs) = vm.sign(claimSignerPrivateKey, createDigest);
        if (cv != 27) cs = cs | bytes32(uint256(1) << 255);
        IPhiFactory.CreateConfig memory config =
            IPhiFactory.CreateConfig(artCreator, receiver, END_TIME, START_TIME, MAX_SUPPLY, MINT_FEE, false);
        vm.expectRevert(); // code will revert because PhiFactory would be msg.sender for createArtFromFactory function and PhiFactory can't receive any ETH because this functionality wasn't intended
        phiFactory.createArt{ value: NFT_ART_CREATE_FEE + 1 }(signCreateData, abi.encodePacked(cr, cs), config); // Sending more than needed by 1 to trigger sending excess ETH back code
    }

```

## Tools Used
Foundry.

## Recommended Mitigation Steps
Replace `_msgSender` with `tx.origin`, or add an additional parameter to provide the art creator’s address.


## Assessed type

ETH-Transfer
Malicious user can block a user's sell trades by buying shares on their behalf.
Audit: 2024-08-phi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/Cred.sol#L188
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/Cred.sol#L644


# Vulnerability details

## Impact

The `Cred` contract allows users to buy and sell shares associated with a specific `credId`. Additionally, users can purchase shares on behalf of other accounts, providing a smoother experience for those managing multiple wallets. However, there is a flaw in how the contract updates the timestamp after a trade. 

When a user buys shares, they are unable to sell any of their shares for that `credId` for 10 minutes ([source](https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/Cred.sol#L625)). The issue arises because shares can be purchased on behalf of others. A malicious actor can exploit this by buying a single share on behalf of a target user, preventing that user from selling any of their shares for 10 minutes ([source](https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/Cred.sol#L644)).

In theory, an attacker could write a bot to monitor the mempool and frontrun any `sellShareCred` transaction by sending a `buyShareCredFor` transaction that would be mined first, causing the user’s sell transaction to fail. The maximum limit of this griefing attack, assuming all shares for a given `credId` are available, would be 7 days or 997 transactions. The user would need to send 997 transactions to eventually become the sole owner of all shares for that `credId`, at which point they could sell everything. However, sending 997 transactions is highly impractical, meaning the user would likely be unable to sell any of their shares until all other shares for the `credId` are owned by someone else.


## Proof of Concept

Insert in Cred.t.sol:

```solidity
 function buyCredForAddress(address buyer, address curator) public{
        uint256 credId = 1;
        vm.deal(buyer, 11_000 ether);
        vm.startPrank(buyer);
        uint256 currentSupply = cred.credInfo(credId).currentSupply;
        uint256 buyAmount = 1;
        uint256 price = bondingCurve.getBuyPriceAfterFee(credId, currentSupply, buyAmount);
        cred.buyShareCredFor{ value: price }(credId, buyAmount, curator, 0);
        vm.stopPrank();
    }

    function sellCredForAddress(address seller) public{
        uint256 credId = 1;
        vm.startPrank(seller);
        uint256 currentSupply = cred.credInfo(credId).currentSupply;
        uint256 sellAmount = 1;
        uint256 sellPrice = bondingCurve.getSellPriceAfterFee(credId, currentSupply, sellAmount);
        uint256 balanceBefore = seller.balance;
@===>   vm.expectRevert(); // HERE FUNCTION WILL REVERT EVERY TIME BECAUSE MALICIOUS USER BUYS SHARE FOR THE USER
        cred.sellShareCred(credId, sellAmount, 0);
        uint256 balanceAfter = seller.balance;
        vm.stopPrank();
    }

    function t
Fund get stuck due to improper refunding
Audit: 2024-08-phi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L739-L741
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L283
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L300
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L319
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/abstract/Claimable.sol#L43
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/abstract/Claimable.sol#L64


# Vulnerability details

## Impact
Users are allowed to claim art rewards by 3 ways:
- EOA calls directly to function `PhiFactory#merkeClaim` and `PhiFactory#signatureClaim` ==> refunding works properly because `msg.sender` is the EOA account from user
- Through functions `PhiFactory#batchClaim` and `PhiFactory#claim`. These functions make external calls to itself, specifically the functions `merkeClaim` and `signatureClaim`  ==> The refunding logics work improperly since `msg.sender` in this case is the `PhiFactory` contract itself
- Through functions `Claimable#signatureClaim` and `Claimable#merkleClaim`. These functions call to `PhiFactory#signatureClaim` and `PhiFactory#merkeClaim` to claim ==> In this case, the contract `PhiNFT1155` will receive refund from `PhiFactory`, and get stuck in the contract `PhiNFT1155`

## Proof of Concept
1. POC for when users claim by calling to function `PhiFactory#claim`
Note: The function `PhiFactory#batchClaim` is similar

Modify the test in file `test/PhiFactory.t.sol` as below:
```diff
    ...
    function test_claimMerkle() public {
        ...
        assertEq(
            phiFactory.checkProof(
                proof,
                keccak256(bytes.concat(keccak256(abi.encode(to, value)))),
                0xe70e719557c28ce2f2f3545d64c633728d70fbcfe6ae3db5fa01420573e0f34b //expectedRoot
            ),
            true,
            "merkle proof is correct"
        );

+        deal(participant, 100 ether);
+        uint256 ethBalanceBefore = participant.balance;
+        uint256 excessAmount = 1 ether;
-        phiFactory.claim{ value: totalMintFee }(dataCompressed);
+        phiFactory.claim{ value: totalMintFee + excessAmount }(dataCompressed);
+        uint256 ethBalanceAfter = participant.balance;
+        assertEq(ethBalanceAfter, ethBalanceBefore - totalMintFee, "excess not refunded");
    }
```
Run the test `test_claimMerkle` and the console shows:
```bash
Failing tests:
Encountered 1 failing test in test/PhiFactory.t.sol:TestPhiFactory
[FAIL. Reason: excess not refunded: 98979100000000000000 != 99979100000000000000] test_claimMerkle() (gas: 1781717)
```

2. When users claim by calling `Claimable#signatureClaim()`.
Note: `Claimable#merkleClaim()` is similar to `Claimable#signatureClaim()`.

Modify th
Block other users from selling Cred shares
Audit: 2024-08-phi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/Cred.sol#L625-L629
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/Cred.sol#L186-L189


# Vulnerability details

## Impact
A share holder is allowed to sell his share if lock duration passes since his last trade timestamp. The last trade timestamp is updated when he buys Cred share.
However, there is a function `Cred#buyShareCredFor()` allows an user to buy share for others. This also updates last trade timestamp for the receiver, which will block the receiver from selling Cred shares for a `SHARE_LOCK_PERIOD` duration.

## Proof of Concept
Modify the test file `test/Cred.t.sol` as below:
```diff
    function test_SellAction() public {
        // NORMAL BUY
        _createCred("BASIC", "SIGNATURE", 0x0);
        vm.startPrank(anyone);
        uint256 buyPrice = bondingCurve.getBuyPriceAfterFee(1, 1, 1);
        uint256 maxPrice = bondingCurve.getBuyPriceAfterFee(1, 1, 2);

        cred.buyShareCred{ value: buyPrice }(1, 1, maxPrice);
        assertEq(cred.isShareHolder(1, anyone), true, "cred 1 is voted by anyone");
        vm.warp(block.timestamp + 10 minutes + 1 seconds);

        address victim = anyone;
        // MALICIOUS BUY FOR VICTIM
        address malicious = makeAddr("malicious");
        vm.startPrank(malicious);
        deal(malicious, 100 ether);
        buyPrice = bondingCurve.getBuyPriceAfterFee(1, 2, 1);
        cred.buyShareCredFor{ value: buyPrice }(1, 1, victim, 0); // buy cred for victim
        
        // VICTIM is blocked
        vm.startPrank(victim);
        vm.expectRevert();
        cred.sellShareCred(1, 1, 0);
    }
```

Run the test, and console shows:
```bash
Ran 1 test for test/Cred.t.sol:TestCred
[PASS] test_SellAction() (gas: 815809)
```

## Tools Used
Manual

## Recommended Mitigation Steps
Consider updating last trade timestamp for caller in case Cred buys:

```diff
-lastTradeTimestamp[credId_][curator_] = block.timestamp;
+lastTradeTimestamp[credId_][_msgSender()] = block.timestamp;
```


## Assessed type

DoS
Can not update protocol fee and art create fee properly
Audit: 2024-08-phi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L420-L426
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L428-L434


# Vulnerability details

## Impact
As from [code comments from function `PhiFactory#setProtocolFee` and `PhiFactory#setArtCreatFee`](https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L420-L434), the protocol mint fee and art create fee are in basis points  with value range `[0, 10_000]`.
However, as confirmed from sponsor and from code implementation, these fees are used as absolute amount, i.e [the use of protocol mint fee in `PhiFactory#getArtMintFee()`](https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L509-L512), [the use of art create fee in `PhiNFT1155#createArtFromFactory()`](https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/art/PhiNFT1155.sol#L138-L156). Also from tests, values used for these fees are in absolute amounts https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/test/helpers/Settings.sol#L111-L113

With this property for fees, these 2 functions `PhiFactory#setProtocolFee` and `PhiFactory#setArtCreatFee` can not update fee with values `> 10_000`. 


## Proof of Concept
Add this test to test file `test/PhiFactory.t.sol`:
```solidity
function test_updateFees() public {
      vm.startPrank(owner);

      uint expectedFeeValue = 0.0001 ether;

      vm.expectRevert();
      phiFactory.setProtocolFee(expectedFeeValue);
      

      vm.expectRevert();
      phiFactory.setArtCreatFee(expectedFeeValue);
    }
```

Run the test and the console shows:
```bash
Ran 1 test for test/PhiFactory.t.sol:TestPhiFactory
[PASS] test_updateFees() (gas: 21888)
```


## Tools Used
Manual

## Recommended Mitigation Steps
Update function `PhiFactory#setProtocolFee` and function `PhiFactory#setArtCreatFee`


## Assessed type

Context
Creating art fails because unable to refund excess ether value
Audit: 2024-08-phi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/art/PhiNFT1155.sol#L137-L156
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L640-L643


# Vulnerability details

## Impact
When creating an art, the function `PhiNFT1155#createArtFromFactory()` is called from `PhiFactory` contract with all `msg.value` sent by user. 
The function `PhiNFT1155#createArtFromFactory()` has the logics to [refund excess value back to `_msgSender()`](https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/art/PhiNFT1155.sol#L151-L153). In this execution step, `_msgSender()` is the contract `PhiFactory`, which is a proxy and will revert because it does not have `receive` or `fallback` in logic contract

## Proof of Concept
Update the test file `test/PhiFactory.t.sol` as below:
```diff
...
function test_createTokenId2() public {
        vm.startPrank(participant);
        string memory artId1 = "rL5L2H5BLDwyojZtOi-7TSCqFM7ISlsDOIlAfTUs5et";
        string memory artId2 = "7TSCqFM7ISlsDOIlAf-7TSCqFM7ISlsDOIlAfTUs5ts";
        _createArt(artId1);

+        uint excessValue = 1 ether;
+        NFT_ART_CREATE_FEE += excessValue; // @audit POC of PhiNFT refund fails due to lack of receive() on Factory
+        deal(participant, 1000 ether);
        _createArt(artId2);

        address artAddress = phiFactory.getArtAddress(1);
        address artAddress2 = phiFactory.getArtAddress(2);

        assertEq(artAddress, artAddress2, "artAddress is correct");
    }
...
```
Run the test `test_createTokenId2` and the console shows:
```bash
Failing tests:
Encountered 1 failing test in test/PhiFactory.t.sol:TestPhiFactory
[FAIL. Reason: CreateFailed()] test_createTokenId2() (gas: 1225443)
```

## Tools Used
Manual

## Recommended Mitigation Steps
Add `receive()` to `PhiFactory` contract to receive ether and update the refund logics when creating an art


## Assessed type

DoS
`PhiFactory` does not refund excess `eth` to the user when `createArt`.
Audit: 2024-08-phi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-phi/blob/main/src/PhiFactory.sol#L210


# Vulnerability details

## Impact
`PhiFactory` does not refund excess `eth` to the user, so the user lose funds.

## Proof of Concept
`PhiFactory.sol#createArt()` function is as follows.
```
    function createArt(
        bytes calldata signedData_,
        bytes calldata signature_,
        CreateConfig memory createConfig_
    )
        external
        payable
        nonReentrant
        whenNotPaused
        returns (address)
    {
        _validateArtCreationSignature(signedData_, signature_);
        (, string memory uri_, bytes memory credData) = abi.decode(signedData_, (uint256, string, bytes));
        ERC1155Data memory erc1155Data = _createERC1155Data(artIdCounter, createConfig_, uri_, credData);
210@>   address artAddress = createERC1155Internal(artIdCounter, erc1155Data);
        artIdCounter++;
        return artAddress;
    }
```
And `createERC1155Internal()` function which is called on L210 is as follows.
```
    function createERC1155Internal(uint256 newArtId, ERC1155Data memory createData_) internal returns (address) {
        // Todo check if artid exists, if artid exists, reverts
        _validateArtCreation(createData_);
        PhiArt storage currentArt = arts[newArtId];
        _initializePhiArt(currentArt, createData_);

        (uint256 credId,, string memory verificationType, uint256 credChainId,) =
            abi.decode(createData_.credData, (uint256, address, string, uint256, bytes32));

        address artAddress;
        if (credNFTContracts[credChainId][credId] == address(0)) {
@>          artAddress = _createNewNFTContract(currentArt, newArtId, createData_, credId, credChainId, verificationType);
        } else {
@>          artAddress = _useExistingNFTContract(currentArt, newArtId, createData_, credId, credChainId);
        }

        return artAddress;
    }
```
Here, `_createNewNFTContract(), _useExistingNFTContract()` functions are as follows.
```
    function _createNewNFTContract(
        PhiArt storage art,
        uint256 newArtId,
        ERC1155Data memory createData_,
        uint256 credId,
        uint256 credChainId,
        string memory verificationType
    )
        private
        returns (address)
    {
        address payable newArt =
            payable(erc1155ArtAddress.cloneDeterministic(keccak256(abi.encodePacked(block.chainid, newArtId, credId))));

        art.artAddress = newArt;

        IPhiNFT1155Ownable(newArt).initialize(credChainId, credId, verificationType, protocolFeeDestination);

        credNFTContracts[credChainId][credId] = address(newArt);

        (bool success_, bytes memory response) =
@>          newArt.call{ value: msg.value }(abi.encodeWithSignature("createArtFromFactory(uint256)", newArtId));

        if (!success_) revert CreateFailed();
        uint256 tokenId = abi.decode(response, (uint256));
        emit ArtContractCreated(createData_.artist, address(newArt), credId
PhiNFT1155 proxy can't be upgraded because the PhiFactory contract doesn't have a function to perform the upgrade.
Audit: 2024-08-phi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/art/PhiNFT1155.sol#L352


# Vulnerability details

## Impact

The `PhiNFT1155` contract, according to the protocol's logic flow, should be deployed using the `PhiFactory` (as referenced here: https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L631-L632) so that the `PhiFactory` has full control over it and becomes the owner of this contracе. However, the issue is that the `PhiNFT1155` contract is a proxy contract, designed with the intention of allowing upgrades. But since the `PhiFactory` lacks any wrapper function to perform upgrades, it is currently impossible to upgrade the contract.

## Proof of Concept

1. The `authorizeUpgrade` function for the `PhiNFT1155` contract is overridden so that only the owner has the ability to upgrade it, as seen here: https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/art/PhiNFT1155.sol#L352.  
2. The owner of the `PhiNFT1155` contract is always the `PhiFactory` contract, as indicated here: https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L631-L632.  
3. However, if we examine the `PhiFactory` contract, we find that there is no function available for upgrading the `PhiNFT1155` contract, leading to the inability to upgrade `PhiNFT1155` at all.

## Tools Used
Manual review.

## Recommended Mitigation Steps

Add a wrapper function for upgrading `PhiNFT1155`, similar to how the pause/unpause functions are implemented (as seen here: https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/PhiFactory.sol#L170-L172).


## Assessed type

Access Control