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

Manager can steal entire User balance #48

Closed
code423n4 opened this issue Dec 10, 2022 · 3 comments
Closed

Manager can steal entire User balance #48

code423n4 opened this issue Dec 10, 2022 · 3 comments
Labels
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 duplicate-254 satisfactory satisfies C4 submission criteria; eligible for awards

Comments

@code423n4
Copy link
Contributor

Lines of code

https://github.com/prepo-io/prepo-monorepo/blob/feat/2022-12-prepo/apps/smart-contracts/core/contracts/Collateral.sol#L80

Vulnerability details

Impact

It seems MANAGER_WITHDRAW_ROLE can steal entire user balance if SET_MIN_RESERVE_PERCENTAGE_ROLE has set setMinReservePercentage to 0%

Proof of Concept

  1. The SET_MIN_RESERVE_PERCENTAGE_ROLE role sets minReservePercentage to 0%
function setMinReservePercentage(uint256 _newMinReservePercentage)
    external
    override
    onlyRole(SET_MIN_RESERVE_PERCENTAGE_ROLE)
  {
    require(_newMinReservePercentage <= PERCENT_DENOMINATOR, ">100%");
    minReservePercentage = _newMinReservePercentage;
    emit MinReservePercentageChange(_newMinReservePercentage);
  }
  1. MANAGER_WITHDRAW_ROLE role simply calls the managerWithdraw with contract balance as _amount
function managerWithdraw(uint256 _amount) external override onlyRole(MANAGER_WITHDRAW_ROLE) nonReentrant {
    if (address(managerWithdrawHook) != address(0)) managerWithdrawHook.hook(msg.sender, _amount, _amount);
    baseToken.transfer(manager, _amount);
  }
  1. This calls hook which allow to withdraw everything above reserve
function hook(
    address,
    uint256,
    uint256 _amountAfterFee
  ) external view override {
    require(
      collateral.getReserve() - _amountAfterFee >= getMinReserve(),
      "reserve would fall below minimum"
    );
  }
  1. getMinReserve is implemented as below. Since minReservePercentage is 0 so getMinReserve becomes 0
function getMinReserve() public view override returns (uint256) {
    return
      (depositRecord.getGlobalNetDepositAmount() * minReservePercentage) /
      PERCENT_DENOMINATOR;
  }
  1. This means user will be able to withdraw full collateral.getReserve() - _amountAfterFee which is approx entire balance (without fees)
function getReserve() external view override returns (uint256) { return baseToken.balanceOf(address(this)); }

Recommended Mitigation Steps

Do not allow SET_MIN_RESERVE_PERCENTAGE_ROLE to set setMinReservePercentage to 0

@code423n4 code423n4 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 Dec 10, 2022
code423n4 added a commit that referenced this issue Dec 10, 2022
@hansfriese
Copy link

duplicate of #254

@c4-judge
Copy link
Contributor

Picodes marked the issue as duplicate of #254

@c4-judge
Copy link
Contributor

c4-judge commented Jan 1, 2023

Picodes marked the issue as satisfactory

@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Jan 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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 duplicate-254 satisfactory satisfies C4 submission criteria; eligible for awards
Projects
None yet
Development

No branches or pull requests

3 participants