/
Scores.sol
72 lines (60 loc) · 2.58 KB
/
Scores.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
import "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol";
import "./FixedMath.sol";
using SafeCastUpgradeable for uint256;
library Scores {
/**
* @notice Calculate a membership score given some amount of `xvs` and `capital`, along
* with some 𝝰 = `alphaNumerator` / `alphaDenominator`.
* @param xvs amount of xvs (xvs, 1e18 decimal places)
* @param capital amount of capital (USDC, 1e6 decimal places)
* @param alphaNumerator alpha param numerator
* @param alphaDenominator alpha param denominator
* @return membership score with 1e18 decimal places
*
* @dev 𝝰 must be in the range [0, 1]
*/
function calculateScore(
uint256 xvs,
uint256 capital,
uint256 alphaNumerator,
uint256 alphaDenominator
) internal pure returns (uint256) {
// Score function is:
// xvs^𝝰 * capital^(1-𝝰)
// = capital * capital^(-𝝰) * xvs^𝝰
// = capital * (xvs / capital)^𝝰
// = capital * (e ^ (ln(xvs / capital))) ^ 𝝰
// = capital * e ^ (𝝰 * ln(xvs / capital)) (1)
// or
// = capital / ( 1 / e ^ (𝝰 * ln(xvs / capital)))
// = capital / (e ^ (𝝰 * ln(xvs / capital)) ^ -1)
// = capital / e ^ (𝝰 * -1 * ln(xvs / capital))
// = capital / e ^ (𝝰 * ln(capital / xvs)) (2)
//
// To avoid overflows, use (1) when xvs < capital and
// use (2) when capital < xvs
assert(alphaNumerator <= alphaDenominator);
// If any side is 0, exit early
if (xvs == 0 || capital == 0) return 0;
// If both sides are equal, we have:
// xvs^𝝰 * capital^(1-𝝰)
// = xvs^𝝰 * xvs^(1-𝝰)
// = xvs^(𝝰 + 1 - 𝝰) = xvs
if (xvs == capital) return xvs;
bool lessxvsThanCapital = xvs < capital;
// (xvs / capital) or (capital / xvs), always in range (0, 1)
int256 ratio = lessxvsThanCapital ? FixedMath.toFixed(xvs, capital) : FixedMath.toFixed(capital, xvs);
// e ^ ( ln(ratio) * 𝝰 )
int256 exponentiation = FixedMath.exp(
(FixedMath.ln(ratio) * alphaNumerator.toInt256()) / alphaDenominator.toInt256()
);
if (lessxvsThanCapital) {
// capital * e ^ (𝝰 * ln(xvs / capital))
return FixedMath.uintMul(capital, exponentiation);
}
// capital / e ^ (𝝰 * ln(capital / xvs))
return FixedMath.uintDiv(capital, exponentiation);
}
}