Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comment and implementation mismatch in UserEscrow::transferOut #235

Closed
c4-submissions opened this issue Sep 13, 2023 · 7 comments
Closed
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue duplicate-653 grade-c low quality report This report is of especially low quality QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax unsatisfactory does not satisfy C4 submission criteria; not eligible for awards

Comments

@c4-submissions
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2023-09-centrifuge/blob/512e7a71ebd9ae76384f837204216f26380c9f91/src/UserEscrow.sol#L39

Vulnerability details

Impact

The current implementation of UserEscrow::transferOut makes it impossible for anyone to call such a function if and only if he is not a ward (given the auth modifier):

    function transferOut(address token, address destination, address receiver, uint256 amount) external auth {
        ...

However, there is a @dev comment which says transferOut can only be initiated by the destination address or an authorized admin, but due to the modifier this won't be possible, as the only one who will be able to call this function will be a ward.

Proof of Concept

Pretty visual.

https://github.com/code-423n4/2023-09-centrifuge/blob/512e7a71ebd9ae76384f837204216f26380c9f91/src/UserEscrow.sol#L36C1-L50C6

    function transferOut(address token, address destination, address receiver, uint256 amount) external auth {
        require(destinations[token][destination] >= amount, "UserEscrow/transfer-failed");
        require(
            /// @dev transferOut can only be initiated by the destination address or an authorized admin.
            ///      The check is just an additional protection to secure destination funds in case of compromized auth.
            ///      Since userEscrow is not able to decrease the allowance for the receiver,
            ///      a transfer is only possible in case receiver has received the full allowance from destination address.
            receiver == destination || (ERC20Like(token).allowance(destination, receiver) == type(uint256).max),
            "UserEscrow/receiver-has-no-allowance"
        );
        destinations[token][destination] -= amount;

        SafeTransferLib.safeTransfer(token, receiver, amount);
        emit TransferOut(token, receiver, amount);
    }

Tools Used

Manual analysis

Recommended Mitigation Steps

Remove the auth modifier for this contract and write at the top of the function something like:

-   function transferOut(address token, address destination, address receiver, uint256 amount) external auth {
+   function transferOut(address token, address destination, address receiver, uint256 amount) external {
+       require(wards[msg.sender] == 1 || msg.sender == destination, "UserEscrow/not-authorized");
        require(destinations[token][destination] >= amount, "UserEscrow/transfer-failed");
        require(
            /// @dev transferOut can only be initiated by the destination address or an authorized admin.
            ///      The check is just an additional protection to secure destination funds in case of compromized auth.
            ///      Since userEscrow is not able to decrease the allowance for the receiver,
            ///      a transfer is only possible in case receiver has received the full allowance from destination address.
            receiver == destination || (ERC20Like(token).allowance(destination, receiver) == type(uint256).max),
            "UserEscrow/receiver-has-no-allowance"
        );
        destinations[token][destination] -= amount;

        SafeTransferLib.safeTransfer(token, receiver, amount);
        emit TransferOut(token, receiver, amount);
    }

Assessed type

Access Control

@c4-submissions c4-submissions added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Sep 13, 2023
c4-submissions added a commit that referenced this issue Sep 13, 2023
@c4-pre-sort
Copy link

raymondfam marked the issue as low quality report

@c4-pre-sort c4-pre-sort added the low quality report This report is of especially low quality label Sep 15, 2023
@c4-pre-sort
Copy link

raymondfam marked the issue as primary issue

@c4-pre-sort c4-pre-sort added the primary issue Highest quality submission among a set of duplicates label Sep 15, 2023
@c4-pre-sort c4-pre-sort added duplicate-217 and removed primary issue Highest quality submission among a set of duplicates labels Sep 15, 2023
@c4-pre-sort
Copy link

raymondfam marked the issue as duplicate of #217

@c4-judge
Copy link

gzeon-c4 marked the issue as not a duplicate

@c4-judge
Copy link

gzeon-c4 marked the issue as duplicate of #653

@c4-judge c4-judge added duplicate-653 unsatisfactory does not satisfy C4 submission criteria; not eligible for awards labels Sep 26, 2023
@c4-judge
Copy link

gzeon-c4 marked the issue as unsatisfactory:
Invalid

@c4-judge
Copy link

gzeon-c4 changed the severity to QA (Quality Assurance)

@c4-judge c4-judge added downgraded by judge Judge downgraded the risk level of this issue QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax and removed 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value labels Sep 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue duplicate-653 grade-c low quality report This report is of especially low quality QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax unsatisfactory does not satisfy C4 submission criteria; not eligible for awards
Projects
None yet
Development

No branches or pull requests

4 participants