PoolTogether V5: Part Deux - Arz's results

A protocol for no-loss prize savings.

General Information

Platform: Code4rena

Start Date: 02/08/2023

Pot Size: $42,000 USDC

Total HM: 13

Participants: 45

Period: 5 days

Judge: hickuphh3

Total Solo HM: 5

Id: 271

League: ETH

PoolTogether

Findings Distribution

Researcher Performance

Rank: 27/45

Findings: 1

Award: $89.63

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Awards

89.6296 USDC - $89.63

Labels

bug
3 (High Risk)
satisfactory
duplicate-82

External Links

Lines of code

https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L131

Vulnerability details

For a draw auction to complete, a bot must relay a completed RNG result to the Prize Pool. This is done by calling rngComplete() and the data must originate from the relayer. However the rngComplete() function is missing a check that the msg.sender is the relayer so this allows anyone to call this function and pass in any data.

Impact

The attacker has the ability to input their own data so he can input his own random number that he will benefit from and ensure that he will win. The attacker can also take advantage of the rewards that he will get and he can make them as big as possible to drain the reserves.

Proof of Concept

https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L77-L79

77:   /// @notice The relayer that RNG results must originate from.
78:   /// @dev Note that this may be a Remote Owner if relayed over an ERC-5164 bridge.
79:   address public immutable rngAuctionRelayer;

As you can see here the rngAuctionRelayer is defined and the comments specify that only the relayer should have the privilege to call rngComplete().

However rngComplete() is missing this check:

https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L131-L138


131: function rngComplete(
132:   uint256 _randomNumber,
133:   uint256 _rngCompletedAt,
134:   address _rewardRecipient,
135:   uint32 _sequenceId,
136:   AuctionResult calldata _rngAuctionResult
137: ) external returns (bytes32) {
138:   if (_sequenceHasCompleted(_sequenceId)) revert SequenceAlreadyCompleted();

The attacker can input his own data like the randomNumber,rewardFraction and etc. The only thing that he has to make sure is that he inputs the correct sequence id.

Tools Used

Manual Review

Add a require statement that ensures that RngRelayAuction::rngComplete() is only callable by the auction relayer

Assessed type

Access Control

#0 - c4-pre-sort

2023-08-08T03:18:17Z

raymondfam marked the issue as duplicate of #82

#1 - c4-judge

2023-08-14T02:47:33Z

HickupHH3 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