prePO contest - obront's results

Decentralized Exchange for Pre-IPO Stocks & Pre-IDO Tokens.

General Information

Platform: Code4rena

Start Date: 09/12/2022

Pot Size: $36,500 USDC

Total HM: 9

Participants: 69

Period: 3 days

Judge: Picodes

Total Solo HM: 2

Id: 190

League: ETH

prePO

Findings Distribution

Researcher Performance

Rank: 36/69

Findings: 2

Award: $96.82

QA:
grade-b

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: obront

Also found by: 8olidity, HE1M, Madalad, Trust, cccz, csanuragjain, deliriusz, hansfriese, hihen, joestakey, rvierdiiev, wait, zaskoh

Labels

bug
2 (Med Risk)
downgraded by judge
primary issue
satisfactory
selected for report
sponsor confirmed
M-06

Awards

68.698 USDC - $68.70

External Links

Lines of code

https://github.com/prepo-io/prepo-monorepo/blob/3541bc704ab185a969f300e96e2f744a572a3640/apps/smart-contracts/core/contracts/WithdrawHook.sol#L53-L79

Vulnerability details

Impact

When a manager withdraws funds from Collateral.sol, there is a check in the managerWithdrawHook to confirm that they aren't pushing the contract below the minimum reserve balance.

require(collateral.getReserve() - _amountAfterFee >= getMinReserve(), "reserve would fall below minimum");

However, a similar check doesn't happen in the withdraw() function.

The manager can use this flaw to get around the reserve balance by making a large deposit, taking a manager withdrawal, and then withdrawing their deposit.

Proof of Concept

Imagine a situation where the token has a balance of 100, deposits of 1000, and a reserve percentage of 10%. In this situation, the manager should not be able to make any withdrawal.

But, with the following series of events, they can:

  • Manager calls deposit() with 100 additional tokens
  • Manager calls managerWithdraw() to pull 100 tokens from the contract
  • Manager calls withdraw() to remove the 100 tokens they added

The result is that they are able to drain the balance of the contract all the way to zero, avoiding the intended restrictions.

Tools Used

Manual Review

Include a check on the reserves in the withdraw() function as well as managerWithdraw().

#0 - Picodes

2022-12-13T20:41:49Z

How would you implement your mitigation ? I don't see how it'd work considering that this would also your PoC would also hold using an other address to do the trick

#1 - Picodes

2022-12-17T09:41:55Z

From what I understand, although it's not clear from the documentation or the code, this minReserve requirement is here to keep some funds in the contract to allow for withdrawals but does not provide any additional safety, and it should be clear for users that a compromised manager would immediately lead to a loss of all funds

#2 - Picodes

2022-12-17T09:47:01Z

I'll merge all issues regarding the manager being able to withdraw all funds, regardless of the method, the core issue being that the managerWithdrawHook check is easily bypassable.

#3 - c4-judge

2022-12-17T09:47:21Z

Picodes marked the issue as primary issue

#4 - c4-sponsor

2022-12-19T21:46:23Z

ramenforbreakfast marked the issue as sponsor disputed

#5 - c4-sponsor

2022-12-19T23:06:12Z

ramenforbreakfast marked the issue as sponsor confirmed

#6 - trust1995

2022-12-24T09:57:13Z

If this is where centralization issues are concentrated, I would suggest dropping the severity to Med.

#7 - Picodes

2023-01-01T17:33:31Z

Indeed, Med severity is more appropriate for this centralization issue. So far it was only the deduping phase.

#8 - c4-judge

2023-01-01T17:33:37Z

Picodes changed the severity to 2 (Med Risk)

#9 - c4-judge

2023-01-01T17:33:43Z

Picodes marked the issue as satisfactory

#10 - c4-judge

2023-01-01T17:37:13Z

Picodes marked the issue as selected for report

#11 - c4-judge

2023-01-01T17:37:19Z

Picodes marked the issue as not selected for report

#12 - c4-judge

2023-01-01T17:40:01Z

Picodes marked the issue as selected for report

#13 - Picodes

2023-01-01T17:40:26Z

Flagging as best for this centralization issue, combined with the other finding by the same warden https://github.com/code-423n4/2022-12-prepo-findings/issues/255

Awards

28.124 USDC - $28.12

Labels

bug
downgraded by judge
grade-b
QA (Quality Assurance)
sponsor disputed
Q-25

External Links

Lines of code

https://github.com/prepo-io/prepo-monorepo/blob/3541bc704ab185a969f300e96e2f744a572a3640/apps/smart-contracts/core/contracts/Collateral.sol#L80-L83

Vulnerability details

Impact

The manager role in Collateral.sol must be set manually. It isn't included in the constructor or initialize functions.

It also isn't necessary in order to set the MANAGER_WITHDRAW_ROLE.

In the case where the MANAGER_WITHDRAW_ROLE is set and manager is not, the user is able to call managerWithdraw().

This will send all requested funds to the zero address, where they will be irretrievable.

Proof of Concept

manager isn't set anywhere in the contract except the setManager function.

There is no requirement that this function must have been called in order to call managerWithdraw().

The result is that any call to managerWithdraw() before manager is set will destroy all funds.

Tools Used

Manual Review

Add a check in this function that the manager is set before sending funds:

require(manager != address(0), 'manager must be set to send funds');

#0 - Picodes

2022-12-13T20:38:54Z

This is theoretically possible but is not a high severity finding. It'd require centralization + errors. So downgrading to low as it's more a safety check.

#1 - c4-judge

2022-12-13T20:39:01Z

Picodes changed the severity to QA (Quality Assurance)

#2 - c4-judge

2022-12-19T13:53:24Z

Picodes marked the issue as grade-b

#3 - c4-sponsor

2022-12-22T10:43:02Z

davidprepo marked the issue as sponsor disputed

#4 - ghost

2022-12-22T10:43:12Z

System will never be left in this state

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter