PoolTogether - Jorgect's results

A protocol for no-loss prize savings

General Information

Platform: Code4rena

Start Date: 07/07/2023

Pot Size: $121,650 USDC

Total HM: 36

Participants: 111

Period: 7 days

Judge: Picodes

Total Solo HM: 13

Id: 258

League: ETH

PoolTogether

Findings Distribution

Researcher Performance

Rank: 86/111

Findings: 1

Award: $19.29

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Findings Information

Awards

19.2867 USDC - $19.29

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
duplicate-431

External Links

Lines of code

https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/PrizePool.sol#L299

Vulnerability details

The prizePool contract is using a drawManager to call some importan function in the prizePool like withdrawReserve to withdraw the resever, closeDraw function in which it setting the winningNumber.

The drawManager is set in the contructor but also have a function to change it. This function itΒ΄s not implementing any access control or modifier to prevent that this function will be call it by a malicius user.

Impact

A malicius user can change the drawManager and withdraw the resever or call a closeDraw and set his own winning number

Proof of Concept

We can analyze the function and the comment:

file: Breadcrumbspt-v5-prize-pool/src/PrizePool.sol /// @notice Allows a caller to set the DrawManager if not already set. /// @dev Notice that this can be front-run: make sure to verify the drawManager after construction /// @param _drawManager The draw manager function setDrawManager(address _drawManager) external { //@audit (high) evryone can set the drawmanager? if (drawManager != address(0)) { revert DrawManagerAlreadySet(); } drawManager = _drawManager; emit DrawManagerSet(_drawManager); }

Link

For the comments "@dev Notice that this can be front-run: make sure to verify the drawManager after construction" we can assume that this function should be call it after the constructor in case that the the drawManager was not set. The problem is that this function can be call it without restrictions. permiting a malicius user becoming it self the drawManager and withdraw the resever:

file: Breadcrumbspt-v5-prize-pool/src/PrizePool.sol function withdrawReserve(address _to, uint104 _amount) external onlyDrawManager { if (_amount > _reserve) { revert InsufficientReserve(_amount, _reserve); } _reserve -= _amount; _transfer(_to, _amount); emit WithdrawReserve(_to, _amount); }

Link

Or close the draw and set his own winning number:

function closeDraw(uint256 winningRandomNumber_) external onlyDrawManager returns (uint16) { ... }

Link

Tools Used

manual

The contract can implement a initializer modifier in the setDrawManager function:

uint256 public initializing = 0; modifier initializer(){ if (initializing == 1){ revert; } initializing=1; } function setDrawManager(address _drawManager) external initializer{ ... }

The contract can add onlyDrawManager in the setDrawManager function:

function setDrawManager(address _drawManager) external onlyDrawManager{ ... }

Assessed type

Access Control

#0 - c4-judge

2023-07-14T22:59:19Z

Picodes marked the issue as duplicate of #356

#1 - c4-judge

2023-08-06T10:31:36Z

Picodes changed the severity to 2 (Med Risk)

#2 - c4-judge

2023-08-06T10:32:21Z

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