prePO contest - Madalad'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: 45/69

Findings: 1

Award: $52.84

🌟 Selected for report: 0

🚀 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)
satisfactory
duplicate-254

Awards

52.8446 USDC - $52.84

External Links

Lines of code

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

Vulnerability details

Impact

managerWithdraw() relies on a calling ManagerWithdrawHook.hook() to ensure that the baseToken reserve does not fall below the minimum.

If the withdrawHook address is the zero address, the call to hook() is skipped. Since there is no check within setManagerWithdrawHook(), the owner can set withdrawHook to the zero address, and then call managerWithdraw() to withdraw Collateral's entire balance (potentially in the same transaction).

Alternatively, the same outcome can be achieved by calling ManagerWithdrawHook.setMinReservePercentage() and passing 0 as the parameter, immediately before calling managerWithdraw().

According to ICollateral.sol, this should not be possible.

Proof of Concept

it("allows deployer to drain the contract", async () => { expect( await collateral.connect(deployer).managerWithdraw(await collateral.getReserve()) ).to.be.revertedWith('reserve would fall below minimum') // set hook to zero address await collateral.connect(deployer).setWithdrawHook(ZERO_ADDRESS) expect(await collateral.getWithdrawHook()).to.eq(ZERO_ADDRESS) // withdraw entire baseToken balance await collateral.connect(deployer).managerWithdraw(await collateral.getReserve()) expect(await collateral.getReserve()).to.eq(0) })

Tools Used

Hardhat

Can do one or more of the following:

  • Add require(_newManagerWithdrawHook != address(0)) to setManagerWithdrawHook()
  • Add require(_newMinReservePercentage != 0) to setMinReservePercentage()
  • Use a timelocked DAO/multisig for admin functions

#0 - hansfriese

2022-12-14T17:42:54Z

duplicate of #254

#1 - c4-judge

2022-12-17T09:51:54Z

Picodes marked the issue as duplicate of #254

#2 - c4-judge

2023-01-01T17:40:56Z

Picodes marked the issue as satisfactory

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