# BancorFormula.sol

[Git Source](https://github.com/InverterNetwork/inverter-contracts/blob/649b450f02fc8b735c128ff0821467e71966c666/src/modules/fundingManager/bondingCurve/formulas/BancorFormula.sol)

**Inherits:** IBancorFormula, Utils, ERC165

**Author:** <https://github.com/AragonBlack/fundraising/blob/master/apps/bancor-formula/contracts/BancorFormula.sol>

The sole modification applied to these contracts involves the alteration of the Solidity version and the version-specific removal of the 'public' keyword from the constructor, coinciding with adjustments in the contract import methodology.

### State Variables

#### version

```solidity
string public version = "0.3";
```

#### ONE

```solidity
uint private constant ONE = 1;
```

#### MAX\_WEIGHT

```solidity
uint32 private constant MAX_WEIGHT = 1_000_000;
```

#### MIN\_PRECISION

```solidity
uint8 private constant MIN_PRECISION = 32;
```

#### MAX\_PRECISION

```solidity
uint8 private constant MAX_PRECISION = 127;
```

#### FIXED\_1

Auto-generated via 'PrintIntScalingFactors.py'

```solidity
uint private constant FIXED_1 = 0x080000000000000000000000000000000;
```

#### FIXED\_2

```solidity
uint private constant FIXED_2 = 0x100000000000000000000000000000000;
```

#### MAX\_NUM

```solidity
uint private constant MAX_NUM = 0x200000000000000000000000000000000;
```

#### LN2\_NUMERATOR

Auto-generated via 'PrintLn2ScalingFactors.py'

```solidity
uint private constant LN2_NUMERATOR = 0x3f80fe03f80fe03f80fe03f80fe03f8;
```

#### LN2\_DENOMINATOR

```solidity
uint private constant LN2_DENOMINATOR = 0x5b9de1d10bf4103d647b0955897ba80;
```

#### OPT\_LOG\_MAX\_VAL

Auto-generated via 'PrintFunctionOptimalLog.py' and 'PrintFunctionOptimalExp.py'

```solidity
uint private constant OPT_LOG_MAX_VAL = 0x15bf0a8b1457695355fb8ac404e7a79e3;
```

#### OPT\_EXP\_MAX\_VAL

```solidity
uint private constant OPT_EXP_MAX_VAL = 0x800000000000000000000000000000000;
```

#### maxExpArray

Auto-generated via 'PrintFunctionConstructor.py'

```solidity
uint[128] private maxExpArray;
```

### Functions

#### supportsInterface

*See {IERC165-supportsInterface}.*

```solidity
function supportsInterface(bytes4 interfaceId)
    public
    view
    virtual
    override(ERC165)
    returns (bool);
```

#### constructor

```solidity
constructor();
```

#### calculatePurchaseReturn

*given a token supply, connector balance, weight and a deposit amount (in the connector token), calculates the return for a given conversion (in the main token) Formula: Return = \_supply \* ((1 + \_depositAmount / \_connectorBalance) ^ (\_connectorWeight / 1000000) - 1)*

```solidity
function calculatePurchaseReturn(
    uint _supply,
    uint _connectorBalance,
    uint32 _connectorWeight,
    uint _depositAmount
) public view returns (uint);
```

**Parameters**

| Name                | Type      | Description                                     |
| ------------------- | --------- | ----------------------------------------------- |
| `_supply`           | `uint256` | token total supply                              |
| `_connectorBalance` | `uint256` | total connector balance                         |
| `_connectorWeight`  | `uint32`  | connector weight, represented in ppm, 1-1000000 |
| `_depositAmount`    | `uint256` | deposit amount, in connector token              |

**Returns**

| Name     | Type      | Description            |
| -------- | --------- | ---------------------- |
| `<none>` | `uint256` | purchase return amount |

#### calculateSaleReturn

*given a token supply, connector balance, weight and a sell amount (in the main token), calculates the return for a given conversion (in the connector token) Formula: Return = \_connectorBalance \* (1 - (1 - \_sellAmount / \_supply) ^ (1 / (\_connectorWeight / 1000000)))*

```solidity
function calculateSaleReturn(
    uint _supply,
    uint _connectorBalance,
    uint32 _connectorWeight,
    uint _sellAmount
) public view returns (uint);
```

**Parameters**

| Name                | Type      | Description                                              |
| ------------------- | --------- | -------------------------------------------------------- |
| `_supply`           | `uint256` | token total supply                                       |
| `_connectorBalance` | `uint256` | total connector                                          |
| `_connectorWeight`  | `uint32`  | constant connector Weight, represented in ppm, 1-1000000 |
| `_sellAmount`       | `uint256` | sell amount, in the token itself                         |

**Returns**

| Name     | Type      | Description        |
| -------- | --------- | ------------------ |
| `<none>` | `uint256` | sale return amount |

#### calculateCrossConnectorReturn

*given two connector balances/weights and a sell amount (in the first connector token), calculates the return for a conversion from the first connector token to the second connector token (in the second connector token) Formula: Return = \_toConnectorBalance \* (1 - (\_fromConnectorBalance / (\_fromConnectorBalance + \_amount)) ^ (\_fromConnectorWeight / \_toConnectorWeight))*

```solidity
function calculateCrossConnectorReturn(
    uint _fromConnectorBalance,
    uint32 _fromConnectorWeight,
    uint _toConnectorBalance,
    uint32 _toConnectorWeight,
    uint _amount
) public view returns (uint);
```

**Parameters**

| Name                    | Type      | Description                                            |
| ----------------------- | --------- | ------------------------------------------------------ |
| `_fromConnectorBalance` | `uint256` | input connector balance                                |
| `_fromConnectorWeight`  | `uint32`  | input connector weight, represented in ppm, 1-1000000  |
| `_toConnectorBalance`   | `uint256` | output connector balance                               |
| `_toConnectorWeight`    | `uint32`  | output connector weight, represented in ppm, 1-1000000 |
| `_amount`               | `uint256` | input connector amount                                 |

**Returns**

| Name     | Type      | Description             |
| -------- | --------- | ----------------------- |
| `<none>` | `uint256` | second connector amount |

#### power

General Description: Determine a value of precision. Calculate an integer approximation of (\_baseN / \_baseD) ^ (\_expN / \_expD) \* 2 ^ precision. Return the result along with the precision used. Detailed Description: Instead of calculating "base ^ exp", we calculate "e ^ (log(base) \* exp)". The value of "log(base)" is represented with an integer slightly smaller than "log(base) \* 2 ^ precision". The larger "precision" is, the more accurately this value represents the real value. However, the larger "precision" is, the more bits are required in order to store this value. And the exponentiation function, which takes "x" and calculates "e ^ x", is limited to a maximum exponent (maximum value of "x"). This maximum exponent depends on the "precision" used, and it is given by "maxExpArray\[precision] >> (MAX\_PRECISION - precision)". Hence we need to determine the highest precision which can be used for the given input, before calling the exponentiation function. This allows us to compute "base ^ exp" with maximum accuracy and without exceeding 256 bits in any of the intermediate computations. This functions assumes that "\_expN < 2 ^ 256 / log(MAX\_NUM - 1)", otherwise the multiplication should be replaced with a "safeMul".

```solidity
function power(uint _baseN, uint _baseD, uint32 _expN, uint32 _expD)
    internal
    view
    returns (uint, uint8);
```

#### generalLog

Compute log(x / FIXED\_1) \* FIXED\_1. This functions assumes that "x >= FIXED\_1", because the output would be negative otherwise.

```solidity
function generalLog(uint x) internal pure returns (uint);
```

#### floorLog2

Compute the largest integer smaller than or equal to the binary logarithm of the input.

```solidity
function floorLog2(uint _n) internal pure returns (uint8);
```

#### findPositionInMaxExpArray

The global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent:

* This function finds the position of \[the smallest value in "maxExpArray" larger than or equal to "x"]
* This function finds the highest position of \[a value in "maxExpArray" larger than or equal to "x"]

```solidity
function findPositionInMaxExpArray(uint _x) internal view returns (uint8);
```

#### generalExp

This function can be auto-generated by the script 'PrintFunctionGeneralExp.py'. It approximates "e ^ x" via maclaurin summation: "(x^0)/0! + (x^1)/1! + ... + (x^n)/n!". It returns "e ^ (x / 2 ^ precision) \* 2 ^ precision", that is, the result is upshifted for accuracy. The global "maxExpArray" maps each "precision" to "((maximumExponent + 1) << (MAX\_PRECISION - precision)) - 1". The maximum permitted value for "x" is therefore given by "maxExpArray\[precision] >> (MAX\_PRECISION - precision)".

```solidity
function generalExp(uint _x, uint8 _precision) internal pure returns (uint);
```

#### optimalLog

Return log(x / FIXED\_1) \* FIXED\_1 Input range: FIXED\_1 <= x <= LOG\_EXP\_MAX\_VAL - 1 Auto-generated via 'PrintFunctionOptimalLog.py' Detailed description:

* Rewrite the input as a product of natural exponents and a single residual r, such that 1 < r < 2
* The natural logarithm of each (pre-calculated) exponent is the degree of the exponent
* The natural logarithm of r is calculated via Taylor series for log(1 + x), where x = r - 1
* The natural logarithm of the input is calculated by summing up the intermediate results above
* For example: log(250) = log(e^4 \* e^1 \* e^0.5 \* 1.021692859) = 4 + 1 + 0.5 + log(1 + 0.021692859)

```solidity
function optimalLog(uint x) internal pure returns (uint);
```

#### optimalExp

Return e ^ (x / FIXED\_1) \* FIXED\_1 Input range: 0 <= x <= OPT\_EXP\_MAX\_VAL - 1 Auto-generated via 'PrintFunctionOptimalExp.py' Detailed description:

* Rewrite the input as a sum of binary exponents and a single residual r, as small as possible
* The exponentiation of each binary exponent is given (pre-calculated)
* The exponentiation of r is calculated via Taylor series for e^x, where x = r
* The exponentiation of the input is calculated by multiplying the intermediate results above
* For example: e^5.521692859 = e^(4 + 1 + 0.5 + 0.021692859) = e^4 \* e^1 \* e^0.5 \* e^0.021692859

```solidity
function optimalExp(uint x) internal pure returns (uint);
```
