PercentageMath

This Aave library provides functions to perform percentage calculations.

  • Percentages are defined by with 2 decimals of precision (100.00).

  • The precision is indicated by PERCENTAGE_FACTOR.

  • Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down.

// Maximum percentage factor (100.00%)
uint256 internal constant PERCENTAGE_FACTOR = 1e4;

// Half percentage factor (50.00%)
uint256 internal constant HALF_PERCENTAGE_FACTOR = 0.5e4;

Fixed-point representations of percentages: (2 dp of precision)

  • 100% is represented as 10000 -> 100.00%

  • 50% is represented as 5000 -> 50.00%

  • 1% is represented as 100 -> 1.00%

percentMul

Test example

  • for value: 10000, percentage: 100 -> result: 100

We know this to be true as 1% of 10000 is indeed 100. Feel free to experiment on remix!

percentMul

Multiplication operation

Let's start by examining the multiplication operation:

  • Divide by PERCENTAGE_FACTOR: To negate the effect of representing 0.01 as 100

  • Adding HALF_PERCENTAGE_FACTOR: For rounding to the nearest integer.

The reason for adding half of the divisor to the dividend was covered earlier, in the fixed-point section on rounding.

* maybe show diag of when round down vs round up?

overflow

Revert if

  • the percentage is 0 , OR

  • value >\gt (type(uint256).max - HALF_PERCENTAGE_FACTOR) / percentage

Why should value ≤ \leq(type(uint256).max - HALF_PERCENTAGE_FACTOR) / percentage, you ask?

The explanation is similar to the overflow check explanation given with regards to wadMul, in the earlier section.

Both percentage and value were received as uint256 inputs - so we have no concerns there of overflow. However, with the manipulations made to the dividend, A, we cannot be sure that in some instances it might not overflow beyond uint256.

  • Essentially, with this condition, we are saying that the dividend cannot exceed what can be represented by uint256.

  • This is a necessary check as we did supply A as a uint256 input, but rather "created" it via our operations within the function.

  • Remember, the compiler checks for {over,under}flow do not apply within assembly blocks!

give example on when inputs lead to overflow?

percentDiv

Division operation

Example

  • value = 100

  • percentage = 100 (1%)

  • result => 10000

Let's start by examining the division operation:

overflow

Revert if:

  • percentage is 0 , OR

  • value >\gt (type(uint256).max - halfPercentage) / PERCENTAGE_FACTOR

The dividend must be <= type(uint256).max to avoid an overflow. The condition is obtained by observing the manipulations made in the dividend:

Last updated

Was this helpful?