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
Rank: 49/111
Findings: 3
Award: $201.15
π Selected for report: 0
π Solo Findings: 0
π Selected for report: Udsen
Also found by: 0x11singh99, 0xPsuedoPandit, Daniel526, Darwin, Inspecktor, Jorgect, Nyx, Praise, Tripathi, YY, catellatech, namx05, squeaky_cactus, xuwinnie
19.2867 USDC - $19.29
https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/PrizePool.sol#L299-L306 https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/PrizePool.sol#L278 https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/PrizePool.sol#L335
The drawManager parameter can be set in the constructor (https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/PrizePool.sol#L278). However, if drawManager = 0 is passed to the constructor, it can be set later in setDrawManager() (https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/PrizePool.sol#L299- L306). The drawManager parameter in setDrawManager() is only updated once.
If you don't set drawManager in the constructor, an attacker can get ahead and set any address in setDrawManager(). The administrator will not be able to change it in the future.
The drawManager parameter is used in modifier onlyDrawManager() { if (msg.sender != drawManager) { revert CallerNotDrawManager(msg.sender, drawManager); } _; } at the time of checking access to the withdrawReserve() and closeDraw() functions.
Suppose someone managed to deposit funds into the prize pool via increaseReserve(). This could result in the funds in withdrawReserve() being stolen by an attacker (https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/PrizePool.sol#L335).
Manual review
Only set the value of drawManager in the constructor. Or set the onlyOwner check for setDrawManager().
Access Control
#0 - c4-judge
2023-07-14T22:58:43Z
Picodes marked the issue as primary issue
#1 - asselstine
2023-07-20T22:14:31Z
This is easily checked after deployment; it's a classic chicken-or-the-egg problem where both contracts need to reference eachother.
#2 - c4-sponsor
2023-07-20T22:14:52Z
asselstine marked the issue as disagree with severity
#3 - c4-judge
2023-08-06T10:31:38Z
Picodes changed the severity to 2 (Med Risk)
#4 - c4-judge
2023-08-06T10:32:02Z
Picodes marked the issue as satisfactory
#5 - c4-judge
2023-08-06T10:33:00Z
Picodes marked issue #431 as primary and marked this issue as a duplicate of 431
π Selected for report: gzeon
Also found by: 0xMirce, Breeje, Inspecktor, ptsanev
165.9409 USDC - $165.94
The deployVault function deploys a clone contract using create, where getting the address depends only on the VaultFactory nonce.
Reorganization can occur in all EVM chains. In Ethereum, where pooltogether is currently deployed, this is not "super common" but still happening, being the last one less than a year ago: https://decrypt.co/101390/ethereum-beacon-chain-blockchain-reorg
An issue can arise when users rely on getting an address beforehand, or try to deploy a clone of a position with the same address on different EVM chains, any funds sent to the new clone could potentially be withdrawn by someone else. In general, this can lead to the theft of users' funds.
An example of a similar error: https://code4rena.com/reports/2023-01-rabbithole#m-01-questfactory-is-suspicious-of-the-reorg-attack
Imagine that Alice deploys a clone of a position and then sends funds to it. Bob sees that the network block is being reorganized and calls deployVault. Thus, a clone of the position is created with the address to which Alice sends funds. Alice's transactions are then executed and Alice transfers the funds to Bob's position contract.
Manual review
Deploy Vault via create2 with salt which includes msg.sender and _asset address.
Context
#0 - c4-judge
2023-07-16T22:27:58Z
Picodes marked the issue as duplicate of #416
#1 - c4-judge
2023-08-06T22:36:03Z
Picodes marked the issue as satisfactory
π Selected for report: bin2chen
Also found by: 0x11singh99, 0xWaitress, 0xbepresent, ABAIKUNANBAEV, ArmedGoose, Bauchibred, DadeKuma, GREY-HAWK-REACH, GalloDaSballo, Inspecktor, Jeiwan, Kaysoft, MohammedRizwan, Rolezn, Vagner, alexzoid, alymurtazamemon, ayden, banpaleo5, catellatech, dacian, erebus, eyexploit, fatherOfBlocks, grearlake, joaovwfreire, keccak123, kutugu, lanrebayode77, markus_ether, nadin, naman1778, rvierdiiev, squeaky_cactus, volodya, yixxas
15.9228 USDC - $15.92
Part of the contributions to the vault is recorded as a reserve. This part serves two purposes:
The reserve contribution uses increaseReserve() (https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/PrizePool.sol#L498-L502), allowing anyone to contribute directly to the prize pool reserve. However, it is not taken into account that some tokens tend to take a built-in commission for the transfer of a token. Thus, the PrizePool.sol account will receive less than expected. At a certain moment, there may not be any tokens in the reserve account at all. Although the contract will assume that there are tokens.
https://github.com/d-xo/weird-erc20#fee-on-transfer
Manual review
In increaseReserve() write the old balance of prizeToken. Transfer the prizeToken to the contract address. Read new balance. Record the difference between the balances of the new and the old in _reserve.
Token-Transfer
#0 - c4-judge
2023-07-16T22:14:04Z
Picodes changed the severity to QA (Quality Assurance)
#1 - Picodes
2023-07-16T22:14:22Z
prizeToken
will be the protocol's native token according to the documentation
#2 - c4-judge
2023-08-08T14:32:08Z
Picodes marked the issue as grade-b