Branch data Line data Source code
1 : : // SPDX-License-Identifier: BUSL-1.1
2 : : pragma solidity ^0.8.0;
3 : :
4 : : /**
5 : : * @title PercentageMath library
6 : : * @author Aave
7 : : * @notice Provides functions to perform percentage calculations
8 : : * @dev Percentages are defined by default with 2 decimals of precision (100.00). The precision is indicated by PERCENTAGE_FACTOR
9 : : * @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down.
10 : : */
11 : : library PercentageMath {
12 : : // Maximum percentage factor (100.00%)
13 : : uint256 internal constant PERCENTAGE_FACTOR = 1e4;
14 : :
15 : : // Half percentage factor (50.00%)
16 : : uint256 internal constant HALF_PERCENTAGE_FACTOR = 0.5e4;
17 : :
18 : : /**
19 : : * @notice Executes a percentage multiplication
20 : : * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
21 : : * @param value The value of which the percentage needs to be calculated
22 : : * @param percentage The percentage of the value to be calculated
23 : : * @return result value percentmul percentage
24 : : */
25 : : function percentMul(uint256 value, uint256 percentage) internal pure returns (uint256 result) {
26 : : // to avoid overflow, value <= (type(uint256).max - HALF_PERCENTAGE_FACTOR) / percentage
27 : : assembly {
28 : 158440 : if iszero(
29 : : or(
30 : : iszero(percentage),
31 : : iszero(gt(value, div(sub(not(0), HALF_PERCENTAGE_FACTOR), percentage)))
32 : : )
33 : : ) {
34 : 303 : revert(0, 0)
35 : : }
36 : :
37 : 158137 : result := div(add(mul(value, percentage), HALF_PERCENTAGE_FACTOR), PERCENTAGE_FACTOR)
38 : : }
39 : : }
40 : :
41 : : /**
42 : : * @notice Executes a percentage division
43 : : * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
44 : : * @param value The value of which the percentage needs to be calculated
45 : : * @param percentage The percentage of the value to be calculated
46 : : * @return result value percentdiv percentage
47 : : */
48 : : function percentDiv(uint256 value, uint256 percentage) internal pure returns (uint256 result) {
49 : : // to avoid overflow, value <= (type(uint256).max - halfPercentage) / PERCENTAGE_FACTOR
50 : : assembly {
51 : 30126 : if or(
52 : : iszero(percentage),
53 : : iszero(iszero(gt(value, div(sub(not(0), div(percentage, 2)), PERCENTAGE_FACTOR))))
54 : : ) {
55 : 74 : revert(0, 0)
56 : : }
57 : :
58 : 30052 : result := div(add(mul(value, PERCENTAGE_FACTOR), div(percentage, 2)), percentage)
59 : : }
60 : : }
61 : : }
|