# rngComplete function should only be called by rngAuctionRelayer

PoolTogether's rngComplete lacked access control, letting anyone front-run the relayer and redirect auction rewards to an arbitrary recipient.

- Payout: Contest reward
- Severity: high
- Program: PoolTogether
- Credited: Aymen0909
- Disclosed: 2023-09-07
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-08-pooltogether-findings/issues/82
- Library page: https://bugbountylibrary.com/r/c4%3A2023-08-pooltogether%3AH-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** RngRelayAuction rngComplete function (Solidity contract)
**Root cause:** rngComplete has no msg.sender check against rngAuctionRelayer and takes _rewardRecipient as an unvalidated argument, so any caller can complete the sequence and set the reward recipient.
**Steps:**
1. Observe rngComplete is external with no modifier or msg.sender check.
2. Call `rngComplete(_randomNumber, _rngCompletedAt, attackerAddress, _sequenceId, _rngAuctionResult)` before the relayer.
3. Function sets `_auctionResults.recipient = _rewardRecipient` and withdraws reserve rewards to that address.
**How found:** Code review of rngComplete noting absence of access control and that _rewardRecipient is caller-supplied with no validation.
**Exploitation:** Attacker front-runs the legitimate relayer's rngComplete call, passing their own address as _rewardRecipient; the function closes the draw and withdraws reserve rewards to the attacker, leaving the true auction winner unpaid.
**Insight:** In auction/relay designs, the completion callback that distributes rewards is a prime target: check whether the reward recipient is caller-supplied and whether the relayer is the only permitted caller, since front-running the completion captures the payout.
