Skip to content

Instantly share code, notes, and snippets.

@BenSchZA
Created May 31, 2019 12:40
Show Gist options
  • Save BenSchZA/190661172b4dc27fac551740a6587a1a to your computer and use it in GitHub Desktop.
Save BenSchZA/190661172b4dc27fac551740a6587a1a to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.5.8+commit.23d335f2.js&optimize=false&gist=
//Write your own contracts here. Currently compiles using solc v0.4.15+commit.bbb8e64f.
pragma solidity ^0.5.7;
/**
* @title SafeMath
* @dev Math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0); // Solidity only automatically asserts when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two numbers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two numbers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
contract AllTheMath {
using SafeMath for uint256;
function curveIntegral(uint256 _x) public view returns (uint256) {
/** This is the formula for the curve
f(x) = gradient*(x + b) + c
f(x) indicates it is a function of x, where x is the token supply
the gradient is the gradient of the curve i.e. the change in price over the change in token supply
c is the y-offset, which is set to 0 for now.
For more information visit:
https://en.wikipedia.org/wiki/Linear_function
*/
uint256 bDenominator = 2;
/* The gradient of a curve is the rate at which it increases its slope.
For example, to increase at a value of 5 DAI for every 1 token,
our gradient would be (change in y)/(change in x) = 5/1 = 5 DAI/Token
Remember that contracts deal with uint256 integers with 18 decimal points, not floating points, so:
to represent our gradient of 0.0005 DAI/Token, we simply divide by the denominator, to avoid floating points,
so we end up with 1/0.0005 = 2000 as our denominator.
*/
/* We need to calculate the definite integral from zero to the defined token supply, x.
A definite integral is essentially the area under the curve, from zero to the defined token supply.
The area under the curve is equivalent to the value of the tokens up until that point.
The integral of the linear curve, f(x), is calculated as:
gradient*0.5*x^2 + cx; where c = 0
Because we are essentially squaring the decimal scaling in the calculation,
we need to divide the result by the scaling factor before returning - this hurt my mind a bit, but mathematically holds true.
*/
uint256 gradientDenominator_ = 17500;
uint256 decimals_ = 18;
// Original function: ((_x**2).div(2*gradientDenominator_).add(c.mul(_x)).div(10**decimals_));
// New function (Python): (math.pow(xT, 2.0)*gradient)/2.0 + b*xT
return (_x**2).div((10**18)**2).div(gradientDenominator_).div(2).add(_x.div(bDenominator));
}
/// @dev Inverse integral to convert the incoming colateral value to token volume
/// @param _x :uint256 The volume to identify the root off
function inverseCurveIntegral(uint256 _x) public view returns(uint256) {
// Original function: sqrt(2*_x*gradientDenominator_*(10**decimals_));
// New function (Python): (-b + math.sqrt(math.pow(b, 2.0) + 2.0*gradient*xD))/(gradient)
// With scaling( -b*math.pow(10, decimals) + math.sqrt(math.pow(b, 2.0) + 2*xD/gradientDenominator)*math.pow(10, decimals))*gradientDenominator/math.pow(10, decimals)
// uint256 gradientDenominator = 17500;
//
// uint256 decimals = 18;
// uint256 bScaled = 5*10**(decimals - 1);
// (-5*math.pow(10, decimals - 1) + math.sqrt(math.pow(-5*math.pow(10, decimals - 1), 2.0)/math.pow(math.pow(10, 18), 2) + 2*xD/gradientDenominator)*math.pow(10, 18))*gradientDenominator/math.pow(10, 18*2)
return (( sqrt((5*10**(18 - 1)**2)/sqrt(10) + _x.mul(2).div(17500)).sub(5*10**(18 - 1)) ).mul(10**18).mul(17500)).div(10**18);
}
function sqrt(uint256 _x) internal pure returns (uint256) {
if (_x == 0) return 0;
else if (_x <= 3) return 1;
uint256 z = (_x + 1) / 2;
uint256 y = _x;
while (z < y)
/// @why3 invariant { to_int !_z = div ((div (to_int arg_x) (to_int !_y)) + (to_int !_y)) 2 }
/// @why3 invariant { to_int arg_x < (to_int !_y + 1) * (to_int !_y + 1) }
/// @why3 invariant { to_int arg_x < (to_int !_z + 1) * (to_int !_z + 1) }
/// @why3 variant { to_int !_y }
{
y = z;
z = (_x / z + z) / 2;
}
return y;
}
uint value;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment