Skip to content

Commit

Permalink
Merge pull request #7 from primitivefinance/develop
Browse files Browse the repository at this point in the history
beta-v0.0.1
  • Loading branch information
0xJepsen authored Jan 2, 2023
2 parents 908660e + 48ee022 commit f314cc4
Show file tree
Hide file tree
Showing 71 changed files with 1,848 additions and 18,924 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
on: [push]

name: test

jobs:
check:
name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Install deps
run: yarn install

- name: Build
run: yarn build

- name: Run tests
run: forge test
env:
FOUNDRY_FUZZ_RUNS: 10000
6 changes: 1 addition & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ coverage
coverage.json
typechain-types
yarn-error.log

#Hardhat files
artifacts/
hh-cache/

dist/

# Foundry
cache
Expand Down
8 changes: 5 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/ds-test"]
path = lib/ds-test
url = https://github.com/dapphub/ds-test
branch = v1.2.0
[submodule "lib/solmate"]
path = lib/solmate
url = https://github.com/transmissions11/solmate
branch = v7
8 changes: 0 additions & 8 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,9 +1 @@
# Ignore artifacts:
artifacts
cache
coverage
coverage*
typechain-types

# Ignore certain files
/contracts/Bisection.sol
423 changes: 205 additions & 218 deletions LICENSE

Large diffs are not rendered by default.

79 changes: 76 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,78 @@
# Hardhat Foundry Template
# SolStat

Combines hardhat and foundry testing frameworks to take advantage of coverage and fuzzing capabiltiies, along with their native tools.
SolStat is a Math library written in solidity for statistical function approximations. The library is composed of two core libraries; Gaussian.sol, and Invariant.sol. We will go over each of these libraries and their testing suites. We at Primitive use these libraries to support development with RMM-01s unique trading function, which utilizes the cumulative distribution function (CDF) of the normal distribution denoted by the greek capital letter Phi($\Phi$) in the literature [1,2]. You may recognize the normal or Gaussian distribution as the bell curve. This distribution is significant in modeling real-valued random numbers of unknown distributions. Within the RMM-01 trading function and options pricing, the CDF is used to model random price movement of a Markov process. Since price paths are commonly modeled with markovian proccesses, we believe that the greater community will find value in this library.

Inspired by [Seaport](https://github.com/ProjectOpenSea/seaport)
## How to use

Requirements: forge, node >=v16.0.0

```
yarn install
forge install
yarn build
forge test
```

To compute values using the gaussian.js library, you can use this commmand in the cli:

```
yarn cli --cdf {value}
yarn cli --pdf {value}
yarn cli --ppf {value}
```

## Irrational Functions

The primary reason for utilizing these approximation algorithms is that computers have trouble expressing irrational functions. This is because irrational numbers have an infinite number of decimals. Some examples of irrational numbers are $\pi$ and $\sqrt(2)$. This only becomes a challenge when we try to compute these numbers. This is because computers don't have an infinite amount of memory. Thus mathematicians and computer scientists have developed a variety of approximation algorithms to achieve varying degrees of speed and accuracy when approximating these irrational functions. These algorithms are commonly iterative and achieve greater accuracy with more iterations.

## Computational Constraints

In classical computing, our computational resources have become [abundant](https://en.wikipedia.org/wiki/Moore%27s_law), allowing us the liberty to iterate these algorithms to achieve our desired accuracy. However, the [Ethereum Virtual Machine (EVM)](https://ethereum.org/en/developers/docs/evm/) has a necessary monetary cost of computation. This computational environment has monetarily motivated developers to find efficient algorithms and hacks to reduce their applications' computational overhead (and thus the cost of computation).

## `Gaussian.sol`

This contract implements a number of functions important to the gaussian distributions. Importantly all these implementations are only for a mean $\mu = 0$ and variance $\sigma = 1$. These implementations are based on the [Numerical Recipes](https://e-maxx.ru/bookz/files/numerical_recipes.pdf) textbook and its C implementation. [Numerical Recipes](https://e-maxx.ru/bookz/files/numerical_recipes.pdf) cites the original text by Abramowitz and Stegun, "[Handbook of Mathematical Functions](https://personal.math.ubc.ca/~cbm/aands/abramowitz_and_stegun.pdf)," which should be read to understand these unique functions and the implications of their numerical approximations. This implementation was also inspired by the [javascript Gausian library](https://github.com/errcw/gaussian), which implements the same algorithm.

### Cumulative Distribution Function

The implementation of the CDF aproximation algorithm takes in a random variable $x$ as a single parameter. The function depends on a special helper functions known as the error function `erf`. The error function’s identity is `erfc(-x) = 2 - erfc(x)` and has a small collection of unique properties:

erfc(-$\infty$) = 2

erfc(0) = 1

erfc($\infty$) = 0

The reference implementation for the error function is on p221 of Numerical Recipes in section C 2e. A helpful resource is this [wolfram notebook](https://mathworld.wolfram.com/Erfc.html).

### Probability Density Function

The library also supports an approximation of the Probability Density Function(PPF) which is mathematically interpeted as $Z(x) = \frac{1}{\sigma\sqrt{2\pi}}e^{\frac{-(x - \mu)^2}{2\sigma^2}}$. This implementation has a maximum error bound of of $1.2e-7$ and can be refrenced in this [wofram notebook](https://mathworld.wolfram.com/ProbabilityDensityFunction.html).

### Percent Point Function / Quantile Function

Furthermore we implemented aproximation algorithms for the Percent Point Function(PPF) sometimes known as the inverse CDF or the quantile function. The function is mathmatically defined as $D(x) = \mu - \sigma\sqrt{2}(ierfc(2x))$, has a maximum error of `1.2e-7`, and depends on the inverse error function `ierf` which satisfies `ierfc(erfc(x)) = erfc(ierfc(x))`. The invers error function, defined as `ierfc(1 - x) = ierf(x)`, has a domain of in the interval $0 < x < 2$ and has some unique properties:

ierfc(0) = $\infty$

ierfc(1) = 0

ierfc(2) = -$\infty$

## `Invariant.sol`

`Invariant.sol` is a contract used to compute the invariant of the RMM-01 trading function such that we compute $y$ in $y = K\Phi(\Phi^{⁻¹}(1-x) - \sigma\sqrt(\tau)) + k$. Notice how we need to compute the normal CDF of a quantity. For a more detailed perspective on the trading function, please see the whitepaper. This is an example of how we have used this library for our research, development, and testing of RMM-01. The function reverts if $x$ is greater than one and simplifies to $K(1+x) + k$ when $\tau$ is zero (at expiry). The function takes in five parameters
`R_x`: The reserves of token $x$ per unit of liquidity, always within the bounds of $[0,1]$.
`strk`: The strike price of the pool.
`vol`: the implied volatility of the pool denoted by the lowercase greek letter sigma in finance literature.
`tau`: The time until the pool expires. Once expired, there can be no swaps.
`inv`: The current invariant given `R_x`.
The function then returns the quantity of token y per unit of liquidity denoted `R_y`, which is always within the bounds of $[0, stk]$. This is a clear example of how one would use this library.

## Differential Testing with Foundry

We leveraged foundry's support of differential testing for this library. Differential testing is a popular technique that seeds inputs to different implementations of the same application and detects differences in their execution. Differential testing is an excellent complement to traditional software testing as it is well suited to detect semantic errors. This library used differential testing against the javascript gaussian library to detect anomalies and varying bugs. This helped us to be confident in the performance and implementation of the library.

[1]: [Replicating Market Makers](https://arxiv.org/pdf/2103.14769.pdf)

[2]: [Replicating Portfolios: Contstructing Permissionless Derivatives](https://arxiv.org/pdf/2205.09890.pdf)
34 changes: 34 additions & 0 deletions cli/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import gaussian from 'gaussian'

const cdf = (x) => {
return gaussian(0, 1).cdf(x)
}

const ppf = (x) => {
return gaussian(0, 1).ppf(x)
}

const pdf = (x) => {
return gaussian(0, 1).pdf(x)
}

async function main() {
const args = process.argv
const [, , flag, value] = args

if (value) {
if (flag && flag === '--cdf') {
console.log(`cdf: ${cdf(value)}`)
} else if (flag && flag === '--ppf') {
console.log(`ppf: ${ppf(value)}`)
} else if (flag && flag === '--pdf') {
console.log(`pdf: ${pdf(value)}`)
} else {
console.log(`Unknown operation: ${flag}`)
}
} else {
console.log('No value supplied...')
}
}

main().catch((err) => process.exit(1))
10 changes: 0 additions & 10 deletions config/.solcover.js

This file was deleted.

53 changes: 0 additions & 53 deletions contracts/Bisection.sol

This file was deleted.

6 changes: 0 additions & 6 deletions contracts/Example.sol

This file was deleted.

26 changes: 0 additions & 26 deletions contracts/test/TestGaussian.sol

This file was deleted.

39 changes: 7 additions & 32 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -1,36 +1,11 @@
[default]
[profile.default]
solc = "0.8.13"
via_ir = true
src = 'contracts'
out = 'out'
libs = ['lib', 'node_modules']
test = 'test/foundry'
optimizer_runs = 15000
ffi = true # important!
remappings = [
'ds-test=lib/ds-test/src/',
'forge-std=lib/forge-std/src/',
'contracts/=contracts/',
'solmate/=lib/solmate/src/'
]
optimizer_runs = 15000
fuzz_runs = 256
fuzz_max_local_rejects = 65536
fuzz_max_global_rejects = 1024

[optimized]
solc = '0.8.13'
out = 'optimized-out'

[test]
solc = '0.8.13'
via_ir = false
src = 'test/foundry'
gas_reports = ["*"]
ffi = true
fuzz_runs = 500

[lite]
out = 'optimized-out'
via_ir = false
fuzz_runs = 1000



# See more config options https://github.com/gakonst/foundry/tree/master/config
[fuzz]
runs = 10000
39 changes: 0 additions & 39 deletions hardhat-coverage.config.ts

This file was deleted.

Loading

0 comments on commit f314cc4

Please sign in to comment.