code-423n4 / 2023-07-pooltogether-findings

12 stars 7 forks source link

Yield fee is neither deducted from user's received shares nor transferred to _yieldFeeRecipient #130

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/GenerationSoftware/pt-v5-vault/blob/b1deb5d494c25f885c34c83f014c8a855c5e2749/src/Vault.sol#L550-#L587

Vulnerability details

Impact

Below is a POC for the above example, for ease of testing, let's place this test case in file vault/test/unit/Vault/Liquidate.t.sol under contract VaultLiquidateTest, then test it using command: forge test --match-path test/unit/Vault/Liquidate.t.sol --match-test testYieldFeeIsNotTransferred -vvvv

function testYieldFeeIsNotTransferred() external {
    _setLiquidationPair();

    // set yield fee percentage and recipient
    vault.setYieldFeePercentage(200000000);
    address newYieldFeeRecipient = address(0x9999);
    vault.setYieldFeeRecipient(newYieldFeeRecipient);

    underlyingAsset.mint(address(this), 1000e18);
    _sponsor(underlyingAsset, vault, 1000e18, address(this));

    // Mint some yield
    underlyingAsset.mint(address(yieldVault), 10e18);

    // Mint some prize tokens for alice
    prizeToken.mint(alice, 1000e18);

    // Alice liquidate (deposit prize tokens in exchange for vault shares)
    uint256 aliceShares = 1e18; // this is also the desired share alice want to receive
    vm.prank(address(liquidationPair));
    vault.liquidate(
      alice,
      address(prizeToken),
      1e18, // this is tokens in
      address(vault),
      aliceShares // amountOut
    );

    // Alice receive full amountOut
    assertEq(vault.balanceOf(alice), aliceShares);

    // _yieldFeeRecipient receives no share

    assertEq(newYieldFeeRecipient, vault.yieldFeeRecipient());
    assertEq(vault.balanceOf(newYieldFeeRecipient), 0);

  }

Tools Used

Manual review

Recommended Mitigation Steps

I recommend deducting the fee from liquidate user's shares and transfer to _yieldFeeRecipient

Assessed type

Other

Picodes commented 1 year ago

This seems to be the desired behavior as the liquidation is handled by another contract

c4-sponsor commented 1 year ago

asselstine marked the issue as sponsor confirmed

PierrickGT commented 1 year ago

I've explained the yield fee mechanism in this comment: https://github.com/code-423n4/2023-07-pooltogether-findings/issues/124#issuecomment-1668505255

For the yield fee recipient to receive his vault shares, he needs to call the mintYieldFee function: https://github.com/GenerationSoftware/pt-v5-vault/blob/44a6c6b081db5cc5e2acc4757a3c9dbaa6f60943/src/Vault.sol#L395

This report is incorrect and should not be part of the final report.

c4-judge commented 1 year ago

Picodes marked the issue as unsatisfactory: Invalid