diff --git a/contracts/experimental/CurveCryptoMath2MAX.vy b/contracts/experimental/CurveCryptoMath2MAX.vy deleted file mode 100644 index 19376a21..00000000 --- a/contracts/experimental/CurveCryptoMath2MAX.vy +++ /dev/null @@ -1,123 +0,0 @@ -# pragma version 0.3.10 -# pragma optimize gas -# pragma evm-version paris - - -N_COINS: constant(uint256) = 2 -A_MULTIPLIER: constant(uint256) = 10000 - -MIN_GAMMA: constant(uint256) = 10**10 -MAX_GAMMA_SMALL: constant(uint256) = 2 * 10**16 -MAX_GAMMA: constant(uint256) = 199 * 10**15 # 1.99 * 10**17 - -MIN_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER / 10 -MAX_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER * 1000 - -MAX_ITER: constant(uint256) = 255 - - -@external -@view -def newton_D() -> ( - uint256[MAX_ITER], - uint256[MAX_ITER], - uint256[MAX_ITER], - uint256[MAX_ITER], - uint256[MAX_ITER], - uint256[MAX_ITER], - uint256[MAX_ITER], - uint256[MAX_ITER] -): - """ - Finding the invariant using Newton method. - ANN is higher by the factor A_MULTIPLIER - ANN is already A * N**N - """ - - # # Safety checks - # assert ANN > MIN_A - 1 and ANN < MAX_A + 1 # dev: unsafe values A - # assert gamma > MIN_GAMMA - 1 and gamma < MAX_GAMMA + 1 # dev: unsafe values gamma - - # # Initial value of invariant D is that for constant-product invariant - # x: uint256[N_COINS] = x_unsorted - # if x[0] < x[1]: - # x = [x_unsorted[1], x_unsorted[0]] - - # assert x[0] > 10**9 - 1 and x[0] < 10**15 * 10**18 + 1 # dev: unsafe values x[0] - # assert unsafe_div(x[1] * 10**18, x[0]) > 10**14 - 1 # dev: unsafe values x[i] (input) - - ANN: uint256 = MAX_A - gamma: uint256 = MAX_GAMMA - - x: uint256[N_COINS] = [10**15 * 10**18, 10**15 * 10**18] - S: uint256 = unsafe_add(x[0], x[1]) # can unsafe add here because we checked x[0] bounds - D: uint256 = N_COINS * isqrt(unsafe_mul(x[0], x[1])) - - __g1k0: uint256 = gamma + 10**18 - diff: uint256 = 0 - - K0_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER]) - _g1k0_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER]) - mul1_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER]) - mul2_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER]) - neg_fprime_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER]) - D_plus_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER]) - D_minus_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER]) - D_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER]) - - for i in range(MAX_ITER): - D_prev: uint256 = D - assert D > 0 - # Unsafe division by D and D_prev is now safe - - # K0: uint256 = 10**18 - # for _x in x: - # K0 = K0 * _x * N_COINS / D - # collapsed for 2 coins - K0: uint256 = unsafe_div(unsafe_div((10**18 * N_COINS**2) * x[0], D) * x[1], D) - - _g1k0: uint256 = __g1k0 - if _g1k0 > K0: - _g1k0 = unsafe_add(unsafe_sub(_g1k0, K0), 1) # > 0 - else: - _g1k0 = unsafe_add(unsafe_sub(K0, _g1k0), 1) # > 0 - # K0 is greater than 0 - # _g1k0 is greater than 0 - - # D / (A * N**N) * _g1k0**2 / gamma**2 - mul1: uint256 = unsafe_div(unsafe_div(unsafe_div(10**18 * D, gamma) * _g1k0, gamma) * _g1k0 * A_MULTIPLIER, ANN) - - # 2*N*K0 / _g1k0 - mul2: uint256 = unsafe_div(((2 * 10**18) * N_COINS) * K0, _g1k0) - - # calculate neg_fprime. here K0 > 0 is being validated (safediv). - neg_fprime: uint256 = ( - S + - unsafe_div(S * mul2, 10**18) + - mul1 * N_COINS / K0 - - unsafe_div(mul2 * D, 10**18) - ) - - # D -= f / fprime; neg_fprime safediv being validated - D_plus: uint256 = D * (neg_fprime + S) / neg_fprime - D_minus: uint256 = unsafe_div(D * D, neg_fprime) - if 10**18 > K0: - D_minus += unsafe_div(unsafe_div(D * unsafe_div(mul1, neg_fprime), 10**18) * unsafe_sub(10**18, K0), K0) - else: - D_minus -= unsafe_div(unsafe_div(D * unsafe_div(mul1, neg_fprime), 10**18) * unsafe_sub(K0, 10**18), K0) - - if D_plus > D_minus: - D = unsafe_sub(D_plus, D_minus) - else: - D = unsafe_div(unsafe_sub(D_minus, D_plus), 2) - - K0_iter[i] = K0 - _g1k0_iter[i] = _g1k0 - mul1_iter[i] = mul1 - mul2_iter[i] = mul2 - neg_fprime_iter[i] = neg_fprime - D_plus_iter[i] = D_plus - D_minus_iter[i] = D_minus - D_iter[i] = D - - return K0_iter, _g1k0_iter, mul1_iter, mul2_iter, neg_fprime_iter, D_plus_iter, D_minus_iter, D_iter diff --git a/scripts/experiments/max_newton_D.ipynb b/scripts/experiments/max_newton_D.ipynb new file mode 100644 index 00000000..48a8d667 --- /dev/null +++ b/scripts/experiments/max_newton_D.ipynb @@ -0,0 +1,233 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import boa\n", + "%load_ext boa.ipython" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%vyper MAXNewton_D\n", + "\n", + "# pragma version 0.3.10\n", + "# pragma optimize gas\n", + "# pragma evm-version paris\n", + "\n", + "\n", + "N_COINS: constant(uint256) = 2\n", + "A_MULTIPLIER: constant(uint256) = 10000\n", + "\n", + "MIN_GAMMA: constant(uint256) = 10**10\n", + "MAX_GAMMA_SMALL: constant(uint256) = 2 * 10**16\n", + "MAX_GAMMA: constant(uint256) = 199 * 10**15 # 1.99 * 10**17\n", + "\n", + "MIN_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER / 10\n", + "MAX_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER * 1000\n", + "\n", + "MAX_ITER: constant(uint256) = 255\n", + "\n", + "\n", + "@external\n", + "@view\n", + "def newton_D() -> (\n", + " uint256[MAX_ITER],\n", + " uint256[MAX_ITER],\n", + " uint256[MAX_ITER],\n", + " uint256[MAX_ITER],\n", + " uint256[MAX_ITER],\n", + " uint256[MAX_ITER],\n", + " uint256[MAX_ITER],\n", + " uint256[MAX_ITER]\n", + "):\n", + " \"\"\"\n", + " Finding the invariant using Newton method.\n", + " ANN is higher by the factor A_MULTIPLIER\n", + " ANN is already A * N**N\n", + " \"\"\"\n", + "\n", + " # # Safety checks\n", + " # assert ANN > MIN_A - 1 and ANN < MAX_A + 1 # dev: unsafe values A\n", + " # assert gamma > MIN_GAMMA - 1 and gamma < MAX_GAMMA + 1 # dev: unsafe values gamma\n", + "\n", + " # # Initial value of invariant D is that for constant-product invariant\n", + " # x: uint256[N_COINS] = x_unsorted\n", + " # if x[0] < x[1]:\n", + " # x = [x_unsorted[1], x_unsorted[0]]\n", + "\n", + " # assert x[0] > 10**9 - 1 and x[0] < 10**15 * 10**18 + 1 # dev: unsafe values x[0]\n", + " # assert unsafe_div(x[1] * 10**18, x[0]) > 10**14 - 1 # dev: unsafe values x[i] (input)\n", + "\n", + " ANN: uint256 = MAX_A\n", + " gamma: uint256 = MAX_GAMMA\n", + "\n", + " x: uint256[N_COINS] = [10**15 * 10**18, 10**15 * 10**18]\n", + " S: uint256 = unsafe_add(x[0], x[1]) # can unsafe add here because we checked x[0] bounds\n", + " D: uint256 = N_COINS * isqrt(unsafe_mul(x[0], x[1]))\n", + "\n", + " __g1k0: uint256 = gamma + 10**18\n", + " diff: uint256 = 0\n", + "\n", + " K0_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER])\n", + " _g1k0_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER])\n", + " mul1_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER])\n", + " mul2_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER])\n", + " neg_fprime_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER])\n", + " D_plus_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER])\n", + " D_minus_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER])\n", + " D_iter: uint256[MAX_ITER] = empty(uint256[MAX_ITER])\n", + "\n", + " for i in range(MAX_ITER):\n", + " D_prev: uint256 = D\n", + " assert D > 0\n", + " # Unsafe division by D and D_prev is now safe\n", + "\n", + " # K0: uint256 = 10**18\n", + " # for _x in x:\n", + " # K0 = K0 * _x * N_COINS / D\n", + " # collapsed for 2 coins\n", + " K0: uint256 = unsafe_div(unsafe_div((10**18 * N_COINS**2) * x[0], D) * x[1], D)\n", + "\n", + " _g1k0: uint256 = __g1k0\n", + " if _g1k0 > K0:\n", + " _g1k0 = unsafe_add(unsafe_sub(_g1k0, K0), 1) # > 0\n", + " else:\n", + " _g1k0 = unsafe_add(unsafe_sub(K0, _g1k0), 1) # > 0\n", + " # K0 is greater than 0\n", + " # _g1k0 is greater than 0\n", + "\n", + " # D / (A * N**N) * _g1k0**2 / gamma**2\n", + " mul1: uint256 = unsafe_div(unsafe_div(unsafe_div(10**18 * D, gamma) * _g1k0, gamma) * _g1k0 * A_MULTIPLIER, ANN)\n", + "\n", + " # 2*N*K0 / _g1k0\n", + " mul2: uint256 = unsafe_div(((2 * 10**18) * N_COINS) * K0, _g1k0)\n", + "\n", + " # calculate neg_fprime. here K0 > 0 is being validated (safediv).\n", + " neg_fprime: uint256 = (\n", + " S +\n", + " unsafe_div(S * mul2, 10**18) +\n", + " mul1 * N_COINS / K0 -\n", + " unsafe_div(mul2 * D, 10**18)\n", + " )\n", + "\n", + " # D -= f / fprime; neg_fprime safediv being validated\n", + " D_plus: uint256 = D * (neg_fprime + S) / neg_fprime\n", + " D_minus: uint256 = unsafe_div(D * D, neg_fprime)\n", + " if 10**18 > K0:\n", + " D_minus += unsafe_div(unsafe_div(D * unsafe_div(mul1, neg_fprime), 10**18) * unsafe_sub(10**18, K0), K0)\n", + " else:\n", + " D_minus -= unsafe_div(unsafe_div(D * unsafe_div(mul1, neg_fprime), 10**18) * unsafe_sub(K0, 10**18), K0)\n", + "\n", + " if D_plus > D_minus:\n", + " D = unsafe_sub(D_plus, D_minus)\n", + " else:\n", + " D = unsafe_div(unsafe_sub(D_minus, D_plus), 2)\n", + "\n", + " K0_iter[i] = K0\n", + " _g1k0_iter[i] = _g1k0\n", + " mul1_iter[i] = mul1\n", + " mul2_iter[i] = mul2\n", + " neg_fprime_iter[i] = neg_fprime\n", + " D_plus_iter[i] = D_plus\n", + " D_minus_iter[i] = D_minus\n", + " D_iter[i] = D\n", + "\n", + " return K0_iter, _g1k0_iter, mul1_iter, mul2_iter, neg_fprime_iter, D_plus_iter, D_minus_iter, D_iter" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "math_contract = MAXNewton_D.deploy()\n", + "output = math_contract.newton_D()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "K0_iter = output[0]\n", + "_g1k0_iter = output[1]\n", + "mul1_iter = output[2]\n", + "mul2_iter = output[3]\n", + "neg_fprime_iter = output[4]\n", + "D_plus_iter = output[5]\n", + "D_minus_iter = output[6]\n", + "D_iter = output[7]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "255" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "D_iter = output[-1]\n", + "len(D_iter)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}