Branch data Line data Source code
1 : : // SPDX-License-Identifier: BUSL-1.1
2 : : pragma solidity ^0.8.0;
3 : :
4 : : import {WadRayMath} from './WadRayMath.sol';
5 : :
6 : : /**
7 : : * @title MathUtils library
8 : : * @author Aave
9 : : * @notice Provides functions to perform linear and compounded interest calculations
10 : : */
11 : : library MathUtils {
12 : : using WadRayMath for uint256;
13 : :
14 : : /// @dev Ignoring leap years
15 : : uint256 internal constant SECONDS_PER_YEAR = 365 days;
16 : :
17 : : /**
18 : : * @dev Function to calculate the interest accumulated using a linear interest rate formula
19 : : * @param rate The interest rate, in ray
20 : : * @param lastUpdateTimestamp The timestamp of the last update of the interest
21 : : * @return The interest rate linearly accumulated during the timeDelta, in ray
22 : : */
23 : : function calculateLinearInterest(
24 : : uint256 rate,
25 : : uint40 lastUpdateTimestamp
26 : : ) internal view returns (uint256) {
27 : : //solium-disable-next-line
28 : 21122 : uint256 result = rate * (block.timestamp - uint256(lastUpdateTimestamp));
29 : : unchecked {
30 : 21122 : result = result / SECONDS_PER_YEAR;
31 : : }
32 : :
33 : 21122 : return WadRayMath.RAY + result;
34 : : }
35 : :
36 : : /**
37 : : * @dev Function to calculate the interest using a compounded interest rate formula
38 : : * To avoid expensive exponentiation, the calculation is performed using a binomial approximation:
39 : : *
40 : : * (1+x)^n = 1+n*x+[n/2*(n-1)]*x^2+[n/6*(n-1)*(n-2)*x^3...
41 : : *
42 : : * The approximation slightly underpays liquidity providers and undercharges borrowers, with the advantage of great
43 : : * gas cost reductions. The whitepaper contains reference to the approximation and a table showing the margin of
44 : : * error per different time periods
45 : : *
46 : : * @param rate The interest rate, in ray
47 : : * @param lastUpdateTimestamp The timestamp of the last update of the interest
48 : : * @return The interest rate compounded during the timeDelta, in ray
49 : : */
50 : : function calculateCompoundedInterest(
51 : : uint256 rate,
52 : : uint40 lastUpdateTimestamp,
53 : : uint256 currentTimestamp
54 : : ) internal pure returns (uint256) {
55 : : //solium-disable-next-line
56 : 13515 : uint256 exp = currentTimestamp - uint256(lastUpdateTimestamp);
57 : :
58 : 13515 : if (exp == 0) {
59 : 1 : return WadRayMath.RAY;
60 : : }
61 : :
62 : 13514 : uint256 expMinusOne;
63 : 13514 : uint256 expMinusTwo;
64 : 13514 : uint256 basePowerTwo;
65 : 13514 : uint256 basePowerThree;
66 : : unchecked {
67 : 13514 : expMinusOne = exp - 1;
68 : :
69 : 13514 : expMinusTwo = exp > 2 ? exp - 2 : 0;
70 : :
71 : 13514 : basePowerTwo = rate.rayMul(rate) / (SECONDS_PER_YEAR * SECONDS_PER_YEAR);
72 : 13514 : basePowerThree = basePowerTwo.rayMul(rate) / SECONDS_PER_YEAR;
73 : : }
74 : :
75 : 13514 : uint256 secondTerm = exp * expMinusOne * basePowerTwo;
76 : : unchecked {
77 : 13514 : secondTerm /= 2;
78 : : }
79 : 13514 : uint256 thirdTerm = exp * expMinusOne * expMinusTwo * basePowerThree;
80 : : unchecked {
81 : 13514 : thirdTerm /= 6;
82 : : }
83 : :
84 : 13514 : return WadRayMath.RAY + (rate * exp) / SECONDS_PER_YEAR + secondTerm + thirdTerm;
85 : : }
86 : :
87 : : /**
88 : : * @dev Calculates the compounded interest between the timestamp of the last update and the current block timestamp
89 : : * @param rate The interest rate (in ray)
90 : : * @param lastUpdateTimestamp The timestamp from which the interest accumulation needs to be calculated
91 : : * @return The interest rate compounded between lastUpdateTimestamp and current block timestamp, in ray
92 : : */
93 : : function calculateCompoundedInterest(
94 : : uint256 rate,
95 : : uint40 lastUpdateTimestamp
96 : : ) internal view returns (uint256) {
97 : 13513 : return calculateCompoundedInterest(rate, lastUpdateTimestamp, block.timestamp);
98 : : }
99 : : }
|