PoolTogether - dd0x7e8's results

General Information

Platform: Code4rena

Start Date: 04/03/2024

Pot Size: $36,500 USDC

Total HM: 9

Participants: 80

Period: 7 days

Judge: hansfriese

Total Solo HM: 2

Id: 332

League: ETH

PoolTogether

Findings Distribution

Researcher Performance

Rank: 61/80

Findings: 1

Award: $1.47

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

1.4652 USDC - $1.47

Labels

bug
3 (High Risk)
satisfactory
sufficient quality report
upgraded by judge
:robot:_10_group
duplicate-59

External Links

Lines of code

https://github.com/code-423n4/2024-03-pooltogether/blob/480d58b9e8611c13587f28811864aea138a0021a/pt-v5-vault/src/PrizeVault.sol#L617

Vulnerability details

Impact

There is a logical error in the claimYieldFeeShares function of the PrizeVault contract.

    function claimYieldFeeShares(uint256 _shares) external onlyYieldFeeRecipient {
        if (_shares == 0) revert MintZeroShares();

        uint256 _yieldFeeBalance = yieldFeeBalance;
        if (_shares > _yieldFeeBalance) revert SharesExceedsYieldFeeBalance(_shares, _yieldFeeBalance);

        yieldFeeBalance -= _yieldFeeBalance;

        _mint(msg.sender, _shares);

        emit ClaimYieldFeeShares(msg.sender, _shares);
    }

This line yieldFeeBalance -= _yieldFeeBalance; is intended to subtract the amount of yield fee shares (_shares) being claimed from the yieldFeeBalance, which tracks the total amount of shares that have been accrued as fees and are claimable by the yieldFeeRecipient.

However, instead of subtracting the shares being claimed (_shares), the current balance itself (_yieldFeeBalance) is being subtracted from yieldFeeBalance. This would incorrectly reduce the yieldFeeBalance to zero regardless of the amount of shares actually claimed, which is not the intended behavior.

Proof of Concept

    function testClaimYieldFeeShares_withdrawPartialBalance() public {
        vault.setYieldFeePercentage(1e8); // 10% fee
        vault.setYieldFeeRecipient(bob);
        vault.setLiquidationPair(address(this));

        // liquidate some yield
        underlyingAsset.mint(address(vault), 1e18);
        uint256 amountOut = vault.liquidatableBalanceOf(address(underlyingAsset));
        assertGt(amountOut, 0);

        vault.transferTokensOut(address(0), alice, address(underlyingAsset), amountOut);
        uint256 yieldFeeBalance = vault.yieldFeeBalance();
        console2.log("Before claiming, yieldFeeBalance = %d", yieldFeeBalance);
        assertGt(yieldFeeBalance, 0);

        vm.startPrank(bob);
        vm.expectEmit();
        emit Transfer(address(0), bob, yieldFeeBalance / 3);
        vm.expectEmit();
        emit ClaimYieldFeeShares(bob, yieldFeeBalance / 3);
        console2.log("Claim one third of all yield fees with shares: %d", yieldFeeBalance / 3);
        vault.claimYieldFeeShares(yieldFeeBalance / 3);
        vm.stopPrank();

        assertEq(vault.balanceOf(bob), yieldFeeBalance / 3);
        yieldFeeBalance = vault.yieldFeeBalance();
        console2.log("After claiming, yieldFeeBalance = %d", yieldFeeBalance);
    }

Test output:

$ forge test --mt testClaimYieldFeeShares_withdrawPartialBalance -vv
[â ’] Compiling...
[â ‘] Compiling 1 files with 0.8.24
[â ˜] Solc 0.8.24 finished in 15.08s
Compiler run successful!

Ran 1 test for test/unit/PrizeVault/Liquidate.t.sol:PrizeVaultLiquidationTest
[PASS] testClaimYieldFeeShares_withdrawPartialBalance() (gas: 319613)
Logs:
  Before claiming, yieldFeeBalance = 99999999999900000
  Claim one third of all yield fees with shares: 33333333333300000
  After claiming, yieldFeeBalance = 0

Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 4.93ms

Tools Used

Foundry, VSCode

The correct implementation should be:

    yieldFeeBalance -= _shares;

Assessed type

Other

#0 - c4-pre-sort

2024-03-11T21:40:53Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-03-11T21:40:58Z

raymondfam marked the issue as duplicate of #10

#2 - c4-pre-sort

2024-03-13T04:38:13Z

raymondfam marked the issue as duplicate of #59

#3 - c4-judge

2024-03-15T07:37:30Z

hansfriese changed the severity to 3 (High Risk)

#4 - c4-judge

2024-03-15T07:40:33Z

hansfriese 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