# PercentageMath

This Aave library provides functions to perform percentage calculations.

* Percentages are defined by with **2 decimals of precision** (100.00).&#x20;
* The precision is indicated by `PERCENTAGE_FACTOR`.
* Operations are rounded. If a value is **>=.5, will be rounded up**, otherwise rounded down.

```solidity
// 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!

<figure><img src="/files/iTYu38vq6svvmvYagFm0" alt=""><figcaption><p>percentMul</p></figcaption></figure>

### Multiplication operation

Let's start by examining the multiplication operation:

```solidity
result := div(add(mul(value, percentage), HALF_PERCENTAGE_FACTOR), PERCENTAGE_FACTOR)

// translated:
[(value * percentage) + HALF_PERCENTAGE_FACTOR] / PERCENTAGE_FACTOR
```

<figure><img src="/files/WfOsiugDbR5SbgGJl8tZ" alt="" width="563"><figcaption></figcaption></figure>

* Divide by `PERCENTAGE_FACTOR`: To negate the effect of representing `0.01` as `100`
* Adding HALF\_PERCENTAGE\_FACTOR: For rounding to the nearest integer.&#x20;

{% hint style="info" %}
The reason for adding half of the divisor to the dividend was covered earlier, in the fixed-point section on rounding.
{% endhint %}

#### \* maybe show diag of when round down vs round up?&#x20;

### overflow

Revert if

* the `percentage` is `0` , OR
* `value` $$\gt$$ `(type(uint256).max - HALF_PERCENTAGE_FACTOR) / percentage`

{% code fullWidth="true" %}

```solidity
if iszero(
  or(
    iszero(percentage),
    iszero(gt(value, div(sub(not(0), HALF_PERCENTAGE_FACTOR), percentage)))
  )
) {
  revert(0, 0)
}

// Overflow check, if percentage != 0
// value <= (type(uint256).max - HALF_PERCENTAGE_FACTOR) / percentage
iszero(percentage), iszero(gt(value, div(sub(not(0), HALF_PERCENTAGE_FACTOR), percentage)))
```

{% endcode %}

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.&#x20;

```solidity
[(value * percentage) + HALF_PERCENTAGE_FACTOR] / PERCENTAGE_FACTOR
A / PERCENTAGE_FACTOR, where A: [(value * percentage) + HALF_PERCENTAGE_FACTOR]
```

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. &#x20;

```solidity
value <= (type(uint256).max - HALF_PERCENTAGE_FACTOR) / percentage
value * percentage <= (type(uint256).max - HALF_PERCENTAGE_FACTOR)
(value * percentage) + HALF_PERCENTAGE_FACTOR <= type(uint256).max
A <= type(uint256).max
dividend <= type(uint256).max
```

* Essentially, with this condition, we are saying that the dividend cannot exceed what can be represented by uint256.&#x20;
* 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!

{% hint style="info" %}
give example on when inputs lead to overflow?
{% endhint %}

## percentDiv

<figure><img src="/files/TYfblErX9zaWa2kYOQn6" alt=""><figcaption></figcaption></figure>

### Division operation

**Example**

* value = 100
* percentage = 100 (1%)
* result => 10000

Let's start by examining the division operation:

```solidity
result := div(add(mul(value, PERCENTAGE_FACTOR), div(percentage, 2)), percentage)

// translated:
[(value * PERCENTAGE_FACTOR) + percentage/2] / percentage
```

<figure><img src="/files/RVDPm44aPHpgG24Dju5q" alt=""><figcaption></figcaption></figure>

### overflow

```solidity
if or(
  iszero(percentage),
  iszero(iszero(gt(value, div(sub(not(0), div(percentage, 2)), PERCENTAGE_FACTOR))))
) {
  revert(0, 0)
}
```

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:

```solidity
[(value * PERCENTAGE_FACTOR) + percentage/2] <= type(uint256).max
(value * PERCENTAGE_FACTOR) <= type(uint256).max - percentage/2
value <= [type(uint256).max - percentage/2] / PERCENTAGE_FACTOR
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://calnix.gitbook.io/aave-book/primer/percentagemath.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
