Fix utilization rate computation and respect reserves when lending
The utilization rate `UR` of an asset forms the basis for interest calculations and is defined as `borrows / ( borrows + cash - reserves)`.\\n```\\n/\\*\\*\\n \\* @notice Calculate the utilization rate: `\\_borrows / (\\_cash + \\_borrows - \\_reserves)`\\n \\* @param \\_cash Asset balance\\n \\* @param \\_borrows Asset borrows\\n \\* @param \\_reserves Asset reserves\\n \\* @return Asset utilization [0, 1e18]\\n \\*/\\nfunction utilizationRate(\\n    uint256 \\_cash,\\n    uint256 \\_borrows,\\n    uint256 \\_reserves\\n) internal pure returns (uint256) {\\n    // Utilization rate is 0 when there are no borrows\\n    if (\\_borrows == 0) return 0;\\n\\n    return \\_borrows.mul(BASE).div(\\_cash.add(\\_borrows).sub(\\_reserves));\\n}\\n```\\n\\nThe implicit assumption here is that `reserves` <= cash; in this case — and if we define `UR` as `0` for `borrows == 0` — we have `0` <= `UR` <=1. We can view `cash` - `reserves` as “available cash”. However, the system does not guarantee that `reserves` never exceeds `cash`. If `reserves` > `cash` (and borrows + `cash` - `reserves` > 0), the formula for `UR` above gives a utilization rate above `1`. This doesn't make much sense conceptually and has undesirable technical consequences; an especially severe one is analyzed in issue 4.4.
If `reserves > cash` — or, in other words, available cash is negative — this means part of the `reserves` have been borrowed, which ideally shouldn't happen in the first place. However, the `reserves` grow automatically over time, so it might be difficult to avoid this entirely. We recommend (1) avoiding this situation whenever it is possible and (2) fixing the `UR` computation such that it deals more gracefully with this scenario. More specifically:\\nLoan amounts should not be checked to be smaller than or equal to `cash` but `cash - reserves` (which might be negative). Note that the current check against `cash` happens more or less implicitly because the transfer just fails for insufficient `cash`.\\nMake the utilization rate computation return `1` if `reserves > cash` (unless borrows == `0`, in which case return `0` as is already the case).\\nRemark\\nInternally, the utilization rate and other fractional values are scaled by `1e18`. The discussion above has a more conceptual than technical perspective, so we used unscaled numbers. When making changes to the code, care must be taken to apply the scaling.
```\\n/\\*\\*\\n \\* @notice Calculate the utilization rate: `\\_borrows / (\\_cash + \\_borrows - \\_reserves)`\\n \\* @param \\_cash Asset balance\\n \\* @param \\_borrows Asset borrows\\n \\* @param \\_reserves Asset reserves\\n \\* @return Asset utilization [0, 1e18]\\n \\*/\\nfunction utilizationRate(\\n    uint256 \\_cash,\\n    uint256 \\_borrows,\\n    uint256 \\_reserves\\n) internal pure returns (uint256) {\\n    // Utilization rate is 0 when there are no borrows\\n    if (\\_borrows == 0) return 0;\\n\\n    return \\_borrows.mul(BASE).div(\\_cash.add(\\_borrows).sub(\\_reserves));\\n}\\n```\\n