code-423n4 / 2022-06-nested-findings

0 stars 1 forks source link

Operator may be removed without checking whether are there fund locked in that operator. #80

Closed code423n4 closed 2 years ago

code423n4 commented 2 years ago

Lines of code

https://github.com/code-423n4/2022-06-nested/blob/b4a153c943d54755711a2f7b80cbbf3a5bb49d76/contracts/NestedFactory.sol#L132-L149

Vulnerability details

Impact

Operator may be removed without checking whether are there fund locked in that operator. Locked fund may not be able to withdraw unless operator is being added back.

Proof of Concept

    /// @inheritdoc INestedFactory
    function removeOperator(bytes32 operator) external override onlyOwner {
        bytes32[] storage operatorsCache = operators;
        uint256 operatorsLength = operatorsCache.length;
        for (uint256 i = 0; i < operatorsLength; i++) {
            if (operatorsCache[i] == operator) {
                operatorsCache[i] = operators[operatorsLength - 1];
                operatorsCache.pop();
                if (operatorCache[operator].implementation != address(0)) {
                    delete operatorCache[operator]; // remove from cache
                }
                rebuildCache();
                emit OperatorRemoved(operator);
                return;
            }
        }
        revert("NF: NON_EXISTENT_OPERATOR");
    }

No checking of locked fund in the operator.

Tools Used

Manual

Recommended Mitigation Steps

obatirou commented 2 years ago

Disputed

Operator are not supposed to be called outside of a delegateCall context. Funds are stored in the NestedReserve. By removing an operator, you remove the ability to interact with it, however funds are not freezed. You can withdraw (function from NestedFactory)