From c5b32c3bb9da6ccb19f0458d96ce36df0603e86e Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Wed, 22 Nov 2023 10:32:09 +0100 Subject: [PATCH] Install pre-commit via docker --- .dockerignore | 78 + .github/workflows/.pre-commit-config.yaml | 36 +- .github/workflows/main.yaml | 58 +- .gitignore | 20 +- .pre-commit-config.yaml | 52 +- Dockerfile | 26 +- LICENSE | 42 +- README.md | 924 +++---- contracts/interfaces/CurvePool.json | 1066 ++++----- contracts/interfaces/CurvePoolV2.json | 1426 +++++------ contracts/interfaces/ERC20.vy | 296 +-- contracts/interfaces/LiquidityGauge.json | 1668 ++++++------- contracts/interfaces/MainRegistry.json | 1880 +++++++-------- contracts/interfaces/ProxyAdmin.json | 422 ++-- contracts/mainnet/MetaRegistry.vy | 1122 ++++----- contracts/mainnet/abi/AddressProvider.json | 618 ++--- contracts/mainnet/abi/CryptoFactory.json | 1270 +++++----- contracts/mainnet/abi/CryptoRegistry.json | 1202 +++++----- contracts/mainnet/abi/GaugeController.json | 1644 ++++++------- contracts/mainnet/abi/ProxyAdmin.json | 408 ++-- contracts/mainnet/abi/StableFactory.json | 2126 ++++++++--------- contracts/mainnet/abi/StableRegistry.json | 1880 +++++++-------- .../mainnet/registries/BasePoolRegistry.vy | 572 ++--- .../mainnet/registries/CryptoRegistryV1.vy | 1926 +++++++-------- .../registry_handlers/CryptoFactoryHandler.vy | 1464 ++++++------ .../CryptoRegistryHandler.vy | 730 +++--- .../registry_handlers/StableFactoryHandler.vy | 1080 ++++----- .../StableRegistryHandler.vy | 716 +++--- docker-compose.yaml | 25 +- pyproject.toml | 54 +- requirements.in | 16 +- requirements.txt | 416 ++-- scripts/boa_scripts/set_up_registries.py | 304 +-- scripts/change_registry_handler.py | 157 +- scripts/deploy.py | 167 +- scripts/deploy_crypto_registry_handler.py | 45 +- scripts/print_missing.py | 108 +- scripts/setup_metaregistry.py | 645 ++--- setup.cfg | 20 +- tests/conftest.py | 186 +- tests/fixtures/accounts.py | 101 +- tests/fixtures/constants.py | 377 ++- tests/fixtures/contracts.py | 18 +- tests/fixtures/deployments.py | 313 +-- tests/fixtures/functions.py | 65 +- .../api/test_find_pool_for_coins.py | 93 +- .../api/test_get_admin_balances.py | 246 +- .../metaregistry/api/test_get_balances.py | 126 +- .../metaregistry/api/test_get_base_pool.py | 31 +- .../metaregistry/api/test_get_coin_indices.py | 378 ++- .../metaregistry/api/test_get_coins.py | 80 +- .../metaregistry/api/test_get_decimals.py | 88 +- .../mainnet/metaregistry/api/test_get_fees.py | 168 +- .../metaregistry/api/test_get_gauge.py | 273 ++- .../metaregistry/api/test_get_lp_token.py | 78 +- .../metaregistry/api/test_get_n_coins.py | 141 +- .../api/test_get_n_underlying_coins.py | 182 +- .../api/test_get_pool_asset_type.py | 71 +- .../api/test_get_pool_from_lp_token.py | 12 +- .../metaregistry/api/test_get_pool_name.py | 133 +- .../metaregistry/api/test_get_pool_params.py | 130 +- .../api/test_get_underlying_balances.py | 314 ++- .../api/test_get_underlying_coins.py | 312 ++- .../api/test_get_underlying_decimals.py | 193 +- .../api/test_get_virtual_price.py | 332 ++- .../metaregistry/api/test_pool_is_metapool.py | 93 +- .../api/test_pool_is_registered.py | 4 +- .../test_add_remove_update_registry.py | 106 +- .../test_base_registry_tracking.py | 185 +- .../registries/test_add_remove_basepool.py | 284 ++- .../registries/test_add_remove_metapool.py | 615 +++-- .../registries/test_add_remove_pool.py | 470 ++-- tests/utils.py | 82 +- 73 files changed, 16512 insertions(+), 16477 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4d80fd8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,78 @@ +# Git +.gitignore +.gitattributes + + +# CI +.codeclimate.yml +.travis.yml +.taskcluster.yml + +# Docker +docker-compose.yml +Dockerfile +.docker +.dockerignore + +# Byte-compiled / optimized / DLL files +**/__pycache__/ +**/*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +# PyBuilder +target/ + +# Virtual environment +.env +.venv/ +venv/ + +# PyCharm +.idea + +# Python mode for VIM +.ropeproject +**/.ropeproject + +# Vim swap files +**/*.swp + +# VS Code +.vscode/ diff --git a/.github/workflows/.pre-commit-config.yaml b/.github/workflows/.pre-commit-config.yaml index f0da0b1..8da260f 100644 --- a/.github/workflows/.pre-commit-config.yaml +++ b/.github/workflows/.pre-commit-config.yaml @@ -1,18 +1,18 @@ -name: pre-commit - -on: [pull_request, push] - -jobs: - pre-commit: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Python 3.10.13 - uses: actions/setup-python@v4 - with: - python-version: 3.10.13 - - - name: Pre-commit checks - uses: pre-commit/action@v3.0.0 +name: pre-commit + +on: [pull_request, push] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python 3.10.13 + uses: actions/setup-python@v4 + with: + python-version: 3.10.13 + + - name: Pre-commit checks + uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 8e2ea13..95b1827 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -1,29 +1,29 @@ -name: unitary - -on: ["push"] - -jobs: - unitary: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Cache Compiler Installations - uses: actions/cache@v3 - with: - path: ~/.vvm - key: compiler-cache - - - name: Setup Python 3.11 - uses: actions/setup-python@v4 - with: - python-version: 3.11.6 - - - name: Install Requirements - run: pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt - - - name: Run Tests - run: pytest - env: - DRPC_KEY: ${{ secrets.DRPC_KEY }} +name: unitary + +on: ["push"] + +jobs: + unitary: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Cache Compiler Installations + uses: actions/cache@v3 + with: + path: ~/.vvm + key: compiler-cache + + - name: Setup Python 3.11 + uses: actions/setup-python@v4 + with: + python-version: 3.11.6 + + - name: Install Requirements + run: pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt + + - name: Run Tests + run: pytest + env: + DRPC_KEY: ${{ secrets.DRPC_KEY }} diff --git a/.gitignore b/.gitignore index 500de94..3c01ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ -.build -build/ -.python-version -.idea -.pytest_cache -__pycache__/ -.DS_Store -venv/ -bvenv/ -.env \ No newline at end of file +.build +build/ +.python-version +.idea +.pytest_cache +__pycache__/ +.DS_Store +venv/ +bvenv/ +.env diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7d6119c..6083256 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,26 +1,26 @@ -# See https://pre-commit.com for more information -# See https://pre-commit.com/hooks.html for more hooks -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - - repo: https://github.com/psf/black - rev: 23.11.0 - hooks: - - id: black - args: [--line-length=79] - - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 - hooks: - - id: flake8 - - repo: https://github.com/pycqa/isort - rev: 5.12.0 - hooks: - - id: isort - args: ["--profile", "black", --line-length=79] - -default_language_version: - python: python3.10 +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - repo: https://github.com/psf/black + rev: 23.11.0 + hooks: + - id: black + args: [--line-length=79] + - repo: https://github.com/pycqa/flake8 + rev: 6.1.0 + hooks: + - id: flake8 + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort + args: ["--profile", "black", --line-length=79] + +default_language_version: + python: python3.11 diff --git a/Dockerfile b/Dockerfile index 38c6a94..9a5238b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,16 @@ -FROM python:3.11-slim - -WORKDIR /usr/app -RUN pip cache purge -COPY requirements.txt ./ -RUN pip install --upgrade pip && \ - pip install --no-cache-dir -r requirements.txt - -COPY . . -CMD pytest +FROM python:3.11-slim as base + +WORKDIR /usr/app +RUN pip cache purge +COPY requirements.txt ./ +RUN pip install --upgrade pip && \ + pip install --no-cache-dir -r requirements.txt + +FROM base as pre-commit +RUN apt-get update && apt-get install git +COPY . . +CMD pre-commit run --all-files + +FROM base as test +COPY . . +CMD pytest diff --git a/LICENSE b/LICENSE index a796f5f..6670467 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2022 Curve - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2022 Curve + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 6c788ee..15d1482 100644 --- a/README.md +++ b/README.md @@ -1,462 +1,462 @@ -# Curve Metaregistry - -The metaregistry is a [Curve Finance](https://curve.exchange/) Pool Registry Aggregator that consolidates different registries used at Curve Finance for a single chain into a single contract. - -The current version of the MetaRegistry aggregates of the following four child registries: - -Mainnet: - -1. Curve Stable Registry: A registry of custom pool implementations deployed by Curve Core. -2. Curve Stable Factory: A permissionless [StableSwap](https://curve.fi/files/stableswap-paper.pdf) pool factory, which also acts as a registry for pools that its users create. -3. Curve Crypto Registry: A registry of custom CryptoSwap pool implementaions deployed by Curve Core. -4. Curve Crypto Factory: A permissionless [CryptoSwap](https://curve.fi/files/crypto-pools-paper.pdf) pool factory, which also acts as a registry for pools that its users create. - -Each of the child registries are accompanied by a RegistryHandler, which is a contract that wraps around the child registry and enforces the abi implemented in the MetaRegistry. These registry handlers are then added to the MetaRegistry using the `MetaRegistry.add_registry_handler` method. - -In principle, a child registry does not need a registry handler wrapper, if it already conforms to the MetaRegistry's abi standards. However, a wrapper around the child registries can be used to hotfix bugs detected in production when such fixes cannot be introduced to the child registry without significant breaking changes. - -# Who should use the MetaRegistry? - -Integrators find it quite challenging to integrate a protocol into their dapp if there are multiple on-chain registry stored in separate contracts: They do not have intrinsic knowledge in the protocol level to accommodate edge cases and onboard multiple registries. A single source of information that aggregates all registries makes integrations trivial. If you are an integrator looking to integrate Curve, the MetaRegistry is your best friend. - -# The MetaRegistry API - -The MetaRegistry offers an on-chain API for various properties of Curve pools. The various getters in the MetaRegistry are explained in the following. - -#### `MetaRegistry.get_registry_handlers_from_pool` - -Gets registries that a pool has been registered in. Usually, each pool is registered in a single registry. - -``` -In [1]: metaregistry.get_registry_handlers_from_pool("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") -Out[1]:[ - '0xc7D231bC7ff5AC1E0e67244d1A273a79bC762bfB', - '0xfBdA211B53e17e10aa5B5c564F19519258dA05B4', - '0x0000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000', - ... - ] -``` - -#### `MetaRegistry.pool_count` - -Returns the total number of pools under all registries registered in the metaregistry. - -``` -In [1]: metaregistry.pool_count() -Out[1]: 284 -``` - -#### `MetaRegistry.pool_list` - -Returns the address of the pool at the input index `i`. - -``` -In [1]: metaregistry.pool_list(0) -Out[1]: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7" -``` - -#### `MetaRegistry.get_pool_name` - -Returns the name of the pool. - -``` -In [1]: metaregistry.get_pool_name("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") -Out[1]: '3pool' -``` - -#### `MetaRegistry.is_meta` - -Metapools are pools that pair a coin to a base pool comprising of multiple coins. - -An example is the [`LUSD-3CRV`](https://etherscan.io/address/0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca) pool which pairs [Liquity's](https://www.liquity.org/) [`LUSD`](https://etherscan.io/address/0x5f98805a4e8be255a32880fdec7f6728c6568ba0) against [`3CRV`](https://etherscan.io/address/0x6c3f90f043a72fa612cbac8115ee7e52bde6e490), where `3CRV` is a liquidity pool token that represents a share of a pool containing `DAI`, `USDC` and `USDT`: - -``` -In [1]: metaregistry.is_meta("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") -Out[1]: True -``` - -#### `MetaRegistry.get_base_pool` - -In the case of the `LUSD-3CRV` pool example, the pool containing `3CRV` underlying coins is the base pool of the `LUSD-3CRV` pool, which is the [`3pool`](https://etherscan.io/address/0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7): - -``` -In [1]: metaregistry.get_base_pool("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") -Out[1]: '0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7' -``` - -It returns `ZERO_ADDRESS` if the pool has no base pool: - -``` -In [1]: metaregistry.get_base_pool("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") -Out[1]: '0x0000000000000000000000000000000000000000' -``` - -#### `MetaRegistry.get_coins` - -Returns coins in a pool. If the pool is a metapool, it then returns the LP token associated with the base pool, and not the underlying coins. - -``` -In [1]: metaregistry.get_coins("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") -Out[1]: [ - '0x5f98805A4E8be255a32880FDeC7F6728C6568bA0', - '0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490', - ... -] -``` - -#### `MetaRegistry.get_underlying_coins` - -Returns underlying coins in a pool. Returns underlying coins of the base pool if the pool is a metapool. - -``` -In [1]: metaregistry.get_underlying_coins("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") -Out[1]: [ - '0x5f98805A4E8be255a32880FDeC7F6728C6568bA0', - '0x6B175474E89094C44Da98b954EedeAC495271d0F', - '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - '0xdAC17F958D2ee523a2206206994597C13D831ec7', - ... -] -``` - -#### `MetaRegistry.get_n_coins` - -Returns number of coins in a pool. - -``` -In [1]: metaregistry.get_n_coins("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") -Out[1]: 3 -``` - -#### `MetaRegistry.get_n_underlying_coins` - -Returns the total number of underlying coins in a pool. - -``` -In [1]: metaregistry.get_n_underlying_coins("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") -Out[1]: 4 -``` - -#### `MetaRegistry.get_decimals` - -Returns decimals of the coins that are returned by `MetaRegistry.get_coins`. - -``` -In [1]: metaregistry.get_decimals("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") -Out[1]: [18, 6, 6, 0, 0, 0, 0, 0] -``` - -#### `MetaRegistry.get_underlying_decimals` - -Returns decimals of coins returned by `MetaRegistry.get_underlying_coins` - -``` -In [1]: metaregistry.get_underlying_decimals("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") -Out[1]: [18, 18, 6, 6, 0, 0, 0, 0] -``` - -#### `MetaRegistry.get_balances` - -Returns balances of each coin in a Curve pool. - -``` -In [1]: metaregistry.get_balances("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") -Out[1]: [344100999218050094997802859, 339451232552152, 323541886417619, 0, 0, 0, 0, 0] -``` - -#### `MetaRegistry.get_underlying_balances` - -Returns a pool's balances of coins returned by `MetaRegistry.get_underlying_coins`. - -``` -In [25]: populated_metaregistry.get_underlying_balances("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") -Out[25]: [5475800032746048063986567, 18068769367677440019648367, 17824609770086, 16989208807146, ...] -``` - -#### `MetaRegistry.get_admin_balances` - -Returns pool's admin balances. These admin balances accrue per swap, since a part of the fees that are generated by Curve pools go to the admin (an external contract, controlled by the Curve DAO). The amount of fees that go to admin and LPs can be set at the time of pool's creation, and for some pools this can be changed later. - -The balances represent the balances per coin, and retain the coin's precision. - -``` -In [1]: metaregistry.get_admin_balances("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") -Out[1]: [3332213937603257114591, 6607424786, 9725600245, 0, 0, 0, 0, 0] -``` - -#### `MetaRegistry.get_fees` - -Returns fees that a Curve pool charges per swap. The returned fee data is different for StableSwap pools (which just use a single parameter for fees, other than admin fees), than CryptoSwap pools (which use multiple parameters for fees, due to its dynamic fee structure). - -For Stableswap, the getter returns the `fee` per swap as well as the `admin_fee` percentage. For the `3pool`, it shows that the pool charges 1 basis points per swap, 50% of which goes to the DAO. - -``` -In [1]: metaregistry.get_fees("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") -Out[1]: [1000000, 5000000000, 0, 0, 0, 0, 0, 0, 0, 0] -``` - -For CryptoSwap, the getter returns: `fee`, `admin_fee` percentage, `mid_fee` and `out_fee`. The fee is the dynamic fee charged per swap, and depends on the `mid_fee` (fee when the CryptoSwap pool is pegged) and the `out_fee`. For understanding the dynamic fee algorithm, the reader is pointed to the [CryptoSwap Paper](https://curve.fi/files/crypto-pools-paper). - -``` -In [1]: metaregistry.get_fees("0xd51a44d3fae010294c616388b506acda1bfaae46") -Out[1]: [5954883, 5000000000, 5000000, 30000000, 0, 0, 0, 0, 0, 0] -``` - -#### `MetaRegistry.find_pool_for_coins` - -Returns a pool that holds two coins (even if the pool is a metapool). The index in the query returns the index of the list of pools containing the two coins. - -``` -In [1]: metaregistry.find_pool_for_coins( - "0x6B175474E89094C44Da98b954EedeAC495271d0F", - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - 0 - ) -Out[1]: '0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7' - -In [2]: metaregistry.find_pool_for_coins( - "0x6B175474E89094C44Da98b954EedeAC495271d0F", - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - 1 - ) -Out[2]: '0xDeBF20617708857ebe4F679508E7b7863a8A8EeE' -``` - -#### `MetaRegistry.find_pools_for_coins` - -Returns a list of pools that holds two coins (even if the pool is a metapool). - -``` -In [1]: metaregistry.find_pools_for_coins( - "0x6B175474E89094C44Da98b954EedeAC495271d0F", - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - ) -Out[1]: -['0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7', - '0xDeBF20617708857ebe4F679508E7b7863a8A8EeE', - '0x79a8C46DeA5aDa233ABaFFD40F3A0A2B1e5A4F27', - '0xA2B47E3D5c44877cca798226B7B8118F9BFb7A56', - '0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF', - '0x06364f10B501e868329afBc005b3492902d6C763', - '0xA5407eAE9Ba41422680e2e00537571bcC53efBfD', - '0xA5407eAE9Ba41422680e2e00537571bcC53efBfD', - '0x52EA46506B9CC5Ef470C5bf89f17Dc28bB35D85C', - '0x45F783CCE6B7FF23B2ab2D70e416cdb7D6055f51'] -``` - -#### `MetaRegistry.get_coin_indices` - -Given a `_from` coin, a `_to` coin, and a `_pool`, this getter returns coin indices and a boolean that indicates if the coin swap involves an underlying market. In case of a non-metapool, the following is returned: - -``` - -In [1]: metaregistry.get_coin_indices( -"0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", -"0x6B175474E89094C44Da98b954EedeAC495271d0F", -"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" -) -Out[1]: (0, 1, False) - -``` - -If the coin combination involves an underlying market (same coins, but with the `LUSD` pool): - -``` - -In [1]: metaregistry.get_coin_indices( -"0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca", -"0x6B175474E89094C44Da98b954EedeAC495271d0F", -"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" -) -Out[1]: (1, 2, True) - -``` - -#### `MetaRegistry.get_pool_params` - -Returns a pool's parameters. - -For StableSwap, the getter returns the amplification coefficient (`A`) of the pool. - -``` - -In [1]: metaregistry.get_pool_params("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") -Out[1]: [2000, ... ] - -``` - -For CryptoSwap, the getter returns: - -1. Amplification coefficient (`A`) -2. Invariant (`D`) -3. Gamma coefficient (`gamma`) -4. Allowed extra profit -5. Fee gamma -6. Adjustment step -7. MA (moving average) half time - -``` - -In [1]: metaregistry.get_pool_params("0xd51a44d3fae010294c616388b506acda1bfaae46") -Out[1]: [1707629, 257946982336455335322438705, 11809167828997, 2000000000000, 500000000000000, 2000000000000000, 600, ... ] - -``` - -#### `MetaRegistry.get_gauge` - -Gets the gauge that receives `CRV` token inflation for depositing the liquidity pool token of a pool. - -``` - -In [1]: metaregistry.get_gauge("0xd51a44d3fae010294c616388b506acda1bfaae46", 0, 0) -Out[1]: '0xDeFd8FdD20e0f34115C7018CCfb655796F6B2168' - -``` - -#### `MetaRegistry.get_gauge_type` - -Gets the gauge type of the gauge associated with a pool. - -``` - -In [1]: metaregistry.get_gauge_type("0xd51a44d3fae010294c616388b506acda1bfaae46", 0, 0) -Out[1]: 5 - -``` - -#### `MetaRegistry.get_lp_token` - -Gets the address of the liquidity pool token minted by a pool. - -``` - -In [1]: metaregistry.get_lp_token("0xd51a44d3fae010294c616388b506acda1bfaae46") -Out[1]: '0xc4AD29ba4B3c580e6D59105FFf484999997675Ff' - -``` - -#### `MetaRegistry.get_pool_asset_type` - -Gets the asset type of a pool. `0` = `USD`, `1` = `ETH`, `2` = `BTC`, `3` = Other, `4` = CryptoPool token. The asset type is a property of StableSwaps, and is not enforced in CryptoSwap pools (which always return `4`). - -StableSwap pool example for `LUSD-3CRV` pool which is a `USD` stablecoin pool: - -``` - -In [1]: metaregistry.get_pool_asset_type("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") -Out[1]: 0 - -``` - -CryptoSwap pool example: - -``` - -In [1]: metaregistry.get_pool_asset_type("0xd51a44d3fae010294c616388b506acda1bfaae46") -Out[1]: 4 - -``` - -#### `MetaRegistry.get_pool_from_lp_token` - -Gets the pool associated with a liquidity pool token. - -``` - -In [1]: metaregistry.get_pool_from_lp_token("0xc4AD29ba4B3c580e6D59105FFf484999997675Ff") -Out[1]: '0xD51a44d3FaE010294C616388b506AcdA1bfAAE46' - -``` - -#### `MetaRegistry.get_virtual_price_from_lp_token` - -Gets a token's virtual price. The virtual price of any pool begins with `1`, and increases as the pool accrues fees. This number constantly increases for StableSwap pools, unless the pool's amplification coefficient changes. For CryptoSwap pools, there are moments when the virtual price can go down (admin fee claims, changes to pool's parameters). - -``` - -In [1]: metaregistry.get_virtual_price_from_lp_token("0xc4AD29ba4B3c580e6D59105FFf484999997675Ff") -Out[1]: 1020841390601246610 - -``` - -# Setup - -Set up the python environment using the following steps: - -``` - -> python -m venv venv -> source ./venv/bin/activate -> python -m pip install --upgrade pip -> pip install -r ./requirements.txt - -``` - -This project uses `titanoboa`. - -### Testing - -To run tests in interactive mode, please do the following: - -``` - -> ape test -I -s - -``` - -# Deployment - -First, set up your account in Ape. If you're using an EOA that is a cold wallet, please do: - -``` -> ape accounts import -``` - -This will prompt you for a private key. If your account is a ledger account, then follow: - -``` -> ape ledger add -``` - -To deploy, please use the following command (example deployment in mainnet-fork): - -``` - -> ape run scripts/deploy.py main --network ethereum:mainnet-fork --account - -``` - -## Adding Registries - -The following command simulates metaregistry setup. For Prod transactions, set network to anything that is not -`ethereum:mainnet-fork` (so: `ethereum:mainnet:geth` or `ethereum:mainnet:alchemy` is fine.) - -``` - -> ape run scripts/setup_metaregistry.py main --network ethereum:mainnet-fork --account - -``` - -#### Deployments - -Ethereum Mainnet: - - -`base_pool_registry`: [0xDE3eAD9B2145bBA2EB74007e58ED07308716B725](https://etherscan.io/address/0xDE3eAD9B2145bBA2EB74007e58ED07308716B725#code) - -`crypto_registry`: [0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0](https://etherscan.io/address/0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0#code) - -`stable_registry_handler`: [0x46a8a9CF4Fc8e99EC3A14558ACABC1D93A27de68](https://etherscan.io/address/0x46a8a9CF4Fc8e99EC3A14558ACABC1D93A27de68#code) - -`stable_factory_handler`: [0x127db66E7F0b16470Bec194d0f496F9Fa065d0A9](https://etherscan.io/address/0x127db66E7F0b16470Bec194d0f496F9Fa065d0A9#code) - -`crypto_registry_handler`: [0x22ceb131d3170f9f2FeA6b4b1dE1B45fcfC86E56](https://etherscan.io/address/0x22ceb131d3170f9f2FeA6b4b1dE1B45fcfC86E56#code) - -`crypto_factory_handler`: [0xC4F389020002396143B863F6325aA6ae481D19CE](https://etherscan.io/address/0xC4F389020002396143B863F6325aA6ae481D19CE#code) - -`metaregistry`: [0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC](https://etherscan.io/address/0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC#code) - -### License - -(c) Curve.Fi, 2023 - [All rights reserved](LICENSE). +# Curve Metaregistry + +The metaregistry is a [Curve Finance](https://curve.exchange/) Pool Registry Aggregator that consolidates different registries used at Curve Finance for a single chain into a single contract. + +The current version of the MetaRegistry aggregates of the following four child registries: + +Mainnet: + +1. Curve Stable Registry: A registry of custom pool implementations deployed by Curve Core. +2. Curve Stable Factory: A permissionless [StableSwap](https://curve.fi/files/stableswap-paper.pdf) pool factory, which also acts as a registry for pools that its users create. +3. Curve Crypto Registry: A registry of custom CryptoSwap pool implementaions deployed by Curve Core. +4. Curve Crypto Factory: A permissionless [CryptoSwap](https://curve.fi/files/crypto-pools-paper.pdf) pool factory, which also acts as a registry for pools that its users create. + +Each of the child registries are accompanied by a RegistryHandler, which is a contract that wraps around the child registry and enforces the abi implemented in the MetaRegistry. These registry handlers are then added to the MetaRegistry using the `MetaRegistry.add_registry_handler` method. + +In principle, a child registry does not need a registry handler wrapper, if it already conforms to the MetaRegistry's abi standards. However, a wrapper around the child registries can be used to hotfix bugs detected in production when such fixes cannot be introduced to the child registry without significant breaking changes. + +# Who should use the MetaRegistry? + +Integrators find it quite challenging to integrate a protocol into their dapp if there are multiple on-chain registry stored in separate contracts: They do not have intrinsic knowledge in the protocol level to accommodate edge cases and onboard multiple registries. A single source of information that aggregates all registries makes integrations trivial. If you are an integrator looking to integrate Curve, the MetaRegistry is your best friend. + +# The MetaRegistry API + +The MetaRegistry offers an on-chain API for various properties of Curve pools. The various getters in the MetaRegistry are explained in the following. + +#### `MetaRegistry.get_registry_handlers_from_pool` + +Gets registries that a pool has been registered in. Usually, each pool is registered in a single registry. + +``` +In [1]: metaregistry.get_registry_handlers_from_pool("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") +Out[1]:[ + '0xc7D231bC7ff5AC1E0e67244d1A273a79bC762bfB', + '0xfBdA211B53e17e10aa5B5c564F19519258dA05B4', + '0x0000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000', + ... + ] +``` + +#### `MetaRegistry.pool_count` + +Returns the total number of pools under all registries registered in the metaregistry. + +``` +In [1]: metaregistry.pool_count() +Out[1]: 284 +``` + +#### `MetaRegistry.pool_list` + +Returns the address of the pool at the input index `i`. + +``` +In [1]: metaregistry.pool_list(0) +Out[1]: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7" +``` + +#### `MetaRegistry.get_pool_name` + +Returns the name of the pool. + +``` +In [1]: metaregistry.get_pool_name("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") +Out[1]: '3pool' +``` + +#### `MetaRegistry.is_meta` + +Metapools are pools that pair a coin to a base pool comprising of multiple coins. + +An example is the [`LUSD-3CRV`](https://etherscan.io/address/0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca) pool which pairs [Liquity's](https://www.liquity.org/) [`LUSD`](https://etherscan.io/address/0x5f98805a4e8be255a32880fdec7f6728c6568ba0) against [`3CRV`](https://etherscan.io/address/0x6c3f90f043a72fa612cbac8115ee7e52bde6e490), where `3CRV` is a liquidity pool token that represents a share of a pool containing `DAI`, `USDC` and `USDT`: + +``` +In [1]: metaregistry.is_meta("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") +Out[1]: True +``` + +#### `MetaRegistry.get_base_pool` + +In the case of the `LUSD-3CRV` pool example, the pool containing `3CRV` underlying coins is the base pool of the `LUSD-3CRV` pool, which is the [`3pool`](https://etherscan.io/address/0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7): + +``` +In [1]: metaregistry.get_base_pool("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") +Out[1]: '0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7' +``` + +It returns `ZERO_ADDRESS` if the pool has no base pool: + +``` +In [1]: metaregistry.get_base_pool("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") +Out[1]: '0x0000000000000000000000000000000000000000' +``` + +#### `MetaRegistry.get_coins` + +Returns coins in a pool. If the pool is a metapool, it then returns the LP token associated with the base pool, and not the underlying coins. + +``` +In [1]: metaregistry.get_coins("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") +Out[1]: [ + '0x5f98805A4E8be255a32880FDeC7F6728C6568bA0', + '0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490', + ... +] +``` + +#### `MetaRegistry.get_underlying_coins` + +Returns underlying coins in a pool. Returns underlying coins of the base pool if the pool is a metapool. + +``` +In [1]: metaregistry.get_underlying_coins("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") +Out[1]: [ + '0x5f98805A4E8be255a32880FDeC7F6728C6568bA0', + '0x6B175474E89094C44Da98b954EedeAC495271d0F', + '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + '0xdAC17F958D2ee523a2206206994597C13D831ec7', + ... +] +``` + +#### `MetaRegistry.get_n_coins` + +Returns number of coins in a pool. + +``` +In [1]: metaregistry.get_n_coins("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") +Out[1]: 3 +``` + +#### `MetaRegistry.get_n_underlying_coins` + +Returns the total number of underlying coins in a pool. + +``` +In [1]: metaregistry.get_n_underlying_coins("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") +Out[1]: 4 +``` + +#### `MetaRegistry.get_decimals` + +Returns decimals of the coins that are returned by `MetaRegistry.get_coins`. + +``` +In [1]: metaregistry.get_decimals("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") +Out[1]: [18, 6, 6, 0, 0, 0, 0, 0] +``` + +#### `MetaRegistry.get_underlying_decimals` + +Returns decimals of coins returned by `MetaRegistry.get_underlying_coins` + +``` +In [1]: metaregistry.get_underlying_decimals("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") +Out[1]: [18, 18, 6, 6, 0, 0, 0, 0] +``` + +#### `MetaRegistry.get_balances` + +Returns balances of each coin in a Curve pool. + +``` +In [1]: metaregistry.get_balances("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") +Out[1]: [344100999218050094997802859, 339451232552152, 323541886417619, 0, 0, 0, 0, 0] +``` + +#### `MetaRegistry.get_underlying_balances` + +Returns a pool's balances of coins returned by `MetaRegistry.get_underlying_coins`. + +``` +In [25]: populated_metaregistry.get_underlying_balances("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") +Out[25]: [5475800032746048063986567, 18068769367677440019648367, 17824609770086, 16989208807146, ...] +``` + +#### `MetaRegistry.get_admin_balances` + +Returns pool's admin balances. These admin balances accrue per swap, since a part of the fees that are generated by Curve pools go to the admin (an external contract, controlled by the Curve DAO). The amount of fees that go to admin and LPs can be set at the time of pool's creation, and for some pools this can be changed later. + +The balances represent the balances per coin, and retain the coin's precision. + +``` +In [1]: metaregistry.get_admin_balances("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") +Out[1]: [3332213937603257114591, 6607424786, 9725600245, 0, 0, 0, 0, 0] +``` + +#### `MetaRegistry.get_fees` + +Returns fees that a Curve pool charges per swap. The returned fee data is different for StableSwap pools (which just use a single parameter for fees, other than admin fees), than CryptoSwap pools (which use multiple parameters for fees, due to its dynamic fee structure). + +For Stableswap, the getter returns the `fee` per swap as well as the `admin_fee` percentage. For the `3pool`, it shows that the pool charges 1 basis points per swap, 50% of which goes to the DAO. + +``` +In [1]: metaregistry.get_fees("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") +Out[1]: [1000000, 5000000000, 0, 0, 0, 0, 0, 0, 0, 0] +``` + +For CryptoSwap, the getter returns: `fee`, `admin_fee` percentage, `mid_fee` and `out_fee`. The fee is the dynamic fee charged per swap, and depends on the `mid_fee` (fee when the CryptoSwap pool is pegged) and the `out_fee`. For understanding the dynamic fee algorithm, the reader is pointed to the [CryptoSwap Paper](https://curve.fi/files/crypto-pools-paper). + +``` +In [1]: metaregistry.get_fees("0xd51a44d3fae010294c616388b506acda1bfaae46") +Out[1]: [5954883, 5000000000, 5000000, 30000000, 0, 0, 0, 0, 0, 0] +``` + +#### `MetaRegistry.find_pool_for_coins` + +Returns a pool that holds two coins (even if the pool is a metapool). The index in the query returns the index of the list of pools containing the two coins. + +``` +In [1]: metaregistry.find_pool_for_coins( + "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + 0 + ) +Out[1]: '0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7' + +In [2]: metaregistry.find_pool_for_coins( + "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + 1 + ) +Out[2]: '0xDeBF20617708857ebe4F679508E7b7863a8A8EeE' +``` + +#### `MetaRegistry.find_pools_for_coins` + +Returns a list of pools that holds two coins (even if the pool is a metapool). + +``` +In [1]: metaregistry.find_pools_for_coins( + "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + ) +Out[1]: +['0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7', + '0xDeBF20617708857ebe4F679508E7b7863a8A8EeE', + '0x79a8C46DeA5aDa233ABaFFD40F3A0A2B1e5A4F27', + '0xA2B47E3D5c44877cca798226B7B8118F9BFb7A56', + '0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF', + '0x06364f10B501e868329afBc005b3492902d6C763', + '0xA5407eAE9Ba41422680e2e00537571bcC53efBfD', + '0xA5407eAE9Ba41422680e2e00537571bcC53efBfD', + '0x52EA46506B9CC5Ef470C5bf89f17Dc28bB35D85C', + '0x45F783CCE6B7FF23B2ab2D70e416cdb7D6055f51'] +``` + +#### `MetaRegistry.get_coin_indices` + +Given a `_from` coin, a `_to` coin, and a `_pool`, this getter returns coin indices and a boolean that indicates if the coin swap involves an underlying market. In case of a non-metapool, the following is returned: + +``` + +In [1]: metaregistry.get_coin_indices( +"0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", +"0x6B175474E89094C44Da98b954EedeAC495271d0F", +"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" +) +Out[1]: (0, 1, False) + +``` + +If the coin combination involves an underlying market (same coins, but with the `LUSD` pool): + +``` + +In [1]: metaregistry.get_coin_indices( +"0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca", +"0x6B175474E89094C44Da98b954EedeAC495271d0F", +"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" +) +Out[1]: (1, 2, True) + +``` + +#### `MetaRegistry.get_pool_params` + +Returns a pool's parameters. + +For StableSwap, the getter returns the amplification coefficient (`A`) of the pool. + +``` + +In [1]: metaregistry.get_pool_params("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") +Out[1]: [2000, ... ] + +``` + +For CryptoSwap, the getter returns: + +1. Amplification coefficient (`A`) +2. Invariant (`D`) +3. Gamma coefficient (`gamma`) +4. Allowed extra profit +5. Fee gamma +6. Adjustment step +7. MA (moving average) half time + +``` + +In [1]: metaregistry.get_pool_params("0xd51a44d3fae010294c616388b506acda1bfaae46") +Out[1]: [1707629, 257946982336455335322438705, 11809167828997, 2000000000000, 500000000000000, 2000000000000000, 600, ... ] + +``` + +#### `MetaRegistry.get_gauge` + +Gets the gauge that receives `CRV` token inflation for depositing the liquidity pool token of a pool. + +``` + +In [1]: metaregistry.get_gauge("0xd51a44d3fae010294c616388b506acda1bfaae46", 0, 0) +Out[1]: '0xDeFd8FdD20e0f34115C7018CCfb655796F6B2168' + +``` + +#### `MetaRegistry.get_gauge_type` + +Gets the gauge type of the gauge associated with a pool. + +``` + +In [1]: metaregistry.get_gauge_type("0xd51a44d3fae010294c616388b506acda1bfaae46", 0, 0) +Out[1]: 5 + +``` + +#### `MetaRegistry.get_lp_token` + +Gets the address of the liquidity pool token minted by a pool. + +``` + +In [1]: metaregistry.get_lp_token("0xd51a44d3fae010294c616388b506acda1bfaae46") +Out[1]: '0xc4AD29ba4B3c580e6D59105FFf484999997675Ff' + +``` + +#### `MetaRegistry.get_pool_asset_type` + +Gets the asset type of a pool. `0` = `USD`, `1` = `ETH`, `2` = `BTC`, `3` = Other, `4` = CryptoPool token. The asset type is a property of StableSwaps, and is not enforced in CryptoSwap pools (which always return `4`). + +StableSwap pool example for `LUSD-3CRV` pool which is a `USD` stablecoin pool: + +``` + +In [1]: metaregistry.get_pool_asset_type("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca") +Out[1]: 0 + +``` + +CryptoSwap pool example: + +``` + +In [1]: metaregistry.get_pool_asset_type("0xd51a44d3fae010294c616388b506acda1bfaae46") +Out[1]: 4 + +``` + +#### `MetaRegistry.get_pool_from_lp_token` + +Gets the pool associated with a liquidity pool token. + +``` + +In [1]: metaregistry.get_pool_from_lp_token("0xc4AD29ba4B3c580e6D59105FFf484999997675Ff") +Out[1]: '0xD51a44d3FaE010294C616388b506AcdA1bfAAE46' + +``` + +#### `MetaRegistry.get_virtual_price_from_lp_token` + +Gets a token's virtual price. The virtual price of any pool begins with `1`, and increases as the pool accrues fees. This number constantly increases for StableSwap pools, unless the pool's amplification coefficient changes. For CryptoSwap pools, there are moments when the virtual price can go down (admin fee claims, changes to pool's parameters). + +``` + +In [1]: metaregistry.get_virtual_price_from_lp_token("0xc4AD29ba4B3c580e6D59105FFf484999997675Ff") +Out[1]: 1020841390601246610 + +``` + +# Setup + +Set up the python environment using the following steps: + +``` + +> python -m venv venv +> source ./venv/bin/activate +> python -m pip install --upgrade pip +> pip install -r ./requirements.txt + +``` + +This project uses `titanoboa`. + +### Testing + +To run tests in interactive mode, please do the following: + +``` + +> ape test -I -s + +``` + +# Deployment + +First, set up your account in Ape. If you're using an EOA that is a cold wallet, please do: + +``` +> ape accounts import +``` + +This will prompt you for a private key. If your account is a ledger account, then follow: + +``` +> ape ledger add +``` + +To deploy, please use the following command (example deployment in mainnet-fork): + +``` + +> ape run scripts/deploy.py main --network ethereum:mainnet-fork --account + +``` + +## Adding Registries + +The following command simulates metaregistry setup. For Prod transactions, set network to anything that is not +`ethereum:mainnet-fork` (so: `ethereum:mainnet:geth` or `ethereum:mainnet:alchemy` is fine.) + +``` + +> ape run scripts/setup_metaregistry.py main --network ethereum:mainnet-fork --account + +``` + +#### Deployments + +Ethereum Mainnet: + + +`base_pool_registry`: [0xDE3eAD9B2145bBA2EB74007e58ED07308716B725](https://etherscan.io/address/0xDE3eAD9B2145bBA2EB74007e58ED07308716B725#code) + +`crypto_registry`: [0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0](https://etherscan.io/address/0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0#code) + +`stable_registry_handler`: [0x46a8a9CF4Fc8e99EC3A14558ACABC1D93A27de68](https://etherscan.io/address/0x46a8a9CF4Fc8e99EC3A14558ACABC1D93A27de68#code) + +`stable_factory_handler`: [0x127db66E7F0b16470Bec194d0f496F9Fa065d0A9](https://etherscan.io/address/0x127db66E7F0b16470Bec194d0f496F9Fa065d0A9#code) + +`crypto_registry_handler`: [0x22ceb131d3170f9f2FeA6b4b1dE1B45fcfC86E56](https://etherscan.io/address/0x22ceb131d3170f9f2FeA6b4b1dE1B45fcfC86E56#code) + +`crypto_factory_handler`: [0xC4F389020002396143B863F6325aA6ae481D19CE](https://etherscan.io/address/0xC4F389020002396143B863F6325aA6ae481D19CE#code) + +`metaregistry`: [0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC](https://etherscan.io/address/0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC#code) + +### License + +(c) Curve.Fi, 2023 - [All rights reserved](LICENSE). diff --git a/contracts/interfaces/CurvePool.json b/contracts/interfaces/CurvePool.json index f7b36e5..44403f6 100644 --- a/contracts/interfaces/CurvePool.json +++ b/contracts/interfaces/CurvePool.json @@ -1,533 +1,533 @@ -[ - { - "name": "Transfer", - "inputs": [ - { "name": "sender", "type": "address", "indexed": true }, - { "name": "receiver", "type": "address", "indexed": true }, - { "name": "value", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "Approval", - "inputs": [ - { "name": "owner", "type": "address", "indexed": true }, - { "name": "spender", "type": "address", "indexed": true }, - { "name": "value", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "TokenExchange", - "inputs": [ - { "name": "buyer", "type": "address", "indexed": true }, - { "name": "sold_id", "type": "int128", "indexed": false }, - { "name": "tokens_sold", "type": "uint256", "indexed": false }, - { "name": "bought_id", "type": "int128", "indexed": false }, - { "name": "tokens_bought", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "TokenExchangeUnderlying", - "inputs": [ - { "name": "buyer", "type": "address", "indexed": true }, - { "name": "sold_id", "type": "int128", "indexed": false }, - { "name": "tokens_sold", "type": "uint256", "indexed": false }, - { "name": "bought_id", "type": "int128", "indexed": false }, - { "name": "tokens_bought", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "AddLiquidity", - "inputs": [ - { "name": "provider", "type": "address", "indexed": true }, - { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, - { "name": "fees", "type": "uint256[2]", "indexed": false }, - { "name": "invariant", "type": "uint256", "indexed": false }, - { "name": "token_supply", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidity", - "inputs": [ - { "name": "provider", "type": "address", "indexed": true }, - { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, - { "name": "fees", "type": "uint256[2]", "indexed": false }, - { "name": "token_supply", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidityOne", - "inputs": [ - { "name": "provider", "type": "address", "indexed": true }, - { "name": "token_amount", "type": "uint256", "indexed": false }, - { "name": "coin_amount", "type": "uint256", "indexed": false }, - { "name": "token_supply", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidityImbalance", - "inputs": [ - { "name": "provider", "type": "address", "indexed": true }, - { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, - { "name": "fees", "type": "uint256[2]", "indexed": false }, - { "name": "invariant", "type": "uint256", "indexed": false }, - { "name": "token_supply", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RampA", - "inputs": [ - { "name": "old_A", "type": "uint256", "indexed": false }, - { "name": "new_A", "type": "uint256", "indexed": false }, - { "name": "initial_time", "type": "uint256", "indexed": false }, - { "name": "future_time", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StopRampA", - "inputs": [ - { "name": "A", "type": "uint256", "indexed": false }, - { "name": "t", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { "stateMutability": "nonpayable", "type": "constructor", "inputs": [], "outputs": [] }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "initialize", - "inputs": [ - { "name": "_name", "type": "string" }, - { "name": "_symbol", "type": "string" }, - { "name": "_coin", "type": "address" }, - { "name": "_rate_multiplier", "type": "uint256" }, - { "name": "_A", "type": "uint256" }, - { "name": "_fee", "type": "uint256" } - ], - "outputs": [], - "gas": 450772 - }, - { - "stateMutability": "view", - "type": "function", - "name": "decimals", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 318 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "transfer", - "inputs": [ - { "name": "_to", "type": "address" }, - { "name": "_value", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "bool" }], - "gas": 77977 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "transferFrom", - "inputs": [ - { "name": "_from", "type": "address" }, - { "name": "_to", "type": "address" }, - { "name": "_value", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "bool" }], - "gas": 115912 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "approve", - "inputs": [ - { "name": "_spender", "type": "address" }, - { "name": "_value", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "bool" }], - "gas": 37851 - }, - { - "stateMutability": "view", - "type": "function", - "name": "admin_fee", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 438 - }, - { - "stateMutability": "view", - "type": "function", - "name": "A", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 10704 - }, - { - "stateMutability": "view", - "type": "function", - "name": "A_precise", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 10666 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_virtual_price", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 1023280 - }, - { - "stateMutability": "view", - "type": "function", - "name": "calc_token_amount", - "inputs": [ - { "name": "_amounts", "type": "uint256[2]" }, - { "name": "_is_deposit", "type": "bool" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4029742 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_liquidity", - "inputs": [ - { "name": "_amounts", "type": "uint256[2]" }, - { "name": "_min_mint_amount", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_liquidity", - "inputs": [ - { "name": "_amounts", "type": "uint256[2]" }, - { "name": "_min_mint_amount", "type": "uint256" }, - { "name": "_receiver", "type": "address" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_dy", - "inputs": [ - { "name": "i", "type": "int128" }, - { "name": "j", "type": "int128" }, - { "name": "dx", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 2466478 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_dy_underlying", - "inputs": [ - { "name": "i", "type": "int128" }, - { "name": "j", "type": "int128" }, - { "name": "dx", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 2475029 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "exchange", - "inputs": [ - { "name": "i", "type": "int128" }, - { "name": "j", "type": "int128" }, - { "name": "_dx", "type": "uint256" }, - { "name": "_min_dy", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "exchange", - "inputs": [ - { "name": "i", "type": "int128" }, - { "name": "j", "type": "int128" }, - { "name": "_dx", "type": "uint256" }, - { "name": "_min_dy", "type": "uint256" }, - { "name": "_receiver", "type": "address" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "exchange_underlying", - "inputs": [ - { "name": "i", "type": "int128" }, - { "name": "j", "type": "int128" }, - { "name": "_dx", "type": "uint256" }, - { "name": "_min_dy", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "exchange_underlying", - "inputs": [ - { "name": "i", "type": "int128" }, - { "name": "j", "type": "int128" }, - { "name": "_dx", "type": "uint256" }, - { "name": "_min_dy", "type": "uint256" }, - { "name": "_receiver", "type": "address" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity", - "inputs": [ - { "name": "_burn_amount", "type": "uint256" }, - { "name": "_min_amounts", "type": "uint256[2]" } - ], - "outputs": [{ "name": "", "type": "uint256[2]" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity", - "inputs": [ - { "name": "_burn_amount", "type": "uint256" }, - { "name": "_min_amounts", "type": "uint256[2]" }, - { "name": "_receiver", "type": "address" } - ], - "outputs": [{ "name": "", "type": "uint256[2]" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity_imbalance", - "inputs": [ - { "name": "_amounts", "type": "uint256[2]" }, - { "name": "_max_burn_amount", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity_imbalance", - "inputs": [ - { "name": "_amounts", "type": "uint256[2]" }, - { "name": "_max_burn_amount", "type": "uint256" }, - { "name": "_receiver", "type": "address" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "view", - "type": "function", - "name": "calc_withdraw_one_coin", - "inputs": [ - { "name": "_burn_amount", "type": "uint256" }, - { "name": "i", "type": "int128" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 1130 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity_one_coin", - "inputs": [ - { "name": "_burn_amount", "type": "uint256" }, - { "name": "i", "type": "int128" }, - { "name": "_min_received", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity_one_coin", - "inputs": [ - { "name": "_burn_amount", "type": "uint256" }, - { "name": "i", "type": "int128" }, - { "name": "_min_received", "type": "uint256" }, - { "name": "_receiver", "type": "address" } - ], - "outputs": [{ "name": "", "type": "uint256" }] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "ramp_A", - "inputs": [ - { "name": "_future_A", "type": "uint256" }, - { "name": "_future_time", "type": "uint256" } - ], - "outputs": [], - "gas": 162101 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "stop_ramp_A", - "inputs": [], - "outputs": [], - "gas": 157565 - }, - { - "stateMutability": "view", - "type": "function", - "name": "admin_balances", - "inputs": [{ "name": "i", "type": "uint256" }], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 7770 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "withdraw_admin_fees", - "inputs": [], - "outputs": [], - "gas": 40657 - }, - { - "stateMutability": "view", - "type": "function", - "name": "coins", - "inputs": [{ "name": "arg0", "type": "uint256" }], - "outputs": [{ "name": "", "type": "address" }], - "gas": 3123 - }, - { - "stateMutability": "view", - "type": "function", - "name": "balances", - "inputs": [{ "name": "arg0", "type": "uint256" }], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3153 - }, - { - "stateMutability": "view", - "type": "function", - "name": "fee", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3138 - }, - { - "stateMutability": "view", - "type": "function", - "name": "initial_A", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3168 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_A", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3198 - }, - { - "stateMutability": "view", - "type": "function", - "name": "initial_A_time", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3228 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_A_time", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3258 - }, - { - "stateMutability": "view", - "type": "function", - "name": "name", - "inputs": [], - "outputs": [{ "name": "", "type": "string" }], - "gas": 13518 - }, - { - "stateMutability": "view", - "type": "function", - "name": "symbol", - "inputs": [], - "outputs": [{ "name": "", "type": "string" }], - "gas": 11271 - }, - { - "stateMutability": "view", - "type": "function", - "name": "balanceOf", - "inputs": [{ "name": "arg0", "type": "address" }], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3563 - }, - { - "stateMutability": "view", - "type": "function", - "name": "allowance", - "inputs": [ - { "name": "arg0", "type": "address" }, - { "name": "arg1", "type": "address" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3808 - }, - { - "stateMutability": "view", - "type": "function", - "name": "totalSupply", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3408 - }, - { - "name":"base_pool", - "outputs":[ - { - "type":"address", - "name":"" - } - ], - "inputs":[ - - ], - "stateMutability":"view", - "type":"function", - "gas":2321 - } -] +[ + { + "name": "Transfer", + "inputs": [ + { "name": "sender", "type": "address", "indexed": true }, + { "name": "receiver", "type": "address", "indexed": true }, + { "name": "value", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "Approval", + "inputs": [ + { "name": "owner", "type": "address", "indexed": true }, + { "name": "spender", "type": "address", "indexed": true }, + { "name": "value", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "TokenExchange", + "inputs": [ + { "name": "buyer", "type": "address", "indexed": true }, + { "name": "sold_id", "type": "int128", "indexed": false }, + { "name": "tokens_sold", "type": "uint256", "indexed": false }, + { "name": "bought_id", "type": "int128", "indexed": false }, + { "name": "tokens_bought", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "TokenExchangeUnderlying", + "inputs": [ + { "name": "buyer", "type": "address", "indexed": true }, + { "name": "sold_id", "type": "int128", "indexed": false }, + { "name": "tokens_sold", "type": "uint256", "indexed": false }, + { "name": "bought_id", "type": "int128", "indexed": false }, + { "name": "tokens_bought", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, + { "name": "fees", "type": "uint256[2]", "indexed": false }, + { "name": "invariant", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, + { "name": "fees", "type": "uint256[2]", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityOne", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amount", "type": "uint256", "indexed": false }, + { "name": "coin_amount", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityImbalance", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, + { "name": "fees", "type": "uint256[2]", "indexed": false }, + { "name": "invariant", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RampA", + "inputs": [ + { "name": "old_A", "type": "uint256", "indexed": false }, + { "name": "new_A", "type": "uint256", "indexed": false }, + { "name": "initial_time", "type": "uint256", "indexed": false }, + { "name": "future_time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StopRampA", + "inputs": [ + { "name": "A", "type": "uint256", "indexed": false }, + { "name": "t", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { "stateMutability": "nonpayable", "type": "constructor", "inputs": [], "outputs": [] }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "initialize", + "inputs": [ + { "name": "_name", "type": "string" }, + { "name": "_symbol", "type": "string" }, + { "name": "_coin", "type": "address" }, + { "name": "_rate_multiplier", "type": "uint256" }, + { "name": "_A", "type": "uint256" }, + { "name": "_fee", "type": "uint256" } + ], + "outputs": [], + "gas": 450772 + }, + { + "stateMutability": "view", + "type": "function", + "name": "decimals", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 318 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "transfer", + "inputs": [ + { "name": "_to", "type": "address" }, + { "name": "_value", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "bool" }], + "gas": 77977 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "transferFrom", + "inputs": [ + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" }, + { "name": "_value", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "bool" }], + "gas": 115912 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "approve", + "inputs": [ + { "name": "_spender", "type": "address" }, + { "name": "_value", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "bool" }], + "gas": 37851 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 438 + }, + { + "stateMutability": "view", + "type": "function", + "name": "A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 10704 + }, + { + "stateMutability": "view", + "type": "function", + "name": "A_precise", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 10666 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 1023280 + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_token_amount", + "inputs": [ + { "name": "_amounts", "type": "uint256[2]" }, + { "name": "_is_deposit", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4029742 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "_amounts", "type": "uint256[2]" }, + { "name": "_min_mint_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "_amounts", "type": "uint256[2]" }, + { "name": "_min_mint_amount", "type": "uint256" }, + { "name": "_receiver", "type": "address" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_dy", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 2466478 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_dy_underlying", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 2475029 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "exchange", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "_dx", "type": "uint256" }, + { "name": "_min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "exchange", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "_dx", "type": "uint256" }, + { "name": "_min_dy", "type": "uint256" }, + { "name": "_receiver", "type": "address" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "exchange_underlying", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "_dx", "type": "uint256" }, + { "name": "_min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "exchange_underlying", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "_dx", "type": "uint256" }, + { "name": "_min_dy", "type": "uint256" }, + { "name": "_receiver", "type": "address" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_burn_amount", "type": "uint256" }, + { "name": "_min_amounts", "type": "uint256[2]" } + ], + "outputs": [{ "name": "", "type": "uint256[2]" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_burn_amount", "type": "uint256" }, + { "name": "_min_amounts", "type": "uint256[2]" }, + { "name": "_receiver", "type": "address" } + ], + "outputs": [{ "name": "", "type": "uint256[2]" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_imbalance", + "inputs": [ + { "name": "_amounts", "type": "uint256[2]" }, + { "name": "_max_burn_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_imbalance", + "inputs": [ + { "name": "_amounts", "type": "uint256[2]" }, + { "name": "_max_burn_amount", "type": "uint256" }, + { "name": "_receiver", "type": "address" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_withdraw_one_coin", + "inputs": [ + { "name": "_burn_amount", "type": "uint256" }, + { "name": "i", "type": "int128" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 1130 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "_burn_amount", "type": "uint256" }, + { "name": "i", "type": "int128" }, + { "name": "_min_received", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "_burn_amount", "type": "uint256" }, + { "name": "i", "type": "int128" }, + { "name": "_min_received", "type": "uint256" }, + { "name": "_receiver", "type": "address" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "ramp_A", + "inputs": [ + { "name": "_future_A", "type": "uint256" }, + { "name": "_future_time", "type": "uint256" } + ], + "outputs": [], + "gas": 162101 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "stop_ramp_A", + "inputs": [], + "outputs": [], + "gas": 157565 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_balances", + "inputs": [{ "name": "i", "type": "uint256" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 7770 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "withdraw_admin_fees", + "inputs": [], + "outputs": [], + "gas": 40657 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coins", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3123 + }, + { + "stateMutability": "view", + "type": "function", + "name": "balances", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3153 + }, + { + "stateMutability": "view", + "type": "function", + "name": "fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3138 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3168 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3198 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3228 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3258 + }, + { + "stateMutability": "view", + "type": "function", + "name": "name", + "inputs": [], + "outputs": [{ "name": "", "type": "string" }], + "gas": 13518 + }, + { + "stateMutability": "view", + "type": "function", + "name": "symbol", + "inputs": [], + "outputs": [{ "name": "", "type": "string" }], + "gas": 11271 + }, + { + "stateMutability": "view", + "type": "function", + "name": "balanceOf", + "inputs": [{ "name": "arg0", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3563 + }, + { + "stateMutability": "view", + "type": "function", + "name": "allowance", + "inputs": [ + { "name": "arg0", "type": "address" }, + { "name": "arg1", "type": "address" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3808 + }, + { + "stateMutability": "view", + "type": "function", + "name": "totalSupply", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3408 + }, + { + "name":"base_pool", + "outputs":[ + { + "type":"address", + "name":"" + } + ], + "inputs":[ + + ], + "stateMutability":"view", + "type":"function", + "gas":2321 + } +] diff --git a/contracts/interfaces/CurvePoolV2.json b/contracts/interfaces/CurvePoolV2.json index a54a933..3ee3b13 100644 --- a/contracts/interfaces/CurvePoolV2.json +++ b/contracts/interfaces/CurvePoolV2.json @@ -1,713 +1,713 @@ -[ - { - "name": "TokenExchange", - "inputs": [ - { "name": "buyer", "type": "address", "indexed": true }, - { "name": "sold_id", "type": "uint256", "indexed": false }, - { "name": "tokens_sold", "type": "uint256", "indexed": false }, - { "name": "bought_id", "type": "uint256", "indexed": false }, - { "name": "tokens_bought", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "AddLiquidity", - "inputs": [ - { "name": "provider", "type": "address", "indexed": true }, - { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, - { "name": "fee", "type": "uint256", "indexed": false }, - { "name": "token_supply", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidity", - "inputs": [ - { "name": "provider", "type": "address", "indexed": true }, - { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, - { "name": "token_supply", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidityOne", - "inputs": [ - { "name": "provider", "type": "address", "indexed": true }, - { "name": "token_amount", "type": "uint256", "indexed": false }, - { "name": "coin_index", "type": "uint256", "indexed": false }, - { "name": "coin_amount", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitNewAdmin", - "inputs": [ - { "name": "deadline", "type": "uint256", "indexed": true }, - { "name": "admin", "type": "address", "indexed": true } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewAdmin", - "inputs": [{ "name": "admin", "type": "address", "indexed": true }], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitNewParameters", - "inputs": [ - { "name": "deadline", "type": "uint256", "indexed": true }, - { "name": "admin_fee", "type": "uint256", "indexed": false }, - { "name": "mid_fee", "type": "uint256", "indexed": false }, - { "name": "out_fee", "type": "uint256", "indexed": false }, - { "name": "fee_gamma", "type": "uint256", "indexed": false }, - { "name": "allowed_extra_profit", "type": "uint256", "indexed": false }, - { "name": "adjustment_step", "type": "uint256", "indexed": false }, - { "name": "ma_half_time", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewParameters", - "inputs": [ - { "name": "admin_fee", "type": "uint256", "indexed": false }, - { "name": "mid_fee", "type": "uint256", "indexed": false }, - { "name": "out_fee", "type": "uint256", "indexed": false }, - { "name": "fee_gamma", "type": "uint256", "indexed": false }, - { "name": "allowed_extra_profit", "type": "uint256", "indexed": false }, - { "name": "adjustment_step", "type": "uint256", "indexed": false }, - { "name": "ma_half_time", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RampAgamma", - "inputs": [ - { "name": "initial_A", "type": "uint256", "indexed": false }, - { "name": "future_A", "type": "uint256", "indexed": false }, - { "name": "initial_gamma", "type": "uint256", "indexed": false }, - { "name": "future_gamma", "type": "uint256", "indexed": false }, - { "name": "initial_time", "type": "uint256", "indexed": false }, - { "name": "future_time", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StopRampA", - "inputs": [ - { "name": "current_A", "type": "uint256", "indexed": false }, - { "name": "current_gamma", "type": "uint256", "indexed": false }, - { "name": "time", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "ClaimAdminFee", - "inputs": [ - { "name": "admin", "type": "address", "indexed": true }, - { "name": "tokens", "type": "uint256", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "constructor", - "inputs": [ - { "name": "owner", "type": "address" }, - { "name": "admin_fee_receiver", "type": "address" }, - { "name": "A", "type": "uint256" }, - { "name": "gamma", "type": "uint256" }, - { "name": "mid_fee", "type": "uint256" }, - { "name": "out_fee", "type": "uint256" }, - { "name": "allowed_extra_profit", "type": "uint256" }, - { "name": "fee_gamma", "type": "uint256" }, - { "name": "adjustment_step", "type": "uint256" }, - { "name": "admin_fee", "type": "uint256" }, - { "name": "ma_half_time", "type": "uint256" }, - { "name": "initial_price", "type": "uint256" } - ], - "outputs": [] - }, - { "stateMutability": "payable", "type": "fallback" }, - { - "stateMutability": "view", - "type": "function", - "name": "token", - "inputs": [], - "outputs": [{ "name": "", "type": "address" }], - "gas": 516 - }, - { - "stateMutability": "view", - "type": "function", - "name": "coins", - "inputs": [{ "name": "i", "type": "uint256" }], - "outputs": [{ "name": "", "type": "address" }], - "gas": 648 - }, - { - "stateMutability": "view", - "type": "function", - "name": "A", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 685 - }, - { - "stateMutability": "view", - "type": "function", - "name": "gamma", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 11789 - }, - { - "stateMutability": "view", - "type": "function", - "name": "fee", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 17633 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_virtual_price", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 364797 - }, - { - "stateMutability": "payable", - "type": "function", - "name": "exchange", - "inputs": [ - { "name": "i", "type": "uint256" }, - { "name": "j", "type": "uint256" }, - { "name": "dx", "type": "uint256" }, - { "name": "min_dy", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 16775598 - }, - { - "stateMutability": "payable", - "type": "function", - "name": "exchange", - "inputs": [ - { "name": "i", "type": "uint256" }, - { "name": "j", "type": "uint256" }, - { "name": "dx", "type": "uint256" }, - { "name": "min_dy", "type": "uint256" }, - { "name": "use_eth", "type": "bool" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 16775598 - }, - { - "stateMutability": "payable", - "type": "function", - "name": "exchange_underlying", - "inputs": [ - { "name": "i", "type": "uint256" }, - { "name": "j", "type": "uint256" }, - { "name": "dx", "type": "uint256" }, - { "name": "min_dy", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 16775396 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_dy", - "inputs": [ - { "name": "i", "type": "uint256" }, - { "name": "j", "type": "uint256" }, - { "name": "dx", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4577515 - }, - { - "stateMutability": "payable", - "type": "function", - "name": "add_liquidity", - "inputs": [ - { "name": "amounts", "type": "uint256[2]" }, - { "name": "min_mint_amount", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 17694821 - }, - { - "stateMutability": "payable", - "type": "function", - "name": "add_liquidity", - "inputs": [ - { "name": "amounts", "type": "uint256[2]" }, - { "name": "min_mint_amount", "type": "uint256" }, - { "name": "use_eth", "type": "bool" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 17694821 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity", - "inputs": [ - { "name": "_amount", "type": "uint256" }, - { "name": "min_amounts", "type": "uint256[2]" } - ], - "outputs": [], - "gas": 263729 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity", - "inputs": [ - { "name": "_amount", "type": "uint256" }, - { "name": "min_amounts", "type": "uint256[2]" }, - { "name": "use_eth", "type": "bool" } - ], - "outputs": [], - "gas": 263729 - }, - { - "stateMutability": "view", - "type": "function", - "name": "calc_token_amount", - "inputs": [{ "name": "amounts", "type": "uint256[2]" }], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 5200947 - }, - { - "stateMutability": "view", - "type": "function", - "name": "calc_withdraw_one_coin", - "inputs": [ - { "name": "token_amount", "type": "uint256" }, - { "name": "i", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 12584 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity_one_coin", - "inputs": [ - { "name": "token_amount", "type": "uint256" }, - { "name": "i", "type": "uint256" }, - { "name": "min_amount", "type": "uint256" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 16702178 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_liquidity_one_coin", - "inputs": [ - { "name": "token_amount", "type": "uint256" }, - { "name": "i", "type": "uint256" }, - { "name": "min_amount", "type": "uint256" }, - { "name": "use_eth", "type": "bool" } - ], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 16702178 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "claim_admin_fees", - "inputs": [], - "outputs": [], - "gas": 3250985 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "ramp_A_gamma", - "inputs": [ - { "name": "future_A", "type": "uint256" }, - { "name": "future_gamma", "type": "uint256" }, - { "name": "future_time", "type": "uint256" } - ], - "outputs": [], - "gas": 161698 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "stop_ramp_A_gamma", - "inputs": [], - "outputs": [], - "gas": 156743 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "commit_new_parameters", - "inputs": [ - { "name": "_new_mid_fee", "type": "uint256" }, - { "name": "_new_out_fee", "type": "uint256" }, - { "name": "_new_admin_fee", "type": "uint256" }, - { "name": "_new_fee_gamma", "type": "uint256" }, - { "name": "_new_allowed_extra_profit", "type": "uint256" }, - { "name": "_new_adjustment_step", "type": "uint256" }, - { "name": "_new_ma_half_time", "type": "uint256" } - ], - "outputs": [], - "gas": 305084 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "apply_new_parameters", - "inputs": [], - "outputs": [], - "gas": 3543175 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "revert_new_parameters", - "inputs": [], - "outputs": [], - "gas": 23142 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "commit_transfer_ownership", - "inputs": [{ "name": "_owner", "type": "address" }], - "outputs": [], - "gas": 78827 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "apply_transfer_ownership", - "inputs": [], - "outputs": [], - "gas": 67042 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "revert_transfer_ownership", - "inputs": [], - "outputs": [], - "gas": 23232 - }, - { "stateMutability": "nonpayable", "type": "function", "name": "kill_me", "inputs": [], "outputs": [], "gas": 40455 }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "unkill_me", - "inputs": [], - "outputs": [], - "gas": 23292 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_admin_fee_receiver", - "inputs": [{ "name": "_admin_fee_receiver", "type": "address" }], - "outputs": [], - "gas": 38482 - }, - { - "stateMutability": "view", - "type": "function", - "name": "lp_price", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 217046 - }, - { - "stateMutability": "view", - "type": "function", - "name": "price_scale", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3426 - }, - { - "stateMutability": "view", - "type": "function", - "name": "price_oracle", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3456 - }, - { - "stateMutability": "view", - "type": "function", - "name": "last_prices", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3486 - }, - { - "stateMutability": "view", - "type": "function", - "name": "last_prices_timestamp", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3516 - }, - { - "stateMutability": "view", - "type": "function", - "name": "initial_A_gamma", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3546 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_A_gamma", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3576 - }, - { - "stateMutability": "view", - "type": "function", - "name": "initial_A_gamma_time", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3606 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_A_gamma_time", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3636 - }, - { - "stateMutability": "view", - "type": "function", - "name": "allowed_extra_profit", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3666 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_allowed_extra_profit", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3696 - }, - { - "stateMutability": "view", - "type": "function", - "name": "fee_gamma", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3726 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_fee_gamma", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3756 - }, - { - "stateMutability": "view", - "type": "function", - "name": "adjustment_step", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3786 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_adjustment_step", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3816 - }, - { - "stateMutability": "view", - "type": "function", - "name": "ma_half_time", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3846 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_ma_half_time", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3876 - }, - { - "stateMutability": "view", - "type": "function", - "name": "mid_fee", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3906 - }, - { - "stateMutability": "view", - "type": "function", - "name": "out_fee", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3936 - }, - { - "stateMutability": "view", - "type": "function", - "name": "admin_fee", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3966 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_mid_fee", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 3996 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_out_fee", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4026 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_admin_fee", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4056 - }, - { - "stateMutability": "view", - "type": "function", - "name": "balances", - "inputs": [{ "name": "arg0", "type": "uint256" }], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4131 - }, - { - "stateMutability": "view", - "type": "function", - "name": "D", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4116 - }, - { - "stateMutability": "view", - "type": "function", - "name": "owner", - "inputs": [], - "outputs": [{ "name": "", "type": "address" }], - "gas": 4146 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_owner", - "inputs": [], - "outputs": [{ "name": "", "type": "address" }], - "gas": 4176 - }, - { - "stateMutability": "view", - "type": "function", - "name": "xcp_profit", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4206 - }, - { - "stateMutability": "view", - "type": "function", - "name": "xcp_profit_a", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4236 - }, - { - "stateMutability": "view", - "type": "function", - "name": "virtual_price", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4266 - }, - { - "stateMutability": "view", - "type": "function", - "name": "is_killed", - "inputs": [], - "outputs": [{ "name": "", "type": "bool" }], - "gas": 4296 - }, - { - "stateMutability": "view", - "type": "function", - "name": "kill_deadline", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4326 - }, - { - "stateMutability": "view", - "type": "function", - "name": "transfer_ownership_deadline", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4356 - }, - { - "stateMutability": "view", - "type": "function", - "name": "admin_actions_deadline", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256" }], - "gas": 4386 - }, - { - "stateMutability": "view", - "type": "function", - "name": "admin_fee_receiver", - "inputs": [], - "outputs": [{ "name": "", "type": "address" }], - "gas": 4416 - } -] +[ + { + "name": "TokenExchange", + "inputs": [ + { "name": "buyer", "type": "address", "indexed": true }, + { "name": "sold_id", "type": "uint256", "indexed": false }, + { "name": "tokens_sold", "type": "uint256", "indexed": false }, + { "name": "bought_id", "type": "uint256", "indexed": false }, + { "name": "tokens_bought", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityOne", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amount", "type": "uint256", "indexed": false }, + { "name": "coin_index", "type": "uint256", "indexed": false }, + { "name": "coin_amount", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitNewAdmin", + "inputs": [ + { "name": "deadline", "type": "uint256", "indexed": true }, + { "name": "admin", "type": "address", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewAdmin", + "inputs": [{ "name": "admin", "type": "address", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitNewParameters", + "inputs": [ + { "name": "deadline", "type": "uint256", "indexed": true }, + { "name": "admin_fee", "type": "uint256", "indexed": false }, + { "name": "mid_fee", "type": "uint256", "indexed": false }, + { "name": "out_fee", "type": "uint256", "indexed": false }, + { "name": "fee_gamma", "type": "uint256", "indexed": false }, + { "name": "allowed_extra_profit", "type": "uint256", "indexed": false }, + { "name": "adjustment_step", "type": "uint256", "indexed": false }, + { "name": "ma_half_time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewParameters", + "inputs": [ + { "name": "admin_fee", "type": "uint256", "indexed": false }, + { "name": "mid_fee", "type": "uint256", "indexed": false }, + { "name": "out_fee", "type": "uint256", "indexed": false }, + { "name": "fee_gamma", "type": "uint256", "indexed": false }, + { "name": "allowed_extra_profit", "type": "uint256", "indexed": false }, + { "name": "adjustment_step", "type": "uint256", "indexed": false }, + { "name": "ma_half_time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RampAgamma", + "inputs": [ + { "name": "initial_A", "type": "uint256", "indexed": false }, + { "name": "future_A", "type": "uint256", "indexed": false }, + { "name": "initial_gamma", "type": "uint256", "indexed": false }, + { "name": "future_gamma", "type": "uint256", "indexed": false }, + { "name": "initial_time", "type": "uint256", "indexed": false }, + { "name": "future_time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StopRampA", + "inputs": [ + { "name": "current_A", "type": "uint256", "indexed": false }, + { "name": "current_gamma", "type": "uint256", "indexed": false }, + { "name": "time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "ClaimAdminFee", + "inputs": [ + { "name": "admin", "type": "address", "indexed": true }, + { "name": "tokens", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { "name": "owner", "type": "address" }, + { "name": "admin_fee_receiver", "type": "address" }, + { "name": "A", "type": "uint256" }, + { "name": "gamma", "type": "uint256" }, + { "name": "mid_fee", "type": "uint256" }, + { "name": "out_fee", "type": "uint256" }, + { "name": "allowed_extra_profit", "type": "uint256" }, + { "name": "fee_gamma", "type": "uint256" }, + { "name": "adjustment_step", "type": "uint256" }, + { "name": "admin_fee", "type": "uint256" }, + { "name": "ma_half_time", "type": "uint256" }, + { "name": "initial_price", "type": "uint256" } + ], + "outputs": [] + }, + { "stateMutability": "payable", "type": "fallback" }, + { + "stateMutability": "view", + "type": "function", + "name": "token", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 516 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coins", + "inputs": [{ "name": "i", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 648 + }, + { + "stateMutability": "view", + "type": "function", + "name": "A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 685 + }, + { + "stateMutability": "view", + "type": "function", + "name": "gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 11789 + }, + { + "stateMutability": "view", + "type": "function", + "name": "fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 17633 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 364797 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "exchange", + "inputs": [ + { "name": "i", "type": "uint256" }, + { "name": "j", "type": "uint256" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16775598 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "exchange", + "inputs": [ + { "name": "i", "type": "uint256" }, + { "name": "j", "type": "uint256" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" }, + { "name": "use_eth", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16775598 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "exchange_underlying", + "inputs": [ + { "name": "i", "type": "uint256" }, + { "name": "j", "type": "uint256" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16775396 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_dy", + "inputs": [ + { "name": "i", "type": "uint256" }, + { "name": "j", "type": "uint256" }, + { "name": "dx", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4577515 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "amounts", "type": "uint256[2]" }, + { "name": "min_mint_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 17694821 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "amounts", "type": "uint256[2]" }, + { "name": "min_mint_amount", "type": "uint256" }, + { "name": "use_eth", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 17694821 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_amount", "type": "uint256" }, + { "name": "min_amounts", "type": "uint256[2]" } + ], + "outputs": [], + "gas": 263729 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_amount", "type": "uint256" }, + { "name": "min_amounts", "type": "uint256[2]" }, + { "name": "use_eth", "type": "bool" } + ], + "outputs": [], + "gas": 263729 + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_token_amount", + "inputs": [{ "name": "amounts", "type": "uint256[2]" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 5200947 + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_withdraw_one_coin", + "inputs": [ + { "name": "token_amount", "type": "uint256" }, + { "name": "i", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 12584 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "token_amount", "type": "uint256" }, + { "name": "i", "type": "uint256" }, + { "name": "min_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16702178 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "token_amount", "type": "uint256" }, + { "name": "i", "type": "uint256" }, + { "name": "min_amount", "type": "uint256" }, + { "name": "use_eth", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16702178 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "claim_admin_fees", + "inputs": [], + "outputs": [], + "gas": 3250985 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "ramp_A_gamma", + "inputs": [ + { "name": "future_A", "type": "uint256" }, + { "name": "future_gamma", "type": "uint256" }, + { "name": "future_time", "type": "uint256" } + ], + "outputs": [], + "gas": 161698 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "stop_ramp_A_gamma", + "inputs": [], + "outputs": [], + "gas": 156743 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_new_parameters", + "inputs": [ + { "name": "_new_mid_fee", "type": "uint256" }, + { "name": "_new_out_fee", "type": "uint256" }, + { "name": "_new_admin_fee", "type": "uint256" }, + { "name": "_new_fee_gamma", "type": "uint256" }, + { "name": "_new_allowed_extra_profit", "type": "uint256" }, + { "name": "_new_adjustment_step", "type": "uint256" }, + { "name": "_new_ma_half_time", "type": "uint256" } + ], + "outputs": [], + "gas": 305084 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "apply_new_parameters", + "inputs": [], + "outputs": [], + "gas": 3543175 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revert_new_parameters", + "inputs": [], + "outputs": [], + "gas": 23142 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_transfer_ownership", + "inputs": [{ "name": "_owner", "type": "address" }], + "outputs": [], + "gas": 78827 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "apply_transfer_ownership", + "inputs": [], + "outputs": [], + "gas": 67042 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revert_transfer_ownership", + "inputs": [], + "outputs": [], + "gas": 23232 + }, + { "stateMutability": "nonpayable", "type": "function", "name": "kill_me", "inputs": [], "outputs": [], "gas": 40455 }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "unkill_me", + "inputs": [], + "outputs": [], + "gas": 23292 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_admin_fee_receiver", + "inputs": [{ "name": "_admin_fee_receiver", "type": "address" }], + "outputs": [], + "gas": 38482 + }, + { + "stateMutability": "view", + "type": "function", + "name": "lp_price", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 217046 + }, + { + "stateMutability": "view", + "type": "function", + "name": "price_scale", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3426 + }, + { + "stateMutability": "view", + "type": "function", + "name": "price_oracle", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3456 + }, + { + "stateMutability": "view", + "type": "function", + "name": "last_prices", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3486 + }, + { + "stateMutability": "view", + "type": "function", + "name": "last_prices_timestamp", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3516 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A_gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3546 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A_gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3576 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A_gamma_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3606 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A_gamma_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3636 + }, + { + "stateMutability": "view", + "type": "function", + "name": "allowed_extra_profit", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3666 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_allowed_extra_profit", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3696 + }, + { + "stateMutability": "view", + "type": "function", + "name": "fee_gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3726 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_fee_gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3756 + }, + { + "stateMutability": "view", + "type": "function", + "name": "adjustment_step", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3786 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_adjustment_step", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3816 + }, + { + "stateMutability": "view", + "type": "function", + "name": "ma_half_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3846 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_ma_half_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3876 + }, + { + "stateMutability": "view", + "type": "function", + "name": "mid_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3906 + }, + { + "stateMutability": "view", + "type": "function", + "name": "out_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3936 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3966 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_mid_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3996 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_out_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4026 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_admin_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4056 + }, + { + "stateMutability": "view", + "type": "function", + "name": "balances", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4131 + }, + { + "stateMutability": "view", + "type": "function", + "name": "D", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4116 + }, + { + "stateMutability": "view", + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 4146 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 4176 + }, + { + "stateMutability": "view", + "type": "function", + "name": "xcp_profit", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4206 + }, + { + "stateMutability": "view", + "type": "function", + "name": "xcp_profit_a", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4236 + }, + { + "stateMutability": "view", + "type": "function", + "name": "virtual_price", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4266 + }, + { + "stateMutability": "view", + "type": "function", + "name": "is_killed", + "inputs": [], + "outputs": [{ "name": "", "type": "bool" }], + "gas": 4296 + }, + { + "stateMutability": "view", + "type": "function", + "name": "kill_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4326 + }, + { + "stateMutability": "view", + "type": "function", + "name": "transfer_ownership_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4356 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_actions_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4386 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_fee_receiver", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 4416 + } +] diff --git a/contracts/interfaces/ERC20.vy b/contracts/interfaces/ERC20.vy index 28ce1eb..10fed05 100644 --- a/contracts/interfaces/ERC20.vy +++ b/contracts/interfaces/ERC20.vy @@ -1,148 +1,148 @@ -# @version 0.3.3 -# @dev Implementation of ERC-20 token standard. -# @author Takayuki Jimba (@yudetamago) -# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md - -from vyper.interfaces import ERC20 -from vyper.interfaces import ERC20Detailed - -implements: ERC20 -implements: ERC20Detailed - -event Transfer: - sender: indexed(address) - receiver: indexed(address) - value: uint256 - -event Approval: - owner: indexed(address) - spender: indexed(address) - value: uint256 - -name: public(String[32]) -symbol: public(String[32]) -decimals: public(uint8) - -# NOTE: By declaring `balanceOf` as public, vyper automatically generates a 'balanceOf()' getter -# method to allow access to account balances. -# The _KeyType will become a required parameter for the getter and it will return _ValueType. -# See: https://vyper.readthedocs.io/en/v0.1.0-beta.8/types.html?highlight=getter#mappings -balanceOf: public(HashMap[address, uint256]) -# By declaring `allowance` as public, vyper automatically generates the `allowance()` getter -allowance: public(HashMap[address, HashMap[address, uint256]]) -# By declaring `totalSupply` as public, we automatically create the `totalSupply()` getter -totalSupply: public(uint256) -minter: address - - -@external -def __init__(_name: String[32], _symbol: String[32], _decimals: uint8, _supply: uint256): - init_supply: uint256 = _supply * 10 ** convert(_decimals, uint256) - self.name = _name - self.symbol = _symbol - self.decimals = _decimals - self.balanceOf[msg.sender] = init_supply - self.totalSupply = init_supply - self.minter = msg.sender - log Transfer(ZERO_ADDRESS, msg.sender, init_supply) - - - -@external -def transfer(_to : address, _value : uint256) -> bool: - """ - @dev Transfer token for a specified address - @param _to The address to transfer to. - @param _value The amount to be transferred. - """ - # NOTE: vyper does not allow underflows - # so the following subtraction would revert on insufficient balance - self.balanceOf[msg.sender] -= _value - self.balanceOf[_to] += _value - log Transfer(msg.sender, _to, _value) - return True - - -@external -def transferFrom(_from : address, _to : address, _value : uint256) -> bool: - """ - @dev Transfer tokens from one address to another. - @param _from address The address which you want to send tokens from - @param _to address The address which you want to transfer to - @param _value uint256 the amount of tokens to be transferred - """ - # NOTE: vyper does not allow underflows - # so the following subtraction would revert on insufficient balance - self.balanceOf[_from] -= _value - self.balanceOf[_to] += _value - # NOTE: vyper does not allow underflows - # so the following subtraction would revert on insufficient allowance - self.allowance[_from][msg.sender] -= _value - log Transfer(_from, _to, _value) - return True - - -@external -def approve(_spender : address, _value : uint256) -> bool: - """ - @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. - Beware that changing an allowance with this method brings the risk that someone may use both the old - and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this - race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: - https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - @param _spender The address which will spend the funds. - @param _value The amount of tokens to be spent. - """ - self.allowance[msg.sender][_spender] = _value - log Approval(msg.sender, _spender, _value) - return True - - -@external -def mint(_to: address, _value: uint256): - """ - @dev Mint an amount of the token and assigns it to an account. - This encapsulates the modification of balances such that the - proper events are emitted. - @param _to The account that will receive the created tokens. - @param _value The amount that will be created. - """ - assert msg.sender == self.minter - assert _to != ZERO_ADDRESS - self.totalSupply += _value - self.balanceOf[_to] += _value - log Transfer(ZERO_ADDRESS, _to, _value) - - -@internal -def _burn(_to: address, _value: uint256): - """ - @dev Internal function that burns an amount of the token of a given - account. - @param _to The account whose tokens will be burned. - @param _value The amount that will be burned. - """ - assert _to != ZERO_ADDRESS - self.totalSupply -= _value - self.balanceOf[_to] -= _value - log Transfer(_to, ZERO_ADDRESS, _value) - - -@external -def burn(_value: uint256): - """ - @dev Burn an amount of the token of msg.sender. - @param _value The amount that will be burned. - """ - self._burn(msg.sender, _value) - - -@external -def burnFrom(_to: address, _value: uint256): - """ - @dev Burn an amount of the token from a given account. - @param _to The account whose tokens will be burned. - @param _value The amount that will be burned. - """ - self.allowance[_to][msg.sender] -= _value - self._burn(_to, _value) +# @version 0.3.3 +# @dev Implementation of ERC-20 token standard. +# @author Takayuki Jimba (@yudetamago) +# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md + +from vyper.interfaces import ERC20 +from vyper.interfaces import ERC20Detailed + +implements: ERC20 +implements: ERC20Detailed + +event Transfer: + sender: indexed(address) + receiver: indexed(address) + value: uint256 + +event Approval: + owner: indexed(address) + spender: indexed(address) + value: uint256 + +name: public(String[32]) +symbol: public(String[32]) +decimals: public(uint8) + +# NOTE: By declaring `balanceOf` as public, vyper automatically generates a 'balanceOf()' getter +# method to allow access to account balances. +# The _KeyType will become a required parameter for the getter and it will return _ValueType. +# See: https://vyper.readthedocs.io/en/v0.1.0-beta.8/types.html?highlight=getter#mappings +balanceOf: public(HashMap[address, uint256]) +# By declaring `allowance` as public, vyper automatically generates the `allowance()` getter +allowance: public(HashMap[address, HashMap[address, uint256]]) +# By declaring `totalSupply` as public, we automatically create the `totalSupply()` getter +totalSupply: public(uint256) +minter: address + + +@external +def __init__(_name: String[32], _symbol: String[32], _decimals: uint8, _supply: uint256): + init_supply: uint256 = _supply * 10 ** convert(_decimals, uint256) + self.name = _name + self.symbol = _symbol + self.decimals = _decimals + self.balanceOf[msg.sender] = init_supply + self.totalSupply = init_supply + self.minter = msg.sender + log Transfer(ZERO_ADDRESS, msg.sender, init_supply) + + + +@external +def transfer(_to : address, _value : uint256) -> bool: + """ + @dev Transfer token for a specified address + @param _to The address to transfer to. + @param _value The amount to be transferred. + """ + # NOTE: vyper does not allow underflows + # so the following subtraction would revert on insufficient balance + self.balanceOf[msg.sender] -= _value + self.balanceOf[_to] += _value + log Transfer(msg.sender, _to, _value) + return True + + +@external +def transferFrom(_from : address, _to : address, _value : uint256) -> bool: + """ + @dev Transfer tokens from one address to another. + @param _from address The address which you want to send tokens from + @param _to address The address which you want to transfer to + @param _value uint256 the amount of tokens to be transferred + """ + # NOTE: vyper does not allow underflows + # so the following subtraction would revert on insufficient balance + self.balanceOf[_from] -= _value + self.balanceOf[_to] += _value + # NOTE: vyper does not allow underflows + # so the following subtraction would revert on insufficient allowance + self.allowance[_from][msg.sender] -= _value + log Transfer(_from, _to, _value) + return True + + +@external +def approve(_spender : address, _value : uint256) -> bool: + """ + @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. + Beware that changing an allowance with this method brings the risk that someone may use both the old + and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + @param _spender The address which will spend the funds. + @param _value The amount of tokens to be spent. + """ + self.allowance[msg.sender][_spender] = _value + log Approval(msg.sender, _spender, _value) + return True + + +@external +def mint(_to: address, _value: uint256): + """ + @dev Mint an amount of the token and assigns it to an account. + This encapsulates the modification of balances such that the + proper events are emitted. + @param _to The account that will receive the created tokens. + @param _value The amount that will be created. + """ + assert msg.sender == self.minter + assert _to != ZERO_ADDRESS + self.totalSupply += _value + self.balanceOf[_to] += _value + log Transfer(ZERO_ADDRESS, _to, _value) + + +@internal +def _burn(_to: address, _value: uint256): + """ + @dev Internal function that burns an amount of the token of a given + account. + @param _to The account whose tokens will be burned. + @param _value The amount that will be burned. + """ + assert _to != ZERO_ADDRESS + self.totalSupply -= _value + self.balanceOf[_to] -= _value + log Transfer(_to, ZERO_ADDRESS, _value) + + +@external +def burn(_value: uint256): + """ + @dev Burn an amount of the token of msg.sender. + @param _value The amount that will be burned. + """ + self._burn(msg.sender, _value) + + +@external +def burnFrom(_to: address, _value: uint256): + """ + @dev Burn an amount of the token from a given account. + @param _to The account whose tokens will be burned. + @param _value The amount that will be burned. + """ + self.allowance[_to][msg.sender] -= _value + self._burn(_to, _value) diff --git a/contracts/interfaces/LiquidityGauge.json b/contracts/interfaces/LiquidityGauge.json index 08e7276..fd56e84 100644 --- a/contracts/interfaces/LiquidityGauge.json +++ b/contracts/interfaces/LiquidityGauge.json @@ -1,834 +1,834 @@ -[{ - "name": "Deposit", - "inputs": [{ - "type": "address", - "name": "provider", - "indexed": true - }, - { - "type": "uint256", - "name": "value", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "Withdraw", - "inputs": [{ - "type": "address", - "name": "provider", - "indexed": true - }, - { - "type": "uint256", - "name": "value", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateLiquidityLimit", - "inputs": [{ - "type": "address", - "name": "user", - "indexed": false - }, - { - "type": "uint256", - "name": "original_balance", - "indexed": false - }, - { - "type": "uint256", - "name": "original_supply", - "indexed": false - }, - { - "type": "uint256", - "name": "working_balance", - "indexed": false - }, - { - "type": "uint256", - "name": "working_supply", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitOwnership", - "inputs": [{ - "type": "address", - "name": "admin", - "indexed": false - }], - "anonymous": false, - "type": "event" - }, - { - "name": "ApplyOwnership", - "inputs": [{ - "type": "address", - "name": "admin", - "indexed": false - }], - "anonymous": false, - "type": "event" - }, - { - "name": "Transfer", - "inputs": [{ - "type": "address", - "name": "_from", - "indexed": true - }, - { - "type": "address", - "name": "_to", - "indexed": true - }, - { - "type": "uint256", - "name": "_value", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "Approval", - "inputs": [{ - "type": "address", - "name": "_owner", - "indexed": true - }, - { - "type": "address", - "name": "_spender", - "indexed": true - }, - { - "type": "uint256", - "name": "_value", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "outputs": [], - "inputs": [{ - "type": "string", - "name": "_name" - }, - { - "type": "string", - "name": "_symbol" - }, - { - "type": "address", - "name": "_lp_token" - }, - { - "type": "address", - "name": "_minter" - }, - { - "type": "address", - "name": "_admin" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "name": "decimals", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 261 - }, - { - "name": "integrate_checkpoint", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1997 - }, - { - "name": "user_checkpoint", - "outputs": [{ - "type": "bool", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "addr" - }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 2070619 - }, - { - "name": "claimable_tokens", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "addr" - }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 1989830 - }, - { - "name": "claimable_reward", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "_addr" - }, - { - "type": "address", - "name": "_token" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 999922 - }, - { - "name": "claim_rewards", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "claim_rewards", - "outputs": [], - "inputs": [{ - "type": "address", - "name": "_addr" - }], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "claim_historic_rewards", - "outputs": [], - "inputs": [{ - "type": "address[8]", - "name": "_reward_tokens" - }], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "claim_historic_rewards", - "outputs": [], - "inputs": [{ - "type": "address[8]", - "name": "_reward_tokens" - }, - { - "type": "address", - "name": "_addr" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "kick", - "outputs": [], - "inputs": [{ - "type": "address", - "name": "addr" - }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 2075807 - }, - { - "name": "set_approve_deposit", - "outputs": [], - "inputs": [{ - "type": "address", - "name": "addr" - }, - { - "type": "bool", - "name": "can_deposit" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 35981 - }, - { - "name": "deposit", - "outputs": [], - "inputs": [{ - "type": "uint256", - "name": "_value" - }], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "deposit", - "outputs": [], - "inputs": [{ - "type": "uint256", - "name": "_value" - }, - { - "type": "address", - "name": "_addr" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "withdraw", - "outputs": [], - "inputs": [{ - "type": "uint256", - "name": "_value" - }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 3125023 - }, - { - "name": "allowance", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "_owner" - }, - { - "type": "address", - "name": "_spender" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 1911 - }, - { - "name": "transfer", - "outputs": [{ - "type": "bool", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "_to" - }, - { - "type": "uint256", - "name": "_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 12092388 - }, - { - "name": "transferFrom", - "outputs": [{ - "type": "bool", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "_from" - }, - { - "type": "address", - "name": "_to" - }, - { - "type": "uint256", - "name": "_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 12129038 - }, - { - "name": "approve", - "outputs": [{ - "type": "bool", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "_spender" - }, - { - "type": "uint256", - "name": "_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 38244 - }, - { - "name": "increaseAllowance", - "outputs": [{ - "type": "bool", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "_spender" - }, - { - "type": "uint256", - "name": "_added_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 39488 - }, - { - "name": "decreaseAllowance", - "outputs": [{ - "type": "bool", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "_spender" - }, - { - "type": "uint256", - "name": "_subtracted_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 39512 - }, - { - "name": "set_rewards", - "outputs": [], - "inputs": [{ - "type": "address", - "name": "_reward_contract" - }, - { - "type": "bytes32", - "name": "_sigs" - }, - { - "type": "address[8]", - "name": "_reward_tokens" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 2268178 - }, - { - "name": "set_killed", - "outputs": [], - "inputs": [{ - "type": "bool", - "name": "_is_killed" - }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 36878 - }, - { - "name": "commit_transfer_ownership", - "outputs": [], - "inputs": [{ - "type": "address", - "name": "addr" - }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 38258 - }, - { - "name": "accept_transfer_ownership", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 38203 - }, - { - "name": "minter", - "outputs": [{ - "type": "address", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1811 - }, - { - "name": "crv_token", - "outputs": [{ - "type": "address", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1841 - }, - { - "name": "lp_token", - "outputs": [{ - "type": "address", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1871 - }, - { - "name": "controller", - "outputs": [{ - "type": "address", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1901 - }, - { - "name": "voting_escrow", - "outputs": [{ - "type": "address", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1931 - }, - { - "name": "future_epoch_time", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1961 - }, - { - "name": "balanceOf", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "arg0" - }], - "stateMutability": "view", - "type": "function", - "gas": 2206 - }, - { - "name": "totalSupply", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2021 - }, - { - "name": "name", - "outputs": [{ - "type": "string", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 8453 - }, - { - "name": "symbol", - "outputs": [{ - "type": "string", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 7506 - }, - { - "name": "approved_to_deposit", - "outputs": [{ - "type": "bool", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "arg0" - }, - { - "type": "address", - "name": "arg1" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2541 - }, - { - "name": "working_balances", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "arg0" - }], - "stateMutability": "view", - "type": "function", - "gas": 2356 - }, - { - "name": "working_supply", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2171 - }, - { - "name": "period", - "outputs": [{ - "type": "int128", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2201 - }, - { - "name": "period_timestamp", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "uint256", - "name": "arg0" - }], - "stateMutability": "view", - "type": "function", - "gas": 2340 - }, - { - "name": "integrate_inv_supply", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "uint256", - "name": "arg0" - }], - "stateMutability": "view", - "type": "function", - "gas": 2370 - }, - { - "name": "integrate_inv_supply_of", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "arg0" - }], - "stateMutability": "view", - "type": "function", - "gas": 2506 - }, - { - "name": "integrate_checkpoint_of", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "arg0" - }], - "stateMutability": "view", - "type": "function", - "gas": 2536 - }, - { - "name": "integrate_fraction", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "arg0" - }], - "stateMutability": "view", - "type": "function", - "gas": 2566 - }, - { - "name": "inflation_rate", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2381 - }, - { - "name": "reward_contract", - "outputs": [{ - "type": "address", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2411 - }, - { - "name": "reward_tokens", - "outputs": [{ - "type": "address", - "name": "" - }], - "inputs": [{ - "type": "uint256", - "name": "arg0" - }], - "stateMutability": "view", - "type": "function", - "gas": 2550 - }, - { - "name": "reward_integral", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "arg0" - }], - "stateMutability": "view", - "type": "function", - "gas": 2686 - }, - { - "name": "reward_integral_for", - "outputs": [{ - "type": "uint256", - "name": "" - }], - "inputs": [{ - "type": "address", - "name": "arg0" - }, - { - "type": "address", - "name": "arg1" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2931 - }, - { - "name": "admin", - "outputs": [{ - "type": "address", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2531 - }, - { - "name": "future_admin", - "outputs": [{ - "type": "address", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2561 - }, - { - "name": "is_killed", - "outputs": [{ - "type": "bool", - "name": "" - }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2591 - } -] +[{ + "name": "Deposit", + "inputs": [{ + "type": "address", + "name": "provider", + "indexed": true + }, + { + "type": "uint256", + "name": "value", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "Withdraw", + "inputs": [{ + "type": "address", + "name": "provider", + "indexed": true + }, + { + "type": "uint256", + "name": "value", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateLiquidityLimit", + "inputs": [{ + "type": "address", + "name": "user", + "indexed": false + }, + { + "type": "uint256", + "name": "original_balance", + "indexed": false + }, + { + "type": "uint256", + "name": "original_supply", + "indexed": false + }, + { + "type": "uint256", + "name": "working_balance", + "indexed": false + }, + { + "type": "uint256", + "name": "working_supply", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitOwnership", + "inputs": [{ + "type": "address", + "name": "admin", + "indexed": false + }], + "anonymous": false, + "type": "event" + }, + { + "name": "ApplyOwnership", + "inputs": [{ + "type": "address", + "name": "admin", + "indexed": false + }], + "anonymous": false, + "type": "event" + }, + { + "name": "Transfer", + "inputs": [{ + "type": "address", + "name": "_from", + "indexed": true + }, + { + "type": "address", + "name": "_to", + "indexed": true + }, + { + "type": "uint256", + "name": "_value", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "Approval", + "inputs": [{ + "type": "address", + "name": "_owner", + "indexed": true + }, + { + "type": "address", + "name": "_spender", + "indexed": true + }, + { + "type": "uint256", + "name": "_value", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "outputs": [], + "inputs": [{ + "type": "string", + "name": "_name" + }, + { + "type": "string", + "name": "_symbol" + }, + { + "type": "address", + "name": "_lp_token" + }, + { + "type": "address", + "name": "_minter" + }, + { + "type": "address", + "name": "_admin" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "name": "decimals", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 261 + }, + { + "name": "integrate_checkpoint", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1997 + }, + { + "name": "user_checkpoint", + "outputs": [{ + "type": "bool", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "addr" + }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 2070619 + }, + { + "name": "claimable_tokens", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "addr" + }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 1989830 + }, + { + "name": "claimable_reward", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "_addr" + }, + { + "type": "address", + "name": "_token" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 999922 + }, + { + "name": "claim_rewards", + "outputs": [], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "claim_rewards", + "outputs": [], + "inputs": [{ + "type": "address", + "name": "_addr" + }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "claim_historic_rewards", + "outputs": [], + "inputs": [{ + "type": "address[8]", + "name": "_reward_tokens" + }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "claim_historic_rewards", + "outputs": [], + "inputs": [{ + "type": "address[8]", + "name": "_reward_tokens" + }, + { + "type": "address", + "name": "_addr" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "kick", + "outputs": [], + "inputs": [{ + "type": "address", + "name": "addr" + }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 2075807 + }, + { + "name": "set_approve_deposit", + "outputs": [], + "inputs": [{ + "type": "address", + "name": "addr" + }, + { + "type": "bool", + "name": "can_deposit" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 35981 + }, + { + "name": "deposit", + "outputs": [], + "inputs": [{ + "type": "uint256", + "name": "_value" + }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "deposit", + "outputs": [], + "inputs": [{ + "type": "uint256", + "name": "_value" + }, + { + "type": "address", + "name": "_addr" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "withdraw", + "outputs": [], + "inputs": [{ + "type": "uint256", + "name": "_value" + }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 3125023 + }, + { + "name": "allowance", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "_owner" + }, + { + "type": "address", + "name": "_spender" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 1911 + }, + { + "name": "transfer", + "outputs": [{ + "type": "bool", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "_to" + }, + { + "type": "uint256", + "name": "_value" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 12092388 + }, + { + "name": "transferFrom", + "outputs": [{ + "type": "bool", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "_from" + }, + { + "type": "address", + "name": "_to" + }, + { + "type": "uint256", + "name": "_value" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 12129038 + }, + { + "name": "approve", + "outputs": [{ + "type": "bool", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "_spender" + }, + { + "type": "uint256", + "name": "_value" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 38244 + }, + { + "name": "increaseAllowance", + "outputs": [{ + "type": "bool", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "_spender" + }, + { + "type": "uint256", + "name": "_added_value" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 39488 + }, + { + "name": "decreaseAllowance", + "outputs": [{ + "type": "bool", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "_spender" + }, + { + "type": "uint256", + "name": "_subtracted_value" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 39512 + }, + { + "name": "set_rewards", + "outputs": [], + "inputs": [{ + "type": "address", + "name": "_reward_contract" + }, + { + "type": "bytes32", + "name": "_sigs" + }, + { + "type": "address[8]", + "name": "_reward_tokens" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 2268178 + }, + { + "name": "set_killed", + "outputs": [], + "inputs": [{ + "type": "bool", + "name": "_is_killed" + }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 36878 + }, + { + "name": "commit_transfer_ownership", + "outputs": [], + "inputs": [{ + "type": "address", + "name": "addr" + }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 38258 + }, + { + "name": "accept_transfer_ownership", + "outputs": [], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": 38203 + }, + { + "name": "minter", + "outputs": [{ + "type": "address", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1811 + }, + { + "name": "crv_token", + "outputs": [{ + "type": "address", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1841 + }, + { + "name": "lp_token", + "outputs": [{ + "type": "address", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1871 + }, + { + "name": "controller", + "outputs": [{ + "type": "address", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1901 + }, + { + "name": "voting_escrow", + "outputs": [{ + "type": "address", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1931 + }, + { + "name": "future_epoch_time", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1961 + }, + { + "name": "balanceOf", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }], + "stateMutability": "view", + "type": "function", + "gas": 2206 + }, + { + "name": "totalSupply", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2021 + }, + { + "name": "name", + "outputs": [{ + "type": "string", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 8453 + }, + { + "name": "symbol", + "outputs": [{ + "type": "string", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 7506 + }, + { + "name": "approved_to_deposit", + "outputs": [{ + "type": "bool", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }, + { + "type": "address", + "name": "arg1" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2541 + }, + { + "name": "working_balances", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }], + "stateMutability": "view", + "type": "function", + "gas": 2356 + }, + { + "name": "working_supply", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2171 + }, + { + "name": "period", + "outputs": [{ + "type": "int128", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2201 + }, + { + "name": "period_timestamp", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "uint256", + "name": "arg0" + }], + "stateMutability": "view", + "type": "function", + "gas": 2340 + }, + { + "name": "integrate_inv_supply", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "uint256", + "name": "arg0" + }], + "stateMutability": "view", + "type": "function", + "gas": 2370 + }, + { + "name": "integrate_inv_supply_of", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }], + "stateMutability": "view", + "type": "function", + "gas": 2506 + }, + { + "name": "integrate_checkpoint_of", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }], + "stateMutability": "view", + "type": "function", + "gas": 2536 + }, + { + "name": "integrate_fraction", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }], + "stateMutability": "view", + "type": "function", + "gas": 2566 + }, + { + "name": "inflation_rate", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2381 + }, + { + "name": "reward_contract", + "outputs": [{ + "type": "address", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2411 + }, + { + "name": "reward_tokens", + "outputs": [{ + "type": "address", + "name": "" + }], + "inputs": [{ + "type": "uint256", + "name": "arg0" + }], + "stateMutability": "view", + "type": "function", + "gas": 2550 + }, + { + "name": "reward_integral", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }], + "stateMutability": "view", + "type": "function", + "gas": 2686 + }, + { + "name": "reward_integral_for", + "outputs": [{ + "type": "uint256", + "name": "" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }, + { + "type": "address", + "name": "arg1" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2931 + }, + { + "name": "admin", + "outputs": [{ + "type": "address", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2531 + }, + { + "name": "future_admin", + "outputs": [{ + "type": "address", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2561 + }, + { + "name": "is_killed", + "outputs": [{ + "type": "bool", + "name": "" + }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2591 + } +] diff --git a/contracts/interfaces/MainRegistry.json b/contracts/interfaces/MainRegistry.json index 4c83faa..ee4462b 100644 --- a/contracts/interfaces/MainRegistry.json +++ b/contracts/interfaces/MainRegistry.json @@ -1,940 +1,940 @@ -[ - { - "name": "PoolAdded", - "inputs": [ - { - "name": "pool", - "type": "address", - "indexed": true - }, - { - "name": "rate_method_id", - "type": "bytes", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "PoolRemoved", - "inputs": [ - { - "name": "pool", - "type": "address", - "indexed": true - } - ], - "anonymous": false, - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "constructor", - "inputs": [ - { - "name": "_address_provider", - "type": "address" - }, - { - "name": "_gauge_controller", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "i", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_n_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[2]" - } - ], - "gas": 1521 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[8]" - } - ], - "gas": 12102 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_underlying_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[8]" - } - ], - "gas": 12194 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_decimals", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 7874 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_underlying_decimals", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 7966 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_rates", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 36992 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_gauges", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[10]" - }, - { - "name": "", - "type": "int128[10]" - } - ], - "gas": 20157 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 16583 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_underlying_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 162842 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_virtual_price_from_lp_token", - "inputs": [ - { - "name": "_token", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 1927 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_A", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 1045 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_parameters", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "A", - "type": "uint256" - }, - { - "name": "future_A", - "type": "uint256" - }, - { - "name": "fee", - "type": "uint256" - }, - { - "name": "admin_fee", - "type": "uint256" - }, - { - "name": "future_fee", - "type": "uint256" - }, - { - "name": "future_admin_fee", - "type": "uint256" - }, - { - "name": "future_owner", - "type": "address" - }, - { - "name": "initial_A", - "type": "uint256" - }, - { - "name": "initial_A_time", - "type": "uint256" - }, - { - "name": "future_A_time", - "type": "uint256" - } - ], - "gas": 6305 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_fees", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[2]" - } - ], - "gas": 1450 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_admin_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 36454 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_indices", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "int128" - }, - { - "name": "", - "type": "int128" - }, - { - "name": "", - "type": "bool" - } - ], - "gas": 27131 - }, - { - "stateMutability": "view", - "type": "function", - "name": "estimate_gas_used", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 32004 - }, - { - "stateMutability": "view", - "type": "function", - "name": "is_meta", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "gas": 1900 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_pool_name", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "gas": 8323 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_swap_count", - "inputs": [ - { - "name": "_coin", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 1951 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_swap_complement", - "inputs": [ - { - "name": "_coin", - "type": "address" - }, - { - "name": "_index", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2090 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_pool_asset_type", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2011 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_pool", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_rate_info", - "type": "bytes32" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_underlying_decimals", - "type": "uint256" - }, - { - "name": "_has_initial_A", - "type": "bool" - }, - { - "name": "_is_v1", - "type": "bool" - }, - { - "name": "_name", - "type": "string" - } - ], - "outputs": [], - "gas": 61485845 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_pool_without_underlying", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_rate_info", - "type": "bytes32" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_use_rates", - "type": "uint256" - }, - { - "name": "_has_initial_A", - "type": "bool" - }, - { - "name": "_is_v1", - "type": "bool" - }, - { - "name": "_name", - "type": "string" - } - ], - "outputs": [], - "gas": 31306062 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_metapool", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_metapool", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - }, - { - "name": "_base_pool", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_pool", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [], - "gas": 779731418758 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_pool_gas_estimates", - "inputs": [ - { - "name": "_addr", - "type": "address[5]" - }, - { - "name": "_amount", - "type": "uint256[2][5]" - } - ], - "outputs": [], - "gas": 390460 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_coin_gas_estimates", - "inputs": [ - { - "name": "_addr", - "type": "address[10]" - }, - { - "name": "_amount", - "type": "uint256[10]" - } - ], - "outputs": [], - "gas": 392047 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_gas_estimate_contract", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_estimator", - "type": "address" - } - ], - "outputs": [], - "gas": 72629 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_liquidity_gauges", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_liquidity_gauges", - "type": "address[10]" - } - ], - "outputs": [], - "gas": 400675 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_pool_asset_type", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_asset_type", - "type": "uint256" - } - ], - "outputs": [], - "gas": 72667 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "batch_set_pool_asset_type", - "inputs": [ - { - "name": "_pools", - "type": "address[32]" - }, - { - "name": "_asset_types", - "type": "uint256[32]" - } - ], - "outputs": [], - "gas": 1173447 - }, - { - "stateMutability": "view", - "type": "function", - "name": "address_provider", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2048 - }, - { - "stateMutability": "view", - "type": "function", - "name": "gauge_controller", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2078 - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_list", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2217 - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_count", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2138 - }, - { - "stateMutability": "view", - "type": "function", - "name": "coin_count", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2168 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2307 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_pool_from_lp_token", - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2443 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_lp_token", - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2473 - }, - { - "stateMutability": "view", - "type": "function", - "name": "last_updated", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2288 - } - ] +[ + { + "name": "PoolAdded", + "inputs": [ + { + "name": "pool", + "type": "address", + "indexed": true + }, + { + "name": "rate_method_id", + "type": "bytes", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "PoolRemoved", + "inputs": [ + { + "name": "pool", + "type": "address", + "indexed": true + } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { + "name": "_address_provider", + "type": "address" + }, + { + "name": "_gauge_controller", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "i", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_n_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[2]" + } + ], + "gas": 1521 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[8]" + } + ], + "gas": 12102 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[8]" + } + ], + "gas": 12194 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_decimals", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 7874 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_decimals", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 7966 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_rates", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 36992 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_gauges", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[10]" + }, + { + "name": "", + "type": "int128[10]" + } + ], + "gas": 20157 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 16583 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 162842 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price_from_lp_token", + "inputs": [ + { + "name": "_token", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 1927 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_A", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 1045 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_parameters", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "A", + "type": "uint256" + }, + { + "name": "future_A", + "type": "uint256" + }, + { + "name": "fee", + "type": "uint256" + }, + { + "name": "admin_fee", + "type": "uint256" + }, + { + "name": "future_fee", + "type": "uint256" + }, + { + "name": "future_admin_fee", + "type": "uint256" + }, + { + "name": "future_owner", + "type": "address" + }, + { + "name": "initial_A", + "type": "uint256" + }, + { + "name": "initial_A_time", + "type": "uint256" + }, + { + "name": "future_A_time", + "type": "uint256" + } + ], + "gas": 6305 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_fees", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[2]" + } + ], + "gas": 1450 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_admin_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 36454 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_indices", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "int128" + }, + { + "name": "", + "type": "int128" + }, + { + "name": "", + "type": "bool" + } + ], + "gas": 27131 + }, + { + "stateMutability": "view", + "type": "function", + "name": "estimate_gas_used", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 32004 + }, + { + "stateMutability": "view", + "type": "function", + "name": "is_meta", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "gas": 1900 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_name", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "gas": 8323 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_count", + "inputs": [ + { + "name": "_coin", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 1951 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_complement", + "inputs": [ + { + "name": "_coin", + "type": "address" + }, + { + "name": "_index", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2090 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_asset_type", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2011 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_pool", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_lp_token", + "type": "address" + }, + { + "name": "_rate_info", + "type": "bytes32" + }, + { + "name": "_decimals", + "type": "uint256" + }, + { + "name": "_underlying_decimals", + "type": "uint256" + }, + { + "name": "_has_initial_A", + "type": "bool" + }, + { + "name": "_is_v1", + "type": "bool" + }, + { + "name": "_name", + "type": "string" + } + ], + "outputs": [], + "gas": 61485845 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_pool_without_underlying", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_lp_token", + "type": "address" + }, + { + "name": "_rate_info", + "type": "bytes32" + }, + { + "name": "_decimals", + "type": "uint256" + }, + { + "name": "_use_rates", + "type": "uint256" + }, + { + "name": "_has_initial_A", + "type": "bool" + }, + { + "name": "_is_v1", + "type": "bool" + }, + { + "name": "_name", + "type": "string" + } + ], + "outputs": [], + "gas": 31306062 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_metapool", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_lp_token", + "type": "address" + }, + { + "name": "_decimals", + "type": "uint256" + }, + { + "name": "_name", + "type": "string" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_metapool", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_lp_token", + "type": "address" + }, + { + "name": "_decimals", + "type": "uint256" + }, + { + "name": "_name", + "type": "string" + }, + { + "name": "_base_pool", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_pool", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [], + "gas": 779731418758 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_pool_gas_estimates", + "inputs": [ + { + "name": "_addr", + "type": "address[5]" + }, + { + "name": "_amount", + "type": "uint256[2][5]" + } + ], + "outputs": [], + "gas": 390460 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_coin_gas_estimates", + "inputs": [ + { + "name": "_addr", + "type": "address[10]" + }, + { + "name": "_amount", + "type": "uint256[10]" + } + ], + "outputs": [], + "gas": 392047 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_gas_estimate_contract", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_estimator", + "type": "address" + } + ], + "outputs": [], + "gas": 72629 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_liquidity_gauges", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_liquidity_gauges", + "type": "address[10]" + } + ], + "outputs": [], + "gas": 400675 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_pool_asset_type", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_asset_type", + "type": "uint256" + } + ], + "outputs": [], + "gas": 72667 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "batch_set_pool_asset_type", + "inputs": [ + { + "name": "_pools", + "type": "address[32]" + }, + { + "name": "_asset_types", + "type": "uint256[32]" + } + ], + "outputs": [], + "gas": 1173447 + }, + { + "stateMutability": "view", + "type": "function", + "name": "address_provider", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2048 + }, + { + "stateMutability": "view", + "type": "function", + "name": "gauge_controller", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2078 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_list", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2217 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_count", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2138 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coin_count", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2168 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2307 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_from_lp_token", + "inputs": [ + { + "name": "arg0", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2443 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_lp_token", + "inputs": [ + { + "name": "arg0", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2473 + }, + { + "stateMutability": "view", + "type": "function", + "name": "last_updated", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2288 + } + ] diff --git a/contracts/interfaces/ProxyAdmin.json b/contracts/interfaces/ProxyAdmin.json index d0a1de2..1d0fd1c 100644 --- a/contracts/interfaces/ProxyAdmin.json +++ b/contracts/interfaces/ProxyAdmin.json @@ -1,211 +1,211 @@ -[ - { - "name": "TransactionExecuted", - "inputs": [ - { - "name": "admin", - "type": "address", - "indexed": true - }, - { - "name": "target", - "type": "address", - "indexed": true - }, - { - "name": "calldata", - "type": "bytes", - "indexed": false - }, - { - "name": "value", - "type": "uint256", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RequestAdminChange", - "inputs": [ - { - "name": "current_admin", - "type": "address", - "indexed": false - }, - { - "name": "future_admin", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RevokeAdminChange", - "inputs": [ - { - "name": "current_admin", - "type": "address", - "indexed": false - }, - { - "name": "future_admin", - "type": "address", - "indexed": false - }, - { - "name": "calling_admin", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "ApproveAdminChange", - "inputs": [ - { - "name": "current_admin", - "type": "address", - "indexed": false - }, - { - "name": "future_admin", - "type": "address", - "indexed": false - }, - { - "name": "calling_admin", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "AcceptAdminChange", - "inputs": [ - { - "name": "previous_admin", - "type": "address", - "indexed": false - }, - { - "name": "current_admin", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "constructor", - "inputs": [ - { - "name": "_authorized", - "type": "address[2]" - } - ], - "outputs": [] - }, - { - "stateMutability": "payable", - "type": "function", - "name": "execute", - "inputs": [ - { - "name": "_target", - "type": "address" - }, - { - "name": "_calldata", - "type": "bytes" - } - ], - "outputs": [], - "gas": 1168658 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_admin_change_status", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "bool" - } - ], - "gas": 4202 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "request_admin_change", - "inputs": [ - { - "name": "_new_admin", - "type": "address" - } - ], - "outputs": [], - "gas": 148342 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "approve_admin_change", - "inputs": [], - "outputs": [], - "gas": 41716 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "revoke_admin_change", - "inputs": [], - "outputs": [], - "gas": 67885 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "accept_admin_change", - "inputs": [], - "outputs": [], - "gas": 101134 - }, - { - "stateMutability": "view", - "type": "function", - "name": "admins", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 1377 - } - ] +[ + { + "name": "TransactionExecuted", + "inputs": [ + { + "name": "admin", + "type": "address", + "indexed": true + }, + { + "name": "target", + "type": "address", + "indexed": true + }, + { + "name": "calldata", + "type": "bytes", + "indexed": false + }, + { + "name": "value", + "type": "uint256", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RequestAdminChange", + "inputs": [ + { + "name": "current_admin", + "type": "address", + "indexed": false + }, + { + "name": "future_admin", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RevokeAdminChange", + "inputs": [ + { + "name": "current_admin", + "type": "address", + "indexed": false + }, + { + "name": "future_admin", + "type": "address", + "indexed": false + }, + { + "name": "calling_admin", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "ApproveAdminChange", + "inputs": [ + { + "name": "current_admin", + "type": "address", + "indexed": false + }, + { + "name": "future_admin", + "type": "address", + "indexed": false + }, + { + "name": "calling_admin", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AcceptAdminChange", + "inputs": [ + { + "name": "previous_admin", + "type": "address", + "indexed": false + }, + { + "name": "current_admin", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { + "name": "_authorized", + "type": "address[2]" + } + ], + "outputs": [] + }, + { + "stateMutability": "payable", + "type": "function", + "name": "execute", + "inputs": [ + { + "name": "_target", + "type": "address" + }, + { + "name": "_calldata", + "type": "bytes" + } + ], + "outputs": [], + "gas": 1168658 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_admin_change_status", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "bool" + } + ], + "gas": 4202 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "request_admin_change", + "inputs": [ + { + "name": "_new_admin", + "type": "address" + } + ], + "outputs": [], + "gas": 148342 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "approve_admin_change", + "inputs": [], + "outputs": [], + "gas": 41716 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revoke_admin_change", + "inputs": [], + "outputs": [], + "gas": 67885 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "accept_admin_change", + "inputs": [], + "outputs": [], + "gas": 101134 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admins", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 1377 + } + ] diff --git a/contracts/mainnet/MetaRegistry.vy b/contracts/mainnet/MetaRegistry.vy index 8660464..4d407a4 100644 --- a/contracts/mainnet/MetaRegistry.vy +++ b/contracts/mainnet/MetaRegistry.vy @@ -1,561 +1,561 @@ -#pragma version ^0.3.7 -""" -@title Curve Meta Registry -@license MIT -""" - -# ---- interfaces ---- # -interface AddressProvider: - def admin() -> address: view - - -# registry and registry handlers are considered to be the same here. -# registry handlers are just wrapper contracts that simplify/fix underlying registries -# for integrating it into the Metaregistry. -interface RegistryHandler: - def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view - def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_base_pool(_pool: address) -> address: view - def get_coins(_pool: address) -> address[MAX_COINS]: view - def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): view - def get_decimals(_pool: address) -> uint256[MAX_COINS]: view - def get_fees(_pool: address) -> uint256[10]: view - def get_gauges(_pool: address) -> (address[10], int128[10]): view - def get_lp_token(_pool: address) -> address: view - def get_n_coins(_pool: address) -> uint256: view - def get_n_underlying_coins(_pool: address) -> uint256: view - def get_pool_asset_type(_pool: address) -> uint256: view - def get_pool_from_lp_token(_lp_token: address) -> address: view - def get_pool_name(_pool: address) -> String[64]: view - def get_pool_params(_pool: address) -> uint256[20]: view - def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_underlying_coins(_pool: address) -> address[MAX_COINS]: view - def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: view - def is_meta(_pool: address) -> bool: view - def is_registered(_pool: address) -> bool: view - def pool_count() -> uint256: view - def pool_list(_index: uint256) -> address: view - def get_virtual_price_from_lp_token(_addr: address) -> uint256: view - def base_registry() -> address: view - - -# ---- events ---- # -event CommitNewAdmin: - deadline: indexed(uint256) - admin: indexed(address) - -event NewAdmin: - admin: indexed(address) - - -# ---- constants ---- # -MAX_REGISTRIES: constant(uint256) = 10 -MAX_COINS: constant(uint256) = 8 -MAX_POOL_PARAMS: constant(uint256) = 20 -ADMIN_ACTIONS_DELAY: constant(uint256) = 3 * 86400 - - -# ---- storage variables ---- # -address_provider: public(AddressProvider) -owner: public(address) - -# get registry/registry_handler by index, index starts at 0: -get_registry: public(HashMap[uint256, address]) -registry_length: public(uint256) - - -# ---- constructor ---- # -@external -def __init__(_address_provider: address): - self.address_provider = AddressProvider(_address_provider) - self.owner = AddressProvider(_address_provider).admin() - - -# ---- internal methods ---- # -@internal -def _update_single_registry(_index: uint256, _registry_handler: address): - assert _index <= self.registry_length - - if _index == self.registry_length: - self.registry_length += 1 - - self.get_registry[_index] = _registry_handler - - -@internal -@view -def _get_pool_from_lp_token(_token: address) -> address: - for i in range(MAX_REGISTRIES): - if i == self.registry_length: - break - handler: address = self.get_registry[i] - pool: address = RegistryHandler(handler).get_pool_from_lp_token(_token) - if pool != empty(address): - return pool - return empty(address) - - -@internal -@view -def _get_registry_handlers_from_pool(_pool: address) -> address[MAX_REGISTRIES]: - """ - @notice Get registry handler that handles the registry api for a pool - @dev sometimes a factory pool can be registered in a manual registry - because of this, we always take the last registry a pool is - registered in and not the first, as manual registries are first - and factories come later - @param _pool address of the pool - @return registry_handlers: address[MAX_REGISTRIES] - """ - - pool_registry_handler: address[MAX_REGISTRIES] = empty(address[MAX_REGISTRIES]) - c: uint256 = 0 - for i in range(MAX_REGISTRIES): - - if i == self.registry_length: - break - handler: address = self.get_registry[i] - - if RegistryHandler(handler).is_registered(_pool): - pool_registry_handler[c] = handler - c += 1 - - if pool_registry_handler[0] == empty(address): - raise "no registry" - return pool_registry_handler - - -# ---- most used methods: Admin / DAO privileged methods ---- # -@external -def add_registry_handler(_registry_handler: address): - """ - @notice Adds a registry from the address provider entry - @param _registry_handler Address of the handler contract - """ - assert msg.sender == self.owner # dev: only owner - - self._update_single_registry(self.registry_length, _registry_handler) - - -@external -def update_registry_handler(_index: uint256, _registry_handler: address): - """ - @notice Updates the contract used to handle a registry - @param _index The index of the registry in get_registry - @param _registry_handler Address of the new handler contract - """ - assert msg.sender == self.owner # dev: only owner - assert _index < self.registry_length - - self._update_single_registry(_index, _registry_handler) - - -# ---- view methods (API) of the contract ---- # - - -@external -@view -def get_registry_handlers_from_pool(_pool: address) -> address[MAX_REGISTRIES]: - """ - @notice Get the registry handlers associated with a pool - @param _pool Pool address - @return List of registry handlers - """ - return self._get_registry_handlers_from_pool(_pool) - - -@external -@view -def get_base_registry(registry_handler: address) -> address: - """ - @notice Get the registry associated with a registry handler - @param registry_handler Registry Handler address - @return Address of base registry - """ - return RegistryHandler(registry_handler).base_registry() - - -@view -@external -def find_pool_for_coins( - _from: address, _to: address, i: uint256 = 0 -) -> address: - """ - @notice Find the ith available pool containing the input pair - @param _from Address of coin to be sent - @param _to Address of coin to be received - @param i Index of the pool to return - @return Pool address - """ - pools_found: uint256 = 0 - pool: address = empty(address) - registry: address = empty(address) - - for registry_index in range(MAX_REGISTRIES): - - registry = self.get_registry[registry_index] - if registry == empty(address): - break - - for j in range(0, 65536): - - pool = RegistryHandler(registry).find_pool_for_coins(_from, _to, j) - if pool == empty(address): - break - pools_found += 1 - if pools_found > i: - return pool - - return pool - - -@view -@external -def find_pools_for_coins(_from: address, _to: address) -> DynArray[address, 1000]: - """ - @notice Find all pools that contain the input pair - @param _from Address of coin to be sent - @param _to Address of coin to be received - @return Pool addresses - """ - pools_found: DynArray[address, 1000]= empty(DynArray[address, 1000]) - pool: address = empty(address) - registry: address = empty(address) - - for registry_index in range(MAX_REGISTRIES): - - registry = self.get_registry[registry_index] - if registry == empty(address): - break - - for j in range(0, 65536): - - pool = RegistryHandler(registry).find_pool_for_coins(_from, _to, j) - if pool == empty(address): - break - pools_found.append(pool) - - return pools_found - - -@external -@view -def get_admin_balances(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: - """ - @notice Get the current admin balances (uncollected fees) for a pool - @dev _handler_id < 1 if pool is registry in one handler, more than 0 otherwise - @param _pool Pool address - @param _handler_id id of registry handler - @return List of uint256 admin balances - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_admin_balances(_pool) - - -@external -@view -def get_balances(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: - """ - @notice Get balances for each coin within a pool - @dev For metapools, these are the wrapped coin balances - @param _pool Pool address - @param _handler_id id of registry handler - @return uint256 list of balances - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_balances(_pool) - - -@external -@view -def get_base_pool(_pool: address, _handler_id: uint256 = 0) -> address: - """ - @notice Get the base pool for a given factory metapool - @dev Will return empty(address) if pool is not a metapool - @param _pool Metapool address - @param _handler_id id of registry handler - @return Address of base pool - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_base_pool(_pool) - - -@view -@external -def get_coin_indices(_pool: address, _from: address, _to: address, _handler_id: uint256 = 0) -> (int128, int128, bool): - """ - @notice Convert coin addresses to indices for use with pool methods - @param _pool Pool address - @param _from Coin address to be used as `i` within a pool - @param _to Coin address to be used as `j` within a pool - @param _handler_id id of registry handler - @return from index, to index, is the market underlying ? - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_coin_indices(_pool, _from, _to) - - -@external -@view -def get_coins(_pool: address, _handler_id: uint256 = 0) -> address[MAX_COINS]: - """ - @notice Get the coins within a pool - @dev For metapools, these are the wrapped coin addresses - @param _pool Pool address - @param _handler_id id of registry handler - @return List of coin addresses - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_coins(_pool) - - -@external -@view -def get_decimals(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: - """ - @notice Get decimal places for each coin within a pool - @dev For metapools, these are the wrapped coin decimal places - @param _pool Pool address - @param _handler_id id of registry handler - @return uint256 list of decimals - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_decimals(_pool) - - -@external -@view -def get_fees(_pool: address, _handler_id: uint256 = 0) -> uint256[10]: - """ - @notice Get pool fees - @dev Fees are expressed as integers - @param _pool Pool address - @param _handler_id id of registry handler - @return Pool fee as uint256 with 1e10 precision - Admin fee as 1e10 percentage of pool fee - Mid fee - Out fee - 6 blank spots for future use cases - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_fees(_pool) - - -@external -@view -def get_gauge(_pool: address, gauge_idx: uint256 = 0, _handler_id: uint256 = 0) -> address: - """ - @notice Get a single liquidity gauge contract associated with a pool - @param _pool Pool address - @param gauge_idx Index of gauge to return - @param _handler_id id of registry handler - @return Address of gauge - """ - registry_handler: RegistryHandler = RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]) - handler_output: address[10] = registry_handler.get_gauges(_pool)[0] - return handler_output[gauge_idx] - - -@external -@view -def get_gauge_type(_pool: address, gauge_idx: uint256 = 0, _handler_id: uint256 = 0) -> int128: - """ - @notice Get gauge_type of a single liquidity gauge contract associated with a pool - @param _pool Pool address - @param gauge_idx Index of gauge to return - @param _handler_id id of registry handler - @return Address of gauge - """ - registry_handler: RegistryHandler = RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]) - handler_output: int128[10] = registry_handler.get_gauges(_pool)[1] - return handler_output[gauge_idx] - - -@external -@view -def get_lp_token(_pool: address, _handler_id: uint256 = 0) -> address: - """ - @notice Get the address of the LP token of a pool - @param _pool Pool address - @param _handler_id id of registry handler - @return Address of the LP token - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_lp_token(_pool) - - -@external -@view -def get_n_coins(_pool: address, _handler_id: uint256 = 0) -> uint256: - """ - @notice Get the number of coins in a pool - @dev For metapools, it is tokens + wrapping/lending token (no underlying) - @param _pool Pool address - @return Number of coins - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_n_coins(_pool) - - -@external -@view -def get_n_underlying_coins(_pool: address, _handler_id: uint256 = 0) -> uint256: - """ - @notice Get the number of underlying coins in a pool - @dev For non metapools, returns the same as get_n_coins - @param _pool Pool address - @return Number of coins - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_n_underlying_coins(_pool) - - -@external -@view -def get_pool_asset_type(_pool: address, _handler_id: uint256 = 0) -> uint256: - """ - @notice Query the asset type of `_pool` - @param _pool Pool Address - @return The asset type as an unstripped string - @dev 0 : USD, 1: ETH, 2: BTC, 3: Other, 4: CryptoSwap - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_pool_asset_type(_pool) - - -@external -@view -def get_pool_from_lp_token(_token: address, _handler_id: uint256 = 0) -> address: - """ - @notice Get the pool associated with an LP token - @param _token LP token address - @return Pool address - """ - return self._get_pool_from_lp_token(_token) - - -@external -@view -def get_pool_params(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_POOL_PARAMS]: - """ - @notice Get the parameters of a pool - @param _pool Pool address - @param _handler_id id of registry handler - @return Pool parameters - """ - registry_handler: address = self._get_registry_handlers_from_pool(_pool)[_handler_id] - return RegistryHandler(registry_handler).get_pool_params(_pool) - - -@external -@view -def get_pool_name(_pool: address, _handler_id: uint256 = 0) -> String[64]: - """ - @notice Get the given name for a pool - @param _pool Pool address - @return The name of a pool - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_pool_name(_pool) - - -@external -@view -def get_underlying_balances(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: - """ - @notice Get balances for each underlying coin within a pool - @dev For non metapools, returns the same value as `get_balances` - @param _pool Pool address - @param _handler_id id of registry handler - @return uint256 List of underlyingbalances - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_underlying_balances(_pool) - - -@external -@view -def get_underlying_coins(_pool: address, _handler_id: uint256 = 0) -> address[MAX_COINS]: - """ - @notice Get the underlying coins within a pool - @dev For non metapools, returns the same value as `get_coins` - @param _pool Pool address - @param _handler_id id of registry handler - @return List of coin addresses - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_underlying_coins(_pool) - - -@external -@view -def get_underlying_decimals(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: - """ - @notice Get decimal places for each underlying coin within a pool - @dev For non metapools, returns the same value as `get_decimals` - @param _pool Pool address - @param _handler_id id of registry handler - @return uint256 list of decimals - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_underlying_decimals(_pool) - - -@external -@view -def get_virtual_price_from_lp_token(_token: address, _handler_id: uint256 = 0) -> uint256: - """ - @notice Get the virtual price of a pool LP token - @param _token LP token address - @param _handler_id id of registry handler - @return uint256 Virtual price - """ - pool: address = self._get_pool_from_lp_token(_token) - registry_handler: address = self._get_registry_handlers_from_pool(pool)[_handler_id] - return RegistryHandler(registry_handler).get_virtual_price_from_lp_token(_token) - - -@external -@view -def is_meta(_pool: address, _handler_id: uint256 = 0) -> bool: - """ - @notice Verify `_pool` is a metapool - @param _pool Pool address - @param _handler_id id of registry handler - @return True if `_pool` is a metapool - """ - return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).is_meta(_pool) - - -@external -@view -def is_registered(_pool: address, _handler_id: uint256 = 0) -> bool: - """ - @notice Check if a pool is in the metaregistry using get_n_coins - @param _pool The address of the pool - @param _handler_id id of registry handler - @return A bool corresponding to whether the pool belongs or not - """ - return self._get_registry_handlers_from_pool(_pool)[_handler_id] != empty(address) - - -@external -@view -def pool_count() -> uint256: - """ - @notice Return the total number of pools tracked by the metaregistry - @return uint256 The number of pools in the metaregistry - """ - total_pools: uint256 = 0 - for i in range(MAX_REGISTRIES): - if i == self.registry_length: - break - handler: address = self.get_registry[i] - total_pools += RegistryHandler(handler).pool_count() - return total_pools - - -@external -@view -def pool_list(_index: uint256) -> address: - """ - @notice Return the pool at a given index in the metaregistry - @param _index The index of the pool in the metaregistry - @return The address of the pool at the given index - """ - pools_skip: uint256 = 0 - for i in range(MAX_REGISTRIES): - if i == self.registry_length: - break - handler: address = self.get_registry[i] - count: uint256 = RegistryHandler(handler).pool_count() - if _index - pools_skip < count: - return RegistryHandler(handler).pool_list(_index - pools_skip) - pools_skip += count - return empty(address) +#pragma version ^0.3.7 +""" +@title Curve Meta Registry +@license MIT +""" + +# ---- interfaces ---- # +interface AddressProvider: + def admin() -> address: view + + +# registry and registry handlers are considered to be the same here. +# registry handlers are just wrapper contracts that simplify/fix underlying registries +# for integrating it into the Metaregistry. +interface RegistryHandler: + def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view + def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_base_pool(_pool: address) -> address: view + def get_coins(_pool: address) -> address[MAX_COINS]: view + def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): view + def get_decimals(_pool: address) -> uint256[MAX_COINS]: view + def get_fees(_pool: address) -> uint256[10]: view + def get_gauges(_pool: address) -> (address[10], int128[10]): view + def get_lp_token(_pool: address) -> address: view + def get_n_coins(_pool: address) -> uint256: view + def get_n_underlying_coins(_pool: address) -> uint256: view + def get_pool_asset_type(_pool: address) -> uint256: view + def get_pool_from_lp_token(_lp_token: address) -> address: view + def get_pool_name(_pool: address) -> String[64]: view + def get_pool_params(_pool: address) -> uint256[20]: view + def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_underlying_coins(_pool: address) -> address[MAX_COINS]: view + def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: view + def is_meta(_pool: address) -> bool: view + def is_registered(_pool: address) -> bool: view + def pool_count() -> uint256: view + def pool_list(_index: uint256) -> address: view + def get_virtual_price_from_lp_token(_addr: address) -> uint256: view + def base_registry() -> address: view + + +# ---- events ---- # +event CommitNewAdmin: + deadline: indexed(uint256) + admin: indexed(address) + +event NewAdmin: + admin: indexed(address) + + +# ---- constants ---- # +MAX_REGISTRIES: constant(uint256) = 10 +MAX_COINS: constant(uint256) = 8 +MAX_POOL_PARAMS: constant(uint256) = 20 +ADMIN_ACTIONS_DELAY: constant(uint256) = 3 * 86400 + + +# ---- storage variables ---- # +address_provider: public(AddressProvider) +owner: public(address) + +# get registry/registry_handler by index, index starts at 0: +get_registry: public(HashMap[uint256, address]) +registry_length: public(uint256) + + +# ---- constructor ---- # +@external +def __init__(_address_provider: address): + self.address_provider = AddressProvider(_address_provider) + self.owner = AddressProvider(_address_provider).admin() + + +# ---- internal methods ---- # +@internal +def _update_single_registry(_index: uint256, _registry_handler: address): + assert _index <= self.registry_length + + if _index == self.registry_length: + self.registry_length += 1 + + self.get_registry[_index] = _registry_handler + + +@internal +@view +def _get_pool_from_lp_token(_token: address) -> address: + for i in range(MAX_REGISTRIES): + if i == self.registry_length: + break + handler: address = self.get_registry[i] + pool: address = RegistryHandler(handler).get_pool_from_lp_token(_token) + if pool != empty(address): + return pool + return empty(address) + + +@internal +@view +def _get_registry_handlers_from_pool(_pool: address) -> address[MAX_REGISTRIES]: + """ + @notice Get registry handler that handles the registry api for a pool + @dev sometimes a factory pool can be registered in a manual registry + because of this, we always take the last registry a pool is + registered in and not the first, as manual registries are first + and factories come later + @param _pool address of the pool + @return registry_handlers: address[MAX_REGISTRIES] + """ + + pool_registry_handler: address[MAX_REGISTRIES] = empty(address[MAX_REGISTRIES]) + c: uint256 = 0 + for i in range(MAX_REGISTRIES): + + if i == self.registry_length: + break + handler: address = self.get_registry[i] + + if RegistryHandler(handler).is_registered(_pool): + pool_registry_handler[c] = handler + c += 1 + + if pool_registry_handler[0] == empty(address): + raise "no registry" + return pool_registry_handler + + +# ---- most used methods: Admin / DAO privileged methods ---- # +@external +def add_registry_handler(_registry_handler: address): + """ + @notice Adds a registry from the address provider entry + @param _registry_handler Address of the handler contract + """ + assert msg.sender == self.owner # dev: only owner + + self._update_single_registry(self.registry_length, _registry_handler) + + +@external +def update_registry_handler(_index: uint256, _registry_handler: address): + """ + @notice Updates the contract used to handle a registry + @param _index The index of the registry in get_registry + @param _registry_handler Address of the new handler contract + """ + assert msg.sender == self.owner # dev: only owner + assert _index < self.registry_length + + self._update_single_registry(_index, _registry_handler) + + +# ---- view methods (API) of the contract ---- # + + +@external +@view +def get_registry_handlers_from_pool(_pool: address) -> address[MAX_REGISTRIES]: + """ + @notice Get the registry handlers associated with a pool + @param _pool Pool address + @return List of registry handlers + """ + return self._get_registry_handlers_from_pool(_pool) + + +@external +@view +def get_base_registry(registry_handler: address) -> address: + """ + @notice Get the registry associated with a registry handler + @param registry_handler Registry Handler address + @return Address of base registry + """ + return RegistryHandler(registry_handler).base_registry() + + +@view +@external +def find_pool_for_coins( + _from: address, _to: address, i: uint256 = 0 +) -> address: + """ + @notice Find the ith available pool containing the input pair + @param _from Address of coin to be sent + @param _to Address of coin to be received + @param i Index of the pool to return + @return Pool address + """ + pools_found: uint256 = 0 + pool: address = empty(address) + registry: address = empty(address) + + for registry_index in range(MAX_REGISTRIES): + + registry = self.get_registry[registry_index] + if registry == empty(address): + break + + for j in range(0, 65536): + + pool = RegistryHandler(registry).find_pool_for_coins(_from, _to, j) + if pool == empty(address): + break + pools_found += 1 + if pools_found > i: + return pool + + return pool + + +@view +@external +def find_pools_for_coins(_from: address, _to: address) -> DynArray[address, 1000]: + """ + @notice Find all pools that contain the input pair + @param _from Address of coin to be sent + @param _to Address of coin to be received + @return Pool addresses + """ + pools_found: DynArray[address, 1000]= empty(DynArray[address, 1000]) + pool: address = empty(address) + registry: address = empty(address) + + for registry_index in range(MAX_REGISTRIES): + + registry = self.get_registry[registry_index] + if registry == empty(address): + break + + for j in range(0, 65536): + + pool = RegistryHandler(registry).find_pool_for_coins(_from, _to, j) + if pool == empty(address): + break + pools_found.append(pool) + + return pools_found + + +@external +@view +def get_admin_balances(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: + """ + @notice Get the current admin balances (uncollected fees) for a pool + @dev _handler_id < 1 if pool is registry in one handler, more than 0 otherwise + @param _pool Pool address + @param _handler_id id of registry handler + @return List of uint256 admin balances + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_admin_balances(_pool) + + +@external +@view +def get_balances(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: + """ + @notice Get balances for each coin within a pool + @dev For metapools, these are the wrapped coin balances + @param _pool Pool address + @param _handler_id id of registry handler + @return uint256 list of balances + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_balances(_pool) + + +@external +@view +def get_base_pool(_pool: address, _handler_id: uint256 = 0) -> address: + """ + @notice Get the base pool for a given factory metapool + @dev Will return empty(address) if pool is not a metapool + @param _pool Metapool address + @param _handler_id id of registry handler + @return Address of base pool + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_base_pool(_pool) + + +@view +@external +def get_coin_indices(_pool: address, _from: address, _to: address, _handler_id: uint256 = 0) -> (int128, int128, bool): + """ + @notice Convert coin addresses to indices for use with pool methods + @param _pool Pool address + @param _from Coin address to be used as `i` within a pool + @param _to Coin address to be used as `j` within a pool + @param _handler_id id of registry handler + @return from index, to index, is the market underlying ? + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_coin_indices(_pool, _from, _to) + + +@external +@view +def get_coins(_pool: address, _handler_id: uint256 = 0) -> address[MAX_COINS]: + """ + @notice Get the coins within a pool + @dev For metapools, these are the wrapped coin addresses + @param _pool Pool address + @param _handler_id id of registry handler + @return List of coin addresses + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_coins(_pool) + + +@external +@view +def get_decimals(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: + """ + @notice Get decimal places for each coin within a pool + @dev For metapools, these are the wrapped coin decimal places + @param _pool Pool address + @param _handler_id id of registry handler + @return uint256 list of decimals + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_decimals(_pool) + + +@external +@view +def get_fees(_pool: address, _handler_id: uint256 = 0) -> uint256[10]: + """ + @notice Get pool fees + @dev Fees are expressed as integers + @param _pool Pool address + @param _handler_id id of registry handler + @return Pool fee as uint256 with 1e10 precision + Admin fee as 1e10 percentage of pool fee + Mid fee + Out fee + 6 blank spots for future use cases + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_fees(_pool) + + +@external +@view +def get_gauge(_pool: address, gauge_idx: uint256 = 0, _handler_id: uint256 = 0) -> address: + """ + @notice Get a single liquidity gauge contract associated with a pool + @param _pool Pool address + @param gauge_idx Index of gauge to return + @param _handler_id id of registry handler + @return Address of gauge + """ + registry_handler: RegistryHandler = RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]) + handler_output: address[10] = registry_handler.get_gauges(_pool)[0] + return handler_output[gauge_idx] + + +@external +@view +def get_gauge_type(_pool: address, gauge_idx: uint256 = 0, _handler_id: uint256 = 0) -> int128: + """ + @notice Get gauge_type of a single liquidity gauge contract associated with a pool + @param _pool Pool address + @param gauge_idx Index of gauge to return + @param _handler_id id of registry handler + @return Address of gauge + """ + registry_handler: RegistryHandler = RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]) + handler_output: int128[10] = registry_handler.get_gauges(_pool)[1] + return handler_output[gauge_idx] + + +@external +@view +def get_lp_token(_pool: address, _handler_id: uint256 = 0) -> address: + """ + @notice Get the address of the LP token of a pool + @param _pool Pool address + @param _handler_id id of registry handler + @return Address of the LP token + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_lp_token(_pool) + + +@external +@view +def get_n_coins(_pool: address, _handler_id: uint256 = 0) -> uint256: + """ + @notice Get the number of coins in a pool + @dev For metapools, it is tokens + wrapping/lending token (no underlying) + @param _pool Pool address + @return Number of coins + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_n_coins(_pool) + + +@external +@view +def get_n_underlying_coins(_pool: address, _handler_id: uint256 = 0) -> uint256: + """ + @notice Get the number of underlying coins in a pool + @dev For non metapools, returns the same as get_n_coins + @param _pool Pool address + @return Number of coins + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_n_underlying_coins(_pool) + + +@external +@view +def get_pool_asset_type(_pool: address, _handler_id: uint256 = 0) -> uint256: + """ + @notice Query the asset type of `_pool` + @param _pool Pool Address + @return The asset type as an unstripped string + @dev 0 : USD, 1: ETH, 2: BTC, 3: Other, 4: CryptoSwap + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_pool_asset_type(_pool) + + +@external +@view +def get_pool_from_lp_token(_token: address, _handler_id: uint256 = 0) -> address: + """ + @notice Get the pool associated with an LP token + @param _token LP token address + @return Pool address + """ + return self._get_pool_from_lp_token(_token) + + +@external +@view +def get_pool_params(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_POOL_PARAMS]: + """ + @notice Get the parameters of a pool + @param _pool Pool address + @param _handler_id id of registry handler + @return Pool parameters + """ + registry_handler: address = self._get_registry_handlers_from_pool(_pool)[_handler_id] + return RegistryHandler(registry_handler).get_pool_params(_pool) + + +@external +@view +def get_pool_name(_pool: address, _handler_id: uint256 = 0) -> String[64]: + """ + @notice Get the given name for a pool + @param _pool Pool address + @return The name of a pool + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_pool_name(_pool) + + +@external +@view +def get_underlying_balances(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: + """ + @notice Get balances for each underlying coin within a pool + @dev For non metapools, returns the same value as `get_balances` + @param _pool Pool address + @param _handler_id id of registry handler + @return uint256 List of underlyingbalances + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_underlying_balances(_pool) + + +@external +@view +def get_underlying_coins(_pool: address, _handler_id: uint256 = 0) -> address[MAX_COINS]: + """ + @notice Get the underlying coins within a pool + @dev For non metapools, returns the same value as `get_coins` + @param _pool Pool address + @param _handler_id id of registry handler + @return List of coin addresses + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_underlying_coins(_pool) + + +@external +@view +def get_underlying_decimals(_pool: address, _handler_id: uint256 = 0) -> uint256[MAX_COINS]: + """ + @notice Get decimal places for each underlying coin within a pool + @dev For non metapools, returns the same value as `get_decimals` + @param _pool Pool address + @param _handler_id id of registry handler + @return uint256 list of decimals + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).get_underlying_decimals(_pool) + + +@external +@view +def get_virtual_price_from_lp_token(_token: address, _handler_id: uint256 = 0) -> uint256: + """ + @notice Get the virtual price of a pool LP token + @param _token LP token address + @param _handler_id id of registry handler + @return uint256 Virtual price + """ + pool: address = self._get_pool_from_lp_token(_token) + registry_handler: address = self._get_registry_handlers_from_pool(pool)[_handler_id] + return RegistryHandler(registry_handler).get_virtual_price_from_lp_token(_token) + + +@external +@view +def is_meta(_pool: address, _handler_id: uint256 = 0) -> bool: + """ + @notice Verify `_pool` is a metapool + @param _pool Pool address + @param _handler_id id of registry handler + @return True if `_pool` is a metapool + """ + return RegistryHandler(self._get_registry_handlers_from_pool(_pool)[_handler_id]).is_meta(_pool) + + +@external +@view +def is_registered(_pool: address, _handler_id: uint256 = 0) -> bool: + """ + @notice Check if a pool is in the metaregistry using get_n_coins + @param _pool The address of the pool + @param _handler_id id of registry handler + @return A bool corresponding to whether the pool belongs or not + """ + return self._get_registry_handlers_from_pool(_pool)[_handler_id] != empty(address) + + +@external +@view +def pool_count() -> uint256: + """ + @notice Return the total number of pools tracked by the metaregistry + @return uint256 The number of pools in the metaregistry + """ + total_pools: uint256 = 0 + for i in range(MAX_REGISTRIES): + if i == self.registry_length: + break + handler: address = self.get_registry[i] + total_pools += RegistryHandler(handler).pool_count() + return total_pools + + +@external +@view +def pool_list(_index: uint256) -> address: + """ + @notice Return the pool at a given index in the metaregistry + @param _index The index of the pool in the metaregistry + @return The address of the pool at the given index + """ + pools_skip: uint256 = 0 + for i in range(MAX_REGISTRIES): + if i == self.registry_length: + break + handler: address = self.get_registry[i] + count: uint256 = RegistryHandler(handler).pool_count() + if _index - pools_skip < count: + return RegistryHandler(handler).pool_list(_index - pools_skip) + pools_skip += count + return empty(address) diff --git a/contracts/mainnet/abi/AddressProvider.json b/contracts/mainnet/abi/AddressProvider.json index 734cd08..063ebe0 100644 --- a/contracts/mainnet/abi/AddressProvider.json +++ b/contracts/mainnet/abi/AddressProvider.json @@ -1,309 +1,309 @@ -[ - { - "name": "NewAddressIdentifier", - "inputs": [ - { - "type": "uint256", - "name": "id", - "indexed": true - }, - { - "type": "address", - "name": "addr", - "indexed": false - }, - { - "type": "string", - "name": "description", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "AddressModified", - "inputs": [ - { - "type": "uint256", - "name": "id", - "indexed": true - }, - { - "type": "address", - "name": "new_address", - "indexed": false - }, - { - "type": "uint256", - "name": "version", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitNewAdmin", - "inputs": [ - { - "type": "uint256", - "name": "deadline", - "indexed": true - }, - { - "type": "address", - "name": "admin", - "indexed": true - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewAdmin", - "inputs": [ - { - "type": "address", - "name": "admin", - "indexed": true - } - ], - "anonymous": false, - "type": "event" - }, - { - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "_admin" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "name": "get_registry", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1061 - }, - { - "name": "max_id", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1258 - }, - { - "name": "get_address", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [ - { - "type": "uint256", - "name": "_id" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 1308 - }, - { - "name": "add_new_id", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "_address" - }, - { - "type": "string", - "name": "_description" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 291275 - }, - { - "name": "set_address", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [ - { - "type": "uint256", - "name": "_id" - }, - { - "type": "address", - "name": "_address" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 182430 - }, - { - "name": "unset_address", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [ - { - "type": "uint256", - "name": "_id" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 101348 - }, - { - "name": "commit_transfer_ownership", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "_new_admin" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 74048 - }, - { - "name": "apply_transfer_ownership", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 60125 - }, - { - "name": "revert_transfer_ownership", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 21400 - }, - { - "name": "admin", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1331 - }, - { - "name": "transfer_ownership_deadline", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1361 - }, - { - "name": "future_admin", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1391 - }, - { - "name": "get_id_info", - "outputs": [ - { - "type": "address", - "name": "addr" - }, - { - "type": "bool", - "name": "is_active" - }, - { - "type": "uint256", - "name": "version" - }, - { - "type": "uint256", - "name": "last_modified" - }, - { - "type": "string", - "name": "description" - } - ], - "inputs": [ - { - "type": "uint256", - "name": "arg0" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 12168 - } -] \ No newline at end of file +[ + { + "name": "NewAddressIdentifier", + "inputs": [ + { + "type": "uint256", + "name": "id", + "indexed": true + }, + { + "type": "address", + "name": "addr", + "indexed": false + }, + { + "type": "string", + "name": "description", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddressModified", + "inputs": [ + { + "type": "uint256", + "name": "id", + "indexed": true + }, + { + "type": "address", + "name": "new_address", + "indexed": false + }, + { + "type": "uint256", + "name": "version", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitNewAdmin", + "inputs": [ + { + "type": "uint256", + "name": "deadline", + "indexed": true + }, + { + "type": "address", + "name": "admin", + "indexed": true + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewAdmin", + "inputs": [ + { + "type": "address", + "name": "admin", + "indexed": true + } + ], + "anonymous": false, + "type": "event" + }, + { + "outputs": [], + "inputs": [ + { + "type": "address", + "name": "_admin" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "name": "get_registry", + "outputs": [ + { + "type": "address", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1061 + }, + { + "name": "max_id", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1258 + }, + { + "name": "get_address", + "outputs": [ + { + "type": "address", + "name": "" + } + ], + "inputs": [ + { + "type": "uint256", + "name": "_id" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 1308 + }, + { + "name": "add_new_id", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "_address" + }, + { + "type": "string", + "name": "_description" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 291275 + }, + { + "name": "set_address", + "outputs": [ + { + "type": "bool", + "name": "" + } + ], + "inputs": [ + { + "type": "uint256", + "name": "_id" + }, + { + "type": "address", + "name": "_address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 182430 + }, + { + "name": "unset_address", + "outputs": [ + { + "type": "bool", + "name": "" + } + ], + "inputs": [ + { + "type": "uint256", + "name": "_id" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 101348 + }, + { + "name": "commit_transfer_ownership", + "outputs": [ + { + "type": "bool", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "_new_admin" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 74048 + }, + { + "name": "apply_transfer_ownership", + "outputs": [ + { + "type": "bool", + "name": "" + } + ], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": 60125 + }, + { + "name": "revert_transfer_ownership", + "outputs": [ + { + "type": "bool", + "name": "" + } + ], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": 21400 + }, + { + "name": "admin", + "outputs": [ + { + "type": "address", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1331 + }, + { + "name": "transfer_ownership_deadline", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1361 + }, + { + "name": "future_admin", + "outputs": [ + { + "type": "address", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1391 + }, + { + "name": "get_id_info", + "outputs": [ + { + "type": "address", + "name": "addr" + }, + { + "type": "bool", + "name": "is_active" + }, + { + "type": "uint256", + "name": "version" + }, + { + "type": "uint256", + "name": "last_modified" + }, + { + "type": "string", + "name": "description" + } + ], + "inputs": [ + { + "type": "uint256", + "name": "arg0" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 12168 + } +] diff --git a/contracts/mainnet/abi/CryptoFactory.json b/contracts/mainnet/abi/CryptoFactory.json index f8c5747..6ae697b 100644 --- a/contracts/mainnet/abi/CryptoFactory.json +++ b/contracts/mainnet/abi/CryptoFactory.json @@ -1,635 +1,635 @@ -[ - { - "name": "CryptoPoolDeployed", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": false - }, - { - "name": "coins", - "type": "address[2]", - "indexed": false - }, - { - "name": "A", - "type": "uint256", - "indexed": false - }, - { - "name": "gamma", - "type": "uint256", - "indexed": false - }, - { - "name": "mid_fee", - "type": "uint256", - "indexed": false - }, - { - "name": "out_fee", - "type": "uint256", - "indexed": false - }, - { - "name": "allowed_extra_profit", - "type": "uint256", - "indexed": false - }, - { - "name": "fee_gamma", - "type": "uint256", - "indexed": false - }, - { - "name": "adjustment_step", - "type": "uint256", - "indexed": false - }, - { - "name": "admin_fee", - "type": "uint256", - "indexed": false - }, - { - "name": "ma_half_time", - "type": "uint256", - "indexed": false - }, - { - "name": "initial_price", - "type": "uint256", - "indexed": false - }, - { - "name": "deployer", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "LiquidityGaugeDeployed", - "inputs": [ - { - "name": "pool", - "type": "address", - "indexed": false - }, - { - "name": "token", - "type": "address", - "indexed": false - }, - { - "name": "gauge", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateFeeReceiver", - "inputs": [ - { - "name": "_old_fee_receiver", - "type": "address", - "indexed": false - }, - { - "name": "_new_fee_receiver", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdatePoolImplementation", - "inputs": [ - { - "name": "_old_pool_implementation", - "type": "address", - "indexed": false - }, - { - "name": "_new_pool_implementation", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateTokenImplementation", - "inputs": [ - { - "name": "_old_token_implementation", - "type": "address", - "indexed": false - }, - { - "name": "_new_token_implementation", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateGaugeImplementation", - "inputs": [ - { - "name": "_old_gauge_implementation", - "type": "address", - "indexed": false - }, - { - "name": "_new_gauge_implementation", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "TransferOwnership", - "inputs": [ - { - "name": "_old_owner", - "type": "address", - "indexed": false - }, - { - "name": "_new_owner", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "constructor", - "inputs": [ - { - "name": "_fee_receiver", - "type": "address" - }, - { - "name": "_pool_implementation", - "type": "address" - }, - { - "name": "_token_implementation", - "type": "address" - }, - { - "name": "_gauge_implementation", - "type": "address" - }, - { - "name": "_weth", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "deploy_pool", - "inputs": [ - { - "name": "_name", - "type": "string" - }, - { - "name": "_symbol", - "type": "string" - }, - { - "name": "_coins", - "type": "address[2]" - }, - { - "name": "A", - "type": "uint256" - }, - { - "name": "gamma", - "type": "uint256" - }, - { - "name": "mid_fee", - "type": "uint256" - }, - { - "name": "out_fee", - "type": "uint256" - }, - { - "name": "allowed_extra_profit", - "type": "uint256" - }, - { - "name": "fee_gamma", - "type": "uint256" - }, - { - "name": "adjustment_step", - "type": "uint256" - }, - { - "name": "admin_fee", - "type": "uint256" - }, - { - "name": "ma_half_time", - "type": "uint256" - }, - { - "name": "initial_price", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "deploy_gauge", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_fee_receiver", - "inputs": [ - { - "name": "_fee_receiver", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_pool_implementation", - "inputs": [ - { - "name": "_pool_implementation", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_token_implementation", - "inputs": [ - { - "name": "_token_implementation", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_gauge_implementation", - "inputs": [ - { - "name": "_gauge_implementation", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "commit_transfer_ownership", - "inputs": [ - { - "name": "_addr", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "accept_transfer_ownership", - "inputs": [], - "outputs": [] - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "i", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[2]" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_decimals", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[2]" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[2]" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_indices", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "uint256" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_gauge", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_eth_index", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_token", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "admin", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_admin", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "fee_receiver", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_implementation", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "token_implementation", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "gauge_implementation", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_count", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_list", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - } -] \ No newline at end of file +[ + { + "name": "CryptoPoolDeployed", + "inputs": [ + { + "name": "token", + "type": "address", + "indexed": false + }, + { + "name": "coins", + "type": "address[2]", + "indexed": false + }, + { + "name": "A", + "type": "uint256", + "indexed": false + }, + { + "name": "gamma", + "type": "uint256", + "indexed": false + }, + { + "name": "mid_fee", + "type": "uint256", + "indexed": false + }, + { + "name": "out_fee", + "type": "uint256", + "indexed": false + }, + { + "name": "allowed_extra_profit", + "type": "uint256", + "indexed": false + }, + { + "name": "fee_gamma", + "type": "uint256", + "indexed": false + }, + { + "name": "adjustment_step", + "type": "uint256", + "indexed": false + }, + { + "name": "admin_fee", + "type": "uint256", + "indexed": false + }, + { + "name": "ma_half_time", + "type": "uint256", + "indexed": false + }, + { + "name": "initial_price", + "type": "uint256", + "indexed": false + }, + { + "name": "deployer", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "LiquidityGaugeDeployed", + "inputs": [ + { + "name": "pool", + "type": "address", + "indexed": false + }, + { + "name": "token", + "type": "address", + "indexed": false + }, + { + "name": "gauge", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateFeeReceiver", + "inputs": [ + { + "name": "_old_fee_receiver", + "type": "address", + "indexed": false + }, + { + "name": "_new_fee_receiver", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdatePoolImplementation", + "inputs": [ + { + "name": "_old_pool_implementation", + "type": "address", + "indexed": false + }, + { + "name": "_new_pool_implementation", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateTokenImplementation", + "inputs": [ + { + "name": "_old_token_implementation", + "type": "address", + "indexed": false + }, + { + "name": "_new_token_implementation", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateGaugeImplementation", + "inputs": [ + { + "name": "_old_gauge_implementation", + "type": "address", + "indexed": false + }, + { + "name": "_new_gauge_implementation", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "TransferOwnership", + "inputs": [ + { + "name": "_old_owner", + "type": "address", + "indexed": false + }, + { + "name": "_new_owner", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { + "name": "_fee_receiver", + "type": "address" + }, + { + "name": "_pool_implementation", + "type": "address" + }, + { + "name": "_token_implementation", + "type": "address" + }, + { + "name": "_gauge_implementation", + "type": "address" + }, + { + "name": "_weth", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "deploy_pool", + "inputs": [ + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_coins", + "type": "address[2]" + }, + { + "name": "A", + "type": "uint256" + }, + { + "name": "gamma", + "type": "uint256" + }, + { + "name": "mid_fee", + "type": "uint256" + }, + { + "name": "out_fee", + "type": "uint256" + }, + { + "name": "allowed_extra_profit", + "type": "uint256" + }, + { + "name": "fee_gamma", + "type": "uint256" + }, + { + "name": "adjustment_step", + "type": "uint256" + }, + { + "name": "admin_fee", + "type": "uint256" + }, + { + "name": "ma_half_time", + "type": "uint256" + }, + { + "name": "initial_price", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "deploy_gauge", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_fee_receiver", + "inputs": [ + { + "name": "_fee_receiver", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_pool_implementation", + "inputs": [ + { + "name": "_pool_implementation", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_token_implementation", + "inputs": [ + { + "name": "_token_implementation", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_gauge_implementation", + "inputs": [ + { + "name": "_gauge_implementation", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_transfer_ownership", + "inputs": [ + { + "name": "_addr", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "accept_transfer_ownership", + "inputs": [], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "i", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[2]" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_decimals", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[2]" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[2]" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_indices", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_gauge", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_eth_index", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_token", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "fee_receiver", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "token_implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "gauge_implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_count", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_list", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + } +] diff --git a/contracts/mainnet/abi/CryptoRegistry.json b/contracts/mainnet/abi/CryptoRegistry.json index 486ef19..c3f997b 100644 --- a/contracts/mainnet/abi/CryptoRegistry.json +++ b/contracts/mainnet/abi/CryptoRegistry.json @@ -1,601 +1,601 @@ -[ - { - "name": "PoolAdded", - "inputs": [ - { - "name": "pool", - "type": "address", - "indexed": true - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "PoolRemoved", - "inputs": [ - { - "name": "pool", - "type": "address", - "indexed": true - } - ], - "anonymous": false, - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "constructor", - "inputs": [ - { - "name": "_address_provider", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3111 - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "i", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3111 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_n_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2834 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[8]" - } - ], - "gas": 22975 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_decimals", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 9818 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_gauges", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[10]" - }, - { - "name": "", - "type": "int128[10]" - } - ], - "gas": 26055 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 41626 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_virtual_price_from_lp_token", - "inputs": [ - { - "name": "_token", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 5321 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_A", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3139 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_D", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3169 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_gamma", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3199 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_fees", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[4]" - } - ], - "gas": 10333 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_admin_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 85771 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_indices", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "uint256" - } - ], - "gas": 23608 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_pool_name", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "gas": 13576 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_swap_count", - "inputs": [ - { - "name": "_coin", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3224 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_swap_complement", - "inputs": [ - { - "name": "_coin", - "type": "address" - }, - { - "name": "_index", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3299 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_pool", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_gauge", - "type": "address" - }, - { - "name": "_zap", - "type": "address" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - } - ], - "outputs": [], - "gas": 18586944 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_pool", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [], - "gas": 399675363514 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_liquidity_gauges", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_liquidity_gauges", - "type": "address[10]" - } - ], - "outputs": [], - "gas": 422284 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "batch_set_liquidity_gauges", - "inputs": [ - { - "name": "_pools", - "type": "address[10]" - }, - { - "name": "_liquidity_gauges", - "type": "address[10]" - } - ], - "outputs": [], - "gas": 444084 - }, - { - "stateMutability": "view", - "type": "function", - "name": "address_provider", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3126 - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_list", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3201 - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_count", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3186 - }, - { - "stateMutability": "view", - "type": "function", - "name": "coin_count", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3216 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3291 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_pool_from_lp_token", - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3548 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_lp_token", - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3578 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_zap", - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3608 - }, - { - "stateMutability": "view", - "type": "function", - "name": "last_updated", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3366 - } -] \ No newline at end of file +[ + { + "name": "PoolAdded", + "inputs": [ + { + "name": "pool", + "type": "address", + "indexed": true + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "PoolRemoved", + "inputs": [ + { + "name": "pool", + "type": "address", + "indexed": true + } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { + "name": "_address_provider", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3111 + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "i", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3111 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_n_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2834 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[8]" + } + ], + "gas": 22975 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_decimals", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 9818 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_gauges", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[10]" + }, + { + "name": "", + "type": "int128[10]" + } + ], + "gas": 26055 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 41626 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price_from_lp_token", + "inputs": [ + { + "name": "_token", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 5321 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_A", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3139 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_D", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3169 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_gamma", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3199 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_fees", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[4]" + } + ], + "gas": 10333 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_admin_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 85771 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_indices", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "gas": 23608 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_name", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "gas": 13576 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_count", + "inputs": [ + { + "name": "_coin", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3224 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_complement", + "inputs": [ + { + "name": "_coin", + "type": "address" + }, + { + "name": "_index", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3299 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_pool", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_lp_token", + "type": "address" + }, + { + "name": "_gauge", + "type": "address" + }, + { + "name": "_zap", + "type": "address" + }, + { + "name": "_decimals", + "type": "uint256" + }, + { + "name": "_name", + "type": "string" + } + ], + "outputs": [], + "gas": 18586944 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_pool", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [], + "gas": 399675363514 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_liquidity_gauges", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_liquidity_gauges", + "type": "address[10]" + } + ], + "outputs": [], + "gas": 422284 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "batch_set_liquidity_gauges", + "inputs": [ + { + "name": "_pools", + "type": "address[10]" + }, + { + "name": "_liquidity_gauges", + "type": "address[10]" + } + ], + "outputs": [], + "gas": 444084 + }, + { + "stateMutability": "view", + "type": "function", + "name": "address_provider", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3126 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_list", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3201 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_count", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3186 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coin_count", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3216 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3291 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_from_lp_token", + "inputs": [ + { + "name": "arg0", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3548 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_lp_token", + "inputs": [ + { + "name": "arg0", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3578 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_zap", + "inputs": [ + { + "name": "arg0", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3608 + }, + { + "stateMutability": "view", + "type": "function", + "name": "last_updated", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3366 + } +] diff --git a/contracts/mainnet/abi/GaugeController.json b/contracts/mainnet/abi/GaugeController.json index 12179c6..c4414a6 100644 --- a/contracts/mainnet/abi/GaugeController.json +++ b/contracts/mainnet/abi/GaugeController.json @@ -1,822 +1,822 @@ -[ - { - "name": "CommitOwnership", - "inputs": [ - { - "type": "address", - "name": "admin", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "ApplyOwnership", - "inputs": [ - { - "type": "address", - "name": "admin", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "AddType", - "inputs": [ - { - "type": "string", - "name": "name", - "indexed": false - }, - { - "type": "int128", - "name": "type_id", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewTypeWeight", - "inputs": [ - { - "type": "int128", - "name": "type_id", - "indexed": false - }, - { - "type": "uint256", - "name": "time", - "indexed": false - }, - { - "type": "uint256", - "name": "weight", - "indexed": false - }, - { - "type": "uint256", - "name": "total_weight", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewGaugeWeight", - "inputs": [ - { - "type": "address", - "name": "gauge_address", - "indexed": false - }, - { - "type": "uint256", - "name": "time", - "indexed": false - }, - { - "type": "uint256", - "name": "weight", - "indexed": false - }, - { - "type": "uint256", - "name": "total_weight", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "VoteForGauge", - "inputs": [ - { - "type": "uint256", - "name": "time", - "indexed": false - }, - { - "type": "address", - "name": "user", - "indexed": false - }, - { - "type": "address", - "name": "gauge_addr", - "indexed": false - }, - { - "type": "uint256", - "name": "weight", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewGauge", - "inputs": [ - { - "type": "address", - "name": "addr", - "indexed": false - }, - { - "type": "int128", - "name": "gauge_type", - "indexed": false - }, - { - "type": "uint256", - "name": "weight", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "_token" - }, - { - "type": "address", - "name": "_voting_escrow" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "name": "commit_transfer_ownership", - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "addr" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37597 - }, - { - "name": "apply_transfer_ownership", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 38497 - }, - { - "name": "gauge_types", - "outputs": [ - { - "type": "int128", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "_addr" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 1625 - }, - { - "name": "add_gauge", - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "addr" - }, - { - "type": "int128", - "name": "gauge_type" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "add_gauge", - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "addr" - }, - { - "type": "int128", - "name": "gauge_type" - }, - { - "type": "uint256", - "name": "weight" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "checkpoint", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 18033784416 - }, - { - "name": "checkpoint_gauge", - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "addr" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 18087678795 - }, - { - "name": "gauge_relative_weight", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "addr" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "name": "gauge_relative_weight", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "addr" - }, - { - "type": "uint256", - "name": "time" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "name": "gauge_relative_weight_write", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "addr" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "gauge_relative_weight_write", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "addr" - }, - { - "type": "uint256", - "name": "time" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "add_type", - "outputs": [], - "inputs": [ - { - "type": "string", - "name": "_name" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "add_type", - "outputs": [], - "inputs": [ - { - "type": "string", - "name": "_name" - }, - { - "type": "uint256", - "name": "weight" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "change_type_weight", - "outputs": [], - "inputs": [ - { - "type": "int128", - "name": "type_id" - }, - { - "type": "uint256", - "name": "weight" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 36246310050 - }, - { - "name": "change_gauge_weight", - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "addr" - }, - { - "type": "uint256", - "name": "weight" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 36354170809 - }, - { - "name": "vote_for_gauge_weights", - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "_gauge_addr" - }, - { - "type": "uint256", - "name": "_user_weight" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 18142052127 - }, - { - "name": "get_gauge_weight", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "addr" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2974 - }, - { - "name": "get_type_weight", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "int128", - "name": "type_id" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2977 - }, - { - "name": "get_total_weight", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2693 - }, - { - "name": "get_weights_sum_per_type", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "int128", - "name": "type_id" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 3109 - }, - { - "name": "admin", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1841 - }, - { - "name": "future_admin", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1871 - }, - { - "name": "token", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1901 - }, - { - "name": "voting_escrow", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1931 - }, - { - "name": "n_gauge_types", - "outputs": [ - { - "type": "int128", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1961 - }, - { - "name": "n_gauges", - "outputs": [ - { - "type": "int128", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1991 - }, - { - "name": "gauge_type_names", - "outputs": [ - { - "type": "string", - "name": "" - } - ], - "inputs": [ - { - "type": "int128", - "name": "arg0" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 8628 - }, - { - "name": "gauges", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [ - { - "type": "uint256", - "name": "arg0" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2160 - }, - { - "name": "vote_user_slopes", - "outputs": [ - { - "type": "uint256", - "name": "slope" - }, - { - "type": "uint256", - "name": "power" - }, - { - "type": "uint256", - "name": "end" - } - ], - "inputs": [ - { - "type": "address", - "name": "arg0" - }, - { - "type": "address", - "name": "arg1" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 5020 - }, - { - "name": "vote_user_power", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "arg0" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2265 - }, - { - "name": "last_user_vote", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "arg0" - }, - { - "type": "address", - "name": "arg1" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2449 - }, - { - "name": "points_weight", - "outputs": [ - { - "type": "uint256", - "name": "bias" - }, - { - "type": "uint256", - "name": "slope" - } - ], - "inputs": [ - { - "type": "address", - "name": "arg0" - }, - { - "type": "uint256", - "name": "arg1" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 3859 - }, - { - "name": "time_weight", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "arg0" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2355 - }, - { - "name": "points_sum", - "outputs": [ - { - "type": "uint256", - "name": "bias" - }, - { - "type": "uint256", - "name": "slope" - } - ], - "inputs": [ - { - "type": "int128", - "name": "arg0" - }, - { - "type": "uint256", - "name": "arg1" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 3970 - }, - { - "name": "time_sum", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "uint256", - "name": "arg0" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2370 - }, - { - "name": "points_total", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "uint256", - "name": "arg0" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2406 - }, - { - "name": "time_total", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2321 - }, - { - "name": "points_type_weight", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "int128", - "name": "arg0" - }, - { - "type": "uint256", - "name": "arg1" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2671 - }, - { - "name": "time_type_weight", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "uint256", - "name": "arg0" - } - ], - "stateMutability": "view", - "type": "function", - "gas": 2490 - } -] \ No newline at end of file +[ + { + "name": "CommitOwnership", + "inputs": [ + { + "type": "address", + "name": "admin", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "ApplyOwnership", + "inputs": [ + { + "type": "address", + "name": "admin", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddType", + "inputs": [ + { + "type": "string", + "name": "name", + "indexed": false + }, + { + "type": "int128", + "name": "type_id", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewTypeWeight", + "inputs": [ + { + "type": "int128", + "name": "type_id", + "indexed": false + }, + { + "type": "uint256", + "name": "time", + "indexed": false + }, + { + "type": "uint256", + "name": "weight", + "indexed": false + }, + { + "type": "uint256", + "name": "total_weight", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewGaugeWeight", + "inputs": [ + { + "type": "address", + "name": "gauge_address", + "indexed": false + }, + { + "type": "uint256", + "name": "time", + "indexed": false + }, + { + "type": "uint256", + "name": "weight", + "indexed": false + }, + { + "type": "uint256", + "name": "total_weight", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "VoteForGauge", + "inputs": [ + { + "type": "uint256", + "name": "time", + "indexed": false + }, + { + "type": "address", + "name": "user", + "indexed": false + }, + { + "type": "address", + "name": "gauge_addr", + "indexed": false + }, + { + "type": "uint256", + "name": "weight", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewGauge", + "inputs": [ + { + "type": "address", + "name": "addr", + "indexed": false + }, + { + "type": "int128", + "name": "gauge_type", + "indexed": false + }, + { + "type": "uint256", + "name": "weight", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "outputs": [], + "inputs": [ + { + "type": "address", + "name": "_token" + }, + { + "type": "address", + "name": "_voting_escrow" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "name": "commit_transfer_ownership", + "outputs": [], + "inputs": [ + { + "type": "address", + "name": "addr" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37597 + }, + { + "name": "apply_transfer_ownership", + "outputs": [], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": 38497 + }, + { + "name": "gauge_types", + "outputs": [ + { + "type": "int128", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "_addr" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 1625 + }, + { + "name": "add_gauge", + "outputs": [], + "inputs": [ + { + "type": "address", + "name": "addr" + }, + { + "type": "int128", + "name": "gauge_type" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "add_gauge", + "outputs": [], + "inputs": [ + { + "type": "address", + "name": "addr" + }, + { + "type": "int128", + "name": "gauge_type" + }, + { + "type": "uint256", + "name": "weight" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "checkpoint", + "outputs": [], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": 18033784416 + }, + { + "name": "checkpoint_gauge", + "outputs": [], + "inputs": [ + { + "type": "address", + "name": "addr" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 18087678795 + }, + { + "name": "gauge_relative_weight", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "addr" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "name": "gauge_relative_weight", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "addr" + }, + { + "type": "uint256", + "name": "time" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "name": "gauge_relative_weight_write", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "addr" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "gauge_relative_weight_write", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "addr" + }, + { + "type": "uint256", + "name": "time" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "add_type", + "outputs": [], + "inputs": [ + { + "type": "string", + "name": "_name" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "add_type", + "outputs": [], + "inputs": [ + { + "type": "string", + "name": "_name" + }, + { + "type": "uint256", + "name": "weight" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "change_type_weight", + "outputs": [], + "inputs": [ + { + "type": "int128", + "name": "type_id" + }, + { + "type": "uint256", + "name": "weight" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 36246310050 + }, + { + "name": "change_gauge_weight", + "outputs": [], + "inputs": [ + { + "type": "address", + "name": "addr" + }, + { + "type": "uint256", + "name": "weight" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 36354170809 + }, + { + "name": "vote_for_gauge_weights", + "outputs": [], + "inputs": [ + { + "type": "address", + "name": "_gauge_addr" + }, + { + "type": "uint256", + "name": "_user_weight" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 18142052127 + }, + { + "name": "get_gauge_weight", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "addr" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2974 + }, + { + "name": "get_type_weight", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "int128", + "name": "type_id" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2977 + }, + { + "name": "get_total_weight", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2693 + }, + { + "name": "get_weights_sum_per_type", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "int128", + "name": "type_id" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 3109 + }, + { + "name": "admin", + "outputs": [ + { + "type": "address", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1841 + }, + { + "name": "future_admin", + "outputs": [ + { + "type": "address", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1871 + }, + { + "name": "token", + "outputs": [ + { + "type": "address", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1901 + }, + { + "name": "voting_escrow", + "outputs": [ + { + "type": "address", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1931 + }, + { + "name": "n_gauge_types", + "outputs": [ + { + "type": "int128", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1961 + }, + { + "name": "n_gauges", + "outputs": [ + { + "type": "int128", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1991 + }, + { + "name": "gauge_type_names", + "outputs": [ + { + "type": "string", + "name": "" + } + ], + "inputs": [ + { + "type": "int128", + "name": "arg0" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 8628 + }, + { + "name": "gauges", + "outputs": [ + { + "type": "address", + "name": "" + } + ], + "inputs": [ + { + "type": "uint256", + "name": "arg0" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2160 + }, + { + "name": "vote_user_slopes", + "outputs": [ + { + "type": "uint256", + "name": "slope" + }, + { + "type": "uint256", + "name": "power" + }, + { + "type": "uint256", + "name": "end" + } + ], + "inputs": [ + { + "type": "address", + "name": "arg0" + }, + { + "type": "address", + "name": "arg1" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 5020 + }, + { + "name": "vote_user_power", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "arg0" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2265 + }, + { + "name": "last_user_vote", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "arg0" + }, + { + "type": "address", + "name": "arg1" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2449 + }, + { + "name": "points_weight", + "outputs": [ + { + "type": "uint256", + "name": "bias" + }, + { + "type": "uint256", + "name": "slope" + } + ], + "inputs": [ + { + "type": "address", + "name": "arg0" + }, + { + "type": "uint256", + "name": "arg1" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 3859 + }, + { + "name": "time_weight", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "address", + "name": "arg0" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2355 + }, + { + "name": "points_sum", + "outputs": [ + { + "type": "uint256", + "name": "bias" + }, + { + "type": "uint256", + "name": "slope" + } + ], + "inputs": [ + { + "type": "int128", + "name": "arg0" + }, + { + "type": "uint256", + "name": "arg1" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 3970 + }, + { + "name": "time_sum", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "uint256", + "name": "arg0" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2370 + }, + { + "name": "points_total", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "uint256", + "name": "arg0" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2406 + }, + { + "name": "time_total", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2321 + }, + { + "name": "points_type_weight", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "int128", + "name": "arg0" + }, + { + "type": "uint256", + "name": "arg1" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2671 + }, + { + "name": "time_type_weight", + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "inputs": [ + { + "type": "uint256", + "name": "arg0" + } + ], + "stateMutability": "view", + "type": "function", + "gas": 2490 + } +] diff --git a/contracts/mainnet/abi/ProxyAdmin.json b/contracts/mainnet/abi/ProxyAdmin.json index d4bc6c0..346cda5 100644 --- a/contracts/mainnet/abi/ProxyAdmin.json +++ b/contracts/mainnet/abi/ProxyAdmin.json @@ -1,204 +1,204 @@ -[ - { - "name": "TransactionExecuted", - "inputs": [ - { - "name": "admin", - "type": "address", - "indexed": true - }, - { - "name": "target", - "type": "address", - "indexed": true - }, - { - "name": "calldata", - "type": "bytes", - "indexed": false - }, - { - "name": "value", - "type": "uint256", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RequestAdminChange", - "inputs": [ - { - "name": "current_admin", - "type": "address", - "indexed": false - }, - { - "name": "future_admin", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RevokeAdminChange", - "inputs": [ - { - "name": "current_admin", - "type": "address", - "indexed": false - }, - { - "name": "future_admin", - "type": "address", - "indexed": false - }, - { - "name": "calling_admin", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "ApproveAdminChange", - "inputs": [ - { - "name": "current_admin", - "type": "address", - "indexed": false - }, - { - "name": "future_admin", - "type": "address", - "indexed": false - }, - { - "name": "calling_admin", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "AcceptAdminChange", - "inputs": [ - { - "name": "previous_admin", - "type": "address", - "indexed": false - }, - { - "name": "current_admin", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "constructor", - "inputs": [ - { - "name": "_authorized", - "type": "address[2]" - } - ], - "outputs": [] - }, - { - "stateMutability": "payable", - "type": "function", - "name": "execute", - "inputs": [ - { - "name": "_target", - "type": "address" - }, - { - "name": "_calldata", - "type": "bytes" - } - ], - "outputs": [] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_admin_change_status", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "bool" - } - ] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "request_admin_change", - "inputs": [ - { - "name": "_new_admin", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "approve_admin_change", - "inputs": [], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "revoke_admin_change", - "inputs": [], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "accept_admin_change", - "inputs": [], - "outputs": [] - }, - { - "stateMutability": "view", - "type": "function", - "name": "admins", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - } -] \ No newline at end of file +[ + { + "name": "TransactionExecuted", + "inputs": [ + { + "name": "admin", + "type": "address", + "indexed": true + }, + { + "name": "target", + "type": "address", + "indexed": true + }, + { + "name": "calldata", + "type": "bytes", + "indexed": false + }, + { + "name": "value", + "type": "uint256", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RequestAdminChange", + "inputs": [ + { + "name": "current_admin", + "type": "address", + "indexed": false + }, + { + "name": "future_admin", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RevokeAdminChange", + "inputs": [ + { + "name": "current_admin", + "type": "address", + "indexed": false + }, + { + "name": "future_admin", + "type": "address", + "indexed": false + }, + { + "name": "calling_admin", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "ApproveAdminChange", + "inputs": [ + { + "name": "current_admin", + "type": "address", + "indexed": false + }, + { + "name": "future_admin", + "type": "address", + "indexed": false + }, + { + "name": "calling_admin", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AcceptAdminChange", + "inputs": [ + { + "name": "previous_admin", + "type": "address", + "indexed": false + }, + { + "name": "current_admin", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { + "name": "_authorized", + "type": "address[2]" + } + ], + "outputs": [] + }, + { + "stateMutability": "payable", + "type": "function", + "name": "execute", + "inputs": [ + { + "name": "_target", + "type": "address" + }, + { + "name": "_calldata", + "type": "bytes" + } + ], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_admin_change_status", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "bool" + } + ] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "request_admin_change", + "inputs": [ + { + "name": "_new_admin", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "approve_admin_change", + "inputs": [], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revoke_admin_change", + "inputs": [], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "accept_admin_change", + "inputs": [], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "admins", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + } +] diff --git a/contracts/mainnet/abi/StableFactory.json b/contracts/mainnet/abi/StableFactory.json index d6697ca..1bb743d 100644 --- a/contracts/mainnet/abi/StableFactory.json +++ b/contracts/mainnet/abi/StableFactory.json @@ -1,1063 +1,1063 @@ -[ - { - "name": "BasePoolAdded", - "inputs": [ - { - "name": "base_pool", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "PlainPoolDeployed", - "inputs": [ - { - "name": "coins", - "type": "address[4]", - "indexed": false - }, - { - "name": "A", - "type": "uint256", - "indexed": false - }, - { - "name": "fee", - "type": "uint256", - "indexed": false - }, - { - "name": "deployer", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "MetaPoolDeployed", - "inputs": [ - { - "name": "coin", - "type": "address", - "indexed": false - }, - { - "name": "base_pool", - "type": "address", - "indexed": false - }, - { - "name": "A", - "type": "uint256", - "indexed": false - }, - { - "name": "fee", - "type": "uint256", - "indexed": false - }, - { - "name": "deployer", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "LiquidityGaugeDeployed", - "inputs": [ - { - "name": "pool", - "type": "address", - "indexed": false - }, - { - "name": "gauge", - "type": "address", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "constructor", - "inputs": [ - { - "name": "_fee_receiver", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "view", - "type": "function", - "name": "metapool_implementations", - "inputs": [ - { - "name": "_base_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[10]" - } - ], - "gas": 21716 - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "i", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_base_pool", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2663 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_n_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2699 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_meta_n_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "uint256" - } - ], - "gas": 5201 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[4]" - } - ], - "gas": 9164 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_underlying_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[8]" - } - ], - "gas": 21345 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_decimals", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[4]" - } - ], - "gas": 20185 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_underlying_decimals", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 19730 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_metapool_rates", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[2]" - } - ], - "gas": 5281 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[4]" - } - ], - "gas": 20435 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_underlying_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 39733 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_A", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3135 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_fees", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "uint256" - } - ], - "gas": 5821 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_admin_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[4]" - } - ], - "gas": 13535 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_indices", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "int128" - }, - { - "name": "", - "type": "int128" - }, - { - "name": "", - "type": "bool" - } - ], - "gas": 33407 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_gauge", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3089 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_implementation_address", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3119 - }, - { - "stateMutability": "view", - "type": "function", - "name": "is_meta", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "gas": 3152 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_pool_asset_type", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 5450 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_fee_receiver", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 5480 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "deploy_plain_pool", - "inputs": [ - { - "name": "_name", - "type": "string" - }, - { - "name": "_symbol", - "type": "string" - }, - { - "name": "_coins", - "type": "address[4]" - }, - { - "name": "_A", - "type": "uint256" - }, - { - "name": "_fee", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "deploy_plain_pool", - "inputs": [ - { - "name": "_name", - "type": "string" - }, - { - "name": "_symbol", - "type": "string" - }, - { - "name": "_coins", - "type": "address[4]" - }, - { - "name": "_A", - "type": "uint256" - }, - { - "name": "_fee", - "type": "uint256" - }, - { - "name": "_asset_type", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "deploy_plain_pool", - "inputs": [ - { - "name": "_name", - "type": "string" - }, - { - "name": "_symbol", - "type": "string" - }, - { - "name": "_coins", - "type": "address[4]" - }, - { - "name": "_A", - "type": "uint256" - }, - { - "name": "_fee", - "type": "uint256" - }, - { - "name": "_asset_type", - "type": "uint256" - }, - { - "name": "_implementation_idx", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "deploy_metapool", - "inputs": [ - { - "name": "_base_pool", - "type": "address" - }, - { - "name": "_name", - "type": "string" - }, - { - "name": "_symbol", - "type": "string" - }, - { - "name": "_coin", - "type": "address" - }, - { - "name": "_A", - "type": "uint256" - }, - { - "name": "_fee", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "deploy_metapool", - "inputs": [ - { - "name": "_base_pool", - "type": "address" - }, - { - "name": "_name", - "type": "string" - }, - { - "name": "_symbol", - "type": "string" - }, - { - "name": "_coin", - "type": "address" - }, - { - "name": "_A", - "type": "uint256" - }, - { - "name": "_fee", - "type": "uint256" - }, - { - "name": "_implementation_idx", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "deploy_gauge", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 93079 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_base_pool", - "inputs": [ - { - "name": "_base_pool", - "type": "address" - }, - { - "name": "_fee_receiver", - "type": "address" - }, - { - "name": "_asset_type", - "type": "uint256" - }, - { - "name": "_implementations", - "type": "address[10]" - } - ], - "outputs": [], - "gas": 1206132 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_metapool_implementations", - "inputs": [ - { - "name": "_base_pool", - "type": "address" - }, - { - "name": "_implementations", - "type": "address[10]" - } - ], - "outputs": [], - "gas": 382072 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_plain_implementations", - "inputs": [ - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_implementations", - "type": "address[10]" - } - ], - "outputs": [], - "gas": 379687 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_gauge_implementation", - "inputs": [ - { - "name": "_gauge_implementation", - "type": "address" - } - ], - "outputs": [], - "gas": 38355 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "batch_set_pool_asset_type", - "inputs": [ - { - "name": "_pools", - "type": "address[32]" - }, - { - "name": "_asset_types", - "type": "uint256[32]" - } - ], - "outputs": [], - "gas": 1139545 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "commit_transfer_ownership", - "inputs": [ - { - "name": "_addr", - "type": "address" - } - ], - "outputs": [], - "gas": 38415 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "accept_transfer_ownership", - "inputs": [], - "outputs": [], - "gas": 58366 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_manager", - "inputs": [ - { - "name": "_manager", - "type": "address" - } - ], - "outputs": [], - "gas": 40996 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_fee_receiver", - "inputs": [ - { - "name": "_base_pool", - "type": "address" - }, - { - "name": "_fee_receiver", - "type": "address" - } - ], - "outputs": [], - "gas": 38770 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "convert_metapool_fees", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "gas": 12880 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_existing_metapools", - "inputs": [ - { - "name": "_pools", - "type": "address[10]" - } - ], - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "gas": 8610792 - }, - { - "stateMutability": "view", - "type": "function", - "name": "admin", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3438 - }, - { - "stateMutability": "view", - "type": "function", - "name": "future_admin", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3468 - }, - { - "stateMutability": "view", - "type": "function", - "name": "manager", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3498 - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_list", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3573 - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_count", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3558 - }, - { - "stateMutability": "view", - "type": "function", - "name": "base_pool_list", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3633 - }, - { - "stateMutability": "view", - "type": "function", - "name": "base_pool_count", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 3618 - }, - { - "stateMutability": "view", - "type": "function", - "name": "base_pool_assets", - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "gas": 3863 - }, - { - "stateMutability": "view", - "type": "function", - "name": "plain_implementations", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - }, - { - "name": "arg1", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3838 - }, - { - "stateMutability": "view", - "type": "function", - "name": "gauge_implementation", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 3708 - } -] \ No newline at end of file +[ + { + "name": "BasePoolAdded", + "inputs": [ + { + "name": "base_pool", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "PlainPoolDeployed", + "inputs": [ + { + "name": "coins", + "type": "address[4]", + "indexed": false + }, + { + "name": "A", + "type": "uint256", + "indexed": false + }, + { + "name": "fee", + "type": "uint256", + "indexed": false + }, + { + "name": "deployer", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "MetaPoolDeployed", + "inputs": [ + { + "name": "coin", + "type": "address", + "indexed": false + }, + { + "name": "base_pool", + "type": "address", + "indexed": false + }, + { + "name": "A", + "type": "uint256", + "indexed": false + }, + { + "name": "fee", + "type": "uint256", + "indexed": false + }, + { + "name": "deployer", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "LiquidityGaugeDeployed", + "inputs": [ + { + "name": "pool", + "type": "address", + "indexed": false + }, + { + "name": "gauge", + "type": "address", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { + "name": "_fee_receiver", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "metapool_implementations", + "inputs": [ + { + "name": "_base_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[10]" + } + ], + "gas": 21716 + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "i", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_base_pool", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2663 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_n_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2699 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_meta_n_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "gas": 5201 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[4]" + } + ], + "gas": 9164 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[8]" + } + ], + "gas": 21345 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_decimals", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[4]" + } + ], + "gas": 20185 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_decimals", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 19730 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_metapool_rates", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[2]" + } + ], + "gas": 5281 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[4]" + } + ], + "gas": 20435 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 39733 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_A", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3135 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_fees", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "gas": 5821 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_admin_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[4]" + } + ], + "gas": 13535 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_indices", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "int128" + }, + { + "name": "", + "type": "int128" + }, + { + "name": "", + "type": "bool" + } + ], + "gas": 33407 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_gauge", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3089 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_implementation_address", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3119 + }, + { + "stateMutability": "view", + "type": "function", + "name": "is_meta", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "gas": 3152 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_asset_type", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 5450 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_fee_receiver", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 5480 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "deploy_plain_pool", + "inputs": [ + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_coins", + "type": "address[4]" + }, + { + "name": "_A", + "type": "uint256" + }, + { + "name": "_fee", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "deploy_plain_pool", + "inputs": [ + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_coins", + "type": "address[4]" + }, + { + "name": "_A", + "type": "uint256" + }, + { + "name": "_fee", + "type": "uint256" + }, + { + "name": "_asset_type", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "deploy_plain_pool", + "inputs": [ + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_coins", + "type": "address[4]" + }, + { + "name": "_A", + "type": "uint256" + }, + { + "name": "_fee", + "type": "uint256" + }, + { + "name": "_asset_type", + "type": "uint256" + }, + { + "name": "_implementation_idx", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "deploy_metapool", + "inputs": [ + { + "name": "_base_pool", + "type": "address" + }, + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_coin", + "type": "address" + }, + { + "name": "_A", + "type": "uint256" + }, + { + "name": "_fee", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "deploy_metapool", + "inputs": [ + { + "name": "_base_pool", + "type": "address" + }, + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_coin", + "type": "address" + }, + { + "name": "_A", + "type": "uint256" + }, + { + "name": "_fee", + "type": "uint256" + }, + { + "name": "_implementation_idx", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "deploy_gauge", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 93079 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_base_pool", + "inputs": [ + { + "name": "_base_pool", + "type": "address" + }, + { + "name": "_fee_receiver", + "type": "address" + }, + { + "name": "_asset_type", + "type": "uint256" + }, + { + "name": "_implementations", + "type": "address[10]" + } + ], + "outputs": [], + "gas": 1206132 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_metapool_implementations", + "inputs": [ + { + "name": "_base_pool", + "type": "address" + }, + { + "name": "_implementations", + "type": "address[10]" + } + ], + "outputs": [], + "gas": 382072 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_plain_implementations", + "inputs": [ + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_implementations", + "type": "address[10]" + } + ], + "outputs": [], + "gas": 379687 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_gauge_implementation", + "inputs": [ + { + "name": "_gauge_implementation", + "type": "address" + } + ], + "outputs": [], + "gas": 38355 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "batch_set_pool_asset_type", + "inputs": [ + { + "name": "_pools", + "type": "address[32]" + }, + { + "name": "_asset_types", + "type": "uint256[32]" + } + ], + "outputs": [], + "gas": 1139545 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_transfer_ownership", + "inputs": [ + { + "name": "_addr", + "type": "address" + } + ], + "outputs": [], + "gas": 38415 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "accept_transfer_ownership", + "inputs": [], + "outputs": [], + "gas": 58366 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_manager", + "inputs": [ + { + "name": "_manager", + "type": "address" + } + ], + "outputs": [], + "gas": 40996 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_fee_receiver", + "inputs": [ + { + "name": "_base_pool", + "type": "address" + }, + { + "name": "_fee_receiver", + "type": "address" + } + ], + "outputs": [], + "gas": 38770 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "convert_metapool_fees", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "gas": 12880 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_existing_metapools", + "inputs": [ + { + "name": "_pools", + "type": "address[10]" + } + ], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "gas": 8610792 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3438 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3468 + }, + { + "stateMutability": "view", + "type": "function", + "name": "manager", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3498 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_list", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3573 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_count", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3558 + }, + { + "stateMutability": "view", + "type": "function", + "name": "base_pool_list", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3633 + }, + { + "stateMutability": "view", + "type": "function", + "name": "base_pool_count", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 3618 + }, + { + "stateMutability": "view", + "type": "function", + "name": "base_pool_assets", + "inputs": [ + { + "name": "arg0", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "gas": 3863 + }, + { + "stateMutability": "view", + "type": "function", + "name": "plain_implementations", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + }, + { + "name": "arg1", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3838 + }, + { + "stateMutability": "view", + "type": "function", + "name": "gauge_implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 3708 + } +] diff --git a/contracts/mainnet/abi/StableRegistry.json b/contracts/mainnet/abi/StableRegistry.json index ac50894..5e0726e 100644 --- a/contracts/mainnet/abi/StableRegistry.json +++ b/contracts/mainnet/abi/StableRegistry.json @@ -1,940 +1,940 @@ -[ - { - "name": "PoolAdded", - "inputs": [ - { - "name": "pool", - "type": "address", - "indexed": true - }, - { - "name": "rate_method_id", - "type": "bytes", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "PoolRemoved", - "inputs": [ - { - "name": "pool", - "type": "address", - "indexed": true - } - ], - "anonymous": false, - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "constructor", - "inputs": [ - { - "name": "_address_provider", - "type": "address" - }, - { - "name": "_gauge_controller", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "find_pool_for_coins", - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "i", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ] - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_n_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[2]" - } - ], - "gas": 1521 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[8]" - } - ], - "gas": 12102 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_underlying_coins", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[8]" - } - ], - "gas": 12194 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_decimals", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 7874 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_underlying_decimals", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 7966 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_rates", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 36992 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_gauges", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address[10]" - }, - { - "name": "", - "type": "int128[10]" - } - ], - "gas": 20157 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 16583 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_underlying_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 162842 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_virtual_price_from_lp_token", - "inputs": [ - { - "name": "_token", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 1927 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_A", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 1045 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_parameters", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "A", - "type": "uint256" - }, - { - "name": "future_A", - "type": "uint256" - }, - { - "name": "fee", - "type": "uint256" - }, - { - "name": "admin_fee", - "type": "uint256" - }, - { - "name": "future_fee", - "type": "uint256" - }, - { - "name": "future_admin_fee", - "type": "uint256" - }, - { - "name": "future_owner", - "type": "address" - }, - { - "name": "initial_A", - "type": "uint256" - }, - { - "name": "initial_A_time", - "type": "uint256" - }, - { - "name": "future_A_time", - "type": "uint256" - } - ], - "gas": 6305 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_fees", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[2]" - } - ], - "gas": 1450 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_admin_balances", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "gas": 36454 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_indices", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "int128" - }, - { - "name": "", - "type": "int128" - }, - { - "name": "", - "type": "bool" - } - ], - "gas": 27131 - }, - { - "stateMutability": "view", - "type": "function", - "name": "estimate_gas_used", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 32004 - }, - { - "stateMutability": "view", - "type": "function", - "name": "is_meta", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "gas": 1900 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_pool_name", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "gas": 8323 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_swap_count", - "inputs": [ - { - "name": "_coin", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 1951 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin_swap_complement", - "inputs": [ - { - "name": "_coin", - "type": "address" - }, - { - "name": "_index", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2090 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_pool_asset_type", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2011 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_pool", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_rate_info", - "type": "bytes32" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_underlying_decimals", - "type": "uint256" - }, - { - "name": "_has_initial_A", - "type": "bool" - }, - { - "name": "_is_v1", - "type": "bool" - }, - { - "name": "_name", - "type": "string" - } - ], - "outputs": [], - "gas": 61485845 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_pool_without_underlying", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_rate_info", - "type": "bytes32" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_use_rates", - "type": "uint256" - }, - { - "name": "_has_initial_A", - "type": "bool" - }, - { - "name": "_is_v1", - "type": "bool" - }, - { - "name": "_name", - "type": "string" - } - ], - "outputs": [], - "gas": 31306062 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_metapool", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "add_metapool", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - }, - { - "name": "_base_pool", - "type": "address" - } - ], - "outputs": [] - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "remove_pool", - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "outputs": [], - "gas": 779731418758 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_pool_gas_estimates", - "inputs": [ - { - "name": "_addr", - "type": "address[5]" - }, - { - "name": "_amount", - "type": "uint256[2][5]" - } - ], - "outputs": [], - "gas": 390460 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_coin_gas_estimates", - "inputs": [ - { - "name": "_addr", - "type": "address[10]" - }, - { - "name": "_amount", - "type": "uint256[10]" - } - ], - "outputs": [], - "gas": 392047 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_gas_estimate_contract", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_estimator", - "type": "address" - } - ], - "outputs": [], - "gas": 72629 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_liquidity_gauges", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_liquidity_gauges", - "type": "address[10]" - } - ], - "outputs": [], - "gas": 400675 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "set_pool_asset_type", - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_asset_type", - "type": "uint256" - } - ], - "outputs": [], - "gas": 72667 - }, - { - "stateMutability": "nonpayable", - "type": "function", - "name": "batch_set_pool_asset_type", - "inputs": [ - { - "name": "_pools", - "type": "address[32]" - }, - { - "name": "_asset_types", - "type": "uint256[32]" - } - ], - "outputs": [], - "gas": 1173447 - }, - { - "stateMutability": "view", - "type": "function", - "name": "address_provider", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2048 - }, - { - "stateMutability": "view", - "type": "function", - "name": "gauge_controller", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2078 - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_list", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2217 - }, - { - "stateMutability": "view", - "type": "function", - "name": "pool_count", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2138 - }, - { - "stateMutability": "view", - "type": "function", - "name": "coin_count", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2168 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_coin", - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2307 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_pool_from_lp_token", - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2443 - }, - { - "stateMutability": "view", - "type": "function", - "name": "get_lp_token", - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "gas": 2473 - }, - { - "stateMutability": "view", - "type": "function", - "name": "last_updated", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "gas": 2288 - } -] \ No newline at end of file +[ + { + "name": "PoolAdded", + "inputs": [ + { + "name": "pool", + "type": "address", + "indexed": true + }, + { + "name": "rate_method_id", + "type": "bytes", + "indexed": false + } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "PoolRemoved", + "inputs": [ + { + "name": "pool", + "type": "address", + "indexed": true + } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { + "name": "_address_provider", + "type": "address" + }, + { + "name": "_gauge_controller", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "i", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_n_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[2]" + } + ], + "gas": 1521 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[8]" + } + ], + "gas": 12102 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_coins", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[8]" + } + ], + "gas": 12194 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_decimals", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 7874 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_decimals", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 7966 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_rates", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 36992 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_gauges", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address[10]" + }, + { + "name": "", + "type": "int128[10]" + } + ], + "gas": 20157 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 16583 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 162842 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price_from_lp_token", + "inputs": [ + { + "name": "_token", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 1927 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_A", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 1045 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_parameters", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "A", + "type": "uint256" + }, + { + "name": "future_A", + "type": "uint256" + }, + { + "name": "fee", + "type": "uint256" + }, + { + "name": "admin_fee", + "type": "uint256" + }, + { + "name": "future_fee", + "type": "uint256" + }, + { + "name": "future_admin_fee", + "type": "uint256" + }, + { + "name": "future_owner", + "type": "address" + }, + { + "name": "initial_A", + "type": "uint256" + }, + { + "name": "initial_A_time", + "type": "uint256" + }, + { + "name": "future_A_time", + "type": "uint256" + } + ], + "gas": 6305 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_fees", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[2]" + } + ], + "gas": 1450 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_admin_balances", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[8]" + } + ], + "gas": 36454 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_indices", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "int128" + }, + { + "name": "", + "type": "int128" + }, + { + "name": "", + "type": "bool" + } + ], + "gas": 27131 + }, + { + "stateMutability": "view", + "type": "function", + "name": "estimate_gas_used", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 32004 + }, + { + "stateMutability": "view", + "type": "function", + "name": "is_meta", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "gas": 1900 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_name", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "gas": 8323 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_count", + "inputs": [ + { + "name": "_coin", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 1951 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_complement", + "inputs": [ + { + "name": "_coin", + "type": "address" + }, + { + "name": "_index", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2090 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_asset_type", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2011 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_pool", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_lp_token", + "type": "address" + }, + { + "name": "_rate_info", + "type": "bytes32" + }, + { + "name": "_decimals", + "type": "uint256" + }, + { + "name": "_underlying_decimals", + "type": "uint256" + }, + { + "name": "_has_initial_A", + "type": "bool" + }, + { + "name": "_is_v1", + "type": "bool" + }, + { + "name": "_name", + "type": "string" + } + ], + "outputs": [], + "gas": 61485845 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_pool_without_underlying", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_lp_token", + "type": "address" + }, + { + "name": "_rate_info", + "type": "bytes32" + }, + { + "name": "_decimals", + "type": "uint256" + }, + { + "name": "_use_rates", + "type": "uint256" + }, + { + "name": "_has_initial_A", + "type": "bool" + }, + { + "name": "_is_v1", + "type": "bool" + }, + { + "name": "_name", + "type": "string" + } + ], + "outputs": [], + "gas": 31306062 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_metapool", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_lp_token", + "type": "address" + }, + { + "name": "_decimals", + "type": "uint256" + }, + { + "name": "_name", + "type": "string" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_metapool", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_n_coins", + "type": "uint256" + }, + { + "name": "_lp_token", + "type": "address" + }, + { + "name": "_decimals", + "type": "uint256" + }, + { + "name": "_name", + "type": "string" + }, + { + "name": "_base_pool", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_pool", + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [], + "gas": 779731418758 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_pool_gas_estimates", + "inputs": [ + { + "name": "_addr", + "type": "address[5]" + }, + { + "name": "_amount", + "type": "uint256[2][5]" + } + ], + "outputs": [], + "gas": 390460 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_coin_gas_estimates", + "inputs": [ + { + "name": "_addr", + "type": "address[10]" + }, + { + "name": "_amount", + "type": "uint256[10]" + } + ], + "outputs": [], + "gas": 392047 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_gas_estimate_contract", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_estimator", + "type": "address" + } + ], + "outputs": [], + "gas": 72629 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_liquidity_gauges", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_liquidity_gauges", + "type": "address[10]" + } + ], + "outputs": [], + "gas": 400675 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_pool_asset_type", + "inputs": [ + { + "name": "_pool", + "type": "address" + }, + { + "name": "_asset_type", + "type": "uint256" + } + ], + "outputs": [], + "gas": 72667 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "batch_set_pool_asset_type", + "inputs": [ + { + "name": "_pools", + "type": "address[32]" + }, + { + "name": "_asset_types", + "type": "uint256[32]" + } + ], + "outputs": [], + "gas": 1173447 + }, + { + "stateMutability": "view", + "type": "function", + "name": "address_provider", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2048 + }, + { + "stateMutability": "view", + "type": "function", + "name": "gauge_controller", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2078 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_list", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2217 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_count", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2138 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coin_count", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2168 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin", + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2307 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_from_lp_token", + "inputs": [ + { + "name": "arg0", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2443 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_lp_token", + "inputs": [ + { + "name": "arg0", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "gas": 2473 + }, + { + "stateMutability": "view", + "type": "function", + "name": "last_updated", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "gas": 2288 + } +] diff --git a/contracts/mainnet/registries/BasePoolRegistry.vy b/contracts/mainnet/registries/BasePoolRegistry.vy index 1f5535b..f39dd9d 100644 --- a/contracts/mainnet/registries/BasePoolRegistry.vy +++ b/contracts/mainnet/registries/BasePoolRegistry.vy @@ -1,286 +1,286 @@ -#pragma version ^0.3.7 -""" -@title Curve BasePool Registry -@license MIT -@author Curve.Fi -""" -MAX_COINS: constant(uint256) = 8 - - -struct BasePool: - location: uint256 - lp_token: address - n_coins: uint256 - is_v2: bool - is_legacy: bool - is_lending: bool - - -interface AddressProvider: - def admin() -> address: view - - -interface ERC20: - def decimals() -> uint256: view - - -interface CurvePoolLegacy: - def coins(i: int128) -> address: view - - -interface CurvePool: - def coins(i: uint256) -> address: view - - -event BasePoolAdded: - basepool: indexed(address) - - -event BasePoolRemoved: - basepool: indexed(address) - - -ADDRESS_PROVIDER: constant(address) = 0x0000000022D53366457F9d5E68Ec105046FC4383 -base_pool: HashMap[address, BasePool] -base_pool_list: public(address[100]) -get_base_pool_for_lp_token: public(HashMap[address, address]) -base_pool_count: public(uint256) -last_updated: public(uint256) - - -@internal -@view -def _get_basepool_coins(_pool: address) -> address[MAX_COINS]: - _n_coins: uint256 = self.base_pool[_pool].n_coins - _is_legacy: bool = self.base_pool[_pool].is_legacy - _coins: address[MAX_COINS] = empty(address[MAX_COINS]) - for i in range(MAX_COINS): - if i == _n_coins: - break - - if _is_legacy: - _coins[i] = CurvePoolLegacy(_pool).coins(convert(i, int128)) - else: - _coins[i] = CurvePool(_pool).coins(i) - - return _coins - - - -@internal -@view -def _get_basepools_for_coin(_coin: address) -> DynArray[address, 1000]: - """ - @notice Gets the base pool for a coin - @dev Some coins can be in multiple base pools, this function returns - the base pool for a coin at a specific index - @param _coin Address of the coin - @return basepool addresses - """ - _base_pools: DynArray[address, 1000] = empty(DynArray[address, 1000]) - for _pool in self.base_pool_list: - _coins: address[MAX_COINS] = self._get_basepool_coins(_pool) - if _coin in _coins: - _base_pools.append(_pool) - - return _base_pools - - -@external -@view -def get_coins(_pool: address) -> address[MAX_COINS]: - """ - @notice Gets coins in a base pool - @param _pool Address of the base pool - @return address[MAX_COINS] with coin addresses - """ - return self._get_basepool_coins(_pool) - - -@external -@view -def get_basepool_for_coin(_coin: address, _idx: uint256 = 0) -> address: - """ - @notice Gets the base pool for a coin - @dev Some coins can be in multiple base pools, this function returns - the base pool for a coin at a specific index - @param _coin Address of the coin - @param _idx Index of base pool that holds the coin - @return basepool address - """ - return self._get_basepools_for_coin(_coin)[_idx] - - -@external -@view -def get_basepools_for_coin(_coin: address) -> DynArray[address, 1000]: - """ - @notice Gets the base pool for a coin - @dev Some coins can be in multiple base pools, this function returns - the base pool for a coin at a specific index - @param _coin Address of the coin - @return basepool addresses - """ - return self._get_basepools_for_coin(_coin) - - -@external -@view -def get_decimals(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Gets decimals of coins in a base pool - @param _pool Address of the base pool - @return uint256[MAX_COINS] containing coin decimals - """ - _coins: address[MAX_COINS] = self._get_basepool_coins(_pool) - _decimals: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) - for i in range(MAX_COINS): - if _coins[i] == empty(address): - break - if _coins[i] == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE: - _decimals[i] = 18 - else: - _decimals[i] = ERC20(_coins[i]).decimals() - - return _decimals - - -@external -@view -def get_lp_token(_pool: address) -> address: - """ - @notice Gets the LP token of a base pool - @param _pool Address of the base pool - @return address of the LP token - """ - return self.base_pool[_pool].lp_token - - -@external -@view -def get_n_coins(_pool: address) -> uint256: - """ - @notice Gets the number of coins in a base pool - @param _pool Address of the base pool - @return uint256 number of coins - """ - return self.base_pool[_pool].n_coins - - -@external -@view -def get_location(_pool: address) -> uint256: - """ - @notice Gets the index where a base pool's - data is stored in the registry - @param _pool Address of the base pool - @return uint256 index of the base pool - """ - return self.base_pool[_pool].location - - -@external -@view -def is_legacy(_pool: address) -> bool: - """ - @notice Checks if a base pool uses Curve's legacy abi - @dev Legacy abi includes int128 indices whereas the newer - abi uses uint256 indices - @param _pool Address of the base pool - @return bool True if legacy abi is used - """ - return self.base_pool[_pool].is_legacy - - -@external -@view -def is_v2(_pool: address) -> bool: - """ - @notice Checks if a base pool is a Curve CryptoSwap pool - @param _pool Address of the base pool - @return bool True if the pool is a Curve CryptoSwap pool - """ - return self.base_pool[_pool].is_v2 - - -@external -@view -def is_lending(_pool: address) -> bool: - """ - @notice Checks if a base pool is a Curve Lending pool - @param _pool Address of the base pool - @return bool True if the pool is a Curve Lending pool - """ - return self.base_pool[_pool].is_lending - - -@external -def add_base_pool(_pool: address, _lp_token: address, _n_coins: uint256, _is_legacy: bool, _is_lending: bool, _is_v2: bool): - """ - @notice Add a base pool to the registry - @param _pool Address of the base pool - @param _lp_token Address of the LP token - @param _n_coins Number of coins in the base pool - @param _is_legacy True if the base pool uses legacy abi - @param _is_lending True if the base pool is a Curve Lending pool - @param _is_v2 True if the base pool is a Curve CryptoSwap pool - """ - assert msg.sender == AddressProvider(ADDRESS_PROVIDER).admin() # dev: admin-only function - assert self.base_pool[_pool].lp_token == empty(address) # dev: pool exists - - # add pool to base_pool_list - base_pool_count: uint256 = self.base_pool_count - self.base_pool[_pool].location = base_pool_count - self.base_pool[_pool].lp_token = _lp_token - self.base_pool[_pool].n_coins = _n_coins - self.base_pool[_pool].is_v2 = _is_v2 - self.base_pool[_pool].is_legacy = _is_legacy - self.base_pool[_pool].is_lending = _is_lending - - # for reverse lookup: - self.get_base_pool_for_lp_token[_lp_token] = _pool - - self.last_updated = block.timestamp - self.base_pool_list[base_pool_count] = _pool - self.base_pool_count = base_pool_count + 1 - log BasePoolAdded(_pool) - - -@external -def remove_base_pool(_pool: address): - """ - @notice Remove a base pool from the registry - @param _pool Address of the base pool - """ - assert msg.sender == AddressProvider(ADDRESS_PROVIDER).admin() # dev: admin-only function - assert _pool != empty(address) - assert self.base_pool[_pool].lp_token != empty(address) # dev: pool doesn't exist - - # reset pool <> lp_token mappings - self.get_base_pool_for_lp_token[self.base_pool[_pool].lp_token] = empty(address) - self.base_pool[_pool].lp_token = empty(address) - self.base_pool[_pool].n_coins = 0 - - # remove base_pool from base_pool_list - location: uint256 = self.base_pool[_pool].location - length: uint256 = self.base_pool_count - 1 - assert location < length - - # because self.base_pool_list is a static array, - # we can replace the last index with empty(address) - # and replace the first index with the base pool - # that was previously in the last index. - # we skip this step if location == last index - if location < length: - # replace _pool with final value in pool_list - addr: address = self.base_pool_list[length] - assert addr != empty(address) - self.base_pool_list[location] = addr - self.base_pool[addr].location = location - - # delete final pool_list value - self.base_pool_list[length] = empty(address) - self.base_pool_count = length - - self.last_updated = block.timestamp - log BasePoolRemoved(_pool) +#pragma version ^0.3.7 +""" +@title Curve BasePool Registry +@license MIT +@author Curve.Fi +""" +MAX_COINS: constant(uint256) = 8 + + +struct BasePool: + location: uint256 + lp_token: address + n_coins: uint256 + is_v2: bool + is_legacy: bool + is_lending: bool + + +interface AddressProvider: + def admin() -> address: view + + +interface ERC20: + def decimals() -> uint256: view + + +interface CurvePoolLegacy: + def coins(i: int128) -> address: view + + +interface CurvePool: + def coins(i: uint256) -> address: view + + +event BasePoolAdded: + basepool: indexed(address) + + +event BasePoolRemoved: + basepool: indexed(address) + + +ADDRESS_PROVIDER: constant(address) = 0x0000000022D53366457F9d5E68Ec105046FC4383 +base_pool: HashMap[address, BasePool] +base_pool_list: public(address[100]) +get_base_pool_for_lp_token: public(HashMap[address, address]) +base_pool_count: public(uint256) +last_updated: public(uint256) + + +@internal +@view +def _get_basepool_coins(_pool: address) -> address[MAX_COINS]: + _n_coins: uint256 = self.base_pool[_pool].n_coins + _is_legacy: bool = self.base_pool[_pool].is_legacy + _coins: address[MAX_COINS] = empty(address[MAX_COINS]) + for i in range(MAX_COINS): + if i == _n_coins: + break + + if _is_legacy: + _coins[i] = CurvePoolLegacy(_pool).coins(convert(i, int128)) + else: + _coins[i] = CurvePool(_pool).coins(i) + + return _coins + + + +@internal +@view +def _get_basepools_for_coin(_coin: address) -> DynArray[address, 1000]: + """ + @notice Gets the base pool for a coin + @dev Some coins can be in multiple base pools, this function returns + the base pool for a coin at a specific index + @param _coin Address of the coin + @return basepool addresses + """ + _base_pools: DynArray[address, 1000] = empty(DynArray[address, 1000]) + for _pool in self.base_pool_list: + _coins: address[MAX_COINS] = self._get_basepool_coins(_pool) + if _coin in _coins: + _base_pools.append(_pool) + + return _base_pools + + +@external +@view +def get_coins(_pool: address) -> address[MAX_COINS]: + """ + @notice Gets coins in a base pool + @param _pool Address of the base pool + @return address[MAX_COINS] with coin addresses + """ + return self._get_basepool_coins(_pool) + + +@external +@view +def get_basepool_for_coin(_coin: address, _idx: uint256 = 0) -> address: + """ + @notice Gets the base pool for a coin + @dev Some coins can be in multiple base pools, this function returns + the base pool for a coin at a specific index + @param _coin Address of the coin + @param _idx Index of base pool that holds the coin + @return basepool address + """ + return self._get_basepools_for_coin(_coin)[_idx] + + +@external +@view +def get_basepools_for_coin(_coin: address) -> DynArray[address, 1000]: + """ + @notice Gets the base pool for a coin + @dev Some coins can be in multiple base pools, this function returns + the base pool for a coin at a specific index + @param _coin Address of the coin + @return basepool addresses + """ + return self._get_basepools_for_coin(_coin) + + +@external +@view +def get_decimals(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Gets decimals of coins in a base pool + @param _pool Address of the base pool + @return uint256[MAX_COINS] containing coin decimals + """ + _coins: address[MAX_COINS] = self._get_basepool_coins(_pool) + _decimals: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) + for i in range(MAX_COINS): + if _coins[i] == empty(address): + break + if _coins[i] == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE: + _decimals[i] = 18 + else: + _decimals[i] = ERC20(_coins[i]).decimals() + + return _decimals + + +@external +@view +def get_lp_token(_pool: address) -> address: + """ + @notice Gets the LP token of a base pool + @param _pool Address of the base pool + @return address of the LP token + """ + return self.base_pool[_pool].lp_token + + +@external +@view +def get_n_coins(_pool: address) -> uint256: + """ + @notice Gets the number of coins in a base pool + @param _pool Address of the base pool + @return uint256 number of coins + """ + return self.base_pool[_pool].n_coins + + +@external +@view +def get_location(_pool: address) -> uint256: + """ + @notice Gets the index where a base pool's + data is stored in the registry + @param _pool Address of the base pool + @return uint256 index of the base pool + """ + return self.base_pool[_pool].location + + +@external +@view +def is_legacy(_pool: address) -> bool: + """ + @notice Checks if a base pool uses Curve's legacy abi + @dev Legacy abi includes int128 indices whereas the newer + abi uses uint256 indices + @param _pool Address of the base pool + @return bool True if legacy abi is used + """ + return self.base_pool[_pool].is_legacy + + +@external +@view +def is_v2(_pool: address) -> bool: + """ + @notice Checks if a base pool is a Curve CryptoSwap pool + @param _pool Address of the base pool + @return bool True if the pool is a Curve CryptoSwap pool + """ + return self.base_pool[_pool].is_v2 + + +@external +@view +def is_lending(_pool: address) -> bool: + """ + @notice Checks if a base pool is a Curve Lending pool + @param _pool Address of the base pool + @return bool True if the pool is a Curve Lending pool + """ + return self.base_pool[_pool].is_lending + + +@external +def add_base_pool(_pool: address, _lp_token: address, _n_coins: uint256, _is_legacy: bool, _is_lending: bool, _is_v2: bool): + """ + @notice Add a base pool to the registry + @param _pool Address of the base pool + @param _lp_token Address of the LP token + @param _n_coins Number of coins in the base pool + @param _is_legacy True if the base pool uses legacy abi + @param _is_lending True if the base pool is a Curve Lending pool + @param _is_v2 True if the base pool is a Curve CryptoSwap pool + """ + assert msg.sender == AddressProvider(ADDRESS_PROVIDER).admin() # dev: admin-only function + assert self.base_pool[_pool].lp_token == empty(address) # dev: pool exists + + # add pool to base_pool_list + base_pool_count: uint256 = self.base_pool_count + self.base_pool[_pool].location = base_pool_count + self.base_pool[_pool].lp_token = _lp_token + self.base_pool[_pool].n_coins = _n_coins + self.base_pool[_pool].is_v2 = _is_v2 + self.base_pool[_pool].is_legacy = _is_legacy + self.base_pool[_pool].is_lending = _is_lending + + # for reverse lookup: + self.get_base_pool_for_lp_token[_lp_token] = _pool + + self.last_updated = block.timestamp + self.base_pool_list[base_pool_count] = _pool + self.base_pool_count = base_pool_count + 1 + log BasePoolAdded(_pool) + + +@external +def remove_base_pool(_pool: address): + """ + @notice Remove a base pool from the registry + @param _pool Address of the base pool + """ + assert msg.sender == AddressProvider(ADDRESS_PROVIDER).admin() # dev: admin-only function + assert _pool != empty(address) + assert self.base_pool[_pool].lp_token != empty(address) # dev: pool doesn't exist + + # reset pool <> lp_token mappings + self.get_base_pool_for_lp_token[self.base_pool[_pool].lp_token] = empty(address) + self.base_pool[_pool].lp_token = empty(address) + self.base_pool[_pool].n_coins = 0 + + # remove base_pool from base_pool_list + location: uint256 = self.base_pool[_pool].location + length: uint256 = self.base_pool_count - 1 + assert location < length + + # because self.base_pool_list is a static array, + # we can replace the last index with empty(address) + # and replace the first index with the base pool + # that was previously in the last index. + # we skip this step if location == last index + if location < length: + # replace _pool with final value in pool_list + addr: address = self.base_pool_list[length] + assert addr != empty(address) + self.base_pool_list[location] = addr + self.base_pool[addr].location = location + + # delete final pool_list value + self.base_pool_list[length] = empty(address) + self.base_pool_count = length + + self.last_updated = block.timestamp + log BasePoolRemoved(_pool) diff --git a/contracts/mainnet/registries/CryptoRegistryV1.vy b/contracts/mainnet/registries/CryptoRegistryV1.vy index ef1690a..d43975f 100644 --- a/contracts/mainnet/registries/CryptoRegistryV1.vy +++ b/contracts/mainnet/registries/CryptoRegistryV1.vy @@ -1,963 +1,963 @@ -#pragma version ^0.3.7 -""" -@title Curve CryptoSwap Registry -@license MIT -@author Curve.Fi -""" - -MAX_COINS: constant(int128) = 8 -CALC_INPUT_SIZE: constant(int128) = 100 - - -struct CoinInfo: - index: uint256 - register_count: uint256 - swap_count: uint256 - swap_for: address[max_value(int128)] - - -struct PoolArray: - location: uint256 - base_pool: address - n_coins: uint256 - name: String[64] - has_positive_rebasing_tokens: bool - - -interface AddressProvider: - def admin() -> address: view - def get_address(_id: uint256) -> address: view - def get_registry() -> address: view - -interface ERC20: - def balanceOf(_addr: address) -> uint256: view - def decimals() -> uint256: view - def totalSupply() -> uint256: view - -interface CurvePool: - def token() -> address: view - def coins(i: uint256) -> address: view - def A() -> uint256: view - def gamma() -> uint256: view - def fee() -> uint256: view - def get_virtual_price() -> uint256: view - def mid_fee() -> uint256: view - def out_fee() -> uint256: view - def admin_fee() -> uint256: view - def balances(i: uint256) -> uint256: view - def D() -> uint256: view - def xcp_profit() -> uint256: view - def xcp_profit_a() -> uint256: view - -interface StableSwapLegacy: - def coins(i: int128) -> address: view - def underlying_coins(i: int128) -> address: view - def balances(i: int128) -> uint256: view - -interface LiquidityGauge: - def lp_token() -> address: view - def is_killed() -> bool: view - -interface GaugeController: - def gauge_types(gauge: address) -> int128: view - -interface BasePoolRegistry: - def get_base_pool_for_lp_token(_lp_token: address) -> address: view - def get_n_coins(_pool: address) -> uint256: view - def get_coins(_pool: address) -> address[MAX_COINS]: view - def get_lp_token(_pool: address) -> address: view - def is_legacy(_pool: address) -> bool: view - - -event PoolAdded: - pool: indexed(address) - -event BasePoolAdded: - basepool: indexed(address) - -event PoolRemoved: - pool: indexed(address) - - -GAUGE_CONTROLLER: constant(address) = 0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB - -address_provider: public(AddressProvider) -base_pool_registry: public(BasePoolRegistry) -pool_list: public(address[65536]) # master list of pools -pool_count: public(uint256) # actual length of pool_list -base_pool_count: public(uint256) -coins: HashMap[address, CoinInfo] -get_coin: public(address[65536]) # unique list of registered coins -coin_swap_indexes: HashMap[uint256, uint256] -coin_count: public(uint256) # total unique coins registered - -pool_data: HashMap[address, PoolArray] - -# lp token -> pool -get_pool_from_lp_token: public(HashMap[address, address]) - -# pool -> lp token -get_lp_token: public(HashMap[address, address]) - -# mapping of coins -> pools for trading -# a mapping key is generated for each pair of addresses via -# `bitwise_xor(convert(a, uint256), convert(b, uint256))` -markets: HashMap[uint256, address[65536]] -market_counts: HashMap[uint256, uint256] - -liquidity_gauges: HashMap[address, address[10]] - -# mapping of pool -> deposit/exchange zap -get_zap: public(HashMap[address, address]) - -last_updated: public(uint256) - - -@external -def __init__(_address_provider: address, _base_pool_registry: address): - self.address_provider = AddressProvider(_address_provider) - self.base_pool_registry = BasePoolRegistry(_base_pool_registry) - - -# internal functionality for getters - -@internal -@view -def _get_coins(_pool: address) -> address[MAX_COINS]: - _coins: address[MAX_COINS] = empty(address[MAX_COINS]) - for i in range(MAX_COINS): - if i == convert(self.pool_data[_pool].n_coins, int128): - break - _coins[i] = CurvePool(_pool).coins(convert(i, uint256)) - return _coins - - -@view -@internal -def _get_decimals(_coins: address[MAX_COINS]) -> uint256[MAX_COINS]: - decimals: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) - value: uint256 = 0 - for i in range(MAX_COINS): - if _coins[i] == empty(address): - break - coin: address = _coins[i] - if coin == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE: - value = 18 - else: - value = ERC20(coin).decimals() - assert value < 256 # dev: decimal overflow - - decimals[i] = value - - return decimals - - -@view -@internal -def _get_underlying_coins_for_metapool(_pool: address) -> address[MAX_COINS]: - - base_pool_coins: address[MAX_COINS] = self.base_pool_registry.get_coins(self.pool_data[_pool].base_pool) - _underlying_coins: address[MAX_COINS] = empty(address[MAX_COINS]) - base_coin_offset: int128 = convert(self.pool_data[_pool].n_coins - 1, int128) - _coins: address[MAX_COINS] = self._get_coins(_pool) - - for i in range(MAX_COINS): - if i < base_coin_offset: - _underlying_coins[i] = _coins[i] - else: - _underlying_coins[i] = base_pool_coins[i - base_coin_offset] - - assert _underlying_coins[0] != empty(address) - - return _underlying_coins - - -@view -@internal -def _get_balances(_pool: address) -> uint256[MAX_COINS]: - balances: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) - _coins: address[MAX_COINS] = self._get_coins(_pool) - for i in range(MAX_COINS): - if _coins[i] == empty(address): - assert i != 0 - break - - balances[i] = CurvePool(_pool).balances(convert(i, uint256)) - - return balances - - -@view -@internal -def _get_meta_underlying_balances(_pool: address) -> uint256[MAX_COINS]: - base_coin_idx: uint256 = self.pool_data[_pool].n_coins - 1 - base_pool: address = self.pool_data[_pool].base_pool - base_total_supply: uint256 = ERC20(self.base_pool_registry.get_lp_token(base_pool)).totalSupply() - - underlying_balances: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) - ul_balance: uint256 = 0 - underlying_pct: uint256 = 0 - if base_total_supply > 0: - underlying_pct = CurvePool(_pool).balances(base_coin_idx) * 10**36 / base_total_supply - - ul_coins: address[MAX_COINS] = self._get_underlying_coins_for_metapool(_pool) - for i in range(MAX_COINS): - - if ul_coins[i] == empty(address): - break - - if i < convert(base_coin_idx, int128): - ul_balance = CurvePool(_pool).balances(convert(i, uint256)) - - else: - - if self.base_pool_registry.is_legacy(base_pool): - ul_balance = StableSwapLegacy(base_pool).balances(i - convert(base_coin_idx, int128)) - else: - ul_balance = CurvePool(base_pool).balances(convert(i, uint256) - base_coin_idx) - ul_balance = ul_balance * underlying_pct / 10**36 - underlying_balances[i] = ul_balance - - return underlying_balances - - -@view -@internal -def _is_meta(_pool: address) -> bool: - return self.pool_data[_pool].base_pool != empty(address) - - -@view -@internal -def _get_coin_indices( - _pool: address, - _from: address, - _to: address -) -> uint256[3]: - # the return value is stored as `uint256[3]` to reduce gas costs - # from index, to index, is the market underlying? - result: uint256[3] = empty(uint256[3]) - _coins: address[MAX_COINS] = self._get_coins(_pool) - found_market: bool = False - - # check coin markets - for x in range(MAX_COINS): - coin: address = _coins[x] - if coin == empty(address): - # if we reach the end of the coins, reset `found_market` and try again - # with the underlying coins - found_market = False - break - if coin == _from: - result[0] = convert(x, uint256) - elif coin == _to: - result[1] = convert(x, uint256) - else: - continue - - if found_market: - # the second time we find a match, break out of the loop - break - # the first time we find a match, set `found_market` to True - found_market = True - - if not found_market and self._is_meta(_pool): - # check underlying coin markets - underlying_coins: address[MAX_COINS] = self._get_underlying_coins_for_metapool(_pool) - for x in range(MAX_COINS): - coin: address = underlying_coins[x] - if coin == empty(address): - raise "No available market" - if coin == _from: - result[0] = convert(x, uint256) - elif coin == _to: - result[1] = convert(x, uint256) - else: - continue - - if found_market: - result[2] = 1 - break - found_market = True - - return result - - -@internal -@view -def _get_gauge_type(_gauge: address) -> int128: - - success: bool = False - response: Bytes[32] = b"" - success, response = raw_call( - GAUGE_CONTROLLER, - concat( - method_id("gauge_type(address)"), - convert(_gauge, bytes32), - ), - max_outsize=32, - revert_on_failure=False, - is_static_call=True - ) - - if success and not LiquidityGauge(_gauge).is_killed(): - return convert(response, int128) - - return 0 - - -# targetted external getters, optimized for on-chain calls - - -@view -@external -def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: - """ - @notice Find an available pool for exchanging two coins - @param _from Address of coin to be sent - @param _to Address of coin to be received - @param i Index value. When multiple pools are available - this value is used to return the n'th address. - @return Pool address - """ - key: uint256 = convert(_from, uint256) ^ convert(_to, uint256) - return self.markets[key][i] - - -@view -@external -def get_n_coins(_pool: address) -> uint256: - """ - @notice Get the number of coins in a pool - @dev For non-metapools, both returned values are identical - even when the pool does not use wrapping/lending - @param _pool Pool address - @return uint256 Number of wrapped coins, number of underlying coins - """ - return self.pool_data[_pool].n_coins - - -@external -@view -def get_n_underlying_coins(_pool: address) -> uint256: - """ - @notice Get the number of underlying coins in a pool - @param _pool Pool address - @return uint256 Number of underlying coins - """ - if not self._is_meta(_pool): - return self.pool_data[_pool].n_coins - - base_pool: address = self.pool_data[_pool].base_pool - return self.pool_data[_pool].n_coins + self.base_pool_registry.get_n_coins(base_pool) - 1 - - -@view -@external -def get_coins(_pool: address) -> address[MAX_COINS]: - """ - @notice Get the coins within a pool - @dev For pools using lending, these are the wrapped coin addresses - @param _pool Pool address - @return address[MAX_COINS] List of coin addresses - """ - return self._get_coins(_pool) - - -@view -@external -def get_underlying_coins(_pool: address) -> address[MAX_COINS]: - """ - @notice Get the underlying coins within a pool - @dev For pools that do not lend, returns the same value as `get_coins` - @param _pool Pool address - @return address[MAX_COINS] of coin addresses - """ - if self._is_meta(_pool): - return self._get_underlying_coins_for_metapool(_pool) - return self._get_coins(_pool) - - -@view -@external -def get_decimals(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get decimal places for each coin within a pool - @dev For pools using lending, these are the wrapped coin decimal places - @param _pool Pool address - @return uint256 list of decimals - """ - _coins: address[MAX_COINS] = self._get_coins(_pool) - return self._get_decimals(_coins) - - -@view -@external -def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get decimal places for each underlying coin within a pool - @dev For pools that do not lend, returns the same value as `get_decimals` - @param _pool Pool address - @return uint256 list of decimals - """ - if self._is_meta(_pool): - _underlying_coins: address[MAX_COINS] = self._get_underlying_coins_for_metapool(_pool) - _decimals: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) - for i in range(MAX_COINS): - if _underlying_coins[i] == empty(address): - break - _decimals[i] = ERC20(_underlying_coins[i]).decimals() - return _decimals - - _coins: address[MAX_COINS] = self._get_coins(_pool) - return self._get_decimals(_coins) - - -@view -@external -def get_gauges(_pool: address) -> (address[10], int128[10]): - """ - @notice Get a list of LiquidityGauge contracts associated with a pool - @param _pool Pool address - @return address[10] of gauge addresses, int128[10] of gauge types - """ - liquidity_gauges: address[10] = empty(address[10]) - gauge_types: int128[10] = empty(int128[10]) - for i in range(10): - gauge: address = self.liquidity_gauges[_pool][i] - if gauge == empty(address): - break - liquidity_gauges[i] = gauge - gauge_types[i] = GaugeController(GAUGE_CONTROLLER).gauge_types(gauge) - - return liquidity_gauges, gauge_types - - -@view -@external -def get_balances(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get balances for each coin within a pool - @dev For pools using lending, these are the wrapped coin balances - @param _pool Pool address - @return uint256 list of balances - """ - return self._get_balances(_pool) - - -@view -@external -def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get balances for each underlying coin within a pool - @dev For pools that do not lend, returns the same value as `get_balances` - @param _pool Pool address - @return uint256 list of underlyingbalances - """ - if not self._is_meta(_pool): - return self._get_balances(_pool) - return self._get_meta_underlying_balances(_pool) - - -@view -@external -def get_virtual_price_from_lp_token(_token: address) -> uint256: - """ - @notice Get the virtual price of a pool LP token - @param _token LP token address - @return uint256 Virtual price - """ - return CurvePool(self.get_pool_from_lp_token[_token]).get_virtual_price() - - -@view -@external -def get_A(_pool: address) -> uint256: - """ - @notice Get a pool's amplification factor - @param _pool Pool address - @return uint256 Amplification factor - """ - return CurvePool(_pool).A() - - -@view -@external -def get_D(_pool: address) -> uint256: - """ - @notice Get invariant of a pool's curve - @param _pool Pool address - @return uint256 Invariant - """ - return CurvePool(_pool).D() - - -@view -@external -def get_gamma(_pool: address) -> uint256: - """ - @notice Get the pool's gamma parameter - @param _pool Pool address - @return uint256 Gamma parameter - """ - return CurvePool(_pool).gamma() - - -@view -@external -def get_fees(_pool: address) -> uint256[4]: - """ - @notice Get the fees for a pool - @dev Fees are expressed as integers - @param _pool Pool address - @return Pool fee as uint256 with 1e10 precision - Admin fee as 1e10 percentage of pool fee - Mid fee - Out fee - """ - return [CurvePool(_pool).fee(), CurvePool(_pool).admin_fee(), CurvePool(_pool).mid_fee(), CurvePool(_pool).out_fee()] - - -@external -@view -def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the admin balances for a pool (accrued fees) - @dev Cryptoswap pools do not store admin fees in the form of - admin token balances. Instead, the admin fees are computed - at the time of claim iff sufficient profits have been made. - These fees are allocated to the admin by minting LP tokens - (dilution). The logic to calculate fees are derived from - cryptopool._claim_admin_fees() method. - @param _pool Pool address - @return uint256 list of admin balances - """ - xcp_profit: uint256 = CurvePool(_pool).xcp_profit() - xcp_profit_a: uint256 = CurvePool(_pool).xcp_profit_a() - admin_fee: uint256 = CurvePool(_pool).admin_fee() - admin_balances: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) - - # admin balances are non zero if pool has made more than allowed profits: - if xcp_profit > xcp_profit_a: - - # calculate admin fees in lp token amounts: - fees: uint256 = (xcp_profit - xcp_profit_a) * admin_fee / (2 * 10**10) - if fees > 0: - vprice: uint256 = CurvePool(_pool).get_virtual_price() - lp_token: address = self.get_lp_token[_pool] - frac: uint256 = vprice * 10**18 / (vprice - fees) - 10**18 - - # the total supply of lp token is current supply + claimable: - lp_token_total_supply: uint256 = ERC20(lp_token).totalSupply() - d_supply: uint256 = lp_token_total_supply * frac / 10**18 - lp_token_total_supply += d_supply - admin_lp_frac: uint256 = d_supply * 10 ** 18 / lp_token_total_supply - - # get admin balances in individual assets: - reserves: uint256[MAX_COINS] = self._get_balances(_pool) - for i in range(MAX_COINS): - admin_balances[i] = admin_lp_frac * reserves[i] / 10 ** 18 - - return admin_balances - - -@view -@external -def get_coin_indices( - _pool: address, - _from: address, - _to: address -) -> (int128, int128, bool): - """ - @notice Convert coin addresses to indices for use with pool methods - @param _pool Pool address - @param _from Coin address to be used as `i` within a pool - @param _to Coin address to be used as `j` within a pool - @return int128 `i`, int128 `j`, boolean indicating if `i` and `j` are underlying coins - """ - result: uint256[3] = self._get_coin_indices(_pool, _from, _to) - return convert(result[0], int128), convert(result[1], int128), result[2] > 0 - - -@view -@external -def is_meta(_pool: address) -> bool: - """ - @notice Verify `_pool` is a metapool - @param _pool Pool address - @return True if `_pool` is a metapool - """ - return self.pool_data[_pool].base_pool != empty(address) - - -@view -@external -def get_base_pool(_pool: address) -> address: - """ - @notice Get the base pool of a metapool - @param _pool Pool address - @return Base pool address - """ - return self.pool_data[_pool].base_pool - - -@view -@external -def get_pool_name(_pool: address) -> String[64]: - """ - @notice Get the given name for a pool - @param _pool Pool address - @return The name of a pool - """ - return self.pool_data[_pool].name - - -# internal functionality used in admin setters - -@internal -def _register_coin(_coin: address): - if self.coins[_coin].register_count == 0: - coin_count: uint256 = self.coin_count - self.coins[_coin].index = coin_count - self.get_coin[coin_count] = _coin - self.coin_count += 1 - self.coins[_coin].register_count += 1 - - -@internal -def _register_coin_pair(_coina: address, _coinb: address, _key: uint256): - # register _coinb in _coina's array of coins - coin_b_pos: uint256 = self.coins[_coina].swap_count - self.coins[_coina].swap_for[coin_b_pos] = _coinb - self.coins[_coina].swap_count += 1 - # register _coina in _coinb's array of coins - coin_a_pos: uint256 = self.coins[_coinb].swap_count - self.coins[_coinb].swap_for[coin_a_pos] = _coina - self.coins[_coinb].swap_count += 1 - # register indexes (coina pos in coinb array, coinb pos in coina array) - if convert(_coina, uint256) < convert(_coinb, uint256): - self.coin_swap_indexes[_key] = shift(coin_a_pos, 128) + coin_b_pos - else: - self.coin_swap_indexes[_key] = shift(coin_b_pos, 128) + coin_a_pos - - -@internal -def _add_coins_to_market(_pool: address, _coin_list: address[MAX_COINS], _is_underlying: bool = False): - - for i in range(MAX_COINS): - - if _coin_list[i] == empty(address): - break - - # we dont want underlying <> underlying markets - # since that should be covered by the base_pool - # and not _pool: underlying <> underlying swaps - # happen at the base_pool level, not at the _pool - # level: - if _is_underlying and i > 0: - break - - # register coin: - self._register_coin(_coin_list[i]) - - # add pool to markets - i2: int128 = i + 1 - for x in range(i2, i2 + MAX_COINS): - - if _coin_list[x] == empty(address): - break - - key: uint256 = ( - convert(_coin_list[i], uint256) ^ convert(_coin_list[x], uint256) - ) - length: uint256 = self.market_counts[key] - self.markets[key][length] = _pool - self.market_counts[key] = length + 1 - - # register the coin pair - if length == 0: - self._register_coin_pair(_coin_list[x], _coin_list[i], key) - - -@internal -@view -def _market_exists(_pool: address, _coina: address, _coinb: address) -> bool: - key: uint256 = convert(_coina, uint256) ^ convert(_coinb, uint256) - if self.market_counts[key] == 0: - return False - return True - - -@internal -def _unregister_coin(_coin: address): - self.coins[_coin].register_count -= 1 - - if self.coins[_coin].register_count == 0: - self.coin_count -= 1 - coin_count: uint256 = self.coin_count - location: uint256 = self.coins[_coin].index - - if location < coin_count: - coin_b: address = self.get_coin[coin_count] - self.get_coin[location] = coin_b - self.coins[coin_b].index = location - - self.coins[_coin].index = 0 - self.get_coin[coin_count] = empty(address) - - -@internal -def _unregister_coin_pair(_coina: address, _coinb: address, _coinb_idx: uint256): - """ - @param _coinb_idx the index of _coinb in _coina's array of unique coin's - """ - # decrement swap counts for both coins - self.coins[_coina].swap_count -= 1 - - # retrieve the last currently occupied index in coina's array - coina_arr_last_idx: uint256 = self.coins[_coina].swap_count - - # if coinb's index in coina's array is less than the last - # overwrite it's position with the last coin - if _coinb_idx < coina_arr_last_idx: - # here's our last coin in coina's array - coin_c: address = self.coins[_coina].swap_for[coina_arr_last_idx] - # get the bitwise_xor of the pair to retrieve their indexes - key: uint256 = convert(_coina, uint256) ^ convert(coin_c, uint256) - indexes: uint256 = self.coin_swap_indexes[key] - - # update the pairing's indexes - if convert(_coina, uint256) < convert(coin_c, uint256): - # least complicated most readable way of shifting twice to remove the lower order bits - self.coin_swap_indexes[key] = shift(shift(indexes, -128), 128) + _coinb_idx - else: - self.coin_swap_indexes[key] = shift(_coinb_idx, 128) + indexes % 2 ** 128 - # set _coinb_idx in coina's array to coin_c - self.coins[_coina].swap_for[_coinb_idx] = coin_c - - self.coins[_coina].swap_for[coina_arr_last_idx] = empty(address) - - -@internal -def _remove_market(_pool: address, _coina: address, _coinb: address): - - key: uint256 = convert(_coina, uint256) ^ convert(_coinb, uint256) - length: uint256 = self.market_counts[key] - 1 - - if length == 0: - indexes: uint256 = self.coin_swap_indexes[key] - if convert(_coina, uint256) < convert(_coinb, uint256): - self._unregister_coin_pair(_coina, _coinb, indexes % 2 ** 128) - self._unregister_coin_pair(_coinb, _coina, shift(indexes, -128)) - else: - self._unregister_coin_pair(_coina, _coinb, shift(indexes, -128)) - self._unregister_coin_pair(_coinb, _coina, indexes % 2 ** 128) - self.coin_swap_indexes[key] = 0 - - for i in range(65536): - if i > length: - break - if self.markets[key][i] == _pool: - if i < length: - self.markets[key][i] = self.markets[key][length] - self.markets[key][length] = empty(address) - self.market_counts[key] = length - break - - -@internal -def _remove_liquidity_gauges(_pool: address): - for i in range(10): - if self.liquidity_gauges[_pool][i] != empty(address): - self.liquidity_gauges[_pool][i] = empty(address) - else: - break - - -# admin functions - - -@external -def add_pool( - _pool: address, - _lp_token: address, - _gauge: address, - _zap: address, - _n_coins: uint256, - _name: String[64], - _base_pool: address = empty(address), - _has_positive_rebasing_tokens: bool = False -): - """ - @notice Add a pool to the registry - @dev Only callable by admin - @param _pool Pool address to add - @param _lp_token Pool deposit token address - @param _gauge Gauge address - @param _zap Zap address - @param _n_coins Number of coins in the pool - @param _name The name of the pool - @param _base_pool Address of base pool - @param _has_positive_rebasing_tokens pool contains positive rebasing tokens - """ - assert msg.sender == self.address_provider.admin() # dev: admin-only function - assert _lp_token != empty(address) - assert self.get_pool_from_lp_token[_lp_token] == empty(address) # dev: pool exists - - # initialise PoolArray struct - length: uint256 = self.pool_count - self.pool_list[length] = _pool - self.pool_count = length + 1 - self.pool_data[_pool].location = length - self.pool_data[_pool].name = _name - self.pool_data[_pool].n_coins = _n_coins - - # update public mappings - if _zap != empty(address): - self.get_zap[_pool] = _zap - - if _gauge != empty(address): - self.liquidity_gauges[_pool][0] = _gauge - - self.get_pool_from_lp_token[_lp_token] = _pool - self.get_lp_token[_pool] = _lp_token - - # add coins mappings: - _coins: address[MAX_COINS] = empty(address[MAX_COINS]) - for i in range(MAX_COINS): - if i == convert(_n_coins, int128): - break - _coins[i] = CurvePool(_pool).coins(convert(i, uint256)) - self._add_coins_to_market(_pool, _coins) - - # the following does not add basepool_lp_token <> underlying_coin mapping - # since that is redundant: - if _base_pool != empty(address): - assert self.base_pool_registry.get_lp_token(_base_pool) != empty(address) - self.pool_data[_pool].base_pool = _base_pool - - _underlying_coins: address[MAX_COINS] = self._get_underlying_coins_for_metapool(_pool) - assert _underlying_coins[0] != empty(address) - - self._add_coins_to_market(_pool, _underlying_coins, True) - - if _has_positive_rebasing_tokens: - self.pool_data[_pool].has_positive_rebasing_tokens = True - - # log pool added: - self.last_updated = block.timestamp - log PoolAdded(_pool) - - -@external -def remove_pool(_pool: address): - """ - @notice Remove a pool to the registry - @dev Only callable by admin - @param _pool Pool address to remove - """ - assert msg.sender == self.address_provider.admin() # dev: admin-only function - assert self.get_lp_token[_pool] != empty(address) # dev: pool does not exist - - self.get_pool_from_lp_token[self.get_lp_token[_pool]] = empty(address) - self.get_lp_token[_pool] = empty(address) - - # remove _pool from pool_list - location: uint256 = self.pool_data[_pool].location - length: uint256 = self.pool_count - 1 - - # because self.pool_list is a static array, - # we can replace the last index with empty(address) - # and replace the first index with the pool - # that was previously in the last index. - # we skip this step if location == last index - if location < length: - # replace _pool with final value in pool_list - addr: address = self.pool_list[length] - self.pool_list[location] = addr - self.pool_data[addr].location = location - - # delete final pool_list value - self.pool_list[length] = empty(address) - self.pool_count = length - - coins: address[MAX_COINS] = self._get_coins(_pool) - ucoins: address[MAX_COINS] = empty(address[MAX_COINS]) - is_meta: bool = self._is_meta(_pool) - if is_meta: - ucoins = self._get_underlying_coins_for_metapool(_pool) - - for i in range(MAX_COINS): - - if coins[i] == empty(address) and ucoins[i] == empty(address): - break - - if coins[i] != empty(address): - self._unregister_coin(coins[i]) - - if ucoins[i] != empty(address): - if self.coins[ucoins[i]].register_count != 0: - self._unregister_coin(ucoins[i]) - - for j in range(MAX_COINS): - - if not j > i: - continue - - if empty(address) not in [coins[i], coins[j]] and self._market_exists(_pool, coins[i], coins[j]): - self._remove_market(_pool, coins[i], coins[j]) - - if empty(address) not in [coins[i], ucoins[j]] and self._market_exists(_pool, coins[i], ucoins[j]): - self._remove_market(_pool, coins[i], ucoins[j]) - - # reset remaining mappings: - self.pool_data[_pool].base_pool = empty(address) - self.pool_data[_pool].n_coins = 0 - self.pool_data[_pool].name = "" - self.get_zap[_pool] = empty(address) - self._remove_liquidity_gauges(_pool) - - self.last_updated = block.timestamp - log PoolRemoved(_pool) - - -@external -def set_liquidity_gauges(_pool: address, _liquidity_gauges: address[10]): - """ - @notice Set liquidity gauge contracts - @param _pool Pool address - @param _liquidity_gauges Liquidity gauge address - """ - assert msg.sender == self.address_provider.admin() # dev: admin-only function - - _lp_token: address = self.get_lp_token[_pool] - for i in range(10): - _gauge: address = _liquidity_gauges[i] - if _gauge != empty(address): - assert LiquidityGauge(_gauge).lp_token() == _lp_token # dev: wrong token - self.liquidity_gauges[_pool][i] = _gauge - elif self.liquidity_gauges[_pool][i] != empty(address): - self.liquidity_gauges[_pool][i] = empty(address) - else: - break - self.last_updated = block.timestamp - - -@external -def batch_set_liquidity_gauges(_pools: address[10], _liquidity_gauges: address[10]): - """ - @notice Set many liquidity gauge contracts - @param _pools List of pool addresses - @param _liquidity_gauges List of liquidity gauge addresses - """ - assert msg.sender == self.address_provider.admin() # dev: admin-only function - - for i in range(10): - _pool: address = _pools[i] - if _pool == empty(address): - break - _gauge: address = _liquidity_gauges[i] - assert LiquidityGauge(_gauge).lp_token() == self.get_lp_token[_pool] # dev: wrong token - self.liquidity_gauges[_pool][0] = _gauge - - self.last_updated = block.timestamp +#pragma version ^0.3.7 +""" +@title Curve CryptoSwap Registry +@license MIT +@author Curve.Fi +""" + +MAX_COINS: constant(int128) = 8 +CALC_INPUT_SIZE: constant(int128) = 100 + + +struct CoinInfo: + index: uint256 + register_count: uint256 + swap_count: uint256 + swap_for: address[max_value(int128)] + + +struct PoolArray: + location: uint256 + base_pool: address + n_coins: uint256 + name: String[64] + has_positive_rebasing_tokens: bool + + +interface AddressProvider: + def admin() -> address: view + def get_address(_id: uint256) -> address: view + def get_registry() -> address: view + +interface ERC20: + def balanceOf(_addr: address) -> uint256: view + def decimals() -> uint256: view + def totalSupply() -> uint256: view + +interface CurvePool: + def token() -> address: view + def coins(i: uint256) -> address: view + def A() -> uint256: view + def gamma() -> uint256: view + def fee() -> uint256: view + def get_virtual_price() -> uint256: view + def mid_fee() -> uint256: view + def out_fee() -> uint256: view + def admin_fee() -> uint256: view + def balances(i: uint256) -> uint256: view + def D() -> uint256: view + def xcp_profit() -> uint256: view + def xcp_profit_a() -> uint256: view + +interface StableSwapLegacy: + def coins(i: int128) -> address: view + def underlying_coins(i: int128) -> address: view + def balances(i: int128) -> uint256: view + +interface LiquidityGauge: + def lp_token() -> address: view + def is_killed() -> bool: view + +interface GaugeController: + def gauge_types(gauge: address) -> int128: view + +interface BasePoolRegistry: + def get_base_pool_for_lp_token(_lp_token: address) -> address: view + def get_n_coins(_pool: address) -> uint256: view + def get_coins(_pool: address) -> address[MAX_COINS]: view + def get_lp_token(_pool: address) -> address: view + def is_legacy(_pool: address) -> bool: view + + +event PoolAdded: + pool: indexed(address) + +event BasePoolAdded: + basepool: indexed(address) + +event PoolRemoved: + pool: indexed(address) + + +GAUGE_CONTROLLER: constant(address) = 0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB + +address_provider: public(AddressProvider) +base_pool_registry: public(BasePoolRegistry) +pool_list: public(address[65536]) # master list of pools +pool_count: public(uint256) # actual length of pool_list +base_pool_count: public(uint256) +coins: HashMap[address, CoinInfo] +get_coin: public(address[65536]) # unique list of registered coins +coin_swap_indexes: HashMap[uint256, uint256] +coin_count: public(uint256) # total unique coins registered + +pool_data: HashMap[address, PoolArray] + +# lp token -> pool +get_pool_from_lp_token: public(HashMap[address, address]) + +# pool -> lp token +get_lp_token: public(HashMap[address, address]) + +# mapping of coins -> pools for trading +# a mapping key is generated for each pair of addresses via +# `bitwise_xor(convert(a, uint256), convert(b, uint256))` +markets: HashMap[uint256, address[65536]] +market_counts: HashMap[uint256, uint256] + +liquidity_gauges: HashMap[address, address[10]] + +# mapping of pool -> deposit/exchange zap +get_zap: public(HashMap[address, address]) + +last_updated: public(uint256) + + +@external +def __init__(_address_provider: address, _base_pool_registry: address): + self.address_provider = AddressProvider(_address_provider) + self.base_pool_registry = BasePoolRegistry(_base_pool_registry) + + +# internal functionality for getters + +@internal +@view +def _get_coins(_pool: address) -> address[MAX_COINS]: + _coins: address[MAX_COINS] = empty(address[MAX_COINS]) + for i in range(MAX_COINS): + if i == convert(self.pool_data[_pool].n_coins, int128): + break + _coins[i] = CurvePool(_pool).coins(convert(i, uint256)) + return _coins + + +@view +@internal +def _get_decimals(_coins: address[MAX_COINS]) -> uint256[MAX_COINS]: + decimals: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) + value: uint256 = 0 + for i in range(MAX_COINS): + if _coins[i] == empty(address): + break + coin: address = _coins[i] + if coin == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE: + value = 18 + else: + value = ERC20(coin).decimals() + assert value < 256 # dev: decimal overflow + + decimals[i] = value + + return decimals + + +@view +@internal +def _get_underlying_coins_for_metapool(_pool: address) -> address[MAX_COINS]: + + base_pool_coins: address[MAX_COINS] = self.base_pool_registry.get_coins(self.pool_data[_pool].base_pool) + _underlying_coins: address[MAX_COINS] = empty(address[MAX_COINS]) + base_coin_offset: int128 = convert(self.pool_data[_pool].n_coins - 1, int128) + _coins: address[MAX_COINS] = self._get_coins(_pool) + + for i in range(MAX_COINS): + if i < base_coin_offset: + _underlying_coins[i] = _coins[i] + else: + _underlying_coins[i] = base_pool_coins[i - base_coin_offset] + + assert _underlying_coins[0] != empty(address) + + return _underlying_coins + + +@view +@internal +def _get_balances(_pool: address) -> uint256[MAX_COINS]: + balances: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) + _coins: address[MAX_COINS] = self._get_coins(_pool) + for i in range(MAX_COINS): + if _coins[i] == empty(address): + assert i != 0 + break + + balances[i] = CurvePool(_pool).balances(convert(i, uint256)) + + return balances + + +@view +@internal +def _get_meta_underlying_balances(_pool: address) -> uint256[MAX_COINS]: + base_coin_idx: uint256 = self.pool_data[_pool].n_coins - 1 + base_pool: address = self.pool_data[_pool].base_pool + base_total_supply: uint256 = ERC20(self.base_pool_registry.get_lp_token(base_pool)).totalSupply() + + underlying_balances: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) + ul_balance: uint256 = 0 + underlying_pct: uint256 = 0 + if base_total_supply > 0: + underlying_pct = CurvePool(_pool).balances(base_coin_idx) * 10**36 / base_total_supply + + ul_coins: address[MAX_COINS] = self._get_underlying_coins_for_metapool(_pool) + for i in range(MAX_COINS): + + if ul_coins[i] == empty(address): + break + + if i < convert(base_coin_idx, int128): + ul_balance = CurvePool(_pool).balances(convert(i, uint256)) + + else: + + if self.base_pool_registry.is_legacy(base_pool): + ul_balance = StableSwapLegacy(base_pool).balances(i - convert(base_coin_idx, int128)) + else: + ul_balance = CurvePool(base_pool).balances(convert(i, uint256) - base_coin_idx) + ul_balance = ul_balance * underlying_pct / 10**36 + underlying_balances[i] = ul_balance + + return underlying_balances + + +@view +@internal +def _is_meta(_pool: address) -> bool: + return self.pool_data[_pool].base_pool != empty(address) + + +@view +@internal +def _get_coin_indices( + _pool: address, + _from: address, + _to: address +) -> uint256[3]: + # the return value is stored as `uint256[3]` to reduce gas costs + # from index, to index, is the market underlying? + result: uint256[3] = empty(uint256[3]) + _coins: address[MAX_COINS] = self._get_coins(_pool) + found_market: bool = False + + # check coin markets + for x in range(MAX_COINS): + coin: address = _coins[x] + if coin == empty(address): + # if we reach the end of the coins, reset `found_market` and try again + # with the underlying coins + found_market = False + break + if coin == _from: + result[0] = convert(x, uint256) + elif coin == _to: + result[1] = convert(x, uint256) + else: + continue + + if found_market: + # the second time we find a match, break out of the loop + break + # the first time we find a match, set `found_market` to True + found_market = True + + if not found_market and self._is_meta(_pool): + # check underlying coin markets + underlying_coins: address[MAX_COINS] = self._get_underlying_coins_for_metapool(_pool) + for x in range(MAX_COINS): + coin: address = underlying_coins[x] + if coin == empty(address): + raise "No available market" + if coin == _from: + result[0] = convert(x, uint256) + elif coin == _to: + result[1] = convert(x, uint256) + else: + continue + + if found_market: + result[2] = 1 + break + found_market = True + + return result + + +@internal +@view +def _get_gauge_type(_gauge: address) -> int128: + + success: bool = False + response: Bytes[32] = b"" + success, response = raw_call( + GAUGE_CONTROLLER, + concat( + method_id("gauge_type(address)"), + convert(_gauge, bytes32), + ), + max_outsize=32, + revert_on_failure=False, + is_static_call=True + ) + + if success and not LiquidityGauge(_gauge).is_killed(): + return convert(response, int128) + + return 0 + + +# targetted external getters, optimized for on-chain calls + + +@view +@external +def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: + """ + @notice Find an available pool for exchanging two coins + @param _from Address of coin to be sent + @param _to Address of coin to be received + @param i Index value. When multiple pools are available + this value is used to return the n'th address. + @return Pool address + """ + key: uint256 = convert(_from, uint256) ^ convert(_to, uint256) + return self.markets[key][i] + + +@view +@external +def get_n_coins(_pool: address) -> uint256: + """ + @notice Get the number of coins in a pool + @dev For non-metapools, both returned values are identical + even when the pool does not use wrapping/lending + @param _pool Pool address + @return uint256 Number of wrapped coins, number of underlying coins + """ + return self.pool_data[_pool].n_coins + + +@external +@view +def get_n_underlying_coins(_pool: address) -> uint256: + """ + @notice Get the number of underlying coins in a pool + @param _pool Pool address + @return uint256 Number of underlying coins + """ + if not self._is_meta(_pool): + return self.pool_data[_pool].n_coins + + base_pool: address = self.pool_data[_pool].base_pool + return self.pool_data[_pool].n_coins + self.base_pool_registry.get_n_coins(base_pool) - 1 + + +@view +@external +def get_coins(_pool: address) -> address[MAX_COINS]: + """ + @notice Get the coins within a pool + @dev For pools using lending, these are the wrapped coin addresses + @param _pool Pool address + @return address[MAX_COINS] List of coin addresses + """ + return self._get_coins(_pool) + + +@view +@external +def get_underlying_coins(_pool: address) -> address[MAX_COINS]: + """ + @notice Get the underlying coins within a pool + @dev For pools that do not lend, returns the same value as `get_coins` + @param _pool Pool address + @return address[MAX_COINS] of coin addresses + """ + if self._is_meta(_pool): + return self._get_underlying_coins_for_metapool(_pool) + return self._get_coins(_pool) + + +@view +@external +def get_decimals(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get decimal places for each coin within a pool + @dev For pools using lending, these are the wrapped coin decimal places + @param _pool Pool address + @return uint256 list of decimals + """ + _coins: address[MAX_COINS] = self._get_coins(_pool) + return self._get_decimals(_coins) + + +@view +@external +def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get decimal places for each underlying coin within a pool + @dev For pools that do not lend, returns the same value as `get_decimals` + @param _pool Pool address + @return uint256 list of decimals + """ + if self._is_meta(_pool): + _underlying_coins: address[MAX_COINS] = self._get_underlying_coins_for_metapool(_pool) + _decimals: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) + for i in range(MAX_COINS): + if _underlying_coins[i] == empty(address): + break + _decimals[i] = ERC20(_underlying_coins[i]).decimals() + return _decimals + + _coins: address[MAX_COINS] = self._get_coins(_pool) + return self._get_decimals(_coins) + + +@view +@external +def get_gauges(_pool: address) -> (address[10], int128[10]): + """ + @notice Get a list of LiquidityGauge contracts associated with a pool + @param _pool Pool address + @return address[10] of gauge addresses, int128[10] of gauge types + """ + liquidity_gauges: address[10] = empty(address[10]) + gauge_types: int128[10] = empty(int128[10]) + for i in range(10): + gauge: address = self.liquidity_gauges[_pool][i] + if gauge == empty(address): + break + liquidity_gauges[i] = gauge + gauge_types[i] = GaugeController(GAUGE_CONTROLLER).gauge_types(gauge) + + return liquidity_gauges, gauge_types + + +@view +@external +def get_balances(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get balances for each coin within a pool + @dev For pools using lending, these are the wrapped coin balances + @param _pool Pool address + @return uint256 list of balances + """ + return self._get_balances(_pool) + + +@view +@external +def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get balances for each underlying coin within a pool + @dev For pools that do not lend, returns the same value as `get_balances` + @param _pool Pool address + @return uint256 list of underlyingbalances + """ + if not self._is_meta(_pool): + return self._get_balances(_pool) + return self._get_meta_underlying_balances(_pool) + + +@view +@external +def get_virtual_price_from_lp_token(_token: address) -> uint256: + """ + @notice Get the virtual price of a pool LP token + @param _token LP token address + @return uint256 Virtual price + """ + return CurvePool(self.get_pool_from_lp_token[_token]).get_virtual_price() + + +@view +@external +def get_A(_pool: address) -> uint256: + """ + @notice Get a pool's amplification factor + @param _pool Pool address + @return uint256 Amplification factor + """ + return CurvePool(_pool).A() + + +@view +@external +def get_D(_pool: address) -> uint256: + """ + @notice Get invariant of a pool's curve + @param _pool Pool address + @return uint256 Invariant + """ + return CurvePool(_pool).D() + + +@view +@external +def get_gamma(_pool: address) -> uint256: + """ + @notice Get the pool's gamma parameter + @param _pool Pool address + @return uint256 Gamma parameter + """ + return CurvePool(_pool).gamma() + + +@view +@external +def get_fees(_pool: address) -> uint256[4]: + """ + @notice Get the fees for a pool + @dev Fees are expressed as integers + @param _pool Pool address + @return Pool fee as uint256 with 1e10 precision + Admin fee as 1e10 percentage of pool fee + Mid fee + Out fee + """ + return [CurvePool(_pool).fee(), CurvePool(_pool).admin_fee(), CurvePool(_pool).mid_fee(), CurvePool(_pool).out_fee()] + + +@external +@view +def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the admin balances for a pool (accrued fees) + @dev Cryptoswap pools do not store admin fees in the form of + admin token balances. Instead, the admin fees are computed + at the time of claim iff sufficient profits have been made. + These fees are allocated to the admin by minting LP tokens + (dilution). The logic to calculate fees are derived from + cryptopool._claim_admin_fees() method. + @param _pool Pool address + @return uint256 list of admin balances + """ + xcp_profit: uint256 = CurvePool(_pool).xcp_profit() + xcp_profit_a: uint256 = CurvePool(_pool).xcp_profit_a() + admin_fee: uint256 = CurvePool(_pool).admin_fee() + admin_balances: uint256[MAX_COINS] = empty(uint256[MAX_COINS]) + + # admin balances are non zero if pool has made more than allowed profits: + if xcp_profit > xcp_profit_a: + + # calculate admin fees in lp token amounts: + fees: uint256 = (xcp_profit - xcp_profit_a) * admin_fee / (2 * 10**10) + if fees > 0: + vprice: uint256 = CurvePool(_pool).get_virtual_price() + lp_token: address = self.get_lp_token[_pool] + frac: uint256 = vprice * 10**18 / (vprice - fees) - 10**18 + + # the total supply of lp token is current supply + claimable: + lp_token_total_supply: uint256 = ERC20(lp_token).totalSupply() + d_supply: uint256 = lp_token_total_supply * frac / 10**18 + lp_token_total_supply += d_supply + admin_lp_frac: uint256 = d_supply * 10 ** 18 / lp_token_total_supply + + # get admin balances in individual assets: + reserves: uint256[MAX_COINS] = self._get_balances(_pool) + for i in range(MAX_COINS): + admin_balances[i] = admin_lp_frac * reserves[i] / 10 ** 18 + + return admin_balances + + +@view +@external +def get_coin_indices( + _pool: address, + _from: address, + _to: address +) -> (int128, int128, bool): + """ + @notice Convert coin addresses to indices for use with pool methods + @param _pool Pool address + @param _from Coin address to be used as `i` within a pool + @param _to Coin address to be used as `j` within a pool + @return int128 `i`, int128 `j`, boolean indicating if `i` and `j` are underlying coins + """ + result: uint256[3] = self._get_coin_indices(_pool, _from, _to) + return convert(result[0], int128), convert(result[1], int128), result[2] > 0 + + +@view +@external +def is_meta(_pool: address) -> bool: + """ + @notice Verify `_pool` is a metapool + @param _pool Pool address + @return True if `_pool` is a metapool + """ + return self.pool_data[_pool].base_pool != empty(address) + + +@view +@external +def get_base_pool(_pool: address) -> address: + """ + @notice Get the base pool of a metapool + @param _pool Pool address + @return Base pool address + """ + return self.pool_data[_pool].base_pool + + +@view +@external +def get_pool_name(_pool: address) -> String[64]: + """ + @notice Get the given name for a pool + @param _pool Pool address + @return The name of a pool + """ + return self.pool_data[_pool].name + + +# internal functionality used in admin setters + +@internal +def _register_coin(_coin: address): + if self.coins[_coin].register_count == 0: + coin_count: uint256 = self.coin_count + self.coins[_coin].index = coin_count + self.get_coin[coin_count] = _coin + self.coin_count += 1 + self.coins[_coin].register_count += 1 + + +@internal +def _register_coin_pair(_coina: address, _coinb: address, _key: uint256): + # register _coinb in _coina's array of coins + coin_b_pos: uint256 = self.coins[_coina].swap_count + self.coins[_coina].swap_for[coin_b_pos] = _coinb + self.coins[_coina].swap_count += 1 + # register _coina in _coinb's array of coins + coin_a_pos: uint256 = self.coins[_coinb].swap_count + self.coins[_coinb].swap_for[coin_a_pos] = _coina + self.coins[_coinb].swap_count += 1 + # register indexes (coina pos in coinb array, coinb pos in coina array) + if convert(_coina, uint256) < convert(_coinb, uint256): + self.coin_swap_indexes[_key] = shift(coin_a_pos, 128) + coin_b_pos + else: + self.coin_swap_indexes[_key] = shift(coin_b_pos, 128) + coin_a_pos + + +@internal +def _add_coins_to_market(_pool: address, _coin_list: address[MAX_COINS], _is_underlying: bool = False): + + for i in range(MAX_COINS): + + if _coin_list[i] == empty(address): + break + + # we dont want underlying <> underlying markets + # since that should be covered by the base_pool + # and not _pool: underlying <> underlying swaps + # happen at the base_pool level, not at the _pool + # level: + if _is_underlying and i > 0: + break + + # register coin: + self._register_coin(_coin_list[i]) + + # add pool to markets + i2: int128 = i + 1 + for x in range(i2, i2 + MAX_COINS): + + if _coin_list[x] == empty(address): + break + + key: uint256 = ( + convert(_coin_list[i], uint256) ^ convert(_coin_list[x], uint256) + ) + length: uint256 = self.market_counts[key] + self.markets[key][length] = _pool + self.market_counts[key] = length + 1 + + # register the coin pair + if length == 0: + self._register_coin_pair(_coin_list[x], _coin_list[i], key) + + +@internal +@view +def _market_exists(_pool: address, _coina: address, _coinb: address) -> bool: + key: uint256 = convert(_coina, uint256) ^ convert(_coinb, uint256) + if self.market_counts[key] == 0: + return False + return True + + +@internal +def _unregister_coin(_coin: address): + self.coins[_coin].register_count -= 1 + + if self.coins[_coin].register_count == 0: + self.coin_count -= 1 + coin_count: uint256 = self.coin_count + location: uint256 = self.coins[_coin].index + + if location < coin_count: + coin_b: address = self.get_coin[coin_count] + self.get_coin[location] = coin_b + self.coins[coin_b].index = location + + self.coins[_coin].index = 0 + self.get_coin[coin_count] = empty(address) + + +@internal +def _unregister_coin_pair(_coina: address, _coinb: address, _coinb_idx: uint256): + """ + @param _coinb_idx the index of _coinb in _coina's array of unique coin's + """ + # decrement swap counts for both coins + self.coins[_coina].swap_count -= 1 + + # retrieve the last currently occupied index in coina's array + coina_arr_last_idx: uint256 = self.coins[_coina].swap_count + + # if coinb's index in coina's array is less than the last + # overwrite it's position with the last coin + if _coinb_idx < coina_arr_last_idx: + # here's our last coin in coina's array + coin_c: address = self.coins[_coina].swap_for[coina_arr_last_idx] + # get the bitwise_xor of the pair to retrieve their indexes + key: uint256 = convert(_coina, uint256) ^ convert(coin_c, uint256) + indexes: uint256 = self.coin_swap_indexes[key] + + # update the pairing's indexes + if convert(_coina, uint256) < convert(coin_c, uint256): + # least complicated most readable way of shifting twice to remove the lower order bits + self.coin_swap_indexes[key] = shift(shift(indexes, -128), 128) + _coinb_idx + else: + self.coin_swap_indexes[key] = shift(_coinb_idx, 128) + indexes % 2 ** 128 + # set _coinb_idx in coina's array to coin_c + self.coins[_coina].swap_for[_coinb_idx] = coin_c + + self.coins[_coina].swap_for[coina_arr_last_idx] = empty(address) + + +@internal +def _remove_market(_pool: address, _coina: address, _coinb: address): + + key: uint256 = convert(_coina, uint256) ^ convert(_coinb, uint256) + length: uint256 = self.market_counts[key] - 1 + + if length == 0: + indexes: uint256 = self.coin_swap_indexes[key] + if convert(_coina, uint256) < convert(_coinb, uint256): + self._unregister_coin_pair(_coina, _coinb, indexes % 2 ** 128) + self._unregister_coin_pair(_coinb, _coina, shift(indexes, -128)) + else: + self._unregister_coin_pair(_coina, _coinb, shift(indexes, -128)) + self._unregister_coin_pair(_coinb, _coina, indexes % 2 ** 128) + self.coin_swap_indexes[key] = 0 + + for i in range(65536): + if i > length: + break + if self.markets[key][i] == _pool: + if i < length: + self.markets[key][i] = self.markets[key][length] + self.markets[key][length] = empty(address) + self.market_counts[key] = length + break + + +@internal +def _remove_liquidity_gauges(_pool: address): + for i in range(10): + if self.liquidity_gauges[_pool][i] != empty(address): + self.liquidity_gauges[_pool][i] = empty(address) + else: + break + + +# admin functions + + +@external +def add_pool( + _pool: address, + _lp_token: address, + _gauge: address, + _zap: address, + _n_coins: uint256, + _name: String[64], + _base_pool: address = empty(address), + _has_positive_rebasing_tokens: bool = False +): + """ + @notice Add a pool to the registry + @dev Only callable by admin + @param _pool Pool address to add + @param _lp_token Pool deposit token address + @param _gauge Gauge address + @param _zap Zap address + @param _n_coins Number of coins in the pool + @param _name The name of the pool + @param _base_pool Address of base pool + @param _has_positive_rebasing_tokens pool contains positive rebasing tokens + """ + assert msg.sender == self.address_provider.admin() # dev: admin-only function + assert _lp_token != empty(address) + assert self.get_pool_from_lp_token[_lp_token] == empty(address) # dev: pool exists + + # initialise PoolArray struct + length: uint256 = self.pool_count + self.pool_list[length] = _pool + self.pool_count = length + 1 + self.pool_data[_pool].location = length + self.pool_data[_pool].name = _name + self.pool_data[_pool].n_coins = _n_coins + + # update public mappings + if _zap != empty(address): + self.get_zap[_pool] = _zap + + if _gauge != empty(address): + self.liquidity_gauges[_pool][0] = _gauge + + self.get_pool_from_lp_token[_lp_token] = _pool + self.get_lp_token[_pool] = _lp_token + + # add coins mappings: + _coins: address[MAX_COINS] = empty(address[MAX_COINS]) + for i in range(MAX_COINS): + if i == convert(_n_coins, int128): + break + _coins[i] = CurvePool(_pool).coins(convert(i, uint256)) + self._add_coins_to_market(_pool, _coins) + + # the following does not add basepool_lp_token <> underlying_coin mapping + # since that is redundant: + if _base_pool != empty(address): + assert self.base_pool_registry.get_lp_token(_base_pool) != empty(address) + self.pool_data[_pool].base_pool = _base_pool + + _underlying_coins: address[MAX_COINS] = self._get_underlying_coins_for_metapool(_pool) + assert _underlying_coins[0] != empty(address) + + self._add_coins_to_market(_pool, _underlying_coins, True) + + if _has_positive_rebasing_tokens: + self.pool_data[_pool].has_positive_rebasing_tokens = True + + # log pool added: + self.last_updated = block.timestamp + log PoolAdded(_pool) + + +@external +def remove_pool(_pool: address): + """ + @notice Remove a pool to the registry + @dev Only callable by admin + @param _pool Pool address to remove + """ + assert msg.sender == self.address_provider.admin() # dev: admin-only function + assert self.get_lp_token[_pool] != empty(address) # dev: pool does not exist + + self.get_pool_from_lp_token[self.get_lp_token[_pool]] = empty(address) + self.get_lp_token[_pool] = empty(address) + + # remove _pool from pool_list + location: uint256 = self.pool_data[_pool].location + length: uint256 = self.pool_count - 1 + + # because self.pool_list is a static array, + # we can replace the last index with empty(address) + # and replace the first index with the pool + # that was previously in the last index. + # we skip this step if location == last index + if location < length: + # replace _pool with final value in pool_list + addr: address = self.pool_list[length] + self.pool_list[location] = addr + self.pool_data[addr].location = location + + # delete final pool_list value + self.pool_list[length] = empty(address) + self.pool_count = length + + coins: address[MAX_COINS] = self._get_coins(_pool) + ucoins: address[MAX_COINS] = empty(address[MAX_COINS]) + is_meta: bool = self._is_meta(_pool) + if is_meta: + ucoins = self._get_underlying_coins_for_metapool(_pool) + + for i in range(MAX_COINS): + + if coins[i] == empty(address) and ucoins[i] == empty(address): + break + + if coins[i] != empty(address): + self._unregister_coin(coins[i]) + + if ucoins[i] != empty(address): + if self.coins[ucoins[i]].register_count != 0: + self._unregister_coin(ucoins[i]) + + for j in range(MAX_COINS): + + if not j > i: + continue + + if empty(address) not in [coins[i], coins[j]] and self._market_exists(_pool, coins[i], coins[j]): + self._remove_market(_pool, coins[i], coins[j]) + + if empty(address) not in [coins[i], ucoins[j]] and self._market_exists(_pool, coins[i], ucoins[j]): + self._remove_market(_pool, coins[i], ucoins[j]) + + # reset remaining mappings: + self.pool_data[_pool].base_pool = empty(address) + self.pool_data[_pool].n_coins = 0 + self.pool_data[_pool].name = "" + self.get_zap[_pool] = empty(address) + self._remove_liquidity_gauges(_pool) + + self.last_updated = block.timestamp + log PoolRemoved(_pool) + + +@external +def set_liquidity_gauges(_pool: address, _liquidity_gauges: address[10]): + """ + @notice Set liquidity gauge contracts + @param _pool Pool address + @param _liquidity_gauges Liquidity gauge address + """ + assert msg.sender == self.address_provider.admin() # dev: admin-only function + + _lp_token: address = self.get_lp_token[_pool] + for i in range(10): + _gauge: address = _liquidity_gauges[i] + if _gauge != empty(address): + assert LiquidityGauge(_gauge).lp_token() == _lp_token # dev: wrong token + self.liquidity_gauges[_pool][i] = _gauge + elif self.liquidity_gauges[_pool][i] != empty(address): + self.liquidity_gauges[_pool][i] = empty(address) + else: + break + self.last_updated = block.timestamp + + +@external +def batch_set_liquidity_gauges(_pools: address[10], _liquidity_gauges: address[10]): + """ + @notice Set many liquidity gauge contracts + @param _pools List of pool addresses + @param _liquidity_gauges List of liquidity gauge addresses + """ + assert msg.sender == self.address_provider.admin() # dev: admin-only function + + for i in range(10): + _pool: address = _pools[i] + if _pool == empty(address): + break + _gauge: address = _liquidity_gauges[i] + assert LiquidityGauge(_gauge).lp_token() == self.get_lp_token[_pool] # dev: wrong token + self.liquidity_gauges[_pool][0] = _gauge + + self.last_updated = block.timestamp diff --git a/contracts/mainnet/registry_handlers/CryptoFactoryHandler.vy b/contracts/mainnet/registry_handlers/CryptoFactoryHandler.vy index 8cf6d1b..20c26d6 100644 --- a/contracts/mainnet/registry_handlers/CryptoFactoryHandler.vy +++ b/contracts/mainnet/registry_handlers/CryptoFactoryHandler.vy @@ -1,732 +1,732 @@ -#pragma version ^0.3.7 -""" -@title Curve Registry Handler for v2 Factory -@license MIT -""" - -# ---- interfaces ---- # -interface BaseRegistry: - def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view - def get_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_coins(_pool: address) -> address[MAX_COINS]: view - def get_decimals(_pool: address) -> uint256[MAX_COINS]: view - def get_gauge(_pool: address) -> address: view - def get_n_coins(_pool: address) -> uint256: view - def get_token(_pool: address) -> address: view - def pool_count() -> uint256: view - def pool_list(pool_id: uint256) -> address: view - - -interface BasePoolRegistry: - def get_base_pool_for_lp_token(_lp_token: address) -> address: view - def get_n_coins(_pool: address) -> uint256: view - def get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: view - def get_lp_token(_pool: address) -> address: view - def is_legacy(_pool: address) -> bool: view - def base_pool_list(i: uint256) -> address: view - def get_basepools_for_coin(_coin: address) -> DynArray[address, 1000]: view - - -interface CurvePool: - def adjustment_step() -> uint256: view - def admin_fee() -> uint256: view - def allowed_extra_profit() -> uint256: view - def A() -> uint256: view - def balances(i: uint256) -> uint256: view - def D() -> uint256: view - def fee() -> uint256: view - def fee_gamma() -> uint256: view - def gamma() -> uint256: view - def get_virtual_price() -> uint256: view - def ma_half_time() -> uint256: view - def mid_fee() -> uint256: view - def out_fee() -> uint256: view - def virtual_price() -> uint256: view - def xcp_profit() -> uint256: view - def xcp_profit_a() -> uint256: view - - -interface StableSwapLegacy: - def coins(i: int128) -> address: view - def underlying_coins(i: int128) -> address: view - def balances(i: int128) -> uint256: view - - -interface ERC20: - def name() -> String[64]: view - def balanceOf(_addr: address) -> uint256: view - def totalSupply() -> uint256: view - def decimals() -> uint256: view - - -interface GaugeController: - def gauge_types(gauge: address) -> int128: view - def gauges(i: uint256) -> address: view - - -interface Gauge: - def is_killed() -> bool: view - - -interface MetaRegistry: - def registry_length() -> uint256: view - - -# ---- constants ---- # -GAUGE_CONTROLLER: constant(address) = 0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB -MAX_COINS: constant(uint256) = 2 -MAX_METAREGISTRY_COINS: constant(uint256) = 8 -MAX_POOLS: constant(uint256) = 65536 -N_COINS: constant(uint256) = 2 - - -# ---- storage variables ---- # -base_registry: public(BaseRegistry) -base_pool_registry: BasePoolRegistry - - -# ---- constructor ---- # -@external -def __init__(_registry_address: address, _base_pool_registry: address): - self.base_registry = BaseRegistry(_registry_address) - self.base_pool_registry = BasePoolRegistry(_base_pool_registry) - - -# ---- internal methods ---- # -@internal -@view -def _pad_uint_array(_array: uint256[MAX_COINS]) -> uint256[MAX_METAREGISTRY_COINS]: - _padded_array: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) - for i in range(MAX_COINS): - _padded_array[i] = _array[i] - return _padded_array - - -@internal -@view -def _get_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - return self._pad_uint_array(self.base_registry.get_balances(_pool)) - - -@internal -@view -def _get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: - _coins: address[MAX_COINS] = self.base_registry.get_coins(_pool) - _padded_coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) - for i in range(MAX_COINS): - _padded_coins[i] = _coins[i] - return _padded_coins - - -@internal -@view -def _get_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - return self._pad_uint_array(self.base_registry.get_decimals(_pool)) - - -@internal -@view -def _get_lp_token(_pool: address) -> address: - return self.base_registry.get_token(_pool) - - -@internal -@view -def _get_n_coins(_pool: address) -> uint256: - - if (self.base_registry.get_coins(_pool)[0] != empty(address)): - return N_COINS - return 0 - - -@internal -@view -def _get_base_pool(_pool: address) -> address: - _coins: address[2] = self.base_registry.get_coins(_pool) - _base_pool: address = empty(address) - for coin in _coins: - _base_pool = self.base_pool_registry.get_base_pool_for_lp_token(coin) - if _base_pool != empty(address): - return _base_pool - return empty(address) - - -@view -@internal -def _get_underlying_coins_for_metapool(_pool: address) -> address[MAX_METAREGISTRY_COINS]: - - base_pool: address = self._get_base_pool(_pool) - assert base_pool != empty(address) - - base_pool_coins: address[MAX_METAREGISTRY_COINS] = self.base_pool_registry.get_coins(base_pool) - _underlying_coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) - base_coin_offset: uint256 = self._get_n_coins(_pool) - 1 - - for i in range(MAX_METAREGISTRY_COINS): - if i < base_coin_offset: - _underlying_coins[i] = self._get_coins(_pool)[i] - else: - _underlying_coins[i] = base_pool_coins[i - base_coin_offset] - - return _underlying_coins - - -@view -@internal -def _is_meta(_pool: address) -> bool: - return self._get_base_pool(_pool) != empty(address) - - -@view -@internal -def _get_meta_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - base_coin_idx: uint256 = self._get_n_coins(_pool) - 1 - base_pool: address = self._get_base_pool(_pool) - base_total_supply: uint256 = ERC20(self.base_pool_registry.get_lp_token(base_pool)).totalSupply() - - ul_balance: uint256 = 0 - underlying_pct: uint256 = 0 - if base_total_supply > 0: - underlying_pct = CurvePool(_pool).balances(base_coin_idx) * 10**36 / base_total_supply - - underlying_balances: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) - ul_coins: address[MAX_METAREGISTRY_COINS] = self._get_underlying_coins_for_metapool(_pool) - for i in range(MAX_METAREGISTRY_COINS): - - if ul_coins[i] == empty(address): - break - - if i < base_coin_idx: - ul_balance = CurvePool(_pool).balances(i) - - else: - - if self.base_pool_registry.is_legacy(base_pool): - ul_balance = StableSwapLegacy(base_pool).balances(convert(i - base_coin_idx, int128)) - else: - ul_balance = CurvePool(base_pool).balances(i - base_coin_idx) - ul_balance = ul_balance * underlying_pct / 10**36 - underlying_balances[i] = ul_balance - - return underlying_balances - - -@internal -@view -def _get_pool_from_lp_token(_lp_token: address) -> address: - max_pools: uint256 = self.base_registry.pool_count() - for i in range(MAX_POOLS): - if i == max_pools: - break - pool: address = self.base_registry.pool_list(i) - token: address = self._get_lp_token(pool) - if token == _lp_token: - return pool - return empty(address) - - -@internal -@view -def _get_gauge_type(_gauge: address) -> int128: - - # try to get gauge type registered in gauge controller - success: bool = False - response: Bytes[32] = b"" - success, response = raw_call( - GAUGE_CONTROLLER, - concat( - method_id("gauge_type(address)"), - convert(_gauge, bytes32), - ), - max_outsize=32, - revert_on_failure=False, - is_static_call=True - ) - - if success and not Gauge(_gauge).is_killed(): - return convert(response, int128) - - # if we are here, the call to get gauge_type failed. - # in such a case, return a default value. - # ethereum: mainnet crypto pools have gauge type 5 - return 5 - - -# ---- view methods (API) of the contract ---- # -@external -@view -def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: - """ - @notice checks if either of the two coins are in a base pool and then checks - if the basepool lp token and the other coin have a pool. - This is done because the factory does not have `underlying` methods in - pools that have a basepool lp token in them - @param _from Address of the _from coin - @param _to Address of the _to coin - @param i Index of the pool to return - @return Address of the pool - """ - _pool: address = self.base_registry.find_pool_for_coins(_from, _to, i) - - if _pool != empty(address): - return _pool - - # could not find a pool for the coins for `i`. check if they are in a base pool: - _pools: address[1000] = empty(address[1000]) - _num_metapool_pairs: uint256 = 0 - - for coin in [_from, _to]: - - # we need to loop over several base pools because a coin can exist in multiple base pools - base_pools: DynArray[address, 1000] = self.base_pool_registry.get_basepools_for_coin(coin) - - if len(base_pools) == 0: - continue - - for _base_pool in base_pools: - - # found a base pool, but is it the right one? - if _base_pool != empty(address): - - base_pool_lp_token: address = self.base_pool_registry.get_lp_token(_base_pool) - - for k in range(100): - - if coin == _from: - - # check if the basepool containing the _from coin has a pair with the _to coin: - _pool = self.base_registry.find_pool_for_coins(base_pool_lp_token, _to, k) - - if _pool == empty(address): - break - - # only append if a pool is found: - _pools[_num_metapool_pairs] = _pool - _num_metapool_pairs += 1 - - elif coin == _to: - - # check if the basepool containing the _to coin has a pair with the _from coin: - _pool = self.base_registry.find_pool_for_coins(_from, base_pool_lp_token, k) - - if _pool == empty(address): - break - - # only append if a pool is found: - _pools[_num_metapool_pairs] = _pool - _num_metapool_pairs += 1 - - # say we found a pair for _from and _to in the base registry without a basepool combination already - # then that pool will be returned when i == 0. But if that same pair exists in a base pool then - # i == 1 will return empty(address) in the base_registry query, but i = 0 for _pools will return - # the metapool pair. But if we keep i == 1 for _pools, it would return empty(address) (unless there - # is another metapool pair of course). So, we first check how many direct pairs exist: - - num_pairs: uint256 = 0 - for k in range(20): - _pool = self.base_registry.find_pool_for_coins(_from, _to, k) - if _pool == empty(address): - break - num_pairs += 1 - - # now we check if the queried pair index `i` is higher than num_pairs. e.g. if num_pairs == 1 and i == 1, - # and _num_metapool_pairs == 1, then i >= num_pairs, and we return _pools[1 - num_pairs]. If there are - # no metapool pairs, then it will automatically return empty(address): - if i >= num_pairs: - return _pools[i - num_pairs] - else: - return _pools[i] - - -@external -@view -def get_admin_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Returns the balances of the admin tokens of the given pool - @dev Cryptoswap pools do not store admin fees in the form of - admin token balances. Instead, the admin fees are computed - at the time of claim iff sufficient profits have been made. - These fees are allocated to the admin by minting LP tokens - (dilution). The logic to calculate fees are derived from - cryptopool._claim_admin_fees() method. - @param _pool Address of the pool - @return uint256[MAX_METAREGISTRY_COINS] Array of admin balances - """ - xcp_profit: uint256 = CurvePool(_pool).xcp_profit() - xcp_profit_a: uint256 = CurvePool(_pool).xcp_profit_a() - admin_fee: uint256 = CurvePool(_pool).admin_fee() - admin_balances: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) - - # admin balances are non zero if pool has made more than allowed profits: - if xcp_profit > xcp_profit_a: - - # calculate admin fees in lp token amounts: - fees: uint256 = (xcp_profit - xcp_profit_a) * admin_fee / (2 * 10**10) - if fees > 0: - vprice: uint256 = CurvePool(_pool).virtual_price() - lp_token: address = self._get_lp_token(_pool) - frac: uint256 = vprice * 10**18 / (vprice - fees) - 10**18 - - # the total supply of lp token is current supply + claimable: - lp_token_total_supply: uint256 = ERC20(lp_token).totalSupply() - d_supply: uint256 = lp_token_total_supply * frac / 10**18 - lp_token_total_supply += d_supply - admin_lp_frac: uint256 = d_supply * 10 ** 18 / lp_token_total_supply - - # get admin balances in individual assets: - reserves: uint256[MAX_METAREGISTRY_COINS] = self._get_balances(_pool) - for i in range(MAX_METAREGISTRY_COINS): - admin_balances[i] = admin_lp_frac * reserves[i] / 10 ** 18 - - return admin_balances - - -@external -@view -def get_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Returns the balances of the tokens of the given pool - @param _pool Address of the pool - @return uint256[MAX_METAREGISTRY_COINS] Array of balances - """ - return self._get_balances(_pool) - - -@external -@view -def get_base_pool(_pool: address) -> address: - """ - @notice Returns the base pool of the given pool - @dev Returns empty(address) if the pool isn't a metapool - @param _pool Address of the pool - @return Address of the base pool - """ - if not self._is_meta(_pool): - return empty(address) - return self._get_base_pool(_pool) - - -@view -@external -def get_coin_indices(_pool: address, _from: address, _to: address) -> (uint256, uint256, bool): - """ - @notice Convert coin addresses to indices for use with pool methods - @param _pool Address of the pool - @param _from Address of the from coin - @param _to Address of the to coin - @return (uint256, uint256, bool) Tuple of indices of the coins in the pool, - and whether the market is an underlying market or not. - """ - # the return value is stored as `uint256[3]` to reduce gas costs - # from index, to index, is the market underlying? - result: uint256[3] = empty(uint256[3]) - _coins: address[MAX_METAREGISTRY_COINS] = self._get_coins(_pool) - found_market: bool = False - - # check coin markets - for x in range(MAX_METAREGISTRY_COINS): - coin: address = _coins[x] - if coin == empty(address): - # if we reach the end of the coins, reset `found_market` and try again - # with the underlying coins - found_market = False - break - if coin == _from: - result[0] = x - elif coin == _to: - result[1] = x - else: - continue - - if found_market: - # the second time we find a match, break out of the loop - break - # the first time we find a match, set `found_market` to True - found_market = True - - if not found_market and self._is_meta(_pool): - # check underlying coin markets - underlying_coins: address[MAX_METAREGISTRY_COINS] = self._get_underlying_coins_for_metapool(_pool) - for x in range(MAX_METAREGISTRY_COINS): - coin: address = underlying_coins[x] - if coin == empty(address): - raise "No available market" - if coin == _from: - result[0] = x - elif coin == _to: - result[1] = x - else: - continue - - if found_market: - result[2] = 1 - break - found_market = True - - return result[0], result[1], result[2] > 0 - - -@external -@view -def get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: - """ - @notice Returns the coins of the given pool - @param _pool Address of the pool - @return address[MAX_METAREGISTRY_COINS] Array of coins - """ - return self._get_coins(_pool) - - -@external -@view -def get_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Returns the decimals of the coins in a given pool - @param _pool Address of the pool - @return uint256[MAX_METAREGISTRY_COINS] Array of decimals - """ - return self._get_decimals(_pool) - - -@external -@view -def get_fees(_pool: address) -> uint256[10]: - """ - @notice Returns the fees of the given pool - @param _pool Address of the pool - @return uint256[10] Array of fees. Fees are arranged as: - 1. swap fee (or `fee`) - 2. admin fee - 3. mid fee (fee when cryptoswap pool is pegged) - 4. out fee (fee when cryptoswap pool depegs) - """ - fees: uint256[10] = empty(uint256[10]) - pool_fees: uint256[4] = [CurvePool(_pool).fee(), CurvePool(_pool).admin_fee(), CurvePool(_pool).mid_fee(), CurvePool(_pool).out_fee()] - for i in range(4): - fees[i] = pool_fees[i] - return fees - - -@external -@view -def get_gauges(_pool: address) -> (address[10], int128[10]): - """ - @notice Returns the gauges of the given pool - @param _pool Address of the pool - @return (address[10], int128[10]) Tuple of gauges. Gauges are arranged as: - 1. gauge addresses - 2. gauge types - """ - gauges: address[10] = empty(address[10]) - types: int128[10] = empty(int128[10]) - gauges[0] = self.base_registry.get_gauge(_pool) - types[0] = self._get_gauge_type(gauges[0]) - return (gauges, types) - - -@external -@view -def get_lp_token(_pool: address) -> address: - """ - @notice Returns the Liquidity Provider token of the given pool - @param _pool Address of the pool - @return Address of the Liquidity Provider token - """ - return self._get_lp_token(_pool) - - -@external -@view -def get_n_coins(_pool: address) -> uint256: - """ - @notice Returns the number of coins in the given pool - @param _pool Address of the pool - @return uint256 Number of coins - """ - return self._get_n_coins(_pool) - - -@external -@view -def get_n_underlying_coins(_pool: address) -> uint256: - """ - @notice Get the number of underlying coins in a pool - @param _pool Address of the pool - @return uint256 Number of underlying coins - """ - _coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) - - if self._is_meta(_pool): - _coins = self._get_underlying_coins_for_metapool(_pool) - else: - _coins = self._get_coins(_pool) - - for i in range(MAX_METAREGISTRY_COINS): - if _coins[i] == empty(address): - return i - raise - - -@external -@view -def get_pool_asset_type(_pool: address) -> uint256: - """ - @notice Returns the asset type of the given pool - @dev Returns 4: 0 = USD, 1 = ETH, 2 = BTC, 3 = Other - @param _pool Address of the pool - @return uint256 Asset type - """ - return 4 - - -@external -@view -def get_pool_from_lp_token(_lp_token: address) -> address: - """ - @notice Returns the pool of the given Liquidity Provider token - @param _lp_token Address of the Liquidity Provider token - @return Address of the pool - """ - max_pools: uint256 = self.base_registry.pool_count() - for i in range(MAX_POOLS): - if i == max_pools: - break - pool: address = self.base_registry.pool_list(i) - token: address = self._get_lp_token(pool) - if token == _lp_token: - return pool - return empty(address) - - -@external -@view -def get_pool_name(_pool: address) -> String[64]: - """ - @notice Returns the name of the given pool - @param _pool Address of the pool - @return String[64] Name of the pool - """ - token: address = self._get_lp_token(_pool) - if token != empty(address): - return ERC20(self.base_registry.get_token(_pool)).name() - else: - return "" - - -@external -@view -def get_pool_params(_pool: address) -> uint256[20]: - """ - @notice returns pool params given a cryptopool address - @dev contains all settable parameter that alter the pool's performance - @dev only applicable for cryptopools - @param _pool Address of the pool for which data is being queried. - """ - - pool_params: uint256[20] = empty(uint256[20]) - pool_params[0] = CurvePool(_pool).A() - pool_params[1] = CurvePool(_pool).D() - pool_params[2] = CurvePool(_pool).gamma() - pool_params[3] = CurvePool(_pool).allowed_extra_profit() - pool_params[4] = CurvePool(_pool).fee_gamma() - pool_params[5] = CurvePool(_pool).adjustment_step() - pool_params[6] = CurvePool(_pool).ma_half_time() - return pool_params - - -@external -@view -def get_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Returns the underlying balances of the given pool - @param _pool Address of the pool - @return uint256[MAX_METAREGISTRY_COINS] Array of underlying balances - """ - if self._is_meta(_pool): - return self._get_meta_underlying_balances(_pool) - return self._get_balances(_pool) - -@external -@view -def get_underlying_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: - """ - @notice Returns the underlying coins of the given pool - @param _pool Address of the pool - @return address[MAX_METAREGISTRY_COINS] Array of underlying coins - """ - if self._is_meta(_pool): - return self._get_underlying_coins_for_metapool(_pool) - return self._get_coins(_pool) - - -@external -@view -def get_underlying_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Returns the underlying decimals of the given pool - @param _pool Address of the pool - @return uint256[MAX_METAREGISTRY_COINS] Array of underlying decimals - """ - if self._is_meta(_pool): - _underlying_coins: address[MAX_METAREGISTRY_COINS] = self._get_underlying_coins_for_metapool(_pool) - _decimals: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) - for i in range(MAX_METAREGISTRY_COINS): - if _underlying_coins[i] == empty(address): - break - _decimals[i] = ERC20(_underlying_coins[i]).decimals() - return _decimals - return self._get_decimals(_pool) - - -@external -@view -def get_virtual_price_from_lp_token(_token: address) -> uint256: - """ - @notice Returns the virtual price of the given Liquidity Provider token - @param _token Address of the Liquidity Provider token - @return uint256 Virtual price - """ - return CurvePool(self._get_pool_from_lp_token(_token)).get_virtual_price() - - -@external -@view -def is_meta(_pool: address) -> bool: - """ - @notice Returns whether the given pool is a meta pool - @param _pool Address of the pool - @return bool Whether the pool is a meta pool - """ - return self._is_meta(_pool) - - -@external -@view -def is_registered(_pool: address) -> bool: - """ - @notice Check if a pool belongs to the registry using get_n_coins - @param _pool The address of the pool - @return A bool corresponding to whether the pool belongs or not - """ - return self._get_n_coins(_pool) > 0 - - -@external -@view -def pool_count() -> uint256: - """ - @notice Returns the number of pools in the registry - @return uint256 Number of pools - """ - return self.base_registry.pool_count() - - -@external -@view -def pool_list(_index: uint256) -> address: - """ - @notice Returns the address of the pool at the given index - @param _index Index of the pool - @return Address of the pool - """ - return self.base_registry.pool_list(_index) +#pragma version ^0.3.7 +""" +@title Curve Registry Handler for v2 Factory +@license MIT +""" + +# ---- interfaces ---- # +interface BaseRegistry: + def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view + def get_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_coins(_pool: address) -> address[MAX_COINS]: view + def get_decimals(_pool: address) -> uint256[MAX_COINS]: view + def get_gauge(_pool: address) -> address: view + def get_n_coins(_pool: address) -> uint256: view + def get_token(_pool: address) -> address: view + def pool_count() -> uint256: view + def pool_list(pool_id: uint256) -> address: view + + +interface BasePoolRegistry: + def get_base_pool_for_lp_token(_lp_token: address) -> address: view + def get_n_coins(_pool: address) -> uint256: view + def get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: view + def get_lp_token(_pool: address) -> address: view + def is_legacy(_pool: address) -> bool: view + def base_pool_list(i: uint256) -> address: view + def get_basepools_for_coin(_coin: address) -> DynArray[address, 1000]: view + + +interface CurvePool: + def adjustment_step() -> uint256: view + def admin_fee() -> uint256: view + def allowed_extra_profit() -> uint256: view + def A() -> uint256: view + def balances(i: uint256) -> uint256: view + def D() -> uint256: view + def fee() -> uint256: view + def fee_gamma() -> uint256: view + def gamma() -> uint256: view + def get_virtual_price() -> uint256: view + def ma_half_time() -> uint256: view + def mid_fee() -> uint256: view + def out_fee() -> uint256: view + def virtual_price() -> uint256: view + def xcp_profit() -> uint256: view + def xcp_profit_a() -> uint256: view + + +interface StableSwapLegacy: + def coins(i: int128) -> address: view + def underlying_coins(i: int128) -> address: view + def balances(i: int128) -> uint256: view + + +interface ERC20: + def name() -> String[64]: view + def balanceOf(_addr: address) -> uint256: view + def totalSupply() -> uint256: view + def decimals() -> uint256: view + + +interface GaugeController: + def gauge_types(gauge: address) -> int128: view + def gauges(i: uint256) -> address: view + + +interface Gauge: + def is_killed() -> bool: view + + +interface MetaRegistry: + def registry_length() -> uint256: view + + +# ---- constants ---- # +GAUGE_CONTROLLER: constant(address) = 0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB +MAX_COINS: constant(uint256) = 2 +MAX_METAREGISTRY_COINS: constant(uint256) = 8 +MAX_POOLS: constant(uint256) = 65536 +N_COINS: constant(uint256) = 2 + + +# ---- storage variables ---- # +base_registry: public(BaseRegistry) +base_pool_registry: BasePoolRegistry + + +# ---- constructor ---- # +@external +def __init__(_registry_address: address, _base_pool_registry: address): + self.base_registry = BaseRegistry(_registry_address) + self.base_pool_registry = BasePoolRegistry(_base_pool_registry) + + +# ---- internal methods ---- # +@internal +@view +def _pad_uint_array(_array: uint256[MAX_COINS]) -> uint256[MAX_METAREGISTRY_COINS]: + _padded_array: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) + for i in range(MAX_COINS): + _padded_array[i] = _array[i] + return _padded_array + + +@internal +@view +def _get_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + return self._pad_uint_array(self.base_registry.get_balances(_pool)) + + +@internal +@view +def _get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: + _coins: address[MAX_COINS] = self.base_registry.get_coins(_pool) + _padded_coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) + for i in range(MAX_COINS): + _padded_coins[i] = _coins[i] + return _padded_coins + + +@internal +@view +def _get_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + return self._pad_uint_array(self.base_registry.get_decimals(_pool)) + + +@internal +@view +def _get_lp_token(_pool: address) -> address: + return self.base_registry.get_token(_pool) + + +@internal +@view +def _get_n_coins(_pool: address) -> uint256: + + if (self.base_registry.get_coins(_pool)[0] != empty(address)): + return N_COINS + return 0 + + +@internal +@view +def _get_base_pool(_pool: address) -> address: + _coins: address[2] = self.base_registry.get_coins(_pool) + _base_pool: address = empty(address) + for coin in _coins: + _base_pool = self.base_pool_registry.get_base_pool_for_lp_token(coin) + if _base_pool != empty(address): + return _base_pool + return empty(address) + + +@view +@internal +def _get_underlying_coins_for_metapool(_pool: address) -> address[MAX_METAREGISTRY_COINS]: + + base_pool: address = self._get_base_pool(_pool) + assert base_pool != empty(address) + + base_pool_coins: address[MAX_METAREGISTRY_COINS] = self.base_pool_registry.get_coins(base_pool) + _underlying_coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) + base_coin_offset: uint256 = self._get_n_coins(_pool) - 1 + + for i in range(MAX_METAREGISTRY_COINS): + if i < base_coin_offset: + _underlying_coins[i] = self._get_coins(_pool)[i] + else: + _underlying_coins[i] = base_pool_coins[i - base_coin_offset] + + return _underlying_coins + + +@view +@internal +def _is_meta(_pool: address) -> bool: + return self._get_base_pool(_pool) != empty(address) + + +@view +@internal +def _get_meta_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + base_coin_idx: uint256 = self._get_n_coins(_pool) - 1 + base_pool: address = self._get_base_pool(_pool) + base_total_supply: uint256 = ERC20(self.base_pool_registry.get_lp_token(base_pool)).totalSupply() + + ul_balance: uint256 = 0 + underlying_pct: uint256 = 0 + if base_total_supply > 0: + underlying_pct = CurvePool(_pool).balances(base_coin_idx) * 10**36 / base_total_supply + + underlying_balances: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) + ul_coins: address[MAX_METAREGISTRY_COINS] = self._get_underlying_coins_for_metapool(_pool) + for i in range(MAX_METAREGISTRY_COINS): + + if ul_coins[i] == empty(address): + break + + if i < base_coin_idx: + ul_balance = CurvePool(_pool).balances(i) + + else: + + if self.base_pool_registry.is_legacy(base_pool): + ul_balance = StableSwapLegacy(base_pool).balances(convert(i - base_coin_idx, int128)) + else: + ul_balance = CurvePool(base_pool).balances(i - base_coin_idx) + ul_balance = ul_balance * underlying_pct / 10**36 + underlying_balances[i] = ul_balance + + return underlying_balances + + +@internal +@view +def _get_pool_from_lp_token(_lp_token: address) -> address: + max_pools: uint256 = self.base_registry.pool_count() + for i in range(MAX_POOLS): + if i == max_pools: + break + pool: address = self.base_registry.pool_list(i) + token: address = self._get_lp_token(pool) + if token == _lp_token: + return pool + return empty(address) + + +@internal +@view +def _get_gauge_type(_gauge: address) -> int128: + + # try to get gauge type registered in gauge controller + success: bool = False + response: Bytes[32] = b"" + success, response = raw_call( + GAUGE_CONTROLLER, + concat( + method_id("gauge_type(address)"), + convert(_gauge, bytes32), + ), + max_outsize=32, + revert_on_failure=False, + is_static_call=True + ) + + if success and not Gauge(_gauge).is_killed(): + return convert(response, int128) + + # if we are here, the call to get gauge_type failed. + # in such a case, return a default value. + # ethereum: mainnet crypto pools have gauge type 5 + return 5 + + +# ---- view methods (API) of the contract ---- # +@external +@view +def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: + """ + @notice checks if either of the two coins are in a base pool and then checks + if the basepool lp token and the other coin have a pool. + This is done because the factory does not have `underlying` methods in + pools that have a basepool lp token in them + @param _from Address of the _from coin + @param _to Address of the _to coin + @param i Index of the pool to return + @return Address of the pool + """ + _pool: address = self.base_registry.find_pool_for_coins(_from, _to, i) + + if _pool != empty(address): + return _pool + + # could not find a pool for the coins for `i`. check if they are in a base pool: + _pools: address[1000] = empty(address[1000]) + _num_metapool_pairs: uint256 = 0 + + for coin in [_from, _to]: + + # we need to loop over several base pools because a coin can exist in multiple base pools + base_pools: DynArray[address, 1000] = self.base_pool_registry.get_basepools_for_coin(coin) + + if len(base_pools) == 0: + continue + + for _base_pool in base_pools: + + # found a base pool, but is it the right one? + if _base_pool != empty(address): + + base_pool_lp_token: address = self.base_pool_registry.get_lp_token(_base_pool) + + for k in range(100): + + if coin == _from: + + # check if the basepool containing the _from coin has a pair with the _to coin: + _pool = self.base_registry.find_pool_for_coins(base_pool_lp_token, _to, k) + + if _pool == empty(address): + break + + # only append if a pool is found: + _pools[_num_metapool_pairs] = _pool + _num_metapool_pairs += 1 + + elif coin == _to: + + # check if the basepool containing the _to coin has a pair with the _from coin: + _pool = self.base_registry.find_pool_for_coins(_from, base_pool_lp_token, k) + + if _pool == empty(address): + break + + # only append if a pool is found: + _pools[_num_metapool_pairs] = _pool + _num_metapool_pairs += 1 + + # say we found a pair for _from and _to in the base registry without a basepool combination already + # then that pool will be returned when i == 0. But if that same pair exists in a base pool then + # i == 1 will return empty(address) in the base_registry query, but i = 0 for _pools will return + # the metapool pair. But if we keep i == 1 for _pools, it would return empty(address) (unless there + # is another metapool pair of course). So, we first check how many direct pairs exist: + + num_pairs: uint256 = 0 + for k in range(20): + _pool = self.base_registry.find_pool_for_coins(_from, _to, k) + if _pool == empty(address): + break + num_pairs += 1 + + # now we check if the queried pair index `i` is higher than num_pairs. e.g. if num_pairs == 1 and i == 1, + # and _num_metapool_pairs == 1, then i >= num_pairs, and we return _pools[1 - num_pairs]. If there are + # no metapool pairs, then it will automatically return empty(address): + if i >= num_pairs: + return _pools[i - num_pairs] + else: + return _pools[i] + + +@external +@view +def get_admin_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Returns the balances of the admin tokens of the given pool + @dev Cryptoswap pools do not store admin fees in the form of + admin token balances. Instead, the admin fees are computed + at the time of claim iff sufficient profits have been made. + These fees are allocated to the admin by minting LP tokens + (dilution). The logic to calculate fees are derived from + cryptopool._claim_admin_fees() method. + @param _pool Address of the pool + @return uint256[MAX_METAREGISTRY_COINS] Array of admin balances + """ + xcp_profit: uint256 = CurvePool(_pool).xcp_profit() + xcp_profit_a: uint256 = CurvePool(_pool).xcp_profit_a() + admin_fee: uint256 = CurvePool(_pool).admin_fee() + admin_balances: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) + + # admin balances are non zero if pool has made more than allowed profits: + if xcp_profit > xcp_profit_a: + + # calculate admin fees in lp token amounts: + fees: uint256 = (xcp_profit - xcp_profit_a) * admin_fee / (2 * 10**10) + if fees > 0: + vprice: uint256 = CurvePool(_pool).virtual_price() + lp_token: address = self._get_lp_token(_pool) + frac: uint256 = vprice * 10**18 / (vprice - fees) - 10**18 + + # the total supply of lp token is current supply + claimable: + lp_token_total_supply: uint256 = ERC20(lp_token).totalSupply() + d_supply: uint256 = lp_token_total_supply * frac / 10**18 + lp_token_total_supply += d_supply + admin_lp_frac: uint256 = d_supply * 10 ** 18 / lp_token_total_supply + + # get admin balances in individual assets: + reserves: uint256[MAX_METAREGISTRY_COINS] = self._get_balances(_pool) + for i in range(MAX_METAREGISTRY_COINS): + admin_balances[i] = admin_lp_frac * reserves[i] / 10 ** 18 + + return admin_balances + + +@external +@view +def get_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Returns the balances of the tokens of the given pool + @param _pool Address of the pool + @return uint256[MAX_METAREGISTRY_COINS] Array of balances + """ + return self._get_balances(_pool) + + +@external +@view +def get_base_pool(_pool: address) -> address: + """ + @notice Returns the base pool of the given pool + @dev Returns empty(address) if the pool isn't a metapool + @param _pool Address of the pool + @return Address of the base pool + """ + if not self._is_meta(_pool): + return empty(address) + return self._get_base_pool(_pool) + + +@view +@external +def get_coin_indices(_pool: address, _from: address, _to: address) -> (uint256, uint256, bool): + """ + @notice Convert coin addresses to indices for use with pool methods + @param _pool Address of the pool + @param _from Address of the from coin + @param _to Address of the to coin + @return (uint256, uint256, bool) Tuple of indices of the coins in the pool, + and whether the market is an underlying market or not. + """ + # the return value is stored as `uint256[3]` to reduce gas costs + # from index, to index, is the market underlying? + result: uint256[3] = empty(uint256[3]) + _coins: address[MAX_METAREGISTRY_COINS] = self._get_coins(_pool) + found_market: bool = False + + # check coin markets + for x in range(MAX_METAREGISTRY_COINS): + coin: address = _coins[x] + if coin == empty(address): + # if we reach the end of the coins, reset `found_market` and try again + # with the underlying coins + found_market = False + break + if coin == _from: + result[0] = x + elif coin == _to: + result[1] = x + else: + continue + + if found_market: + # the second time we find a match, break out of the loop + break + # the first time we find a match, set `found_market` to True + found_market = True + + if not found_market and self._is_meta(_pool): + # check underlying coin markets + underlying_coins: address[MAX_METAREGISTRY_COINS] = self._get_underlying_coins_for_metapool(_pool) + for x in range(MAX_METAREGISTRY_COINS): + coin: address = underlying_coins[x] + if coin == empty(address): + raise "No available market" + if coin == _from: + result[0] = x + elif coin == _to: + result[1] = x + else: + continue + + if found_market: + result[2] = 1 + break + found_market = True + + return result[0], result[1], result[2] > 0 + + +@external +@view +def get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: + """ + @notice Returns the coins of the given pool + @param _pool Address of the pool + @return address[MAX_METAREGISTRY_COINS] Array of coins + """ + return self._get_coins(_pool) + + +@external +@view +def get_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Returns the decimals of the coins in a given pool + @param _pool Address of the pool + @return uint256[MAX_METAREGISTRY_COINS] Array of decimals + """ + return self._get_decimals(_pool) + + +@external +@view +def get_fees(_pool: address) -> uint256[10]: + """ + @notice Returns the fees of the given pool + @param _pool Address of the pool + @return uint256[10] Array of fees. Fees are arranged as: + 1. swap fee (or `fee`) + 2. admin fee + 3. mid fee (fee when cryptoswap pool is pegged) + 4. out fee (fee when cryptoswap pool depegs) + """ + fees: uint256[10] = empty(uint256[10]) + pool_fees: uint256[4] = [CurvePool(_pool).fee(), CurvePool(_pool).admin_fee(), CurvePool(_pool).mid_fee(), CurvePool(_pool).out_fee()] + for i in range(4): + fees[i] = pool_fees[i] + return fees + + +@external +@view +def get_gauges(_pool: address) -> (address[10], int128[10]): + """ + @notice Returns the gauges of the given pool + @param _pool Address of the pool + @return (address[10], int128[10]) Tuple of gauges. Gauges are arranged as: + 1. gauge addresses + 2. gauge types + """ + gauges: address[10] = empty(address[10]) + types: int128[10] = empty(int128[10]) + gauges[0] = self.base_registry.get_gauge(_pool) + types[0] = self._get_gauge_type(gauges[0]) + return (gauges, types) + + +@external +@view +def get_lp_token(_pool: address) -> address: + """ + @notice Returns the Liquidity Provider token of the given pool + @param _pool Address of the pool + @return Address of the Liquidity Provider token + """ + return self._get_lp_token(_pool) + + +@external +@view +def get_n_coins(_pool: address) -> uint256: + """ + @notice Returns the number of coins in the given pool + @param _pool Address of the pool + @return uint256 Number of coins + """ + return self._get_n_coins(_pool) + + +@external +@view +def get_n_underlying_coins(_pool: address) -> uint256: + """ + @notice Get the number of underlying coins in a pool + @param _pool Address of the pool + @return uint256 Number of underlying coins + """ + _coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) + + if self._is_meta(_pool): + _coins = self._get_underlying_coins_for_metapool(_pool) + else: + _coins = self._get_coins(_pool) + + for i in range(MAX_METAREGISTRY_COINS): + if _coins[i] == empty(address): + return i + raise + + +@external +@view +def get_pool_asset_type(_pool: address) -> uint256: + """ + @notice Returns the asset type of the given pool + @dev Returns 4: 0 = USD, 1 = ETH, 2 = BTC, 3 = Other + @param _pool Address of the pool + @return uint256 Asset type + """ + return 4 + + +@external +@view +def get_pool_from_lp_token(_lp_token: address) -> address: + """ + @notice Returns the pool of the given Liquidity Provider token + @param _lp_token Address of the Liquidity Provider token + @return Address of the pool + """ + max_pools: uint256 = self.base_registry.pool_count() + for i in range(MAX_POOLS): + if i == max_pools: + break + pool: address = self.base_registry.pool_list(i) + token: address = self._get_lp_token(pool) + if token == _lp_token: + return pool + return empty(address) + + +@external +@view +def get_pool_name(_pool: address) -> String[64]: + """ + @notice Returns the name of the given pool + @param _pool Address of the pool + @return String[64] Name of the pool + """ + token: address = self._get_lp_token(_pool) + if token != empty(address): + return ERC20(self.base_registry.get_token(_pool)).name() + else: + return "" + + +@external +@view +def get_pool_params(_pool: address) -> uint256[20]: + """ + @notice returns pool params given a cryptopool address + @dev contains all settable parameter that alter the pool's performance + @dev only applicable for cryptopools + @param _pool Address of the pool for which data is being queried. + """ + + pool_params: uint256[20] = empty(uint256[20]) + pool_params[0] = CurvePool(_pool).A() + pool_params[1] = CurvePool(_pool).D() + pool_params[2] = CurvePool(_pool).gamma() + pool_params[3] = CurvePool(_pool).allowed_extra_profit() + pool_params[4] = CurvePool(_pool).fee_gamma() + pool_params[5] = CurvePool(_pool).adjustment_step() + pool_params[6] = CurvePool(_pool).ma_half_time() + return pool_params + + +@external +@view +def get_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Returns the underlying balances of the given pool + @param _pool Address of the pool + @return uint256[MAX_METAREGISTRY_COINS] Array of underlying balances + """ + if self._is_meta(_pool): + return self._get_meta_underlying_balances(_pool) + return self._get_balances(_pool) + +@external +@view +def get_underlying_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: + """ + @notice Returns the underlying coins of the given pool + @param _pool Address of the pool + @return address[MAX_METAREGISTRY_COINS] Array of underlying coins + """ + if self._is_meta(_pool): + return self._get_underlying_coins_for_metapool(_pool) + return self._get_coins(_pool) + + +@external +@view +def get_underlying_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Returns the underlying decimals of the given pool + @param _pool Address of the pool + @return uint256[MAX_METAREGISTRY_COINS] Array of underlying decimals + """ + if self._is_meta(_pool): + _underlying_coins: address[MAX_METAREGISTRY_COINS] = self._get_underlying_coins_for_metapool(_pool) + _decimals: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) + for i in range(MAX_METAREGISTRY_COINS): + if _underlying_coins[i] == empty(address): + break + _decimals[i] = ERC20(_underlying_coins[i]).decimals() + return _decimals + return self._get_decimals(_pool) + + +@external +@view +def get_virtual_price_from_lp_token(_token: address) -> uint256: + """ + @notice Returns the virtual price of the given Liquidity Provider token + @param _token Address of the Liquidity Provider token + @return uint256 Virtual price + """ + return CurvePool(self._get_pool_from_lp_token(_token)).get_virtual_price() + + +@external +@view +def is_meta(_pool: address) -> bool: + """ + @notice Returns whether the given pool is a meta pool + @param _pool Address of the pool + @return bool Whether the pool is a meta pool + """ + return self._is_meta(_pool) + + +@external +@view +def is_registered(_pool: address) -> bool: + """ + @notice Check if a pool belongs to the registry using get_n_coins + @param _pool The address of the pool + @return A bool corresponding to whether the pool belongs or not + """ + return self._get_n_coins(_pool) > 0 + + +@external +@view +def pool_count() -> uint256: + """ + @notice Returns the number of pools in the registry + @return uint256 Number of pools + """ + return self.base_registry.pool_count() + + +@external +@view +def pool_list(_index: uint256) -> address: + """ + @notice Returns the address of the pool at the given index + @param _index Index of the pool + @return Address of the pool + """ + return self.base_registry.pool_list(_index) diff --git a/contracts/mainnet/registry_handlers/CryptoRegistryHandler.vy b/contracts/mainnet/registry_handlers/CryptoRegistryHandler.vy index a008331..f582054 100644 --- a/contracts/mainnet/registry_handlers/CryptoRegistryHandler.vy +++ b/contracts/mainnet/registry_handlers/CryptoRegistryHandler.vy @@ -1,365 +1,365 @@ -#pragma version ^0.3.7 -""" -@title Curve Registry Handler for v2 Crypto Registry -@license MIT -""" - -# ---- interfaces --- # -interface BaseRegistry: - def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view - def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_base_pool(_pool: address) -> address: view - def get_coins(_pool: address) -> address[MAX_COINS]: view - def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): view - def get_decimals(_pool: address) -> uint256[MAX_COINS]: view - def get_fees(_pool: address) -> uint256[4]: view - def get_gauges(_pool: address) -> (address[10], int128[10]): view - def get_lp_token(_pool: address) -> address: view - def get_n_coins(_pool: address) -> uint256: view - def get_pool_from_lp_token(_lp_token: address) -> address: view - def get_pool_name(_pool: address) -> String[64]: view - def get_n_underlying_coins(_pool: address) -> uint256: view - def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_underlying_coins(_pool: address) -> address[MAX_COINS]: view - def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: view - def get_virtual_price_from_lp_token(_token: address) -> uint256: view - def is_meta(_pool: address) -> bool: view - def pool_count() -> uint256: view - def pool_list(pool_id: uint256) -> address: view - - -interface CurvePool: - def adjustment_step() -> uint256: view - def admin_fee() -> uint256: view - def allowed_extra_profit() -> uint256: view - def A() -> uint256: view - def D() -> uint256: view - def fee() -> uint256: view - def fee_gamma() -> uint256: view - def gamma() -> uint256: view - def get_virtual_price() -> uint256: view - def ma_half_time() -> uint256: view - def mid_fee() -> uint256: view - def out_fee() -> uint256: view - def virtual_price() -> uint256: view - def xcp_profit() -> uint256: view - def xcp_profit_a() -> uint256: view - - -interface ERC20: - def name() -> String[64]: view - def balanceOf(_addr: address) -> uint256: view - def totalSupply() -> uint256: view - - -interface MetaRegistry: - def registry_length() -> uint256: view - - -# ---- constants ---- # -MAX_COINS: constant(uint256) = 8 - -# ---- storage variables ---- # -base_registry: public(BaseRegistry) - - -# ---- constructor ---- # -@external -def __init__(_base_registry: address): - self.base_registry = BaseRegistry(_base_registry) - - -# ---- internal methods ---- # - - -@internal -@view -def _get_lp_token(_pool: address) -> address: - return self.base_registry.get_lp_token(_pool) - - -# ---- view methods (API) of the contract ---- # -@external -@view -def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: - """ - @notice Find the pool that has the given coins. - @param _from The address of the coin holder. - @param _to The address of the coin holder. - @param i The index of the pool in the list of pools containing the two coins. - @return The address of the pool. - """ - return self.base_registry.find_pool_for_coins(_from, _to, i) - - -@external -@view -def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the admin balances of the given pool. - @param _pool The address of the pool. - @return The admin balances of the pool. - """ - return self.base_registry.get_admin_balances(_pool) - - -@external -@view -def get_balances(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the balances of the given pool. - @param _pool The address of the pool. - @return The balances of the pool. - """ - return self.base_registry.get_balances(_pool) - - -@external -@view -def get_base_pool(_pool: address) -> address: - """ - @notice Get the base pool of the given pool. - @param _pool The address of the pool. - @return The base pool of the pool. - """ - return self.base_registry.get_base_pool(_pool) - - -@view -@external -def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): - """ - @notice Get the indices of the coins in the given pool. - @param _pool The address of the pool. - @param _from The _from coin address. - @param _to The _to coin address. - @return The indices of the coins in the pool. - """ - return self.base_registry.get_coin_indices(_pool, _from, _to) - - -@external -@view -def get_coins(_pool: address) -> address[MAX_COINS]: - """ - @notice Get the coins of the given pool. - @param _pool The address of the pool. - @return address[MAX_COINS] list of coins in the pool. - """ - return self.base_registry.get_coins(_pool) - - -@external -@view -def get_decimals(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the decimals of the given pool. - @param _pool The address of the pool. - @return uint256[MAX_COINS] list of decimals of the coins in the pool. - """ - return self.base_registry.get_decimals(_pool) - - -@external -@view -def get_fees(_pool: address) -> uint256[10]: - """ - @notice Get the fees of the given pool. - @param _pool The address of the pool. - @return Pool fee as uint256 with 1e10 precision - Admin fee as 1e10 percentage of pool fee - Mid fee - Out fee - """ - fees: uint256[10] = empty(uint256[10]) - pool_fees: uint256[4] = self.base_registry.get_fees(_pool) - for i in range(4): - fees[i] = pool_fees[i] - return fees - - -@external -@view -def get_gauges(_pool: address) -> (address[10], int128[10]): - """ - @notice Get the gauges and gauge_types for a given pool. - @param _pool The address of the pool. - @return The gauges of the pool. - """ - return self.base_registry.get_gauges(_pool) - - -@external -@view -def get_lp_token(_pool: address) -> address: - """ - @notice Get the LP token of the given pool. - @param _pool The address of the pool. - @return The LP token of the pool. - """ - return self._get_lp_token(_pool) - - -@external -@view -def get_n_coins(_pool: address) -> uint256: - """ - @notice Get the number of coins in the given pool. - @param _pool The address of the pool. - @return The number of coins in the pool. - """ - return self.base_registry.get_n_coins(_pool) - - -@external -@view -def get_n_underlying_coins(_pool: address) -> uint256: - """ - @notice Get the number of underlying coins in the given pool. - @param _pool The address of the pool. - @return The number of underlying coins in the pool. - """ - return self.base_registry.get_n_underlying_coins(_pool) - - -@external -@view -def get_pool_asset_type(_pool: address) -> uint256: - """ - @notice Get the asset type of the given pool. - @dev Returns 4: 0 = USD, 1 = ETH, 2 = BTC, 3 = Other - @param _pool The address of the pool. - @return The asset type of the pool. - """ - return 4 - - -@external -@view -def get_pool_from_lp_token(_lp_token: address) -> address: - """ - @notice Get the pool of the given LP token. - @param _lp_token The address of the LP token. - @return The address of the pool. - """ - return self.base_registry.get_pool_from_lp_token(_lp_token) - - -@external -@view -def get_pool_name(_pool: address) -> String[64]: - """ - @notice Get the name of the given pool. - @param _pool The address of the pool. - @return The name of the pool. - """ - return self.base_registry.get_pool_name(_pool) - - -@external -@view -def get_pool_params(_pool: address) -> uint256[20]: - """ - @notice returns pool params given a cryptopool address - @dev contains all settable parameter that alter the pool's performance - @dev only applicable for cryptopools - @param _pool Address of the pool for which data is being queried. - """ - - pool_params: uint256[20] = empty(uint256[20]) - pool_params[0] = CurvePool(_pool).A() - pool_params[1] = CurvePool(_pool).D() - pool_params[2] = CurvePool(_pool).gamma() - pool_params[3] = CurvePool(_pool).allowed_extra_profit() - pool_params[4] = CurvePool(_pool).fee_gamma() - pool_params[5] = CurvePool(_pool).adjustment_step() - pool_params[6] = CurvePool(_pool).ma_half_time() - return pool_params - - -@external -@view -def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the underlying balances of the given pool. - @param _pool The address of the pool. - @return The underlying balances of the pool. - """ - return self.base_registry.get_underlying_balances(_pool) - - -@external -@view -def get_underlying_coins(_pool: address) -> address[MAX_COINS]: - """ - @notice Get the underlying coins of the given pool. - @param _pool The address of the pool. - @return The underlying coins of the pool. - """ - return self.base_registry.get_underlying_coins(_pool) - - -@external -@view -def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the underlying decimals of coins in a given pool. - @param _pool The address of the pool. - @return The underlying decimals of coins in the pool. - """ - return self.base_registry.get_underlying_decimals(_pool) - - -@external -@view -def get_virtual_price_from_lp_token(_token: address) -> uint256: - """ - @notice Get the virtual price of the given LP token. - @param _token The address of the LP token. - @return uint256 The virtual price of the LP token. - """ - return self.base_registry.get_virtual_price_from_lp_token(_token) - - -@external -@view -def is_meta(_pool: address) -> bool: - """ - @notice Check if the given pool is a meta pool. - @param _pool The address of the pool. - @return True if the pool is a meta pool, false otherwise. - """ - return self.base_registry.is_meta(_pool) - - -@external -@view -def is_registered(_pool: address) -> bool: - """ - @notice Check if a pool belongs to the registry using get_n_coins - @param _pool The address of the pool - @return A bool corresponding to whether the pool belongs or not - """ - return self.base_registry.get_n_coins(_pool) > 0 - - -@external -@view -def pool_count() -> uint256: - """ - @notice Get the number of pools in the registry. - @return The number of pools in the registry. - """ - return self.base_registry.pool_count() - - -@external -@view -def pool_list(_index: uint256) -> address: - """ - @notice Get the address of the pool at the given index. - @param _index The index of the pool. - @return The address of the pool. - """ - return self.base_registry.pool_list(_index) +#pragma version ^0.3.7 +""" +@title Curve Registry Handler for v2 Crypto Registry +@license MIT +""" + +# ---- interfaces --- # +interface BaseRegistry: + def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view + def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_base_pool(_pool: address) -> address: view + def get_coins(_pool: address) -> address[MAX_COINS]: view + def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): view + def get_decimals(_pool: address) -> uint256[MAX_COINS]: view + def get_fees(_pool: address) -> uint256[4]: view + def get_gauges(_pool: address) -> (address[10], int128[10]): view + def get_lp_token(_pool: address) -> address: view + def get_n_coins(_pool: address) -> uint256: view + def get_pool_from_lp_token(_lp_token: address) -> address: view + def get_pool_name(_pool: address) -> String[64]: view + def get_n_underlying_coins(_pool: address) -> uint256: view + def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_underlying_coins(_pool: address) -> address[MAX_COINS]: view + def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: view + def get_virtual_price_from_lp_token(_token: address) -> uint256: view + def is_meta(_pool: address) -> bool: view + def pool_count() -> uint256: view + def pool_list(pool_id: uint256) -> address: view + + +interface CurvePool: + def adjustment_step() -> uint256: view + def admin_fee() -> uint256: view + def allowed_extra_profit() -> uint256: view + def A() -> uint256: view + def D() -> uint256: view + def fee() -> uint256: view + def fee_gamma() -> uint256: view + def gamma() -> uint256: view + def get_virtual_price() -> uint256: view + def ma_half_time() -> uint256: view + def mid_fee() -> uint256: view + def out_fee() -> uint256: view + def virtual_price() -> uint256: view + def xcp_profit() -> uint256: view + def xcp_profit_a() -> uint256: view + + +interface ERC20: + def name() -> String[64]: view + def balanceOf(_addr: address) -> uint256: view + def totalSupply() -> uint256: view + + +interface MetaRegistry: + def registry_length() -> uint256: view + + +# ---- constants ---- # +MAX_COINS: constant(uint256) = 8 + +# ---- storage variables ---- # +base_registry: public(BaseRegistry) + + +# ---- constructor ---- # +@external +def __init__(_base_registry: address): + self.base_registry = BaseRegistry(_base_registry) + + +# ---- internal methods ---- # + + +@internal +@view +def _get_lp_token(_pool: address) -> address: + return self.base_registry.get_lp_token(_pool) + + +# ---- view methods (API) of the contract ---- # +@external +@view +def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: + """ + @notice Find the pool that has the given coins. + @param _from The address of the coin holder. + @param _to The address of the coin holder. + @param i The index of the pool in the list of pools containing the two coins. + @return The address of the pool. + """ + return self.base_registry.find_pool_for_coins(_from, _to, i) + + +@external +@view +def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the admin balances of the given pool. + @param _pool The address of the pool. + @return The admin balances of the pool. + """ + return self.base_registry.get_admin_balances(_pool) + + +@external +@view +def get_balances(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the balances of the given pool. + @param _pool The address of the pool. + @return The balances of the pool. + """ + return self.base_registry.get_balances(_pool) + + +@external +@view +def get_base_pool(_pool: address) -> address: + """ + @notice Get the base pool of the given pool. + @param _pool The address of the pool. + @return The base pool of the pool. + """ + return self.base_registry.get_base_pool(_pool) + + +@view +@external +def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): + """ + @notice Get the indices of the coins in the given pool. + @param _pool The address of the pool. + @param _from The _from coin address. + @param _to The _to coin address. + @return The indices of the coins in the pool. + """ + return self.base_registry.get_coin_indices(_pool, _from, _to) + + +@external +@view +def get_coins(_pool: address) -> address[MAX_COINS]: + """ + @notice Get the coins of the given pool. + @param _pool The address of the pool. + @return address[MAX_COINS] list of coins in the pool. + """ + return self.base_registry.get_coins(_pool) + + +@external +@view +def get_decimals(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the decimals of the given pool. + @param _pool The address of the pool. + @return uint256[MAX_COINS] list of decimals of the coins in the pool. + """ + return self.base_registry.get_decimals(_pool) + + +@external +@view +def get_fees(_pool: address) -> uint256[10]: + """ + @notice Get the fees of the given pool. + @param _pool The address of the pool. + @return Pool fee as uint256 with 1e10 precision + Admin fee as 1e10 percentage of pool fee + Mid fee + Out fee + """ + fees: uint256[10] = empty(uint256[10]) + pool_fees: uint256[4] = self.base_registry.get_fees(_pool) + for i in range(4): + fees[i] = pool_fees[i] + return fees + + +@external +@view +def get_gauges(_pool: address) -> (address[10], int128[10]): + """ + @notice Get the gauges and gauge_types for a given pool. + @param _pool The address of the pool. + @return The gauges of the pool. + """ + return self.base_registry.get_gauges(_pool) + + +@external +@view +def get_lp_token(_pool: address) -> address: + """ + @notice Get the LP token of the given pool. + @param _pool The address of the pool. + @return The LP token of the pool. + """ + return self._get_lp_token(_pool) + + +@external +@view +def get_n_coins(_pool: address) -> uint256: + """ + @notice Get the number of coins in the given pool. + @param _pool The address of the pool. + @return The number of coins in the pool. + """ + return self.base_registry.get_n_coins(_pool) + + +@external +@view +def get_n_underlying_coins(_pool: address) -> uint256: + """ + @notice Get the number of underlying coins in the given pool. + @param _pool The address of the pool. + @return The number of underlying coins in the pool. + """ + return self.base_registry.get_n_underlying_coins(_pool) + + +@external +@view +def get_pool_asset_type(_pool: address) -> uint256: + """ + @notice Get the asset type of the given pool. + @dev Returns 4: 0 = USD, 1 = ETH, 2 = BTC, 3 = Other + @param _pool The address of the pool. + @return The asset type of the pool. + """ + return 4 + + +@external +@view +def get_pool_from_lp_token(_lp_token: address) -> address: + """ + @notice Get the pool of the given LP token. + @param _lp_token The address of the LP token. + @return The address of the pool. + """ + return self.base_registry.get_pool_from_lp_token(_lp_token) + + +@external +@view +def get_pool_name(_pool: address) -> String[64]: + """ + @notice Get the name of the given pool. + @param _pool The address of the pool. + @return The name of the pool. + """ + return self.base_registry.get_pool_name(_pool) + + +@external +@view +def get_pool_params(_pool: address) -> uint256[20]: + """ + @notice returns pool params given a cryptopool address + @dev contains all settable parameter that alter the pool's performance + @dev only applicable for cryptopools + @param _pool Address of the pool for which data is being queried. + """ + + pool_params: uint256[20] = empty(uint256[20]) + pool_params[0] = CurvePool(_pool).A() + pool_params[1] = CurvePool(_pool).D() + pool_params[2] = CurvePool(_pool).gamma() + pool_params[3] = CurvePool(_pool).allowed_extra_profit() + pool_params[4] = CurvePool(_pool).fee_gamma() + pool_params[5] = CurvePool(_pool).adjustment_step() + pool_params[6] = CurvePool(_pool).ma_half_time() + return pool_params + + +@external +@view +def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the underlying balances of the given pool. + @param _pool The address of the pool. + @return The underlying balances of the pool. + """ + return self.base_registry.get_underlying_balances(_pool) + + +@external +@view +def get_underlying_coins(_pool: address) -> address[MAX_COINS]: + """ + @notice Get the underlying coins of the given pool. + @param _pool The address of the pool. + @return The underlying coins of the pool. + """ + return self.base_registry.get_underlying_coins(_pool) + + +@external +@view +def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the underlying decimals of coins in a given pool. + @param _pool The address of the pool. + @return The underlying decimals of coins in the pool. + """ + return self.base_registry.get_underlying_decimals(_pool) + + +@external +@view +def get_virtual_price_from_lp_token(_token: address) -> uint256: + """ + @notice Get the virtual price of the given LP token. + @param _token The address of the LP token. + @return uint256 The virtual price of the LP token. + """ + return self.base_registry.get_virtual_price_from_lp_token(_token) + + +@external +@view +def is_meta(_pool: address) -> bool: + """ + @notice Check if the given pool is a meta pool. + @param _pool The address of the pool. + @return True if the pool is a meta pool, false otherwise. + """ + return self.base_registry.is_meta(_pool) + + +@external +@view +def is_registered(_pool: address) -> bool: + """ + @notice Check if a pool belongs to the registry using get_n_coins + @param _pool The address of the pool + @return A bool corresponding to whether the pool belongs or not + """ + return self.base_registry.get_n_coins(_pool) > 0 + + +@external +@view +def pool_count() -> uint256: + """ + @notice Get the number of pools in the registry. + @return The number of pools in the registry. + """ + return self.base_registry.pool_count() + + +@external +@view +def pool_list(_index: uint256) -> address: + """ + @notice Get the address of the pool at the given index. + @param _index The index of the pool. + @return The address of the pool. + """ + return self.base_registry.pool_list(_index) diff --git a/contracts/mainnet/registry_handlers/StableFactoryHandler.vy b/contracts/mainnet/registry_handlers/StableFactoryHandler.vy index 32d1fe1..1b9a91a 100644 --- a/contracts/mainnet/registry_handlers/StableFactoryHandler.vy +++ b/contracts/mainnet/registry_handlers/StableFactoryHandler.vy @@ -1,540 +1,540 @@ -#pragma version ^0.3.7 -""" -@title Curve Registry Handler for v1 Factory (latest) -@license MIT -""" - -# ---- interfaces ---- # -interface BaseRegistry: - def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view - def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_A(_pool: address) -> uint256: view - def get_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_base_pool(_pool: address) -> address: view - def get_coins(_pool: address) -> address[MAX_COINS]: view - def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128): view - def get_decimals(_pool: address) -> uint256[MAX_COINS]: view - def get_fees(_pool: address) -> uint256[2]: view - def get_gauge(_pool: address) -> address: view - def get_lp_token(_pool: address) -> address: view - def get_meta_n_coins(_pool: address) -> (uint256, uint256): view - def get_n_coins(_pool: address) -> uint256: view - def get_pool_asset_type(_pool: address) -> uint256: view - def get_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: view - def get_underlying_coins(_pool: address) -> address[MAX_COINS]: view - def get_underlying_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: view - def is_meta(_pool: address) -> bool: view - def pool_count() -> uint256: view - def pool_list(pool_id: uint256) -> address: view - - -interface BasePoolRegistry: - def get_base_pool_for_lp_token(_lp_token: address) -> address: view - def get_n_coins(_pool: address) -> uint256: view - def get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: view - def get_lp_token(_pool: address) -> address: view - def is_legacy(_pool: address) -> bool: view - def base_pool_list(i: uint256) -> address: view - - -interface CurveLegacyPool: - def balances(i: int128) -> uint256: view - - -interface CurvePool: - def admin_balances(i: uint256) -> uint256: view - def balances(i: uint256) -> uint256: view - def get_virtual_price() -> uint256: view - - -interface ERC20: - def balanceOf(_addr: address) -> uint256: view - def decimals() -> uint256: view - def name() -> String[64]: view - def totalSupply() -> uint256: view - - -interface GaugeController: - def gauge_types(gauge: address) -> int128: view - def gauges(i: uint256) -> address: view - - -interface Gauge: - def is_killed() -> bool: view - - -interface MetaRegistry: - def registry_length() -> uint256: view - - -# ---- constants ---- # -GAUGE_CONTROLLER: constant(address) = 0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB -MAX_COINS: constant(uint256) = 4 -MAX_METAREGISTRY_COINS: constant(uint256) = 8 - - -# ---- storage variables ---- # -base_registry: public(BaseRegistry) -base_pool_registry: public(BasePoolRegistry) - - -# ---- constructor ---- # -@external -def __init__(_registry_address: address, _base_pool_registry: address): - self.base_registry = BaseRegistry(_registry_address) - self.base_pool_registry = BasePoolRegistry(_base_pool_registry) - - -# ---- internal methods ---- # -@internal -@view -def _is_meta(_pool: address) -> bool: - return self.base_registry.is_meta(_pool) - - -@internal -@view -def _get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: - _coins: address[MAX_COINS] = self.base_registry.get_coins(_pool) - _padded_coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) - for i in range(MAX_COINS): - _padded_coins[i] = _coins[i] - return _padded_coins - - -@internal -@view -def _get_underlying_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: - _coins: address[MAX_COINS] = self.base_registry.get_underlying_coins(_pool) - _padded_coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) - for i in range(MAX_COINS): - _padded_coins[i] = _coins[i] - return _padded_coins - - -@internal -@view -def _get_n_coins(_pool: address) -> uint256: - if self._is_meta(_pool): - return 2 - return self.base_registry.get_n_coins(_pool) - - -@internal -@view -def _get_base_pool(_pool: address) -> address: - _coins: address[MAX_METAREGISTRY_COINS] = self._get_coins(_pool) - _base_pool: address = empty(address) - for coin in _coins: - _base_pool = self.base_pool_registry.get_base_pool_for_lp_token(coin) - if _base_pool != empty(address): - return _base_pool - return empty(address) - - -@view -@internal -def _get_meta_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - base_coin_idx: uint256 = self._get_n_coins(_pool) - 1 - base_pool: address = self._get_base_pool(_pool) - base_total_supply: uint256 = ERC20(self.base_pool_registry.get_lp_token(base_pool)).totalSupply() - - ul_balance: uint256 = 0 - underlying_pct: uint256 = 0 - if base_total_supply > 0: - underlying_pct = CurvePool(_pool).balances(base_coin_idx) * 10**36 / base_total_supply - - underlying_balances: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) - ul_coins: address[MAX_METAREGISTRY_COINS] = self._get_underlying_coins(_pool) - for i in range(MAX_METAREGISTRY_COINS): - - if ul_coins[i] == empty(address): - break - - if i < base_coin_idx: - ul_balance = CurvePool(_pool).balances(i) - - else: - - if self.base_pool_registry.is_legacy(base_pool): - ul_balance = CurveLegacyPool(base_pool).balances(convert(i - base_coin_idx, int128)) - else: - ul_balance = CurvePool(base_pool).balances(i - base_coin_idx) - ul_balance = ul_balance * underlying_pct / 10**36 - underlying_balances[i] = ul_balance - - return underlying_balances - - -@internal -@view -def _pad_uint_array(_array: uint256[MAX_COINS]) -> uint256[MAX_METAREGISTRY_COINS]: - _padded_array: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) - for i in range(MAX_COINS): - _padded_array[i] = _array[i] - return _padded_array - - -@internal -@view -def _get_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - return self._pad_uint_array(self.base_registry.get_balances(_pool)) - - -@internal -@view -def _get_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - return self._pad_uint_array(self.base_registry.get_decimals(_pool)) - - -@internal -@view -def _get_gauge_type(_gauge: address) -> int128: - - success: bool = False - response: Bytes[32] = b"" - success, response = raw_call( - GAUGE_CONTROLLER, - concat( - method_id("gauge_type(address)"), - convert(_gauge, bytes32), - ), - max_outsize=32, - revert_on_failure=False, - is_static_call=True - ) - - if success and not Gauge(_gauge).is_killed(): - return convert(response, int128) - - return 0 - - -# ---- view methods (API) of the contract ---- # -@external -@view -def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: - return self.base_registry.find_pool_for_coins(_from, _to, i) - - -@external -@view -def get_admin_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Get the balances of the admin of the pool - @dev does not use base registry admin_balances because that has errors - in the getter for n_coins (some pools show zero, so admin balances is zero) - @param _pool address of the pool - @return balances of the admin of the pool - """ - n_coins: uint256 = self._get_n_coins(_pool) - admin_balances: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) - for i in range(MAX_METAREGISTRY_COINS): - if i == n_coins: - break - admin_balances[i] = CurvePool(_pool).admin_balances(i) - return admin_balances - - -@external -@view -def get_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Get the balances of the pool - @param _pool address of the pool - @return balances of the pool - """ - return self._get_balances(_pool) - - -@external -@view -def get_base_pool(_pool: address) -> address: - """ - @notice Get the base pool of the pool - @param _pool address of the pool - @return base pool of the pool - """ - return self._get_base_pool(_pool) - - -@view -@external -def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): - """ - @notice Get the indices of the coins in the pool - @param _pool address of the pool - @param _from address of the coin - @param _to address of the coin - @return coin indices and whether the coin swap involves an underlying market or not - """ - coin1: int128 = 0 - coin2: int128 = 0 - is_underlying: bool = False - - (coin1, coin2) = self.base_registry.get_coin_indices(_pool, _from, _to) - - # due to a bug in original factory contract, `is_underlying`` is always True - # to fix this, we first check if it is a metapool, and if not then we return - # False. If so, then we check if basepool lp token is one of the two coins, - # in which case `is_underlying` would be False - if self._is_meta(_pool): - base_pool_lp_token: address = self.base_registry.get_coins(_pool)[1] - if base_pool_lp_token not in [_from, _to]: - is_underlying = True - - return (coin1, coin2, is_underlying) - - -@external -@view -def get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: - """ - @notice Get the coins of the pool - @param _pool address of the pool - @return coins of the pool - """ - return self._get_coins(_pool) - - -@external -@view -def get_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Get the decimals of coins in the pool - @param _pool address of the pool - @return decimals of coins in the pool - """ - return self._get_decimals(_pool) - - -@external -@view -def get_fees(_pool: address) -> uint256[10]: - """ - @notice Get the fees of the pool - @param _pool address of the pool - @return fees of the pool - """ - fees: uint256[10] = empty(uint256[10]) - pool_fees: uint256[2] = self.base_registry.get_fees(_pool) - for i in range(2): - fees[i] = pool_fees[i] - return fees - - -@external -@view -def get_virtual_price_from_lp_token(_pool: address) -> uint256: - """ - @notice Get the virtual price of the pool - @param _pool address of the pool - @return virtual price of the pool - """ - return CurvePool(_pool).get_virtual_price() - - -@external -@view -def get_gauges(_pool: address) -> (address[10], int128[10]): - """ - @notice Get the gauges and gauge types of the pool - @param _pool address of the pool - @return gauges of the pool - """ - gauges: address[10] = empty(address[10]) - types: int128[10] = empty(int128[10]) - gauges[0] = self.base_registry.get_gauge(_pool) - types[0] = self._get_gauge_type(gauges[0]) - return (gauges, types) - - -@external -@view -def get_lp_token(_pool: address) -> address: - """ - @notice Get the lp token of the pool - @dev for stableswap factory pools, the pool is the lp token itself - @param _pool address of the pool - @return lp token of the pool - """ - return _pool - - -@external -@view -def get_n_coins(_pool: address) -> uint256: - """ - @notice Get the number of coins in the pool - @param _pool address of the pool - @return number of coins in the pool - """ - return self._get_n_coins(_pool) - - -@external -@view -def get_n_underlying_coins(_pool: address) -> uint256: - """ - @notice Get the number of underlying coins in the pool - @param _pool address of the pool - @return number of underlying coins in the pool - """ - # need to check if any of the token is a base pool LP token - # since a metapool can be lptoken:lptoken, and it would count - # underlying coins as 1 + base_pool_n_coins instead of 2 x base_pool_n_coins - coins: address[MAX_METAREGISTRY_COINS] = self._get_coins(_pool) - base_pool: address = empty(address) - num_coins: uint256 = 0 - for i in range(MAX_METAREGISTRY_COINS): - - if coins[i] == empty(address): - break - - base_pool = self.base_pool_registry.get_base_pool_for_lp_token(coins[i]) - if base_pool == empty(address) and coins[i] != empty(address): - num_coins += 1 - else: - num_coins += self.base_pool_registry.get_n_coins(base_pool) - - return num_coins - - -@external -@view -def get_pool_asset_type(_pool: address) -> uint256: - """ - @notice Get the asset type of the coins in the pool - @dev 0 = USD, 1 = ETH, 2 = BTC, 3 = Other - @param _pool address of the pool - @return pool asset type of the pool - """ - return self.base_registry.get_pool_asset_type(_pool) - - -@external -@view -def get_pool_from_lp_token(_lp_token: address) -> address: - """ - @notice Get the pool of the lp token - @dev This is more or less like a pass through method. Can be ignored but - We leave it in for consistency across registry handlers. - @param _lp_token address of the lp token (which is also the pool) - @return pool of the lp token - """ - if self._get_n_coins(_lp_token) > 0: - return _lp_token - return empty(address) - - -@external -@view -def get_pool_name(_pool: address) -> String[64]: - """ - @notice Get the name of the pool - @dev stable factory pools are ERC20 tokenized - @return name of the pool - """ - if self._get_n_coins(_pool) == 0: - # _pool is not in base registry, so we ignore: - return "" - return ERC20(_pool).name() - - -@external -@view -def get_pool_params(_pool: address) -> uint256[20]: - """ - @notice Get the parameters of the pool - @param _pool address of the pool - @return parameters of the pool - """ - stableswap_pool_params: uint256[20] = empty(uint256[20]) - stableswap_pool_params[0] = self.base_registry.get_A(_pool) - return stableswap_pool_params - - -@external -@view -def get_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Get the underlying balances of the pool - @param _pool address of the pool - @return underlying balances of the pool - """ - if not self._is_meta(_pool): - return self._get_balances(_pool) - return self._get_meta_underlying_balances(_pool) - - -@external -@view -def get_underlying_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: - """ - @notice Get the underlying coins of the pool - @param _pool address of the pool - @return underlying coins of the pool - """ - if not self._is_meta(_pool): - return self._get_coins(_pool) - return self._get_underlying_coins(_pool) - - -@external -@view -def get_underlying_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: - """ - @notice Get the underlying decimals of the pool - @dev If it is a metapool, method uses the base registry. Else it uses a - custom getter. This is because the base registry cannot unpack decimals - (stored as a bitmap) if there is no metapool. So it returns the decimals of - only the first coin. - @param _pool Address of the pool - @return underlying decimals of the pool - """ - if not self._is_meta(_pool): - return self._get_decimals(_pool) - return self.base_registry.get_underlying_decimals(_pool) - - -@external -@view -def is_meta(_pool: address) -> bool: - """ - @notice Check if the pool is a metapool - @param _pool address of the pool - @return True if the pool is a metapool - """ - return self._is_meta(_pool) - - -@external -@view -def is_registered(_pool: address) -> bool: - """ - @notice Check if a pool belongs to the registry using get_n_coins - @param _pool The address of the pool - @return A bool corresponding to whether the pool belongs or not - """ - return self._get_n_coins(_pool) > 0 - - -@external -@view -def pool_count() -> uint256: - """ - @notice Get the number of pools in the registry - @return number of pools in the registry - """ - return self.base_registry.pool_count() - - -@external -@view -def pool_list(_index: uint256) -> address: - """ - @notice Get the address of the pool at the given index - @param _index The index of the pool - @return The address of the pool - """ - return self.base_registry.pool_list(_index) +#pragma version ^0.3.7 +""" +@title Curve Registry Handler for v1 Factory (latest) +@license MIT +""" + +# ---- interfaces ---- # +interface BaseRegistry: + def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view + def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_A(_pool: address) -> uint256: view + def get_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_base_pool(_pool: address) -> address: view + def get_coins(_pool: address) -> address[MAX_COINS]: view + def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128): view + def get_decimals(_pool: address) -> uint256[MAX_COINS]: view + def get_fees(_pool: address) -> uint256[2]: view + def get_gauge(_pool: address) -> address: view + def get_lp_token(_pool: address) -> address: view + def get_meta_n_coins(_pool: address) -> (uint256, uint256): view + def get_n_coins(_pool: address) -> uint256: view + def get_pool_asset_type(_pool: address) -> uint256: view + def get_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: view + def get_underlying_coins(_pool: address) -> address[MAX_COINS]: view + def get_underlying_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: view + def is_meta(_pool: address) -> bool: view + def pool_count() -> uint256: view + def pool_list(pool_id: uint256) -> address: view + + +interface BasePoolRegistry: + def get_base_pool_for_lp_token(_lp_token: address) -> address: view + def get_n_coins(_pool: address) -> uint256: view + def get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: view + def get_lp_token(_pool: address) -> address: view + def is_legacy(_pool: address) -> bool: view + def base_pool_list(i: uint256) -> address: view + + +interface CurveLegacyPool: + def balances(i: int128) -> uint256: view + + +interface CurvePool: + def admin_balances(i: uint256) -> uint256: view + def balances(i: uint256) -> uint256: view + def get_virtual_price() -> uint256: view + + +interface ERC20: + def balanceOf(_addr: address) -> uint256: view + def decimals() -> uint256: view + def name() -> String[64]: view + def totalSupply() -> uint256: view + + +interface GaugeController: + def gauge_types(gauge: address) -> int128: view + def gauges(i: uint256) -> address: view + + +interface Gauge: + def is_killed() -> bool: view + + +interface MetaRegistry: + def registry_length() -> uint256: view + + +# ---- constants ---- # +GAUGE_CONTROLLER: constant(address) = 0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB +MAX_COINS: constant(uint256) = 4 +MAX_METAREGISTRY_COINS: constant(uint256) = 8 + + +# ---- storage variables ---- # +base_registry: public(BaseRegistry) +base_pool_registry: public(BasePoolRegistry) + + +# ---- constructor ---- # +@external +def __init__(_registry_address: address, _base_pool_registry: address): + self.base_registry = BaseRegistry(_registry_address) + self.base_pool_registry = BasePoolRegistry(_base_pool_registry) + + +# ---- internal methods ---- # +@internal +@view +def _is_meta(_pool: address) -> bool: + return self.base_registry.is_meta(_pool) + + +@internal +@view +def _get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: + _coins: address[MAX_COINS] = self.base_registry.get_coins(_pool) + _padded_coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) + for i in range(MAX_COINS): + _padded_coins[i] = _coins[i] + return _padded_coins + + +@internal +@view +def _get_underlying_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: + _coins: address[MAX_COINS] = self.base_registry.get_underlying_coins(_pool) + _padded_coins: address[MAX_METAREGISTRY_COINS] = empty(address[MAX_METAREGISTRY_COINS]) + for i in range(MAX_COINS): + _padded_coins[i] = _coins[i] + return _padded_coins + + +@internal +@view +def _get_n_coins(_pool: address) -> uint256: + if self._is_meta(_pool): + return 2 + return self.base_registry.get_n_coins(_pool) + + +@internal +@view +def _get_base_pool(_pool: address) -> address: + _coins: address[MAX_METAREGISTRY_COINS] = self._get_coins(_pool) + _base_pool: address = empty(address) + for coin in _coins: + _base_pool = self.base_pool_registry.get_base_pool_for_lp_token(coin) + if _base_pool != empty(address): + return _base_pool + return empty(address) + + +@view +@internal +def _get_meta_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + base_coin_idx: uint256 = self._get_n_coins(_pool) - 1 + base_pool: address = self._get_base_pool(_pool) + base_total_supply: uint256 = ERC20(self.base_pool_registry.get_lp_token(base_pool)).totalSupply() + + ul_balance: uint256 = 0 + underlying_pct: uint256 = 0 + if base_total_supply > 0: + underlying_pct = CurvePool(_pool).balances(base_coin_idx) * 10**36 / base_total_supply + + underlying_balances: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) + ul_coins: address[MAX_METAREGISTRY_COINS] = self._get_underlying_coins(_pool) + for i in range(MAX_METAREGISTRY_COINS): + + if ul_coins[i] == empty(address): + break + + if i < base_coin_idx: + ul_balance = CurvePool(_pool).balances(i) + + else: + + if self.base_pool_registry.is_legacy(base_pool): + ul_balance = CurveLegacyPool(base_pool).balances(convert(i - base_coin_idx, int128)) + else: + ul_balance = CurvePool(base_pool).balances(i - base_coin_idx) + ul_balance = ul_balance * underlying_pct / 10**36 + underlying_balances[i] = ul_balance + + return underlying_balances + + +@internal +@view +def _pad_uint_array(_array: uint256[MAX_COINS]) -> uint256[MAX_METAREGISTRY_COINS]: + _padded_array: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) + for i in range(MAX_COINS): + _padded_array[i] = _array[i] + return _padded_array + + +@internal +@view +def _get_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + return self._pad_uint_array(self.base_registry.get_balances(_pool)) + + +@internal +@view +def _get_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + return self._pad_uint_array(self.base_registry.get_decimals(_pool)) + + +@internal +@view +def _get_gauge_type(_gauge: address) -> int128: + + success: bool = False + response: Bytes[32] = b"" + success, response = raw_call( + GAUGE_CONTROLLER, + concat( + method_id("gauge_type(address)"), + convert(_gauge, bytes32), + ), + max_outsize=32, + revert_on_failure=False, + is_static_call=True + ) + + if success and not Gauge(_gauge).is_killed(): + return convert(response, int128) + + return 0 + + +# ---- view methods (API) of the contract ---- # +@external +@view +def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: + return self.base_registry.find_pool_for_coins(_from, _to, i) + + +@external +@view +def get_admin_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Get the balances of the admin of the pool + @dev does not use base registry admin_balances because that has errors + in the getter for n_coins (some pools show zero, so admin balances is zero) + @param _pool address of the pool + @return balances of the admin of the pool + """ + n_coins: uint256 = self._get_n_coins(_pool) + admin_balances: uint256[MAX_METAREGISTRY_COINS] = empty(uint256[MAX_METAREGISTRY_COINS]) + for i in range(MAX_METAREGISTRY_COINS): + if i == n_coins: + break + admin_balances[i] = CurvePool(_pool).admin_balances(i) + return admin_balances + + +@external +@view +def get_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Get the balances of the pool + @param _pool address of the pool + @return balances of the pool + """ + return self._get_balances(_pool) + + +@external +@view +def get_base_pool(_pool: address) -> address: + """ + @notice Get the base pool of the pool + @param _pool address of the pool + @return base pool of the pool + """ + return self._get_base_pool(_pool) + + +@view +@external +def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): + """ + @notice Get the indices of the coins in the pool + @param _pool address of the pool + @param _from address of the coin + @param _to address of the coin + @return coin indices and whether the coin swap involves an underlying market or not + """ + coin1: int128 = 0 + coin2: int128 = 0 + is_underlying: bool = False + + (coin1, coin2) = self.base_registry.get_coin_indices(_pool, _from, _to) + + # due to a bug in original factory contract, `is_underlying`` is always True + # to fix this, we first check if it is a metapool, and if not then we return + # False. If so, then we check if basepool lp token is one of the two coins, + # in which case `is_underlying` would be False + if self._is_meta(_pool): + base_pool_lp_token: address = self.base_registry.get_coins(_pool)[1] + if base_pool_lp_token not in [_from, _to]: + is_underlying = True + + return (coin1, coin2, is_underlying) + + +@external +@view +def get_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: + """ + @notice Get the coins of the pool + @param _pool address of the pool + @return coins of the pool + """ + return self._get_coins(_pool) + + +@external +@view +def get_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Get the decimals of coins in the pool + @param _pool address of the pool + @return decimals of coins in the pool + """ + return self._get_decimals(_pool) + + +@external +@view +def get_fees(_pool: address) -> uint256[10]: + """ + @notice Get the fees of the pool + @param _pool address of the pool + @return fees of the pool + """ + fees: uint256[10] = empty(uint256[10]) + pool_fees: uint256[2] = self.base_registry.get_fees(_pool) + for i in range(2): + fees[i] = pool_fees[i] + return fees + + +@external +@view +def get_virtual_price_from_lp_token(_pool: address) -> uint256: + """ + @notice Get the virtual price of the pool + @param _pool address of the pool + @return virtual price of the pool + """ + return CurvePool(_pool).get_virtual_price() + + +@external +@view +def get_gauges(_pool: address) -> (address[10], int128[10]): + """ + @notice Get the gauges and gauge types of the pool + @param _pool address of the pool + @return gauges of the pool + """ + gauges: address[10] = empty(address[10]) + types: int128[10] = empty(int128[10]) + gauges[0] = self.base_registry.get_gauge(_pool) + types[0] = self._get_gauge_type(gauges[0]) + return (gauges, types) + + +@external +@view +def get_lp_token(_pool: address) -> address: + """ + @notice Get the lp token of the pool + @dev for stableswap factory pools, the pool is the lp token itself + @param _pool address of the pool + @return lp token of the pool + """ + return _pool + + +@external +@view +def get_n_coins(_pool: address) -> uint256: + """ + @notice Get the number of coins in the pool + @param _pool address of the pool + @return number of coins in the pool + """ + return self._get_n_coins(_pool) + + +@external +@view +def get_n_underlying_coins(_pool: address) -> uint256: + """ + @notice Get the number of underlying coins in the pool + @param _pool address of the pool + @return number of underlying coins in the pool + """ + # need to check if any of the token is a base pool LP token + # since a metapool can be lptoken:lptoken, and it would count + # underlying coins as 1 + base_pool_n_coins instead of 2 x base_pool_n_coins + coins: address[MAX_METAREGISTRY_COINS] = self._get_coins(_pool) + base_pool: address = empty(address) + num_coins: uint256 = 0 + for i in range(MAX_METAREGISTRY_COINS): + + if coins[i] == empty(address): + break + + base_pool = self.base_pool_registry.get_base_pool_for_lp_token(coins[i]) + if base_pool == empty(address) and coins[i] != empty(address): + num_coins += 1 + else: + num_coins += self.base_pool_registry.get_n_coins(base_pool) + + return num_coins + + +@external +@view +def get_pool_asset_type(_pool: address) -> uint256: + """ + @notice Get the asset type of the coins in the pool + @dev 0 = USD, 1 = ETH, 2 = BTC, 3 = Other + @param _pool address of the pool + @return pool asset type of the pool + """ + return self.base_registry.get_pool_asset_type(_pool) + + +@external +@view +def get_pool_from_lp_token(_lp_token: address) -> address: + """ + @notice Get the pool of the lp token + @dev This is more or less like a pass through method. Can be ignored but + We leave it in for consistency across registry handlers. + @param _lp_token address of the lp token (which is also the pool) + @return pool of the lp token + """ + if self._get_n_coins(_lp_token) > 0: + return _lp_token + return empty(address) + + +@external +@view +def get_pool_name(_pool: address) -> String[64]: + """ + @notice Get the name of the pool + @dev stable factory pools are ERC20 tokenized + @return name of the pool + """ + if self._get_n_coins(_pool) == 0: + # _pool is not in base registry, so we ignore: + return "" + return ERC20(_pool).name() + + +@external +@view +def get_pool_params(_pool: address) -> uint256[20]: + """ + @notice Get the parameters of the pool + @param _pool address of the pool + @return parameters of the pool + """ + stableswap_pool_params: uint256[20] = empty(uint256[20]) + stableswap_pool_params[0] = self.base_registry.get_A(_pool) + return stableswap_pool_params + + +@external +@view +def get_underlying_balances(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Get the underlying balances of the pool + @param _pool address of the pool + @return underlying balances of the pool + """ + if not self._is_meta(_pool): + return self._get_balances(_pool) + return self._get_meta_underlying_balances(_pool) + + +@external +@view +def get_underlying_coins(_pool: address) -> address[MAX_METAREGISTRY_COINS]: + """ + @notice Get the underlying coins of the pool + @param _pool address of the pool + @return underlying coins of the pool + """ + if not self._is_meta(_pool): + return self._get_coins(_pool) + return self._get_underlying_coins(_pool) + + +@external +@view +def get_underlying_decimals(_pool: address) -> uint256[MAX_METAREGISTRY_COINS]: + """ + @notice Get the underlying decimals of the pool + @dev If it is a metapool, method uses the base registry. Else it uses a + custom getter. This is because the base registry cannot unpack decimals + (stored as a bitmap) if there is no metapool. So it returns the decimals of + only the first coin. + @param _pool Address of the pool + @return underlying decimals of the pool + """ + if not self._is_meta(_pool): + return self._get_decimals(_pool) + return self.base_registry.get_underlying_decimals(_pool) + + +@external +@view +def is_meta(_pool: address) -> bool: + """ + @notice Check if the pool is a metapool + @param _pool address of the pool + @return True if the pool is a metapool + """ + return self._is_meta(_pool) + + +@external +@view +def is_registered(_pool: address) -> bool: + """ + @notice Check if a pool belongs to the registry using get_n_coins + @param _pool The address of the pool + @return A bool corresponding to whether the pool belongs or not + """ + return self._get_n_coins(_pool) > 0 + + +@external +@view +def pool_count() -> uint256: + """ + @notice Get the number of pools in the registry + @return number of pools in the registry + """ + return self.base_registry.pool_count() + + +@external +@view +def pool_list(_index: uint256) -> address: + """ + @notice Get the address of the pool at the given index + @param _index The index of the pool + @return The address of the pool + """ + return self.base_registry.pool_list(_index) diff --git a/contracts/mainnet/registry_handlers/StableRegistryHandler.vy b/contracts/mainnet/registry_handlers/StableRegistryHandler.vy index 80c0ad8..edb5434 100644 --- a/contracts/mainnet/registry_handlers/StableRegistryHandler.vy +++ b/contracts/mainnet/registry_handlers/StableRegistryHandler.vy @@ -1,358 +1,358 @@ -#pragma version ^0.3.7 -""" -@title Curve Registry Handler for v1 Registry -@license MIT -""" -# ---- interface ---- # -interface BaseRegistry: - def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view - def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_A(_pool: address) -> uint256: view - def get_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_coins(_pool: address) -> address[MAX_COINS]: view - def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): view - def get_decimals(_pool: address) -> uint256[MAX_COINS]: view - def get_fees(_pool: address) -> uint256[2]: view - def get_gauges(_pool: address) -> (address[10], int128[10]): view - def get_lp_token(_pool: address) -> address: view - def get_n_coins(_pool: address) -> uint256[2]: view - def get_pool_asset_type(_pool: address) -> uint256: view - def get_pool_from_lp_token(_lp_token: address) -> address: view - def get_pool_name(_pool: address) -> String[64]: view - def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: view - def get_underlying_coins(_pool: address) -> address[MAX_COINS]: view - def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: view - def get_virtual_price_from_lp_token(_token: address) -> uint256: view - def is_meta(_pool: address) -> bool: view - def pool_count() -> uint256: view - def pool_list(pool_id: uint256) -> address: view - - -interface CurvePool: - def base_pool() -> address: view - -interface ERC20: - def decimals() -> uint256: view - - -interface MetaRegistry: - def registry_length() -> uint256: view - - -# ---- constants ---- # -MAX_COINS: constant(uint256) = 8 - - -# ---- storage variables ---- # -base_registry: public(BaseRegistry) - - -# ---- constructor ---- # -@external -def __init__(_base_registry: address): - self.base_registry = BaseRegistry(_base_registry) - - -# ---- internal methods ---- # -@internal -@view -def _get_n_coins(_pool: address) -> uint256: - return self.base_registry.get_n_coins(_pool)[0] - - -@internal -@view -def _is_meta(_pool: address) -> bool: - return self.base_registry.is_meta(_pool) - - -# ---- view methods (API) of the contract ---- # -@external -@view -def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: - """ - @notice Find the pool that has the given coins. - @param _from address of coin. - @param _to address of coin. - @param i index of list of found pools to return - @return address of pool at index `i` of pools that hold the two coins - """ - return self.base_registry.find_pool_for_coins(_from, _to, i) - - -@external -@view -def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the admin balances of the given pool. - @param _pool address of pool. - @return admin balances of the pool. - """ - return self.base_registry.get_admin_balances(_pool) - - -@external -@view -def get_balances(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the balances of the given pool. - @param _pool address of pool. - @return balances of the pool. - """ - return self.base_registry.get_balances(_pool) - - -@external -@view -def get_base_pool(_pool: address) -> address: - """ - @notice Get the base pool of the given pool. - @param _pool address of pool. - @return base pool of the pool. - """ - if not(self._is_meta(_pool)): - return empty(address) - return self.base_registry.get_pool_from_lp_token(self.base_registry.get_coins(_pool)[1]) - - -@view -@external -def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): - """ - @notice Get the indices of the given coins in the given pool. - @param _pool address of pool. - @param _from address of coin. - @param _to address of coin. - @return index of _from, index of _to, bool indicating whether the - coins are in an underlying market - """ - return self.base_registry.get_coin_indices(_pool, _from, _to) - - -@external -@view -def get_coins(_pool: address) -> address[MAX_COINS]: - """ - @notice Get the coins of the given pool. - @param _pool address of pool. - @return coins of the pool. - """ - return self.base_registry.get_coins(_pool) - - -@external -@view -def get_decimals(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the decimals of the coins in given pool. - @param _pool address of pool. - @return decimals of the coins in the pool. - """ - return self.base_registry.get_decimals(_pool) - - -@external -@view -def get_fees(_pool: address) -> uint256[10]: - """ - @notice Get the fees of the given pool. - @param _pool address of pool. - @return fees of the pool. - """ - fees: uint256[10] = empty(uint256[10]) - pool_fees: uint256[2] = self.base_registry.get_fees(_pool) - for i in range(2): - fees[i] = pool_fees[i] - return fees - - -@external -@view -def get_gauges(_pool: address) -> (address[10], int128[10]): - """ - @notice Get the gauges and gauge types of the given pool. - @param _pool address of pool. - @return gauges of the pool. - """ - return self.base_registry.get_gauges(_pool) - - -@external -@view -def get_lp_token(_pool: address) -> address: - """ - @notice Get the LP token of the given pool. - @param _pool address of pool. - @return LP token of the pool. - """ - return self.base_registry.get_lp_token(_pool) - - -@external -@view -def get_n_coins(_pool: address) -> uint256: - """ - @notice Get the number of coins in the given pool. - @param _pool address of pool. - @return number of coins in the pool. - """ - return self._get_n_coins(_pool) - - -@external -@view -def get_n_underlying_coins(_pool: address) -> uint256: - """ - @notice Get the number of underlying coins in the given pool. - @param _pool address of pool. - @return number of underlying coins in the pool. - """ - return self.base_registry.get_n_coins(_pool)[1] - - -@external -@view -def get_pool_asset_type(_pool: address) -> uint256: - """ - @notice Get the asset type of coins in a given pool. - @dev 0 = USD, 1 = ETH, 2 = BTC, 3 = Other - @param _pool address of pool. - @return asset type of the pool. - """ - return self.base_registry.get_pool_asset_type(_pool) - - -@external -@view -def get_pool_from_lp_token(_lp_token: address) -> address: - """ - @notice Get the pool of the given LP token. - @param _lp_token address of LP token. - @return pool of the LP token. - """ - return self.base_registry.get_pool_from_lp_token(_lp_token) - - -@external -@view -def get_pool_name(_pool: address) -> String[64]: - """ - @notice Get the name of the given pool. - @param _pool address of pool. - @return name of the pool. - """ - return self.base_registry.get_pool_name(_pool) - - -@external -@view -def get_pool_params(_pool: address) -> uint256[20]: - """ - @notice Get the parameters of the given pool. - @param _pool address of pool. - @return parameters of the pool. - """ - stableswap_pool_params: uint256[20] = empty(uint256[20]) - stableswap_pool_params[0] = self.base_registry.get_A(_pool) - return stableswap_pool_params - - -@external -@view -def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the underlying balances of the given pool. - @dev returns coin balances if pool is not a metapool - @param _pool address of pool. - @return underlying balances of the pool. - """ - if not self._is_meta(_pool): - return self.base_registry.get_balances(_pool) - return self.base_registry.get_underlying_balances(_pool) - - -@external -@view -def get_underlying_coins(_pool: address) -> address[MAX_COINS]: - """ - @notice Get the underlying coins of the given pool. - @dev For pools that do not lend, the base registry returns the - same value as `get_coins` - @param _pool address of pool. - @return underlying coins of the pool. - """ - return self.base_registry.get_underlying_coins(_pool) - - -@external -@view -def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: - """ - @notice Get the underlying decimals of coins in the given pool. - @param _pool address of pool. - @return underlying decimals of the coins in the pool. - """ - coin_decimals: uint256[MAX_COINS] = self.base_registry.get_decimals(_pool) - underlying_coin_decimals: uint256[MAX_COINS] = self.base_registry.get_underlying_decimals(_pool) - - # this is a check for cases where base_registry.get_underlying_decimals - # returns wrong values but base_registry.get_decimals is the right one: - for i in range(MAX_COINS): - if underlying_coin_decimals[i] == 0: - underlying_coin_decimals[i] = coin_decimals[i] - - return underlying_coin_decimals - - -@external -@view -def get_virtual_price_from_lp_token(_token: address) -> uint256: - """ - @notice Get the virtual price of the given LP token. - @param _token address of LP token. - @return virtual price of the LP token. - """ - return self.base_registry.get_virtual_price_from_lp_token(_token) - - -@external -@view -def is_meta(_pool: address) -> bool: - """ - @notice Check if the given pool is a metapool. - @param _pool address of pool. - @return true if the pool is a metapool. - """ - return self._is_meta(_pool) - - -@external -@view -def is_registered(_pool: address) -> bool: - """ - @notice Check if a pool belongs to the registry using get_n_coins - @param _pool The address of the pool - @return A bool corresponding to whether the pool belongs or not - """ - return self._get_n_coins(_pool) > 0 - - -@external -@view -def pool_count() -> uint256: - """ - @notice Get the number of pools in the registry. - @return number of pools in the registry. - """ - return self.base_registry.pool_count() - - -@external -@view -def pool_list(_index: uint256) -> address: - """ - @notice Get the address of the pool at the given index. - @param _index index of the pool. - @return address of the pool. - """ - return self.base_registry.pool_list(_index) +#pragma version ^0.3.7 +""" +@title Curve Registry Handler for v1 Registry +@license MIT +""" +# ---- interface ---- # +interface BaseRegistry: + def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: view + def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_A(_pool: address) -> uint256: view + def get_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_coins(_pool: address) -> address[MAX_COINS]: view + def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): view + def get_decimals(_pool: address) -> uint256[MAX_COINS]: view + def get_fees(_pool: address) -> uint256[2]: view + def get_gauges(_pool: address) -> (address[10], int128[10]): view + def get_lp_token(_pool: address) -> address: view + def get_n_coins(_pool: address) -> uint256[2]: view + def get_pool_asset_type(_pool: address) -> uint256: view + def get_pool_from_lp_token(_lp_token: address) -> address: view + def get_pool_name(_pool: address) -> String[64]: view + def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: view + def get_underlying_coins(_pool: address) -> address[MAX_COINS]: view + def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: view + def get_virtual_price_from_lp_token(_token: address) -> uint256: view + def is_meta(_pool: address) -> bool: view + def pool_count() -> uint256: view + def pool_list(pool_id: uint256) -> address: view + + +interface CurvePool: + def base_pool() -> address: view + +interface ERC20: + def decimals() -> uint256: view + + +interface MetaRegistry: + def registry_length() -> uint256: view + + +# ---- constants ---- # +MAX_COINS: constant(uint256) = 8 + + +# ---- storage variables ---- # +base_registry: public(BaseRegistry) + + +# ---- constructor ---- # +@external +def __init__(_base_registry: address): + self.base_registry = BaseRegistry(_base_registry) + + +# ---- internal methods ---- # +@internal +@view +def _get_n_coins(_pool: address) -> uint256: + return self.base_registry.get_n_coins(_pool)[0] + + +@internal +@view +def _is_meta(_pool: address) -> bool: + return self.base_registry.is_meta(_pool) + + +# ---- view methods (API) of the contract ---- # +@external +@view +def find_pool_for_coins(_from: address, _to: address, i: uint256 = 0) -> address: + """ + @notice Find the pool that has the given coins. + @param _from address of coin. + @param _to address of coin. + @param i index of list of found pools to return + @return address of pool at index `i` of pools that hold the two coins + """ + return self.base_registry.find_pool_for_coins(_from, _to, i) + + +@external +@view +def get_admin_balances(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the admin balances of the given pool. + @param _pool address of pool. + @return admin balances of the pool. + """ + return self.base_registry.get_admin_balances(_pool) + + +@external +@view +def get_balances(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the balances of the given pool. + @param _pool address of pool. + @return balances of the pool. + """ + return self.base_registry.get_balances(_pool) + + +@external +@view +def get_base_pool(_pool: address) -> address: + """ + @notice Get the base pool of the given pool. + @param _pool address of pool. + @return base pool of the pool. + """ + if not(self._is_meta(_pool)): + return empty(address) + return self.base_registry.get_pool_from_lp_token(self.base_registry.get_coins(_pool)[1]) + + +@view +@external +def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): + """ + @notice Get the indices of the given coins in the given pool. + @param _pool address of pool. + @param _from address of coin. + @param _to address of coin. + @return index of _from, index of _to, bool indicating whether the + coins are in an underlying market + """ + return self.base_registry.get_coin_indices(_pool, _from, _to) + + +@external +@view +def get_coins(_pool: address) -> address[MAX_COINS]: + """ + @notice Get the coins of the given pool. + @param _pool address of pool. + @return coins of the pool. + """ + return self.base_registry.get_coins(_pool) + + +@external +@view +def get_decimals(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the decimals of the coins in given pool. + @param _pool address of pool. + @return decimals of the coins in the pool. + """ + return self.base_registry.get_decimals(_pool) + + +@external +@view +def get_fees(_pool: address) -> uint256[10]: + """ + @notice Get the fees of the given pool. + @param _pool address of pool. + @return fees of the pool. + """ + fees: uint256[10] = empty(uint256[10]) + pool_fees: uint256[2] = self.base_registry.get_fees(_pool) + for i in range(2): + fees[i] = pool_fees[i] + return fees + + +@external +@view +def get_gauges(_pool: address) -> (address[10], int128[10]): + """ + @notice Get the gauges and gauge types of the given pool. + @param _pool address of pool. + @return gauges of the pool. + """ + return self.base_registry.get_gauges(_pool) + + +@external +@view +def get_lp_token(_pool: address) -> address: + """ + @notice Get the LP token of the given pool. + @param _pool address of pool. + @return LP token of the pool. + """ + return self.base_registry.get_lp_token(_pool) + + +@external +@view +def get_n_coins(_pool: address) -> uint256: + """ + @notice Get the number of coins in the given pool. + @param _pool address of pool. + @return number of coins in the pool. + """ + return self._get_n_coins(_pool) + + +@external +@view +def get_n_underlying_coins(_pool: address) -> uint256: + """ + @notice Get the number of underlying coins in the given pool. + @param _pool address of pool. + @return number of underlying coins in the pool. + """ + return self.base_registry.get_n_coins(_pool)[1] + + +@external +@view +def get_pool_asset_type(_pool: address) -> uint256: + """ + @notice Get the asset type of coins in a given pool. + @dev 0 = USD, 1 = ETH, 2 = BTC, 3 = Other + @param _pool address of pool. + @return asset type of the pool. + """ + return self.base_registry.get_pool_asset_type(_pool) + + +@external +@view +def get_pool_from_lp_token(_lp_token: address) -> address: + """ + @notice Get the pool of the given LP token. + @param _lp_token address of LP token. + @return pool of the LP token. + """ + return self.base_registry.get_pool_from_lp_token(_lp_token) + + +@external +@view +def get_pool_name(_pool: address) -> String[64]: + """ + @notice Get the name of the given pool. + @param _pool address of pool. + @return name of the pool. + """ + return self.base_registry.get_pool_name(_pool) + + +@external +@view +def get_pool_params(_pool: address) -> uint256[20]: + """ + @notice Get the parameters of the given pool. + @param _pool address of pool. + @return parameters of the pool. + """ + stableswap_pool_params: uint256[20] = empty(uint256[20]) + stableswap_pool_params[0] = self.base_registry.get_A(_pool) + return stableswap_pool_params + + +@external +@view +def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the underlying balances of the given pool. + @dev returns coin balances if pool is not a metapool + @param _pool address of pool. + @return underlying balances of the pool. + """ + if not self._is_meta(_pool): + return self.base_registry.get_balances(_pool) + return self.base_registry.get_underlying_balances(_pool) + + +@external +@view +def get_underlying_coins(_pool: address) -> address[MAX_COINS]: + """ + @notice Get the underlying coins of the given pool. + @dev For pools that do not lend, the base registry returns the + same value as `get_coins` + @param _pool address of pool. + @return underlying coins of the pool. + """ + return self.base_registry.get_underlying_coins(_pool) + + +@external +@view +def get_underlying_decimals(_pool: address) -> uint256[MAX_COINS]: + """ + @notice Get the underlying decimals of coins in the given pool. + @param _pool address of pool. + @return underlying decimals of the coins in the pool. + """ + coin_decimals: uint256[MAX_COINS] = self.base_registry.get_decimals(_pool) + underlying_coin_decimals: uint256[MAX_COINS] = self.base_registry.get_underlying_decimals(_pool) + + # this is a check for cases where base_registry.get_underlying_decimals + # returns wrong values but base_registry.get_decimals is the right one: + for i in range(MAX_COINS): + if underlying_coin_decimals[i] == 0: + underlying_coin_decimals[i] = coin_decimals[i] + + return underlying_coin_decimals + + +@external +@view +def get_virtual_price_from_lp_token(_token: address) -> uint256: + """ + @notice Get the virtual price of the given LP token. + @param _token address of LP token. + @return virtual price of the LP token. + """ + return self.base_registry.get_virtual_price_from_lp_token(_token) + + +@external +@view +def is_meta(_pool: address) -> bool: + """ + @notice Check if the given pool is a metapool. + @param _pool address of pool. + @return true if the pool is a metapool. + """ + return self._is_meta(_pool) + + +@external +@view +def is_registered(_pool: address) -> bool: + """ + @notice Check if a pool belongs to the registry using get_n_coins + @param _pool The address of the pool + @return A bool corresponding to whether the pool belongs or not + """ + return self._get_n_coins(_pool) > 0 + + +@external +@view +def pool_count() -> uint256: + """ + @notice Get the number of pools in the registry. + @return number of pools in the registry. + """ + return self.base_registry.pool_count() + + +@external +@view +def pool_list(_index: uint256) -> address: + """ + @notice Get the address of the pool at the given index. + @param _index index of the pool. + @return address of the pool. + """ + return self.base_registry.pool_list(_index) diff --git a/docker-compose.yaml b/docker-compose.yaml index 385d6ca..d7b23e8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,7 +1,18 @@ -version: '3.1' - -services: - test: - build: ./ - container_name: metaregistry-test - env_file: .env +version: '3.8' + +services: + test: + build: ./ + container_name: metaregistry-test + env_file: .env + volumes: + - ./:/usr/app + + pre-commit: + build: + context: ./ + target: pre-commit + container_name: metaregistry-pre-commit + command: pre-commit run --all-files + volumes: + - ./:/usr/app diff --git a/pyproject.toml b/pyproject.toml index 13a4b84..a9e944e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,27 +1,27 @@ -# code formatter settings: -[tool.black] -line-length = 100 -target-version = ['py38'] -include = '\.pyi?$' -exclude = ''' -/( - \.eggs - | \.git - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | _build - | buck-out - | build - | dist - | env - | venv -)/ -''' - -# Set root for pytest: https://stackoverflow.com/a/50610630 -[tool.pytest.ini_options] -pythonpath = [ - "." -] +# code formatter settings: +[tool.black] +line-length = 100 +target-version = ['py38'] +include = '\.pyi?$' +exclude = ''' +/( + \.eggs + | \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + | env + | venv +)/ +''' + +# Set root for pytest: https://stackoverflow.com/a/50610630 +[tool.pytest.ini_options] +pythonpath = [ + "." +] diff --git a/requirements.in b/requirements.in index 478b710..abb78bf 100644 --- a/requirements.in +++ b/requirements.in @@ -1,8 +1,8 @@ -titanoboa[forking-recommended]==0.1.8 -black -flake8 -isort -pip-tools -pre-commit -tabulate -rich +titanoboa[forking-recommended]==0.1.8 +black +flake8 +isort +pip-tools +pre-commit +tabulate +rich diff --git a/requirements.txt b/requirements.txt index 221dcb9..0dda1d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,208 +1,208 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile -# -asttokens==2.4.1 - # via vyper -attrs==23.1.0 - # via hypothesis -bitarray==2.8.3 - # via eth-account -black==23.11.0 - # via -r requirements.in -build==1.0.3 - # via pip-tools -cached-property==1.5.2 - # via - # py-ecc - # py-evm -cbor2==5.5.1 - # via vyper -certifi==2023.11.17 - # via requests -cfgv==3.4.0 - # via pre-commit -charset-normalizer==3.3.2 - # via requests -click==8.1.7 - # via - # black - # pip-tools -cytoolz==0.12.2 - # via eth-utils -distlib==0.3.7 - # via virtualenv -eth-abi==4.2.1 - # via - # eth-account - # titanoboa -eth-account==0.10.0 - # via titanoboa -eth-bloom==3.0.0 - # via py-evm -eth-hash[pycryptodome]==0.5.2 - # via - # eth-bloom - # eth-hash - # eth-utils - # trie -eth-keyfile==0.6.1 - # via eth-account -eth-keys==0.4.0 - # via - # eth-account - # eth-keyfile - # py-evm -eth-rlp==0.3.0 - # via eth-account -eth-stdlib==0.2.7 - # via titanoboa -eth-typing==3.5.2 - # via - # eth-abi - # eth-keys - # eth-utils - # py-ecc - # py-evm - # titanoboa -eth-utils==2.3.1 - # via - # eth-abi - # eth-account - # eth-keyfile - # eth-keys - # eth-rlp - # py-ecc - # py-evm - # rlp - # trie -filelock==3.13.1 - # via virtualenv -flake8==6.1.0 - # via -r requirements.in -hexbytes==0.3.1 - # via - # eth-account - # eth-rlp - # trie -hypothesis==6.90.0 - # via titanoboa -identify==2.5.32 - # via pre-commit -idna==3.4 - # via requests -importlib-metadata==6.8.0 - # via vyper -iniconfig==2.0.0 - # via pytest -isort==5.12.0 - # via -r requirements.in -lru-dict==1.3.0 - # via py-evm -markdown-it-py==3.0.0 - # via rich -mccabe==0.7.0 - # via flake8 -mdurl==0.1.2 - # via markdown-it-py -mypy-extensions==1.0.0 - # via - # black - # py-ecc - # py-evm -nodeenv==1.8.0 - # via pre-commit -packaging==23.2 - # via - # black - # build - # pytest - # vyper -parsimonious==0.9.0 - # via eth-abi -pathspec==0.11.2 - # via black -pip-tools==7.3.0 - # via -r requirements.in -platformdirs==4.0.0 - # via - # black - # virtualenv -pluggy==1.3.0 - # via pytest -pre-commit==3.5.0 - # via -r requirements.in -py-ecc==6.0.0 - # via py-evm -py-evm==0.8.0b1 - # via titanoboa -pycodestyle==2.11.1 - # via flake8 -pycryptodome==3.19.0 - # via - # eth-hash - # eth-keyfile - # eth-stdlib - # vyper -pyflakes==3.1.0 - # via flake8 -pygments==2.17.2 - # via rich -pyproject-hooks==1.0.0 - # via build -pytest==7.4.3 - # via titanoboa -pyyaml==6.0.1 - # via pre-commit -regex==2023.10.3 - # via parsimonious -requests==2.31.0 - # via titanoboa -rich==13.7.0 - # via - # -r requirements.in - # titanoboa -rlp==3.0.0 - # via - # eth-account - # eth-rlp - # py-evm - # trie -six==1.16.0 - # via asttokens -sortedcontainers==2.4.0 - # via - # hypothesis - # trie -tabulate==0.9.0 - # via -r requirements.in -titanoboa[forking-recommended]==0.1.8 - # via - # -r requirements.in - # titanoboa -toolz==0.12.0 - # via cytoolz -trie==2.2.0 - # via py-evm -typing-extensions==4.8.0 - # via eth-typing -ujson==5.8.0 - # via titanoboa -urllib3==2.1.0 - # via requests -virtualenv==20.24.7 - # via pre-commit -vyper==0.3.10 - # via titanoboa -wheel==0.41.3 - # via - # pip-tools - # vyper -zipp==3.17.0 - # via importlib-metadata - -# The following packages are considered to be unsafe in a requirements file: -# pip -# setuptools +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile +# +asttokens==2.4.1 + # via vyper +attrs==23.1.0 + # via hypothesis +bitarray==2.8.3 + # via eth-account +black==23.11.0 + # via -r requirements.in +build==1.0.3 + # via pip-tools +cached-property==1.5.2 + # via + # py-ecc + # py-evm +cbor2==5.5.1 + # via vyper +certifi==2023.11.17 + # via requests +cfgv==3.4.0 + # via pre-commit +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # black + # pip-tools +cytoolz==0.12.2 + # via eth-utils +distlib==0.3.7 + # via virtualenv +eth-abi==4.2.1 + # via + # eth-account + # titanoboa +eth-account==0.10.0 + # via titanoboa +eth-bloom==3.0.0 + # via py-evm +eth-hash[pycryptodome]==0.5.2 + # via + # eth-bloom + # eth-hash + # eth-utils + # trie +eth-keyfile==0.6.1 + # via eth-account +eth-keys==0.4.0 + # via + # eth-account + # eth-keyfile + # py-evm +eth-rlp==0.3.0 + # via eth-account +eth-stdlib==0.2.7 + # via titanoboa +eth-typing==3.5.2 + # via + # eth-abi + # eth-keys + # eth-utils + # py-ecc + # py-evm + # titanoboa +eth-utils==2.3.1 + # via + # eth-abi + # eth-account + # eth-keyfile + # eth-keys + # eth-rlp + # py-ecc + # py-evm + # rlp + # trie +filelock==3.13.1 + # via virtualenv +flake8==6.1.0 + # via -r requirements.in +hexbytes==0.3.1 + # via + # eth-account + # eth-rlp + # trie +hypothesis==6.90.0 + # via titanoboa +identify==2.5.32 + # via pre-commit +idna==3.4 + # via requests +importlib-metadata==6.8.0 + # via vyper +iniconfig==2.0.0 + # via pytest +isort==5.12.0 + # via -r requirements.in +lru-dict==1.3.0 + # via py-evm +markdown-it-py==3.0.0 + # via rich +mccabe==0.7.0 + # via flake8 +mdurl==0.1.2 + # via markdown-it-py +mypy-extensions==1.0.0 + # via + # black + # py-ecc + # py-evm +nodeenv==1.8.0 + # via pre-commit +packaging==23.2 + # via + # black + # build + # pytest + # vyper +parsimonious==0.9.0 + # via eth-abi +pathspec==0.11.2 + # via black +pip-tools==7.3.0 + # via -r requirements.in +platformdirs==4.0.0 + # via + # black + # virtualenv +pluggy==1.3.0 + # via pytest +pre-commit==3.5.0 + # via -r requirements.in +py-ecc==6.0.0 + # via py-evm +py-evm==0.8.0b1 + # via titanoboa +pycodestyle==2.11.1 + # via flake8 +pycryptodome==3.19.0 + # via + # eth-hash + # eth-keyfile + # eth-stdlib + # vyper +pyflakes==3.1.0 + # via flake8 +pygments==2.17.2 + # via rich +pyproject-hooks==1.0.0 + # via build +pytest==7.4.3 + # via titanoboa +pyyaml==6.0.1 + # via pre-commit +regex==2023.10.3 + # via parsimonious +requests==2.31.0 + # via titanoboa +rich==13.7.0 + # via + # -r requirements.in + # titanoboa +rlp==3.0.0 + # via + # eth-account + # eth-rlp + # py-evm + # trie +six==1.16.0 + # via asttokens +sortedcontainers==2.4.0 + # via + # hypothesis + # trie +tabulate==0.9.0 + # via -r requirements.in +titanoboa[forking-recommended]==0.1.8 + # via + # -r requirements.in + # titanoboa +toolz==0.12.0 + # via cytoolz +trie==2.2.0 + # via py-evm +typing-extensions==4.8.0 + # via eth-typing +ujson==5.8.0 + # via titanoboa +urllib3==2.1.0 + # via requests +virtualenv==20.24.7 + # via pre-commit +vyper==0.3.10 + # via titanoboa +wheel==0.41.3 + # via + # pip-tools + # vyper +zipp==3.17.0 + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# pip +# setuptools diff --git a/scripts/boa_scripts/set_up_registries.py b/scripts/boa_scripts/set_up_registries.py index 1a3cb6b..0e65c04 100644 --- a/scripts/boa_scripts/set_up_registries.py +++ b/scripts/boa_scripts/set_up_registries.py @@ -1,149 +1,155 @@ -# flake8: noqa - -import os -import sys -from dataclasses import dataclass -from typing import List - -import boa -import deployment_utils as deploy_utils -from boa.network import NetworkEnv -from deploy_infra import deployments -from eth_account import Account -from eth_typing import Address -from eth_utils import to_checksum_address -from rich.console import Console as RichConsole - -logger = RichConsole(file=sys.stdout) - - -def deploy_factory_handler(): - - pass - - -def set_up_registries(network: str, url: str, account: str, fork: bool = False): - """ - Set up registries for the Curve StableSwapNG factory. - :param network: Network to deploy to. - :param url: URL to connect to. - :param account: Account to use. - :param fork: Whether to deploy to a fork (test) network. - """ - - logger.log(f"Connecting to {network} ...") - if fork: - boa.env.fork(url) - boa.env.eoa = deploy_utils.FIDDYDEPLOYER - logger.log("Forkmode") - else: - logger.log("Prodmode") - boa.set_env(NetworkEnv(url)) - boa.env.add_account(Account.from_key(os.environ[account])) - - data = next((data for _network, data in deploy_utils.curve_dao_network_settings.items() - if _network in network), None) - - owner = data.dao_ownership_contract - fee_receiver = data.fee_receiver_address - address_provider = Contract(data.address_provider) - assert owner, f"Curve's DAO contracts may not be on {network}." - assert fee_receiver, f"Curve's DAO contracts may not be on {network}." - - # -------------------------- Register into AddressProvider -------------------------- - - max_id = address_provider.max_id() - description = "Curve StableSwapNG" - boss = Contract(address_provider.admin()) - - # check if account can handle boss: - account_is_boss_handler = any( - account.address.lower() == boss.admins(i).lower() for i in range(2) - ) - assert account_is_boss_handler # only authorised accounts can write to address provider # noqa: E501 - - is_new_deployment = not any( - address_provider.get_id_info(i).description is description - for i in range(max_id + 1) - ) - - if is_new_deployment: - - logger.info(f"Adding a new registry provider entry at id: {max_id + 1}") - - # we're adding a new id - with accounts.use_sender(account) as account: - boss.execute( - address_provider.address, - address_provider.add_new_id.encode_input(factory, description), - gas_limit=400000, - **deploy_utils._get_tx_params(), - ) - - else: - - assert address_provider.get_id_info(index).description == description - - logger.info( - f"Updating existing registry provider entry at id: {index}" - ) - - # we're updating an existing id with the same description: - with accounts.use_sender(account) as account: - boss.execute( - address_provider.address, - address_provider.set_address.encode_input(index, factory), - gas_limit=200000, - **deploy_utils._get_tx_params(), - ) - - assert address_provider.get_id_info(index).addr.lower() == factory.lower() - - logger.info("AddressProvider integration complete!") - - # -------------------------- Set up metaregistry -------------------------- - - metaregistry_address = deploy_utils.curve_dao_network_settings[ - network - ].metaregistry_address - base_pool_registry_address = deploy_utils.curve_dao_network_settings[ - network - ].base_pool_registry_address - - if metaregistry_address: - - metaregistry = Contract(metaregistry_address) - boss = Contract(metaregistry.owner()) - - # set up metaregistry integration: - logger.info("Integrate into Metaregistry ...") - logger.info( - "Deploying Factory handler to integrate it to the metaregistry:" - ) - factory_handler = account.deploy( - project.CurveStableSwapFactoryNGHandler, - factory.address, - base_pool_registry_address, - **deploy_utils._get_tx_params(), - ) - - boss.execute( - metaregistry.address, - metaregistry.add_registry_handler.encode_input(factory_handler), - **deploy_utils._get_tx_params(), - ) - - logger.info("Metaregistry integration complete!") - - -def main(): - set_up_registries( - "ethereum:mainnet", - os.environ["RPC_ETHEREUM"], - "FIDDYDEPLOYER", - fork=False, - ) - - -if __name__ == "__main__": - main() +# flake8: noqa + +import os +import sys +from dataclasses import dataclass +from typing import List + +import boa +import deployment_utils as deploy_utils +from boa.network import NetworkEnv +from deploy_infra import deployments +from eth_account import Account +from eth_typing import Address +from eth_utils import to_checksum_address +from rich.console import Console as RichConsole + +logger = RichConsole(file=sys.stdout) + + +def deploy_factory_handler(): + pass + + +def set_up_registries( + network: str, url: str, account: str, fork: bool = False +): + """ + Set up registries for the Curve StableSwapNG factory. + :param network: Network to deploy to. + :param url: URL to connect to. + :param account: Account to use. + :param fork: Whether to deploy to a fork (test) network. + """ + + logger.log(f"Connecting to {network} ...") + if fork: + boa.env.fork(url) + boa.env.eoa = deploy_utils.FIDDYDEPLOYER + logger.log("Forkmode") + else: + logger.log("Prodmode") + boa.set_env(NetworkEnv(url)) + boa.env.add_account(Account.from_key(os.environ[account])) + + data = next( + ( + data + for _network, data in deploy_utils.curve_dao_network_settings.items() + if _network in network + ), + None, + ) + + owner = data.dao_ownership_contract + fee_receiver = data.fee_receiver_address + address_provider = Contract(data.address_provider) + assert owner, f"Curve's DAO contracts may not be on {network}." + assert fee_receiver, f"Curve's DAO contracts may not be on {network}." + + # -------------------------- Register into AddressProvider -------------------------- + + max_id = address_provider.max_id() + description = "Curve StableSwapNG" + boss = Contract(address_provider.admin()) + + # check if account can handle boss: + account_is_boss_handler = any( + account.address.lower() == boss.admins(i).lower() for i in range(2) + ) + assert account_is_boss_handler # only authorised accounts can write to address provider # noqa: E501 + + is_new_deployment = not any( + address_provider.get_id_info(i).description is description + for i in range(max_id + 1) + ) + + if is_new_deployment: + logger.info( + f"Adding a new registry provider entry at id: {max_id + 1}" + ) + + # we're adding a new id + with accounts.use_sender(account) as account: + boss.execute( + address_provider.address, + address_provider.add_new_id.encode_input(factory, description), + gas_limit=400000, + **deploy_utils._get_tx_params(), + ) + + else: + assert address_provider.get_id_info(index).description == description + + logger.info( + f"Updating existing registry provider entry at id: {index}" + ) + + # we're updating an existing id with the same description: + with accounts.use_sender(account) as account: + boss.execute( + address_provider.address, + address_provider.set_address.encode_input(index, factory), + gas_limit=200000, + **deploy_utils._get_tx_params(), + ) + + assert address_provider.get_id_info(index).addr.lower() == factory.lower() + + logger.info("AddressProvider integration complete!") + + # -------------------------- Set up metaregistry -------------------------- + + metaregistry_address = deploy_utils.curve_dao_network_settings[ + network + ].metaregistry_address + base_pool_registry_address = deploy_utils.curve_dao_network_settings[ + network + ].base_pool_registry_address + + if metaregistry_address: + metaregistry = Contract(metaregistry_address) + boss = Contract(metaregistry.owner()) + + # set up metaregistry integration: + logger.info("Integrate into Metaregistry ...") + logger.info( + "Deploying Factory handler to integrate it to the metaregistry:" + ) + factory_handler = account.deploy( + project.CurveStableSwapFactoryNGHandler, + factory.address, + base_pool_registry_address, + **deploy_utils._get_tx_params(), + ) + + boss.execute( + metaregistry.address, + metaregistry.add_registry_handler.encode_input(factory_handler), + **deploy_utils._get_tx_params(), + ) + + logger.info("Metaregistry integration complete!") + + +def main(): + set_up_registries( + "ethereum:mainnet", + os.environ["RPC_ETHEREUM"], + "FIDDYDEPLOYER", + fork=False, + ) + + +if __name__ == "__main__": + main() diff --git a/scripts/change_registry_handler.py b/scripts/change_registry_handler.py index a68f2fe..ada5114 100644 --- a/scripts/change_registry_handler.py +++ b/scripts/change_registry_handler.py @@ -1,79 +1,78 @@ -import sys - -from brownie import ( - AddressProvider, - CryptoRegistry, - MetaRegistry, - ProxyAdmin, - accounts, - network, -) -from brownie.network.gas.strategies import GasNowScalingStrategy -from rich.console import Console as RichConsole - -RICH_CONSOLE = RichConsole(file=sys.stdout) -ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383" -CRYPTO_REGISTRY_HANDLER = "0x5f493fEE8D67D3AE3bA730827B34126CFcA0ae94" -CRYPTO_REGISTRY_HANDLER_ID = 2 -OLD_CRYPTO_REGISTRY_HANDLER = "0x22ceb131d3170f9f2FeA6b4b1dE1B45fcfC86E56" -CRYPTO_REGISTRY = "0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0" -ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" - - -if network.show_active() == "mainnet": - RICH_CONSOLE.log("Writing on mainnet") - accounts.load("babe") - txparams = {"from": accounts[0], "required_confs": 5} - try: - network.gas_price(GasNowScalingStrategy("slow", "fast")) - except ConnectionError: - pass - -else: - RICH_CONSOLE.log("Simulation Mode. Writing to mainnet-fork.") - txparams = { - "from": accounts.at( - "0xbabe61887f1de2713c6f97e567623453d3C79f67", force=True - ) - } - - -def main(): - - # admin only: only admin of ADDRESSPROVIDER's proxy admin can do the following: - address_provider = AddressProvider.at(ADDRESS_PROVIDER) - address_provider_admin = address_provider.admin() - proxy_admin = ProxyAdmin.at(address_provider_admin) - - metaregistry = MetaRegistry.at( - "0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC" - ) - - assert ( - metaregistry.get_registry(CRYPTO_REGISTRY_HANDLER_ID) - == OLD_CRYPTO_REGISTRY_HANDLER - ) - num_pools = metaregistry.pool_count() - num_registries = metaregistry.registry_length() - num_pools_in_crypto_registry = CryptoRegistry.at( - CRYPTO_REGISTRY - ).pool_count() - - call_data = metaregistry.update_registry_handler.encode_input( - CRYPTO_REGISTRY_HANDLER_ID, - CRYPTO_REGISTRY_HANDLER, - ) - proxy_admin.execute(metaregistry.address, call_data, txparams) - - assert ( - metaregistry.pool_count() == num_pools + num_pools_in_crypto_registry - ) - assert metaregistry.registry_length() == num_registries - assert ( - metaregistry.get_gauge("0xD51a44d3FaE010294C616388b506AcdA1bfAAE46") - != ZERO_ADDRESS - ) - - -if __name__ == "__main__": - main() +import sys + +from brownie import ( + AddressProvider, + CryptoRegistry, + MetaRegistry, + ProxyAdmin, + accounts, + network, +) +from brownie.network.gas.strategies import GasNowScalingStrategy +from rich.console import Console as RichConsole + +RICH_CONSOLE = RichConsole(file=sys.stdout) +ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383" +CRYPTO_REGISTRY_HANDLER = "0x5f493fEE8D67D3AE3bA730827B34126CFcA0ae94" +CRYPTO_REGISTRY_HANDLER_ID = 2 +OLD_CRYPTO_REGISTRY_HANDLER = "0x22ceb131d3170f9f2FeA6b4b1dE1B45fcfC86E56" +CRYPTO_REGISTRY = "0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0" +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" + + +if network.show_active() == "mainnet": + RICH_CONSOLE.log("Writing on mainnet") + accounts.load("babe") + txparams = {"from": accounts[0], "required_confs": 5} + try: + network.gas_price(GasNowScalingStrategy("slow", "fast")) + except ConnectionError: + pass + +else: + RICH_CONSOLE.log("Simulation Mode. Writing to mainnet-fork.") + txparams = { + "from": accounts.at( + "0xbabe61887f1de2713c6f97e567623453d3C79f67", force=True + ) + } + + +def main(): + # admin only: only admin of ADDRESSPROVIDER's proxy admin can do the following: + address_provider = AddressProvider.at(ADDRESS_PROVIDER) + address_provider_admin = address_provider.admin() + proxy_admin = ProxyAdmin.at(address_provider_admin) + + metaregistry = MetaRegistry.at( + "0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC" + ) + + assert ( + metaregistry.get_registry(CRYPTO_REGISTRY_HANDLER_ID) + == OLD_CRYPTO_REGISTRY_HANDLER + ) + num_pools = metaregistry.pool_count() + num_registries = metaregistry.registry_length() + num_pools_in_crypto_registry = CryptoRegistry.at( + CRYPTO_REGISTRY + ).pool_count() + + call_data = metaregistry.update_registry_handler.encode_input( + CRYPTO_REGISTRY_HANDLER_ID, + CRYPTO_REGISTRY_HANDLER, + ) + proxy_admin.execute(metaregistry.address, call_data, txparams) + + assert ( + metaregistry.pool_count() == num_pools + num_pools_in_crypto_registry + ) + assert metaregistry.registry_length() == num_registries + assert ( + metaregistry.get_gauge("0xD51a44d3FaE010294C616388b506AcdA1bfAAE46") + != ZERO_ADDRESS + ) + + +if __name__ == "__main__": + main() diff --git a/scripts/deploy.py b/scripts/deploy.py index 76cdf05..7dc2aca 100644 --- a/scripts/deploy.py +++ b/scripts/deploy.py @@ -1,84 +1,83 @@ -import click -from ape import project -from ape.cli import NetworkBoundCommand, account_option, network_option -from eth_abi import encode - -ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383" -STABLE_REGISTRY_ADDRESS = "0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5" -STABLE_FACTORY_ADDRESS = "0xB9fC157394Af804a3578134A6585C0dc9cc990d4" -CRYPTO_REGISTRY_ADDRESS = "" # left blank because a new one gets deployed -CRYPTO_FACTORY_ADDRESS = "0xF18056Bbd320E96A48e3Fbf8bC061322531aac99" - - -@click.group(short_help="Deploy the project") -def cli(): - pass - - -@cli.command(cls=NetworkBoundCommand) -@network_option() -@account_option() -def main(network, account): - - # deploy basepool registry: - base_pool_registry = account.deploy(project.BasePoolRegistry) - - # deploy crypto registry: - print( - "Crypto Registry constructor arguments: ", - encode(["address", "address"], [ADDRESS_PROVIDER, base_pool_registry]), - ) - crypto_registry = account.deploy( - project.CryptoRegistryV1, - ADDRESS_PROVIDER, - base_pool_registry, - ) - - # deploy stable registry handler: - print( - "Stable Registry Handler constructor arguments: ", - encode(["address"], [STABLE_REGISTRY_ADDRESS]).hex(), - ) - account.deploy(project.StableRegistryHandler, STABLE_REGISTRY_ADDRESS) - - # deploy stable factory handler: - print( - "Stable Factory Handler constructor arguments: ", - encode( - ["address", "address"], - [STABLE_FACTORY_ADDRESS, base_pool_registry], - ).hex(), - ) - account.deploy( - project.StableFactoryHandler, - STABLE_FACTORY_ADDRESS, - base_pool_registry, - ) - - # deploy crypto registry handler: - print( - "Crypto Registry Handler constructor arguments: ", - encode(["address"], [crypto_registry]).hex(), - ) - account.deploy(project.CryptoRegistryHandler, crypto_registry) - - # deploy crypto factory handler: - print( - "Crypto Factory Handler constructor arguments: ", - encode( - ["address", "address"], - [CRYPTO_FACTORY_ADDRESS, base_pool_registry], - ).hex(), - ) - account.deploy( - project.CryptoFactoryHandler, - CRYPTO_FACTORY_ADDRESS, - base_pool_registry, - ) - - # deploy metaregistry: - print( - "MetaRegistry constructor arguments: ", - encode(["address"], [ADDRESS_PROVIDER]).hex(), - ) - account.deploy(project.MetaRegistry, ADDRESS_PROVIDER) +import click +from ape import project +from ape.cli import NetworkBoundCommand, account_option, network_option +from eth_abi import encode + +ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383" +STABLE_REGISTRY_ADDRESS = "0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5" +STABLE_FACTORY_ADDRESS = "0xB9fC157394Af804a3578134A6585C0dc9cc990d4" +CRYPTO_REGISTRY_ADDRESS = "" # left blank because a new one gets deployed +CRYPTO_FACTORY_ADDRESS = "0xF18056Bbd320E96A48e3Fbf8bC061322531aac99" + + +@click.group(short_help="Deploy the project") +def cli(): + pass + + +@cli.command(cls=NetworkBoundCommand) +@network_option() +@account_option() +def main(network, account): + # deploy basepool registry: + base_pool_registry = account.deploy(project.BasePoolRegistry) + + # deploy crypto registry: + print( + "Crypto Registry constructor arguments: ", + encode(["address", "address"], [ADDRESS_PROVIDER, base_pool_registry]), + ) + crypto_registry = account.deploy( + project.CryptoRegistryV1, + ADDRESS_PROVIDER, + base_pool_registry, + ) + + # deploy stable registry handler: + print( + "Stable Registry Handler constructor arguments: ", + encode(["address"], [STABLE_REGISTRY_ADDRESS]).hex(), + ) + account.deploy(project.StableRegistryHandler, STABLE_REGISTRY_ADDRESS) + + # deploy stable factory handler: + print( + "Stable Factory Handler constructor arguments: ", + encode( + ["address", "address"], + [STABLE_FACTORY_ADDRESS, base_pool_registry], + ).hex(), + ) + account.deploy( + project.StableFactoryHandler, + STABLE_FACTORY_ADDRESS, + base_pool_registry, + ) + + # deploy crypto registry handler: + print( + "Crypto Registry Handler constructor arguments: ", + encode(["address"], [crypto_registry]).hex(), + ) + account.deploy(project.CryptoRegistryHandler, crypto_registry) + + # deploy crypto factory handler: + print( + "Crypto Factory Handler constructor arguments: ", + encode( + ["address", "address"], + [CRYPTO_FACTORY_ADDRESS, base_pool_registry], + ).hex(), + ) + account.deploy( + project.CryptoFactoryHandler, + CRYPTO_FACTORY_ADDRESS, + base_pool_registry, + ) + + # deploy metaregistry: + print( + "MetaRegistry constructor arguments: ", + encode(["address"], [ADDRESS_PROVIDER]).hex(), + ) + account.deploy(project.MetaRegistry, ADDRESS_PROVIDER) diff --git a/scripts/deploy_crypto_registry_handler.py b/scripts/deploy_crypto_registry_handler.py index 8ca850c..f1ca00e 100644 --- a/scripts/deploy_crypto_registry_handler.py +++ b/scripts/deploy_crypto_registry_handler.py @@ -1,23 +1,22 @@ -import click -from ape import project -from ape.cli import NetworkBoundCommand, account_option, network_option -from eth_abi import encode - -CRYPTO_REGISTRY_ADDRESS = "0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0" - - -@click.group(short_help="Deploy the registry handler") -def cli(): - pass - - -@cli.command(cls=NetworkBoundCommand) -@network_option() -@account_option() -def main(network, account): - - print( - "Crypto Registry Handler constructor arguments: ", - encode(["address"], [CRYPTO_REGISTRY_ADDRESS]).hex(), - ) - account.deploy(project.CryptoRegistryHandler, CRYPTO_REGISTRY_ADDRESS) +import click +from ape import project +from ape.cli import NetworkBoundCommand, account_option, network_option +from eth_abi import encode + +CRYPTO_REGISTRY_ADDRESS = "0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0" + + +@click.group(short_help="Deploy the registry handler") +def cli(): + pass + + +@cli.command(cls=NetworkBoundCommand) +@network_option() +@account_option() +def main(network, account): + print( + "Crypto Registry Handler constructor arguments: ", + encode(["address"], [CRYPTO_REGISTRY_ADDRESS]).hex(), + ) + account.deploy(project.CryptoRegistryHandler, CRYPTO_REGISTRY_ADDRESS) diff --git a/scripts/print_missing.py b/scripts/print_missing.py index 82d75e5..7bb34ea 100644 --- a/scripts/print_missing.py +++ b/scripts/print_missing.py @@ -1,54 +1,54 @@ -from tabulate import tabulate - -MISSING = "\033[33m✖\033[0m" -PRESENT = "\033[32m✓\033[0m" - - -def main(): - def get_non_indexed_view_functions( - registry_selectors, registry_abi, fn_index - ): - view_fns = { - d["name"] - for d in registry_abi - if d.get("stateMutability") == "view" - } - non_indexed_fns = dict(registry_selectors.items() - fn_index.items()) - return { - k: registry_selectors[k] - for k, v in non_indexed_fns.items() - if registry_selectors[k] in view_fns - } - - function_index = get_non_indexed_view_functions( - MetaRegistry.selectors, MetaRegistry.abi, {} - ) - registry_coverage = [[PRESENT] * len(function_index)] - registry_names = [ - f"{a}{b}" - for a in ["Crypto", "Stable"] - for b in ["Factory", "Registry"] - ] - - for registry_name in registry_names: - # registry = getattr(interface, registry_name) # TODO: fix this! - registry = None - non_indexed_view_fns = get_non_indexed_view_functions( - registry.selectors, registry.abi, function_index - ) - function_index.update(non_indexed_view_fns) - registry_coverage.append( - [ - PRESENT if fn in registry.selectors else MISSING - for fn in function_index.keys() - ] - ) - - registry_coverage = [ - coverage + [MISSING] * (len(function_index) - len(coverage)) - for coverage in registry_coverage - ] - res = sorted(zip(function_index.values(), *registry_coverage)) - print( - tabulate(res, headers=["Functions", "MetaRegistry"] + registry_names) - ) +from tabulate import tabulate + +MISSING = "\033[33m✖\033[0m" +PRESENT = "\033[32m✓\033[0m" + + +def main(): + def get_non_indexed_view_functions( + registry_selectors, registry_abi, fn_index + ): + view_fns = { + d["name"] + for d in registry_abi + if d.get("stateMutability") == "view" + } + non_indexed_fns = dict(registry_selectors.items() - fn_index.items()) + return { + k: registry_selectors[k] + for k, v in non_indexed_fns.items() + if registry_selectors[k] in view_fns + } + + function_index = get_non_indexed_view_functions( + MetaRegistry.selectors, MetaRegistry.abi, {} + ) + registry_coverage = [[PRESENT] * len(function_index)] + registry_names = [ + f"{a}{b}" + for a in ["Crypto", "Stable"] + for b in ["Factory", "Registry"] + ] + + for registry_name in registry_names: + # registry = getattr(interface, registry_name) # TODO: fix this! + registry = None + non_indexed_view_fns = get_non_indexed_view_functions( + registry.selectors, registry.abi, function_index + ) + function_index.update(non_indexed_view_fns) + registry_coverage.append( + [ + PRESENT if fn in registry.selectors else MISSING + for fn in function_index.keys() + ] + ) + + registry_coverage = [ + coverage + [MISSING] * (len(function_index) - len(coverage)) + for coverage in registry_coverage + ] + res = sorted(zip(function_index.values(), *registry_coverage)) + print( + tabulate(res, headers=["Functions", "MetaRegistry"] + registry_names) + ) diff --git a/scripts/setup_metaregistry.py b/scripts/setup_metaregistry.py index 4e41fe8..18aede1 100644 --- a/scripts/setup_metaregistry.py +++ b/scripts/setup_metaregistry.py @@ -1,317 +1,328 @@ -import sys - -import click -from tests.utils import ZERO_ADDRESS -from rich.console import Console as RichConsole - -from tests.utils import get_deployed_contract - -RICH_CONSOLE = RichConsole(file=sys.stdout) - -ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383" -BASE_POOLS = { - "tripool": { - "pool": "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", - "lp_token": "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", - "num_coins": 3, - "is_legacy": False, - "is_lending": False, - "is_v2": False, - }, - "fraxusdc": { - "pool": "0xdcef968d416a41cdac0ed8702fac8128a64241a2", - "lp_token": "0x3175df0976dfa876431c2e9ee6bc45b65d3473cc", - "num_coins": 2, - "is_legacy": False, - "is_lending": False, - "is_v2": False, - }, - "sbtc": { - "pool": "0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714", - "lp_token": "0x075b1bb99792c9E1041bA13afEf80C91a1e70fB3", - "num_coins": 3, - "is_legacy": True, - "is_lending": False, - "is_v2": False, - }, -} -CRYPTO_REGISTRY_POOLS = { - "tricrypto2": { - "pool": "0xD51a44d3FaE010294C616388b506AcdA1bfAAE46", - "lp_token": "0xc4AD29ba4B3c580e6D59105FFf484999997675Ff", - "gauge": "0xDeFd8FdD20e0f34115C7018CCfb655796F6B2168", - "zap": "0x3993d34e7e99Abf6B6f367309975d1360222D446", - "num_coins": 3, - "name": "tricrypto2", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - }, - "eurt3crv": { - "pool": "0x9838eccc42659fa8aa7daf2ad134b53984c9427b", - "lp_token": "0x3b6831c0077a1e44ed0a21841c3bc4dc11bce833", - "gauge": "0x4Fd86Ce7Ecea88F7E0aA78DC12625996Fb3a04bC", - "zap": "0x5D0F47B32fDd343BfA74cE221808e2abE4A53827", - "num_coins": 2, - "name": "eurtusd", - "base_pool": BASE_POOLS["tripool"]["pool"], - "has_positive_rebasing_tokens": False, - }, - "eursusdc": { - "pool": "0x98a7F18d4E56Cfe84E3D081B40001B3d5bD3eB8B", - "lp_token": "0x3D229E1B4faab62F621eF2F6A610961f7BD7b23B", - "gauge": "0x65CA7Dc5CB661fC58De57B1E1aF404649a27AD35", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "eursusd", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - }, - "crveth": { - "pool": "0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511", - "lp_token": "0xEd4064f376cB8d68F770FB1Ff088a3d0F3FF5c4d", - "gauge": "0x1cEBdB0856dd985fAe9b8fEa2262469360B8a3a6", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "crveth", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - }, - "cvxeth": { - "pool": "0xB576491F1E6e5E62f1d8F26062Ee822B40B0E0d4", - "lp_token": "0x3A283D9c08E8b55966afb64C515f5143cf907611", - "gauge": "0x7E1444BA99dcdFfE8fBdb42C02F0005D14f13BE1", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "cvxeth", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - }, - "xaut3crv": { - "pool": "0xAdCFcf9894335dC340f6Cd182aFA45999F45Fc44", - "lp_token": "0x8484673cA7BfF40F82B041916881aeA15ee84834", - "gauge": "0x1B3E14157ED33F60668f2103bCd5Db39a1573E5B", - "zap": "0xc5FA220347375ac4f91f9E4A4AAb362F22801504", - "num_coins": 2, - "name": "xaut3crv", - "base_pool": BASE_POOLS["tripool"]["pool"], - "has_positive_rebasing_tokens": False, - }, - "spelleth": { - "pool": "0x98638FAcf9a3865cd033F36548713183f6996122", - "lp_token": "0x8282BD15dcA2EA2bDf24163E8f2781B30C43A2ef", - "gauge": "0x08380a4999Be1a958E2abbA07968d703C7A3027C", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "spelleth", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - }, - "teth": { - "pool": "0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC", - "lp_token": "0xCb08717451aaE9EF950a2524E33B6DCaBA60147B", - "gauge": "0x6070fBD4E608ee5391189E7205d70cc4A274c017", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "teth", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - }, - "eurocusd": { - "pool": "0xE84f5b1582BA325fDf9cE6B0c1F087ccfC924e54", - "lp_token": "0x70fc957eb90e37af82acdbd12675699797745f68", - "gauge": "0x4329c8F09725c0e3b6884C1daB1771bcE17934F9", - "zap": "0xd446a98f88e1d053d1f64986e3ed083bb1ab7e5a", - "num_coins": 2, - "name": "eurocusd", - "base_pool": BASE_POOLS["tripool"]["pool"], - "has_positive_rebasing_tokens": False, - }, -} - - -@click.group(short_help="Deploy the project") -def cli(): - pass - - -@cli.command(cls=NetworkBoundCommand) -@network_option() -@account_option() -def main(network: str, account: str): - - # admin only: only admin of ADDRESSPROVIDER's proxy admin can do the following: - address_provider = get_deployed_contract('AddressProvider', ADDRESS_PROVIDER) - address_provider_admin = address_provider.admin() - proxy_admin = get_deployed_contract('ProxyAdmin', address_provider_admin) - - if network == "ethereum:mainnet-fork": - RICH_CONSOLE.log("Simulation mode.") - account = accounts[proxy_admin.admins(1)] - - # deployed contracts: - base_pool_registry = get_deployed_contract('BasePoolRegistry', "0xDE3eAD9B2145bBA2EB74007e58ED07308716B725") - crypto_registry = get_deployed_contract('CryptoRegistryV1', "0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0") - stable_registry_handler = get_deployed_contract('StableRegistryHandler', "0x46a8a9CF4Fc8e99EC3A14558ACABC1D93A27de68") - stable_factory_handler = get_deployed_contract('StableFactoryHandler', "0x127db66E7F0b16470Bec194d0f496F9Fa065d0A9") - crypto_registry_handler = get_deployed_contract('CryptoRegistryHandler', "0x5f493fEE8D67D3AE3bA730827B34126CFcA0ae94") - crypto_factory_handler = get_deployed_contract('CryptoFactoryHandler', "0xC4F389020002396143B863F6325aA6ae481D19CE") - metaregistry = get_deployed_contract('MetaRegistry', "0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC") - registry_handlers = [ - stable_registry_handler, - stable_factory_handler, - crypto_registry_handler, - crypto_factory_handler, - ] - - # set up the metaregistry: - - total_gas_used = ( - 0 # gets total gas used for setting up. should be about 5mil gas. - ) - - # populate base pool registry: - base_pool_index = 0 - for _, data in BASE_POOLS.items(): - - # check if base pool already exists in the registry: - entry_at_index = base_pool_registry.base_pool_list( - base_pool_index - ).lower() - if entry_at_index == data["pool"].lower(): - base_pool_index += 1 - continue - - # set up tx calldata for proxy admin: - call_data = base_pool_registry.add_base_pool.as_transaction( - data["pool"], - data["lp_token"], - data["num_coins"], - data["is_legacy"], - data["is_lending"], - data["is_v2"], - sender=address_provider_admin, - ).data - - # add base_pool to registry: - tx = proxy_admin.execute(base_pool_registry, call_data, sender=account) - total_gas_used += tx.gas_used - - # check if deployment is correct: - assert ( - base_pool_registry.base_pool_list(base_pool_index).lower() - == data["pool"].lower() - ) - RICH_CONSOLE.log( - f"Added base pool [blue]{data['pool']} to base pool registry. " - f"Gas used: [green]{tx.gas_used}" - ) - base_pool_index += 1 - - # populate crypto registry: - crypto_pool_index = 0 - for _, pool in CRYPTO_REGISTRY_POOLS.items(): - - # check if base pool already exists in the registry: - entry_at_index = crypto_registry.pool_list(crypto_pool_index).lower() - if entry_at_index == pool["pool"].lower(): - crypto_pool_index += 1 - continue - - # set up tx calldata for proxy admin: - call_data = crypto_registry.add_pool.as_transaction( - pool["pool"], - pool["lp_token"], - pool["gauge"], - pool["zap"], - pool["num_coins"], - pool["name"], - pool["base_pool"], - pool["has_positive_rebasing_tokens"], - sender=address_provider_admin, - ).data - - # add pool to registry: - tx = proxy_admin.execute(crypto_registry, call_data, sender=account) - total_gas_used += tx.gas_used - - # check if deployment is correct: - assert ( - crypto_registry.pool_list(crypto_pool_index).lower() - == pool["pool"].lower() - ) - RICH_CONSOLE.log( - f"Added pool [blue]{pool['pool']} to crypto registry. " - f"Gas used: [green]{tx.gas_used}" - ) - crypto_pool_index += 1 - - # populate metaregistry: - registry_handler_index = 0 - for registry_handler in registry_handlers: - - # check if base pool already exists in the registry: - entry_at_index = metaregistry.get_registry( - registry_handler_index - ).lower() - if entry_at_index == registry_handler.address.lower(): - registry_handler_index += 1 - continue - - # set up tx calldata for proxy admin: - call_data = metaregistry.add_registry_handler.as_transaction( - registry_handler.address, sender=address_provider_admin - ).data - - # add registry handler to metaregistry: - tx = proxy_admin.execute(metaregistry, call_data, sender=account) - total_gas_used += tx.gas_used - - # check if deployment is correct: - assert ( - metaregistry.get_registry(registry_handler_index).lower() - == registry_handler.address.lower() - ) - RICH_CONSOLE.log( - f"Added registry handler [blue]{registry_handler.address} to metaregistry. " - f"Gas used: [green]{tx.gas_used}" - ) - registry_handler_index += 1 - - # add metaregistry to address provider: - max_id = address_provider.max_id() - RICH_CONSOLE.log( - f"Max id: [yellow]{max_id}, entry: [blue]{address_provider.get_address(max_id)}." - ) - metaregistry_description = "Metaregistry" - call_data = address_provider.add_new_id.as_transaction( - metaregistry.address, - metaregistry_description, - sender=address_provider_admin, - ).data - tx = proxy_admin.execute( - address_provider.address, call_data, sender=account - ) - total_gas_used += tx.gas_used - - # check if adding metaregistry was done properly: - new_max_id = address_provider.max_id() - assert new_max_id > max_id - assert ( - address_provider.get_address(new_max_id).lower() - == metaregistry.address.lower() - ) - RICH_CONSOLE.log( - f"Added Metaregistry [blue]{metaregistry.address} to AddressProvider. " - f"Gas used: [green]{tx.gas_used}" - ) - RICH_CONSOLE.log( - f"Deployment complete! Total gas used: [green]{total_gas_used}" - ) - - # test metaregistry. get a list of pools that have shibainu <> frax: - print( - metaregistry.find_pools_for_coins( - "0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE", - "0x853d955aCEf822Db058eb8505911ED77F175b99e", - ) - ) +import sys + +import click +from rich.console import Console as RichConsole + +from tests.utils import ZERO_ADDRESS, get_deployed_contract + +RICH_CONSOLE = RichConsole(file=sys.stdout) + +ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383" +BASE_POOLS = { + "tripool": { + "pool": "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", + "lp_token": "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", + "num_coins": 3, + "is_legacy": False, + "is_lending": False, + "is_v2": False, + }, + "fraxusdc": { + "pool": "0xdcef968d416a41cdac0ed8702fac8128a64241a2", + "lp_token": "0x3175df0976dfa876431c2e9ee6bc45b65d3473cc", + "num_coins": 2, + "is_legacy": False, + "is_lending": False, + "is_v2": False, + }, + "sbtc": { + "pool": "0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714", + "lp_token": "0x075b1bb99792c9E1041bA13afEf80C91a1e70fB3", + "num_coins": 3, + "is_legacy": True, + "is_lending": False, + "is_v2": False, + }, +} +CRYPTO_REGISTRY_POOLS = { + "tricrypto2": { + "pool": "0xD51a44d3FaE010294C616388b506AcdA1bfAAE46", + "lp_token": "0xc4AD29ba4B3c580e6D59105FFf484999997675Ff", + "gauge": "0xDeFd8FdD20e0f34115C7018CCfb655796F6B2168", + "zap": "0x3993d34e7e99Abf6B6f367309975d1360222D446", + "num_coins": 3, + "name": "tricrypto2", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + }, + "eurt3crv": { + "pool": "0x9838eccc42659fa8aa7daf2ad134b53984c9427b", + "lp_token": "0x3b6831c0077a1e44ed0a21841c3bc4dc11bce833", + "gauge": "0x4Fd86Ce7Ecea88F7E0aA78DC12625996Fb3a04bC", + "zap": "0x5D0F47B32fDd343BfA74cE221808e2abE4A53827", + "num_coins": 2, + "name": "eurtusd", + "base_pool": BASE_POOLS["tripool"]["pool"], + "has_positive_rebasing_tokens": False, + }, + "eursusdc": { + "pool": "0x98a7F18d4E56Cfe84E3D081B40001B3d5bD3eB8B", + "lp_token": "0x3D229E1B4faab62F621eF2F6A610961f7BD7b23B", + "gauge": "0x65CA7Dc5CB661fC58De57B1E1aF404649a27AD35", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "eursusd", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + }, + "crveth": { + "pool": "0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511", + "lp_token": "0xEd4064f376cB8d68F770FB1Ff088a3d0F3FF5c4d", + "gauge": "0x1cEBdB0856dd985fAe9b8fEa2262469360B8a3a6", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "crveth", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + }, + "cvxeth": { + "pool": "0xB576491F1E6e5E62f1d8F26062Ee822B40B0E0d4", + "lp_token": "0x3A283D9c08E8b55966afb64C515f5143cf907611", + "gauge": "0x7E1444BA99dcdFfE8fBdb42C02F0005D14f13BE1", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "cvxeth", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + }, + "xaut3crv": { + "pool": "0xAdCFcf9894335dC340f6Cd182aFA45999F45Fc44", + "lp_token": "0x8484673cA7BfF40F82B041916881aeA15ee84834", + "gauge": "0x1B3E14157ED33F60668f2103bCd5Db39a1573E5B", + "zap": "0xc5FA220347375ac4f91f9E4A4AAb362F22801504", + "num_coins": 2, + "name": "xaut3crv", + "base_pool": BASE_POOLS["tripool"]["pool"], + "has_positive_rebasing_tokens": False, + }, + "spelleth": { + "pool": "0x98638FAcf9a3865cd033F36548713183f6996122", + "lp_token": "0x8282BD15dcA2EA2bDf24163E8f2781B30C43A2ef", + "gauge": "0x08380a4999Be1a958E2abbA07968d703C7A3027C", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "spelleth", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + }, + "teth": { + "pool": "0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC", + "lp_token": "0xCb08717451aaE9EF950a2524E33B6DCaBA60147B", + "gauge": "0x6070fBD4E608ee5391189E7205d70cc4A274c017", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "teth", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + }, + "eurocusd": { + "pool": "0xE84f5b1582BA325fDf9cE6B0c1F087ccfC924e54", + "lp_token": "0x70fc957eb90e37af82acdbd12675699797745f68", + "gauge": "0x4329c8F09725c0e3b6884C1daB1771bcE17934F9", + "zap": "0xd446a98f88e1d053d1f64986e3ed083bb1ab7e5a", + "num_coins": 2, + "name": "eurocusd", + "base_pool": BASE_POOLS["tripool"]["pool"], + "has_positive_rebasing_tokens": False, + }, +} + + +@click.group(short_help="Deploy the project") +def cli(): + pass + + +@cli.command(cls=NetworkBoundCommand) +@network_option() +@account_option() +def main(network: str, account: str): + # admin only: only admin of ADDRESSPROVIDER's proxy admin can do the following: + address_provider = get_deployed_contract( + "AddressProvider", ADDRESS_PROVIDER + ) + address_provider_admin = address_provider.admin() + proxy_admin = get_deployed_contract("ProxyAdmin", address_provider_admin) + + if network == "ethereum:mainnet-fork": + RICH_CONSOLE.log("Simulation mode.") + account = accounts[proxy_admin.admins(1)] + + # deployed contracts: + base_pool_registry = get_deployed_contract( + "BasePoolRegistry", "0xDE3eAD9B2145bBA2EB74007e58ED07308716B725" + ) + crypto_registry = get_deployed_contract( + "CryptoRegistryV1", "0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0" + ) + stable_registry_handler = get_deployed_contract( + "StableRegistryHandler", "0x46a8a9CF4Fc8e99EC3A14558ACABC1D93A27de68" + ) + stable_factory_handler = get_deployed_contract( + "StableFactoryHandler", "0x127db66E7F0b16470Bec194d0f496F9Fa065d0A9" + ) + crypto_registry_handler = get_deployed_contract( + "CryptoRegistryHandler", "0x5f493fEE8D67D3AE3bA730827B34126CFcA0ae94" + ) + crypto_factory_handler = get_deployed_contract( + "CryptoFactoryHandler", "0xC4F389020002396143B863F6325aA6ae481D19CE" + ) + metaregistry = get_deployed_contract( + "MetaRegistry", "0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC" + ) + registry_handlers = [ + stable_registry_handler, + stable_factory_handler, + crypto_registry_handler, + crypto_factory_handler, + ] + + # set up the metaregistry: + + total_gas_used = ( + 0 # gets total gas used for setting up. should be about 5mil gas. + ) + + # populate base pool registry: + base_pool_index = 0 + for _, data in BASE_POOLS.items(): + # check if base pool already exists in the registry: + entry_at_index = base_pool_registry.base_pool_list( + base_pool_index + ).lower() + if entry_at_index == data["pool"].lower(): + base_pool_index += 1 + continue + + # set up tx calldata for proxy admin: + call_data = base_pool_registry.add_base_pool.as_transaction( + data["pool"], + data["lp_token"], + data["num_coins"], + data["is_legacy"], + data["is_lending"], + data["is_v2"], + sender=address_provider_admin, + ).data + + # add base_pool to registry: + tx = proxy_admin.execute(base_pool_registry, call_data, sender=account) + total_gas_used += tx.gas_used + + # check if deployment is correct: + assert ( + base_pool_registry.base_pool_list(base_pool_index).lower() + == data["pool"].lower() + ) + RICH_CONSOLE.log( + f"Added base pool [blue]{data['pool']} to base pool registry. " + f"Gas used: [green]{tx.gas_used}" + ) + base_pool_index += 1 + + # populate crypto registry: + crypto_pool_index = 0 + for _, pool in CRYPTO_REGISTRY_POOLS.items(): + # check if base pool already exists in the registry: + entry_at_index = crypto_registry.pool_list(crypto_pool_index).lower() + if entry_at_index == pool["pool"].lower(): + crypto_pool_index += 1 + continue + + # set up tx calldata for proxy admin: + call_data = crypto_registry.add_pool.as_transaction( + pool["pool"], + pool["lp_token"], + pool["gauge"], + pool["zap"], + pool["num_coins"], + pool["name"], + pool["base_pool"], + pool["has_positive_rebasing_tokens"], + sender=address_provider_admin, + ).data + + # add pool to registry: + tx = proxy_admin.execute(crypto_registry, call_data, sender=account) + total_gas_used += tx.gas_used + + # check if deployment is correct: + assert ( + crypto_registry.pool_list(crypto_pool_index).lower() + == pool["pool"].lower() + ) + RICH_CONSOLE.log( + f"Added pool [blue]{pool['pool']} to crypto registry. " + f"Gas used: [green]{tx.gas_used}" + ) + crypto_pool_index += 1 + + # populate metaregistry: + registry_handler_index = 0 + for registry_handler in registry_handlers: + # check if base pool already exists in the registry: + entry_at_index = metaregistry.get_registry( + registry_handler_index + ).lower() + if entry_at_index == registry_handler.address.lower(): + registry_handler_index += 1 + continue + + # set up tx calldata for proxy admin: + call_data = metaregistry.add_registry_handler.as_transaction( + registry_handler.address, sender=address_provider_admin + ).data + + # add registry handler to metaregistry: + tx = proxy_admin.execute(metaregistry, call_data, sender=account) + total_gas_used += tx.gas_used + + # check if deployment is correct: + assert ( + metaregistry.get_registry(registry_handler_index).lower() + == registry_handler.address.lower() + ) + RICH_CONSOLE.log( + f"Added registry handler [blue]{registry_handler.address} to metaregistry. " + f"Gas used: [green]{tx.gas_used}" + ) + registry_handler_index += 1 + + # add metaregistry to address provider: + max_id = address_provider.max_id() + RICH_CONSOLE.log( + f"Max id: [yellow]{max_id}, entry: [blue]{address_provider.get_address(max_id)}." + ) + metaregistry_description = "Metaregistry" + call_data = address_provider.add_new_id.as_transaction( + metaregistry.address, + metaregistry_description, + sender=address_provider_admin, + ).data + tx = proxy_admin.execute( + address_provider.address, call_data, sender=account + ) + total_gas_used += tx.gas_used + + # check if adding metaregistry was done properly: + new_max_id = address_provider.max_id() + assert new_max_id > max_id + assert ( + address_provider.get_address(new_max_id).lower() + == metaregistry.address.lower() + ) + RICH_CONSOLE.log( + f"Added Metaregistry [blue]{metaregistry.address} to AddressProvider. " + f"Gas used: [green]{tx.gas_used}" + ) + RICH_CONSOLE.log( + f"Deployment complete! Total gas used: [green]{total_gas_used}" + ) + + # test metaregistry. get a list of pools that have shibainu <> frax: + print( + metaregistry.find_pools_for_coins( + "0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE", + "0x853d955aCEf822Db058eb8505911ED77F175b99e", + ) + ) diff --git a/setup.cfg b/setup.cfg index 5fe5328..676a557 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,10 +1,10 @@ -[flake8] -max-line-length = 100 -ignore = E203,W503 - -[tool:isort] -force_grid_wrap = 0 -include_trailing_comma = True -line_length = 100 -multi_line_output = 3 -use_parentheses = True +[flake8] +max-line-length = 100 +ignore = E203,W503 + +[tool:isort] +force_grid_wrap = 0 +include_trailing_comma = True +line_length = 100 +multi_line_output = 3 +use_parentheses = True diff --git a/tests/conftest.py b/tests/conftest.py index bd9aa58..ade7ee8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,88 +1,98 @@ -from os import environ - -import boa -import pytest - -from tests.utils import get_contract_pools - -pytest_plugins = [ - "fixtures.accounts", - "fixtures.constants", - "fixtures.contracts", - "fixtures.deployments", - "fixtures.functions", -] - -CRYPTO_REGISTRY_POOLS = None -CRYPTO_FACTORY_POOLS = None -STABLE_REGISTRY_POOLS = None -STABLE_FACTORY_POOLS = None -ALL_POOLS = None - - -def pytest_sessionstart(): - """Set up pools into global variables at session start""" - global CRYPTO_REGISTRY_POOLS - global CRYPTO_FACTORY_POOLS - global STABLE_FACTORY_POOLS - global STABLE_REGISTRY_POOLS - global ALL_POOLS - - # connect to the network. TODO: use Drpc-Key header instead of GET param - boa.env.fork(f"https://lb.drpc.org/ogrpc?network=ethereum&dkey={environ['DRPC_KEY']}") - - # store instance of registries globally, so we don't have to recreate multiple times when generating tests. - # TODO: Can we move these to fixtures? - STABLE_REGISTRY_POOLS = get_contract_pools("StableRegistry", "0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5") - STABLE_FACTORY_POOLS = get_contract_pools("StableFactory", "0xB9fC157394Af804a3578134A6585C0dc9cc990d4") - CRYPTO_REGISTRY_POOLS = get_contract_pools("CryptoRegistry", "0x8F942C20D02bEfc377D41445793068908E2250D0") - CRYPTO_FACTORY_POOLS = get_contract_pools("CryptoFactory", "0xF18056Bbd320E96A48e3Fbf8bC061322531aac99") - - ALL_POOLS = ( - STABLE_REGISTRY_POOLS - + STABLE_FACTORY_POOLS - + CRYPTO_REGISTRY_POOLS - + CRYPTO_FACTORY_POOLS - ) - - -def pytest_generate_tests(metafunc): - if "stable_registry_pool" in metafunc.fixturenames: - metafunc.parametrize("stable_registry_pool", STABLE_REGISTRY_POOLS) - - if "stable_factory_pool" in metafunc.fixturenames: - metafunc.parametrize("stable_factory_pool", STABLE_FACTORY_POOLS) - - if "crypto_registry_pool" in metafunc.fixturenames: - metafunc.parametrize("crypto_registry_pool", CRYPTO_REGISTRY_POOLS) - - if "crypto_factory_pool" in metafunc.fixturenames: - metafunc.parametrize("crypto_factory_pool", CRYPTO_FACTORY_POOLS) - - if "pool" in metafunc.fixturenames: - metafunc.parametrize("pool", ALL_POOLS) - - -@pytest.fixture(scope="session") -def stable_registry_pool(): - yield STABLE_REGISTRY_POOLS - - -@pytest.fixture(scope="session") -def stable_factory_pool(): - yield STABLE_FACTORY_POOLS - - -@pytest.fixture(scope="session") -def crypto_registry_pool(): - yield CRYPTO_REGISTRY_POOLS - - -@pytest.fixture(scope="session") -def crypto_factory_pool(): - yield CRYPTO_FACTORY_POOLS - - -@pytest.fixture(scope="session") -def pool(): - yield ALL_POOLS +from os import environ + +import boa +import pytest + +from tests.utils import get_contract_pools + +pytest_plugins = [ + "fixtures.accounts", + "fixtures.constants", + "fixtures.contracts", + "fixtures.deployments", + "fixtures.functions", +] + +CRYPTO_REGISTRY_POOLS = None +CRYPTO_FACTORY_POOLS = None +STABLE_REGISTRY_POOLS = None +STABLE_FACTORY_POOLS = None +ALL_POOLS = None + + +def pytest_sessionstart(): + """Set up pools into global variables at session start""" + global CRYPTO_REGISTRY_POOLS + global CRYPTO_FACTORY_POOLS + global STABLE_FACTORY_POOLS + global STABLE_REGISTRY_POOLS + global ALL_POOLS + + # connect to the network. TODO: use Drpc-Key header instead of GET param + boa.env.fork( + f"https://lb.drpc.org/ogrpc?network=ethereum&dkey={environ['DRPC_KEY']}" + ) + + # store instance of registries globally, so we don't have to recreate multiple times when generating tests. + # TODO: Can we move these to fixtures? + STABLE_REGISTRY_POOLS = get_contract_pools( + "StableRegistry", "0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5" + ) + STABLE_FACTORY_POOLS = get_contract_pools( + "StableFactory", "0xB9fC157394Af804a3578134A6585C0dc9cc990d4" + ) + CRYPTO_REGISTRY_POOLS = get_contract_pools( + "CryptoRegistry", "0x8F942C20D02bEfc377D41445793068908E2250D0" + ) + CRYPTO_FACTORY_POOLS = get_contract_pools( + "CryptoFactory", "0xF18056Bbd320E96A48e3Fbf8bC061322531aac99" + ) + + ALL_POOLS = ( + STABLE_REGISTRY_POOLS + + STABLE_FACTORY_POOLS + + CRYPTO_REGISTRY_POOLS + + CRYPTO_FACTORY_POOLS + ) + + +def pytest_generate_tests(metafunc): + if "stable_registry_pool" in metafunc.fixturenames: + metafunc.parametrize("stable_registry_pool", STABLE_REGISTRY_POOLS) + + if "stable_factory_pool" in metafunc.fixturenames: + metafunc.parametrize("stable_factory_pool", STABLE_FACTORY_POOLS) + + if "crypto_registry_pool" in metafunc.fixturenames: + metafunc.parametrize("crypto_registry_pool", CRYPTO_REGISTRY_POOLS) + + if "crypto_factory_pool" in metafunc.fixturenames: + metafunc.parametrize("crypto_factory_pool", CRYPTO_FACTORY_POOLS) + + if "pool" in metafunc.fixturenames: + metafunc.parametrize("pool", ALL_POOLS) + + +@pytest.fixture(scope="session") +def stable_registry_pool(): + yield STABLE_REGISTRY_POOLS + + +@pytest.fixture(scope="session") +def stable_factory_pool(): + yield STABLE_FACTORY_POOLS + + +@pytest.fixture(scope="session") +def crypto_registry_pool(): + yield CRYPTO_REGISTRY_POOLS + + +@pytest.fixture(scope="session") +def crypto_factory_pool(): + yield CRYPTO_FACTORY_POOLS + + +@pytest.fixture(scope="session") +def pool(): + yield ALL_POOLS diff --git a/tests/fixtures/accounts.py b/tests/fixtures/accounts.py index 2119c8e..860bdcc 100644 --- a/tests/fixtures/accounts.py +++ b/tests/fixtures/accounts.py @@ -1,47 +1,54 @@ -import pytest -from eth_account import Account -from eth_account.hdaccount import HDPath -from eth_account.hdaccount.mnemonic import Mnemonic -from eth_account.signers.local import LocalAccount - -from tests.utils import get_deployed_contract - - -@pytest.fixture(scope="session") -def seed() -> bytes: - return Mnemonic.to_seed("test") - -@pytest.fixture(scope="session") -def accounts(seed) -> list[LocalAccount]: - """ - Generate 10 dev accounts from a seed. - Based on ape's `generate_test_accounts` method: - https://github.com/ApeWorX/ape/blob/9d4b66786/src/ape/utils/testing.py#L28 - TODO: replace by boa.env.generate_address()? - """ - def generate_account(index: int, hd_path_format="m/44'/60'/0'/{}") -> LocalAccount: - hd_path = HDPath(hd_path_format.format(index)) - private_key = f"0x{hd_path.derive(seed).hex()}" - return Account.from_key(private_key) - - return [generate_account(index) for index in range(10)] - -@pytest.fixture(scope="session") -def alice_address(accounts): - return accounts[0].address - - -@pytest.fixture(scope="session") -def unauthorised_address(accounts): - return accounts[1].address - - -@pytest.fixture(scope="session") -def random_address(accounts): - return accounts[2].address - - -@pytest.fixture(scope="module") -def owner(accounts): - address_provider = get_deployed_contract('AddressProvider', "0x0000000022D53366457F9d5E68Ec105046FC4383") - return address_provider.admin() +import pytest +from eth_account import Account +from eth_account.hdaccount import HDPath +from eth_account.hdaccount.mnemonic import Mnemonic +from eth_account.signers.local import LocalAccount + +from tests.utils import get_deployed_contract + + +@pytest.fixture(scope="session") +def seed() -> bytes: + return Mnemonic.to_seed("test") + + +@pytest.fixture(scope="session") +def accounts(seed) -> list[LocalAccount]: + """ + Generate 10 dev accounts from a seed. + Based on ape's `generate_test_accounts` method: + https://github.com/ApeWorX/ape/blob/9d4b66786/src/ape/utils/testing.py#L28 + TODO: replace by boa.env.generate_address()? + """ + + def generate_account( + index: int, hd_path_format="m/44'/60'/0'/{}" + ) -> LocalAccount: + hd_path = HDPath(hd_path_format.format(index)) + private_key = f"0x{hd_path.derive(seed).hex()}" + return Account.from_key(private_key) + + return [generate_account(index) for index in range(10)] + + +@pytest.fixture(scope="session") +def alice_address(accounts): + return accounts[0].address + + +@pytest.fixture(scope="session") +def unauthorised_address(accounts): + return accounts[1].address + + +@pytest.fixture(scope="session") +def random_address(accounts): + return accounts[2].address + + +@pytest.fixture(scope="module") +def owner(accounts): + address_provider = get_deployed_contract( + "AddressProvider", "0x0000000022D53366457F9d5E68Ec105046FC4383" + ) + return address_provider.admin() diff --git a/tests/fixtures/constants.py b/tests/fixtures/constants.py index 5001718..50230a8 100644 --- a/tests/fixtures/constants.py +++ b/tests/fixtures/constants.py @@ -1,190 +1,187 @@ -import pytest - - -ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" - - -@pytest.fixture(scope="module") -def base_pools(): - - base_pool_data = {} - base_pool_data["tripool"] = { - "pool": "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", - "lp_token": "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", - "num_coins": 3, - "is_legacy": False, - "is_lending": False, - "is_v2": False, - } - - base_pool_data["fraxusdc"] = { - "pool": "0xdcef968d416a41cdac0ed8702fac8128a64241a2", - "lp_token": "0x3175df0976dfa876431c2e9ee6bc45b65d3473cc", - "num_coins": 2, - "is_legacy": False, - "is_lending": False, - "is_v2": False, - } - - base_pool_data["sbtc"] = { - "pool": "0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714", - "lp_token": "0x075b1bb99792c9E1041bA13afEf80C91a1e70fB3", - "num_coins": 3, - "is_legacy": True, - "is_lending": False, - "is_v2": False, - } - - return base_pool_data - - -@pytest.fixture(scope="module") -def crypto_registry_pools(base_pools): - - pool_data = {} - pool_data["tricrypto2"] = { - "pool": "0xD51a44d3FaE010294C616388b506AcdA1bfAAE46", - "lp_token": "0xc4AD29ba4B3c580e6D59105FFf484999997675Ff", - "gauge": "0xDeFd8FdD20e0f34115C7018CCfb655796F6B2168", - "zap": "0x3993d34e7e99Abf6B6f367309975d1360222D446", - "num_coins": 3, - "name": "tricrypto2", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - } - - pool_data["eurt3crv"] = { - "pool": "0x9838eccc42659fa8aa7daf2ad134b53984c9427b", - "lp_token": "0x3b6831c0077a1e44ed0a21841c3bc4dc11bce833", - "gauge": "0x4Fd86Ce7Ecea88F7E0aA78DC12625996Fb3a04bC", - "zap": "0x5D0F47B32fDd343BfA74cE221808e2abE4A53827", - "num_coins": 2, - "name": "eurtusd", - "base_pool": base_pools["tripool"]["pool"], - "has_positive_rebasing_tokens": False, - } - - pool_data["eursusdc"] = { - "pool": "0x98a7F18d4E56Cfe84E3D081B40001B3d5bD3eB8B", - "lp_token": "0x3D229E1B4faab62F621eF2F6A610961f7BD7b23B", - "gauge": "0x65CA7Dc5CB661fC58De57B1E1aF404649a27AD35", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "eursusd", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - } - - pool_data["crveth"] = { - "pool": "0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511", - "lp_token": "0xEd4064f376cB8d68F770FB1Ff088a3d0F3FF5c4d", - "gauge": "0x1cEBdB0856dd985fAe9b8fEa2262469360B8a3a6", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "crveth", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - } - - pool_data["cvxeth"] = { - "pool": "0xB576491F1E6e5E62f1d8F26062Ee822B40B0E0d4", - "lp_token": "0x3A283D9c08E8b55966afb64C515f5143cf907611", - "gauge": "0x7E1444BA99dcdFfE8fBdb42C02F0005D14f13BE1", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "cvxeth", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - } - - pool_data["xaut3crv"] = { - "pool": "0xAdCFcf9894335dC340f6Cd182aFA45999F45Fc44", - "lp_token": "0x8484673cA7BfF40F82B041916881aeA15ee84834", - "gauge": "0x1B3E14157ED33F60668f2103bCd5Db39a1573E5B", - "zap": "0xc5FA220347375ac4f91f9E4A4AAb362F22801504", - "num_coins": 2, - "name": "xaut3crv", - "base_pool": base_pools["tripool"]["pool"], - "has_positive_rebasing_tokens": False, - } - - pool_data["spelleth"] = { - "pool": "0x98638FAcf9a3865cd033F36548713183f6996122", - "lp_token": "0x8282BD15dcA2EA2bDf24163E8f2781B30C43A2ef", - "gauge": "0x08380a4999Be1a958E2abbA07968d703C7A3027C", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "spelleth", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - } - - pool_data["teth"] = { - "pool": "0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC", - "lp_token": "0xCb08717451aaE9EF950a2524E33B6DCaBA60147B", - "gauge": "0x6070fBD4E608ee5391189E7205d70cc4A274c017", - "zap": ZERO_ADDRESS, - "num_coins": 2, - "name": "teth", - "base_pool": ZERO_ADDRESS, - "has_positive_rebasing_tokens": False, - } - - pool_data["eurocusd"] = { - "pool": "0xE84f5b1582BA325fDf9cE6B0c1F087ccfC924e54", - "lp_token": "0x70fc957eb90e37af82acdbd12675699797745f68", - "gauge": "0x4329c8F09725c0e3b6884C1daB1771bcE17934F9", - "zap": "0xd446a98f88e1d053d1f64986e3ed083bb1ab7e5a", - "num_coins": 2, - "name": "eurocusd", - "base_pool": base_pools["tripool"]["pool"], - "has_positive_rebasing_tokens": False, - } - - return pool_data - - -@pytest.fixture(scope="module") -def max_coins(): - return 8 - - -# ---- contract addresses ---- - - -@pytest.fixture(scope="module") -def crypto_pool_implementation(): - return "0xa85461afc2deec01bda23b5cd267d51f765fba10" - - -@pytest.fixture(scope="module") -def crypto_token_implementation(): - return "0xc08550a4cc5333f40e593ecc4c4724808085d304" - - -@pytest.fixture(scope="module") -def admin_fee_receiver(): - return "0xeCb456EA5365865EbAb8a2661B0c503410e9B347" - - -@pytest.fixture(scope="module") -def tokens(): - return { - "eth": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "weth": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", - "dai": "0x6B175474E89094C44Da98b954EedeAC495271d0F", - "usdc": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - "usdt": "0xdac17f958d2ee523a2206206994597c13d831ec7", - "renbtc": "0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D", - "wbtc": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", - "sbtc": "0xfE18be6b3Bd88A2D2A7f928d00292E7a9963CfC6", - "eurt": "0xC581b735A1688071A1746c968e0798D642EDE491", - } - - -@pytest.fixture(scope="module") -def lp_tokens(): - return { - "cvxFXSFXS-f": "0xF3A43307DcAFa93275993862Aae628fCB50dC768", - "bveCVX-CVX-f": "0x04c90C198b2eFF55716079bc06d7CCc4aa4d7512", - } +import pytest + +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" + + +@pytest.fixture(scope="module") +def base_pools(): + base_pool_data = {} + base_pool_data["tripool"] = { + "pool": "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", + "lp_token": "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", + "num_coins": 3, + "is_legacy": False, + "is_lending": False, + "is_v2": False, + } + + base_pool_data["fraxusdc"] = { + "pool": "0xdcef968d416a41cdac0ed8702fac8128a64241a2", + "lp_token": "0x3175df0976dfa876431c2e9ee6bc45b65d3473cc", + "num_coins": 2, + "is_legacy": False, + "is_lending": False, + "is_v2": False, + } + + base_pool_data["sbtc"] = { + "pool": "0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714", + "lp_token": "0x075b1bb99792c9E1041bA13afEf80C91a1e70fB3", + "num_coins": 3, + "is_legacy": True, + "is_lending": False, + "is_v2": False, + } + + return base_pool_data + + +@pytest.fixture(scope="module") +def crypto_registry_pools(base_pools): + pool_data = {} + pool_data["tricrypto2"] = { + "pool": "0xD51a44d3FaE010294C616388b506AcdA1bfAAE46", + "lp_token": "0xc4AD29ba4B3c580e6D59105FFf484999997675Ff", + "gauge": "0xDeFd8FdD20e0f34115C7018CCfb655796F6B2168", + "zap": "0x3993d34e7e99Abf6B6f367309975d1360222D446", + "num_coins": 3, + "name": "tricrypto2", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + } + + pool_data["eurt3crv"] = { + "pool": "0x9838eccc42659fa8aa7daf2ad134b53984c9427b", + "lp_token": "0x3b6831c0077a1e44ed0a21841c3bc4dc11bce833", + "gauge": "0x4Fd86Ce7Ecea88F7E0aA78DC12625996Fb3a04bC", + "zap": "0x5D0F47B32fDd343BfA74cE221808e2abE4A53827", + "num_coins": 2, + "name": "eurtusd", + "base_pool": base_pools["tripool"]["pool"], + "has_positive_rebasing_tokens": False, + } + + pool_data["eursusdc"] = { + "pool": "0x98a7F18d4E56Cfe84E3D081B40001B3d5bD3eB8B", + "lp_token": "0x3D229E1B4faab62F621eF2F6A610961f7BD7b23B", + "gauge": "0x65CA7Dc5CB661fC58De57B1E1aF404649a27AD35", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "eursusd", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + } + + pool_data["crveth"] = { + "pool": "0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511", + "lp_token": "0xEd4064f376cB8d68F770FB1Ff088a3d0F3FF5c4d", + "gauge": "0x1cEBdB0856dd985fAe9b8fEa2262469360B8a3a6", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "crveth", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + } + + pool_data["cvxeth"] = { + "pool": "0xB576491F1E6e5E62f1d8F26062Ee822B40B0E0d4", + "lp_token": "0x3A283D9c08E8b55966afb64C515f5143cf907611", + "gauge": "0x7E1444BA99dcdFfE8fBdb42C02F0005D14f13BE1", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "cvxeth", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + } + + pool_data["xaut3crv"] = { + "pool": "0xAdCFcf9894335dC340f6Cd182aFA45999F45Fc44", + "lp_token": "0x8484673cA7BfF40F82B041916881aeA15ee84834", + "gauge": "0x1B3E14157ED33F60668f2103bCd5Db39a1573E5B", + "zap": "0xc5FA220347375ac4f91f9E4A4AAb362F22801504", + "num_coins": 2, + "name": "xaut3crv", + "base_pool": base_pools["tripool"]["pool"], + "has_positive_rebasing_tokens": False, + } + + pool_data["spelleth"] = { + "pool": "0x98638FAcf9a3865cd033F36548713183f6996122", + "lp_token": "0x8282BD15dcA2EA2bDf24163E8f2781B30C43A2ef", + "gauge": "0x08380a4999Be1a958E2abbA07968d703C7A3027C", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "spelleth", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + } + + pool_data["teth"] = { + "pool": "0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC", + "lp_token": "0xCb08717451aaE9EF950a2524E33B6DCaBA60147B", + "gauge": "0x6070fBD4E608ee5391189E7205d70cc4A274c017", + "zap": ZERO_ADDRESS, + "num_coins": 2, + "name": "teth", + "base_pool": ZERO_ADDRESS, + "has_positive_rebasing_tokens": False, + } + + pool_data["eurocusd"] = { + "pool": "0xE84f5b1582BA325fDf9cE6B0c1F087ccfC924e54", + "lp_token": "0x70fc957eb90e37af82acdbd12675699797745f68", + "gauge": "0x4329c8F09725c0e3b6884C1daB1771bcE17934F9", + "zap": "0xd446a98f88e1d053d1f64986e3ed083bb1ab7e5a", + "num_coins": 2, + "name": "eurocusd", + "base_pool": base_pools["tripool"]["pool"], + "has_positive_rebasing_tokens": False, + } + + return pool_data + + +@pytest.fixture(scope="module") +def max_coins(): + return 8 + + +# ---- contract addresses ---- + + +@pytest.fixture(scope="module") +def crypto_pool_implementation(): + return "0xa85461afc2deec01bda23b5cd267d51f765fba10" + + +@pytest.fixture(scope="module") +def crypto_token_implementation(): + return "0xc08550a4cc5333f40e593ecc4c4724808085d304" + + +@pytest.fixture(scope="module") +def admin_fee_receiver(): + return "0xeCb456EA5365865EbAb8a2661B0c503410e9B347" + + +@pytest.fixture(scope="module") +def tokens(): + return { + "eth": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + "weth": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "dai": "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "usdc": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "usdt": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "renbtc": "0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D", + "wbtc": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + "sbtc": "0xfE18be6b3Bd88A2D2A7f928d00292E7a9963CfC6", + "eurt": "0xC581b735A1688071A1746c968e0798D642EDE491", + } + + +@pytest.fixture(scope="module") +def lp_tokens(): + return { + "cvxFXSFXS-f": "0xF3A43307DcAFa93275993862Aae628fCB50dC768", + "bveCVX-CVX-f": "0x04c90C198b2eFF55716079bc06d7CCc4aa4d7512", + } diff --git a/tests/fixtures/contracts.py b/tests/fixtures/contracts.py index b7192f2..be3c22c 100644 --- a/tests/fixtures/contracts.py +++ b/tests/fixtures/contracts.py @@ -1,9 +1,9 @@ -import pytest - - -@pytest.fixture(scope="module") -def address_provider_contract(accounts): - address_provider = get_deployed_contract('AddressProvider', - "0x0000000022D53366457F9d5E68Ec105046FC4383" - ) - return accounts[address_provider.admin()] +import pytest + + +@pytest.fixture(scope="module") +def address_provider_contract(accounts): + address_provider = get_deployed_contract( + "AddressProvider", "0x0000000022D53366457F9d5E68Ec105046FC4383" + ) + return accounts[address_provider.admin()] diff --git a/tests/fixtures/deployments.py b/tests/fixtures/deployments.py index e393835..c0efbd7 100644 --- a/tests/fixtures/deployments.py +++ b/tests/fixtures/deployments.py @@ -1,135 +1,178 @@ -import boa -import pytest -from boa.vyper.contract import VyperContract - -from tests.utils import get_deployed_contract, deploy_contract - -ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383" - - -@pytest.fixture(scope="module", autouse=True) -def gauge_controller() -> VyperContract: - return get_deployed_contract('GaugeController', "0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB") - - -@pytest.fixture(scope="module", autouse=True) -def stable_registry() -> VyperContract: - return get_deployed_contract('StableRegistry', "0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5") - - -@pytest.fixture(scope="module", autouse=True) -def stable_factory() -> VyperContract: - return get_deployed_contract('StableFactory', "0xB9fC157394Af804a3578134A6585C0dc9cc990d4") - - -@pytest.fixture(scope="module", autouse=True) -def crypto_factory() -> VyperContract: - return get_deployed_contract('CryptoFactory', "0xF18056Bbd320E96A48e3Fbf8bC061322531aac99") - - -@pytest.fixture(scope="module", autouse=True) -def base_pool_registry(alice_address): - return deploy_contract("BasePoolRegistry", sender=alice_address, directory="registries") - - -@pytest.fixture(scope="module", autouse=True) -def populated_base_pool_registry(base_pool_registry, owner, base_pools): - boa.env.eoa = owner - for data in base_pools.values(): - base_pool_registry.add_base_pool( - data["pool"], - data["lp_token"], - data["num_coins"], - data["is_legacy"], - data["is_lending"], - data["is_v2"], - ) - return base_pool_registry - - -@pytest.fixture(scope="module", autouse=True) -def crypto_registry( - populated_base_pool_registry, owner, crypto_registry_pools -): - crypto_registry = deploy_contract("CryptoRegistryV1", ADDRESS_PROVIDER, populated_base_pool_registry, - directory="registries", sender=owner) - - boa.env.eoa = owner - for _, pool in crypto_registry_pools.items(): - crypto_registry.add_pool( - pool["pool"], - pool["lp_token"], - pool["gauge"], - pool["zap"], - pool["num_coins"], - pool["name"], - pool["base_pool"], - pool["has_positive_rebasing_tokens"], - ) - - return crypto_registry - - -@pytest.fixture(scope="module", autouse=True) -def address_provider(crypto_registry, owner): - contract = get_deployed_contract('AddressProvider', ADDRESS_PROVIDER) - contract.set_address(5, crypto_registry, sender=owner) - return contract - - -@pytest.fixture(scope="module", autouse=True) -def metaregistry(address_provider, owner): - return deploy_contract("MetaRegistry", address_provider, sender=owner) - - -@pytest.fixture(scope="module", autouse=True) -def stable_registry_handler(stable_registry, owner): - return deploy_contract( - "StableRegistryHandler", stable_registry.address, sender=owner, directory="registry_handlers", - ) - - -@pytest.fixture(scope="module", autouse=True) -def stable_factory_handler(populated_base_pool_registry, stable_factory, owner): - return deploy_contract( - "StableFactoryHandler", stable_factory.address, populated_base_pool_registry.address, - sender=owner, directory="registry_handlers", - ) - - -@pytest.fixture(scope="module", autouse=True) -def crypto_registry_handler(owner, crypto_registry): - return deploy_contract( - "CryptoRegistryHandler", crypto_registry.address, sender=owner, directory="registry_handlers", - ) - - -@pytest.fixture(scope="module", autouse=True) -def crypto_factory_handler(populated_base_pool_registry, crypto_factory, owner): - return deploy_contract( - "CryptoFactoryHandler", crypto_factory.address, populated_base_pool_registry.address, - sender=owner, directory="registry_handlers", - ) - - -@pytest.fixture(scope="module") -def registries(stable_registry, stable_factory, crypto_registry, crypto_factory): - return [stable_registry, stable_factory, crypto_registry, crypto_factory] - - -@pytest.fixture(scope="module") -def handlers(stable_registry_handler, stable_factory_handler, crypto_registry_handler, crypto_factory_handler): - return [stable_registry_handler, stable_factory_handler, crypto_registry_handler, crypto_factory_handler] - - -# TODO: Get rid of the autouse, it might make some tests slower than needed -@pytest.fixture(scope="module", autouse=True) -def populated_metaregistry(metaregistry, handlers, owner): - for handler in handlers: - metaregistry.add_registry_handler(handler.address, sender=owner) - return metaregistry - - -@pytest.fixture(scope="module") -def stable_registry_handler_index(): - return 0 +import boa +import pytest +from boa.vyper.contract import VyperContract + +from tests.utils import deploy_contract, get_deployed_contract + +ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383" + + +@pytest.fixture(scope="module", autouse=True) +def gauge_controller() -> VyperContract: + return get_deployed_contract( + "GaugeController", "0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB" + ) + + +@pytest.fixture(scope="module", autouse=True) +def stable_registry() -> VyperContract: + return get_deployed_contract( + "StableRegistry", "0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5" + ) + + +@pytest.fixture(scope="module", autouse=True) +def stable_factory() -> VyperContract: + return get_deployed_contract( + "StableFactory", "0xB9fC157394Af804a3578134A6585C0dc9cc990d4" + ) + + +@pytest.fixture(scope="module", autouse=True) +def crypto_factory() -> VyperContract: + return get_deployed_contract( + "CryptoFactory", "0xF18056Bbd320E96A48e3Fbf8bC061322531aac99" + ) + + +@pytest.fixture(scope="module", autouse=True) +def base_pool_registry(alice_address): + return deploy_contract( + "BasePoolRegistry", sender=alice_address, directory="registries" + ) + + +@pytest.fixture(scope="module", autouse=True) +def populated_base_pool_registry(base_pool_registry, owner, base_pools): + boa.env.eoa = owner + for data in base_pools.values(): + base_pool_registry.add_base_pool( + data["pool"], + data["lp_token"], + data["num_coins"], + data["is_legacy"], + data["is_lending"], + data["is_v2"], + ) + return base_pool_registry + + +@pytest.fixture(scope="module", autouse=True) +def crypto_registry( + populated_base_pool_registry, owner, crypto_registry_pools +): + crypto_registry = deploy_contract( + "CryptoRegistryV1", + ADDRESS_PROVIDER, + populated_base_pool_registry, + directory="registries", + sender=owner, + ) + + boa.env.eoa = owner + for _, pool in crypto_registry_pools.items(): + crypto_registry.add_pool( + pool["pool"], + pool["lp_token"], + pool["gauge"], + pool["zap"], + pool["num_coins"], + pool["name"], + pool["base_pool"], + pool["has_positive_rebasing_tokens"], + ) + + return crypto_registry + + +@pytest.fixture(scope="module", autouse=True) +def address_provider(crypto_registry, owner): + contract = get_deployed_contract("AddressProvider", ADDRESS_PROVIDER) + contract.set_address(5, crypto_registry, sender=owner) + return contract + + +@pytest.fixture(scope="module", autouse=True) +def metaregistry(address_provider, owner): + return deploy_contract("MetaRegistry", address_provider, sender=owner) + + +@pytest.fixture(scope="module", autouse=True) +def stable_registry_handler(stable_registry, owner): + return deploy_contract( + "StableRegistryHandler", + stable_registry.address, + sender=owner, + directory="registry_handlers", + ) + + +@pytest.fixture(scope="module", autouse=True) +def stable_factory_handler( + populated_base_pool_registry, stable_factory, owner +): + return deploy_contract( + "StableFactoryHandler", + stable_factory.address, + populated_base_pool_registry.address, + sender=owner, + directory="registry_handlers", + ) + + +@pytest.fixture(scope="module", autouse=True) +def crypto_registry_handler(owner, crypto_registry): + return deploy_contract( + "CryptoRegistryHandler", + crypto_registry.address, + sender=owner, + directory="registry_handlers", + ) + + +@pytest.fixture(scope="module", autouse=True) +def crypto_factory_handler( + populated_base_pool_registry, crypto_factory, owner +): + return deploy_contract( + "CryptoFactoryHandler", + crypto_factory.address, + populated_base_pool_registry.address, + sender=owner, + directory="registry_handlers", + ) + + +@pytest.fixture(scope="module") +def registries( + stable_registry, stable_factory, crypto_registry, crypto_factory +): + return [stable_registry, stable_factory, crypto_registry, crypto_factory] + + +@pytest.fixture(scope="module") +def handlers( + stable_registry_handler, + stable_factory_handler, + crypto_registry_handler, + crypto_factory_handler, +): + return [ + stable_registry_handler, + stable_factory_handler, + crypto_registry_handler, + crypto_factory_handler, + ] + + +# TODO: Get rid of the autouse, it might make some tests slower than needed +@pytest.fixture(scope="module", autouse=True) +def populated_metaregistry(metaregistry, handlers, owner): + for handler in handlers: + metaregistry.add_registry_handler(handler.address, sender=owner) + return metaregistry + + +@pytest.fixture(scope="module") +def stable_registry_handler_index(): + return 0 diff --git a/tests/fixtures/functions.py b/tests/fixtures/functions.py index 0acbddd..3236b65 100644 --- a/tests/fixtures/functions.py +++ b/tests/fixtures/functions.py @@ -1,33 +1,32 @@ -from typing import Callable - -import pytest -from boa.vyper.contract import VyperContract - -from tests.utils import get_deployed_contract - - -# ---- Factories ---- - - -@pytest.fixture(scope="module") -def curve_pool(project) -> Callable: - def _initialise(_pool: str) -> VyperContract: - return get_deployed_contract('CurvePool', _pool) - - return _initialise - - -@pytest.fixture(scope="module") -def curve_pool_v2(project) -> Callable: - def _initialise(_pool: str) -> VyperContract: - return get_deployed_contract('CurvePoolV2', _pool) - - return _initialise - - -@pytest.fixture(scope="module") -def liquidity_gauge(project) -> Callable: - def _initialise(_gauge: str) -> VyperContract: - return get_deployed_contract('LiquidityGauge', _gauge) - - return _initialise +from typing import Callable + +import pytest +from boa.vyper.contract import VyperContract + +from tests.utils import get_deployed_contract + +# ---- Factories ---- + + +@pytest.fixture(scope="module") +def curve_pool(project) -> Callable: + def _initialise(_pool: str) -> VyperContract: + return get_deployed_contract("CurvePool", _pool) + + return _initialise + + +@pytest.fixture(scope="module") +def curve_pool_v2(project) -> Callable: + def _initialise(_pool: str) -> VyperContract: + return get_deployed_contract("CurvePoolV2", _pool) + + return _initialise + + +@pytest.fixture(scope="module") +def liquidity_gauge(project) -> Callable: + def _initialise(_gauge: str) -> VyperContract: + return get_deployed_contract("LiquidityGauge", _gauge) + + return _initialise diff --git a/tests/mainnet/metaregistry/api/test_find_pool_for_coins.py b/tests/mainnet/metaregistry/api/test_find_pool_for_coins.py index 5222659..670039f 100644 --- a/tests/mainnet/metaregistry/api/test_find_pool_for_coins.py +++ b/tests/mainnet/metaregistry/api/test_find_pool_for_coins.py @@ -1,49 +1,44 @@ -import itertools - -from tests.utils import ZERO_ADDRESS - - -# NOTE: This is the most important method in the metaregistry contract since it will be used -# by integrators to find pools for coin pairs. It finds pools even if the coin pair is not -# a direct coin pair, but has a path through a metapool. - - -def _get_all_combinations(metaregistry, pool): - - pool_coins = [ - coin - for coin in metaregistry.get_coins(pool) - if coin != ZERO_ADDRESS - ] - base_combinations = list(itertools.combinations(pool_coins, 2)) - all_combinations = base_combinations - - if metaregistry.is_meta(pool): - underlying_coins = [ - coin - for coin in metaregistry.get_underlying_coins(pool) - if coin != ZERO_ADDRESS - ] - all_combinations = all_combinations + [ - (pool_coins[0], coin) - for coin in underlying_coins - if pool_coins[0] != coin - ] - - return all_combinations - - -def test_all(populated_metaregistry, pool): - - combinations = _get_all_combinations(populated_metaregistry, pool) - for combination in combinations: - pools_containing_pair = populated_metaregistry.find_pools_for_coins( - *combination - ) - assert pool in pools_containing_pair - - for i, found_pool in enumerate(pools_containing_pair): - assert ( - populated_metaregistry.find_pool_for_coins(*combination, i) - == found_pool - ) +import itertools + +from tests.utils import ZERO_ADDRESS + +# NOTE: This is the most important method in the metaregistry contract since it will be used +# by integrators to find pools for coin pairs. It finds pools even if the coin pair is not +# a direct coin pair, but has a path through a metapool. + + +def _get_all_combinations(metaregistry, pool): + pool_coins = [ + coin for coin in metaregistry.get_coins(pool) if coin != ZERO_ADDRESS + ] + base_combinations = list(itertools.combinations(pool_coins, 2)) + all_combinations = base_combinations + + if metaregistry.is_meta(pool): + underlying_coins = [ + coin + for coin in metaregistry.get_underlying_coins(pool) + if coin != ZERO_ADDRESS + ] + all_combinations = all_combinations + [ + (pool_coins[0], coin) + for coin in underlying_coins + if pool_coins[0] != coin + ] + + return all_combinations + + +def test_all(populated_metaregistry, pool): + combinations = _get_all_combinations(populated_metaregistry, pool) + for combination in combinations: + pools_containing_pair = populated_metaregistry.find_pools_for_coins( + *combination + ) + assert pool in pools_containing_pair + + for i, found_pool in enumerate(pools_containing_pair): + assert ( + populated_metaregistry.find_pool_for_coins(*combination, i) + == found_pool + ) diff --git a/tests/mainnet/metaregistry/api/test_get_admin_balances.py b/tests/mainnet/metaregistry/api/test_get_admin_balances.py index 7c4e131..b9e2805 100644 --- a/tests/mainnet/metaregistry/api/test_get_admin_balances.py +++ b/tests/mainnet/metaregistry/api/test_get_admin_balances.py @@ -1,121 +1,125 @@ -import pytest - - -def pre_test_checks(metaregistry, pool): - - if sum(metaregistry.get_balances(pool)) == 0: - pytest.skip("empty pool: skipping") - - try: - if VyperContract(metaregistry.get_lp_token(pool)).totalSupply() == 0: - pytest.skip("lp token supply is zero") - except SignatureError: - pytest.skip( - f"SignatureError for token {metaregistry.get_lp_token(pool)}: skipping" - ) - - -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - pre_test_checks(populated_metaregistry, stable_registry_pool) - - actual_output = stable_registry.get_admin_balances(stable_registry_pool) - metaregistry_output = populated_metaregistry.get_admin_balances( - stable_registry_pool - ) - for i, output in enumerate(actual_output): - assert output == metaregistry_output[i] - - -def test_stable_factory_pools( - populated_metaregistry, - stable_factory_pool, - curve_pool, -): - - pre_test_checks(populated_metaregistry, stable_factory_pool) - - pool = curve_pool(stable_factory_pool) - metaregistry_output = populated_metaregistry.get_admin_balances( - stable_factory_pool - ) - for i in range(populated_metaregistry.get_n_coins(pool)): - assert pool.admin_balances(i) == metaregistry_output[i] - - -# ---- crypto pools are treated differently ---- - - -def _get_crypto_pool_admin_fees( - populated_metaregistry, pool, fee_receiver, project, alice_address, chain -): - - lp_token = VyperContract(populated_metaregistry.get_lp_token(pool)) - fee_receiver_token_balance_before = lp_token.balanceOf(fee_receiver) - - chain.snapshot() - pool.claim_admin_fees(sender=alice_address) - - claimed_lp_token_as_fee = ( - lp_token.balanceOf(fee_receiver) - fee_receiver_token_balance_before - ) - total_supply_lp_token = lp_token.totalSupply() - frac_admin_fee = int( - claimed_lp_token_as_fee * 10**18 / total_supply_lp_token - ) - - # get admin balances in individual assets: - reserves = populated_metaregistry.get_balances(pool) - admin_balances = [0] * 8 - for i in range(8): - admin_balances[i] = int(frac_admin_fee * reserves[i] / 10**18) - - chain.restore() - return admin_balances - - -def test_crypto_registry_pools( - populated_metaregistry, - crypto_registry_pool, - curve_pool_v2, - alice_address, - chain, - project, -): - - pre_test_checks(populated_metaregistry, crypto_registry_pool) - - pool = curve_pool_v2(crypto_registry_pool) - fee_receiver = pool.admin_fee_receiver() - admin_balances = _get_crypto_pool_admin_fees( - populated_metaregistry, pool, fee_receiver, project, alice_address, chain - ) - - metaregistry_output = populated_metaregistry.get_admin_balances(pool) - for i, output in enumerate(admin_balances): - assert output == pytest.approx(metaregistry_output[i]) - - -def test_crypto_factory_pools( - populated_metaregistry, - crypto_factory_pool, - crypto_factory, - curve_pool_v2, - alice_address, - chain, - project, -): - - pre_test_checks(populated_metaregistry, crypto_factory_pool) - - pool = curve_pool_v2(crypto_factory_pool) - fee_receiver = crypto_factory.fee_receiver() - admin_balances = _get_crypto_pool_admin_fees( - populated_metaregistry, pool, fee_receiver, project, alice_address, chain - ) - - metaregistry_output = populated_metaregistry.get_admin_balances(pool) - for i, output in enumerate(admin_balances): - assert output == pytest.approx(metaregistry_output[i]) +import pytest + + +def pre_test_checks(metaregistry, pool): + if sum(metaregistry.get_balances(pool)) == 0: + pytest.skip("empty pool: skipping") + + try: + if VyperContract(metaregistry.get_lp_token(pool)).totalSupply() == 0: + pytest.skip("lp token supply is zero") + except SignatureError: + pytest.skip( + f"SignatureError for token {metaregistry.get_lp_token(pool)}: skipping" + ) + + +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + pre_test_checks(populated_metaregistry, stable_registry_pool) + + actual_output = stable_registry.get_admin_balances(stable_registry_pool) + metaregistry_output = populated_metaregistry.get_admin_balances( + stable_registry_pool + ) + for i, output in enumerate(actual_output): + assert output == metaregistry_output[i] + + +def test_stable_factory_pools( + populated_metaregistry, + stable_factory_pool, + curve_pool, +): + pre_test_checks(populated_metaregistry, stable_factory_pool) + + pool = curve_pool(stable_factory_pool) + metaregistry_output = populated_metaregistry.get_admin_balances( + stable_factory_pool + ) + for i in range(populated_metaregistry.get_n_coins(pool)): + assert pool.admin_balances(i) == metaregistry_output[i] + + +# ---- crypto pools are treated differently ---- + + +def _get_crypto_pool_admin_fees( + populated_metaregistry, pool, fee_receiver, project, alice_address, chain +): + lp_token = VyperContract(populated_metaregistry.get_lp_token(pool)) + fee_receiver_token_balance_before = lp_token.balanceOf(fee_receiver) + + chain.snapshot() + pool.claim_admin_fees(sender=alice_address) + + claimed_lp_token_as_fee = ( + lp_token.balanceOf(fee_receiver) - fee_receiver_token_balance_before + ) + total_supply_lp_token = lp_token.totalSupply() + frac_admin_fee = int( + claimed_lp_token_as_fee * 10**18 / total_supply_lp_token + ) + + # get admin balances in individual assets: + reserves = populated_metaregistry.get_balances(pool) + admin_balances = [0] * 8 + for i in range(8): + admin_balances[i] = int(frac_admin_fee * reserves[i] / 10**18) + + chain.restore() + return admin_balances + + +def test_crypto_registry_pools( + populated_metaregistry, + crypto_registry_pool, + curve_pool_v2, + alice_address, + chain, + project, +): + pre_test_checks(populated_metaregistry, crypto_registry_pool) + + pool = curve_pool_v2(crypto_registry_pool) + fee_receiver = pool.admin_fee_receiver() + admin_balances = _get_crypto_pool_admin_fees( + populated_metaregistry, + pool, + fee_receiver, + project, + alice_address, + chain, + ) + + metaregistry_output = populated_metaregistry.get_admin_balances(pool) + for i, output in enumerate(admin_balances): + assert output == pytest.approx(metaregistry_output[i]) + + +def test_crypto_factory_pools( + populated_metaregistry, + crypto_factory_pool, + crypto_factory, + curve_pool_v2, + alice_address, + chain, + project, +): + pre_test_checks(populated_metaregistry, crypto_factory_pool) + + pool = curve_pool_v2(crypto_factory_pool) + fee_receiver = crypto_factory.fee_receiver() + admin_balances = _get_crypto_pool_admin_fees( + populated_metaregistry, + pool, + fee_receiver, + project, + alice_address, + chain, + ) + + metaregistry_output = populated_metaregistry.get_admin_balances(pool) + for i, output in enumerate(admin_balances): + assert output == pytest.approx(metaregistry_output[i]) diff --git a/tests/mainnet/metaregistry/api/test_get_balances.py b/tests/mainnet/metaregistry/api/test_get_balances.py index 5f437b1..ddf4341 100644 --- a/tests/mainnet/metaregistry/api/test_get_balances.py +++ b/tests/mainnet/metaregistry/api/test_get_balances.py @@ -1,65 +1,61 @@ -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - actual_output = stable_registry.get_balances(stable_registry_pool) - metaregistry_output = populated_metaregistry.get_balances( - stable_registry_pool - ) - for i in range(populated_metaregistry.get_n_coins(stable_registry_pool)): - assert actual_output[i] == metaregistry_output[i] - - -def test_stable_factory_pools( - populated_metaregistry, stable_factory_pool, stable_factory -): - - actual_output = stable_factory.get_balances(stable_factory_pool) - metaregistry_output = populated_metaregistry.get_balances( - stable_factory_pool - ) - for i in range(populated_metaregistry.get_n_coins(stable_factory_pool)): - assert actual_output[i] == metaregistry_output[i] - - -def test_crypto_registry_pools( - populated_metaregistry, - crypto_registry_pool, - crypto_registry, - curve_pool_v2, -): - - try: - actual_output = crypto_registry.get_balances(crypto_registry_pool) - except ContractLogicError: - actual_output = [] - pool = curve_pool_v2(crypto_registry_pool) - for i in range( - populated_metaregistry.get_n_coins(crypto_registry_pool) - ): - actual_output.append(pool.balances(i)) - - metaregistry_output = populated_metaregistry.get_balances( - crypto_registry_pool - ) - for i in range(populated_metaregistry.get_n_coins(crypto_registry_pool)): - assert actual_output[i] == metaregistry_output[i] - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, crypto_factory, curve_pool_v2 -): - - try: - actual_output = crypto_factory.get_balances(crypto_factory_pool) - except ContractLogicError: - actual_output = [] - pool = curve_pool_v2(crypto_factory_pool) - for i in range(2): - actual_output.append(pool.balances(i)) - - metaregistry_output = populated_metaregistry.get_balances( - crypto_factory_pool - ) - for i in range(populated_metaregistry.get_n_coins(crypto_factory_pool)): - assert actual_output[i] == metaregistry_output[i] +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + actual_output = stable_registry.get_balances(stable_registry_pool) + metaregistry_output = populated_metaregistry.get_balances( + stable_registry_pool + ) + for i in range(populated_metaregistry.get_n_coins(stable_registry_pool)): + assert actual_output[i] == metaregistry_output[i] + + +def test_stable_factory_pools( + populated_metaregistry, stable_factory_pool, stable_factory +): + actual_output = stable_factory.get_balances(stable_factory_pool) + metaregistry_output = populated_metaregistry.get_balances( + stable_factory_pool + ) + for i in range(populated_metaregistry.get_n_coins(stable_factory_pool)): + assert actual_output[i] == metaregistry_output[i] + + +def test_crypto_registry_pools( + populated_metaregistry, + crypto_registry_pool, + crypto_registry, + curve_pool_v2, +): + try: + actual_output = crypto_registry.get_balances(crypto_registry_pool) + except ContractLogicError: + actual_output = [] + pool = curve_pool_v2(crypto_registry_pool) + for i in range( + populated_metaregistry.get_n_coins(crypto_registry_pool) + ): + actual_output.append(pool.balances(i)) + + metaregistry_output = populated_metaregistry.get_balances( + crypto_registry_pool + ) + for i in range(populated_metaregistry.get_n_coins(crypto_registry_pool)): + assert actual_output[i] == metaregistry_output[i] + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, crypto_factory, curve_pool_v2 +): + try: + actual_output = crypto_factory.get_balances(crypto_factory_pool) + except ContractLogicError: + actual_output = [] + pool = curve_pool_v2(crypto_factory_pool) + for i in range(2): + actual_output.append(pool.balances(i)) + + metaregistry_output = populated_metaregistry.get_balances( + crypto_factory_pool + ) + for i in range(populated_metaregistry.get_n_coins(crypto_factory_pool)): + assert actual_output[i] == metaregistry_output[i] diff --git a/tests/mainnet/metaregistry/api/test_get_base_pool.py b/tests/mainnet/metaregistry/api/test_get_base_pool.py index 02cd692..89c0e0e 100644 --- a/tests/mainnet/metaregistry/api/test_get_base_pool.py +++ b/tests/mainnet/metaregistry/api/test_get_base_pool.py @@ -1,16 +1,15 @@ -from tests.utils import ZERO_ADDRESS - - -def test_all(populated_metaregistry, populated_base_pool_registry, pool): - - coins = populated_metaregistry.get_coins(pool) - actual_output = ZERO_ADDRESS - for coin in coins: - actual_output = ( - populated_base_pool_registry.get_base_pool_for_lp_token(coin) - ) - if actual_output != ZERO_ADDRESS: - break - - metaregistry_output = populated_metaregistry.get_base_pool(pool) - assert metaregistry_output == actual_output +from tests.utils import ZERO_ADDRESS + + +def test_all(populated_metaregistry, populated_base_pool_registry, pool): + coins = populated_metaregistry.get_coins(pool) + actual_output = ZERO_ADDRESS + for coin in coins: + actual_output = ( + populated_base_pool_registry.get_base_pool_for_lp_token(coin) + ) + if actual_output != ZERO_ADDRESS: + break + + metaregistry_output = populated_metaregistry.get_base_pool(pool) + assert metaregistry_output == actual_output diff --git a/tests/mainnet/metaregistry/api/test_get_coin_indices.py b/tests/mainnet/metaregistry/api/test_get_coin_indices.py index f4b7e59..1779b03 100644 --- a/tests/mainnet/metaregistry/api/test_get_coin_indices.py +++ b/tests/mainnet/metaregistry/api/test_get_coin_indices.py @@ -1,195 +1,183 @@ -import itertools -import warnings - -import pytest -from tests.utils import ZERO_ADDRESS - - -def _reject_pools_with_one_coin(metaregistry, pool): - - pool_coins = [ - coin - for coin in metaregistry.get_coins(pool) - if coin != ZERO_ADDRESS - ] - if len(list(set(pool_coins))) == 1: - warnings.warn(f"Pool {pool} has only one coin!") - pytest.skip("Pool has only one coin") - - -def _get_coin_combinations(metaregistry, pool): - - # skip tests if pool has only one coin: - _reject_pools_with_one_coin(metaregistry, pool) - - is_meta = metaregistry.is_meta(pool) - pool_coins = [ - coin - for coin in metaregistry.get_coins(pool) - if coin != ZERO_ADDRESS - ] - - base_combinations = list(itertools.combinations(pool_coins, 2)) - all_combinations = base_combinations - if is_meta: - underlying_coins = [ - coin - for coin in metaregistry.get_underlying_coins(pool) - if coin != ZERO_ADDRESS - ] - all_combinations = all_combinations + [ - (pool_coins[0], coin) for coin in underlying_coins - ] - - return all_combinations - - -def _get_coin_indices(pool, coin_a, coin_b, metaregistry, max_coins): - # this is the exact same logic as in the crypto factory handler - - _coins = metaregistry.get_coins(pool) - found_market: bool = False - result = [0] * 3 - - # check coin markets - for x in range(max_coins): - coin = _coins[x] - if coin == ZERO_ADDRESS: - # if we reach the end of the coins, reset `found_market` and try again - # with the underlying coins - found_market = False - break - if coin == coin_a: - result[0] = x - elif coin == coin_b: - result[1] = x - else: - continue - - if found_market: - # the second time we find a match, break out of the loop - break - # the first time we find a match, set `found_market` to True - found_market = True - - if not found_market and metaregistry.is_meta(pool): - - # check underlying coin markets - underlying_coins = metaregistry.get_underlying_coins(pool) - - for x in range(max_coins): - coin = underlying_coins[x] - if coin == ZERO_ADDRESS: - raise "No available market" - if coin == coin_a: - result[0] = x - elif coin == coin_b: - result[1] = x - else: - continue - - if found_market: - result[2] = 1 - break - found_market = True - - return result[0], result[1], result[2] > 0 - - -def _test_coin_indices(coin_a, coin_b, metaregistry, pool, max_coins): - - if coin_a != coin_b: - - metaregistry_output = metaregistry.get_coin_indices( - pool, coin_a, coin_b - ) - - actual_output = _get_coin_indices( - pool, - coin_a, - coin_b, - metaregistry, - max_coins, - ) - - assert tuple(actual_output) == metaregistry_output - - -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, max_coins -): - - all_combinations = _get_coin_combinations( - populated_metaregistry, stable_registry_pool - ) - - for combination in all_combinations: - if combination[0] == combination[1]: - continue - _test_coin_indices( - combination[0], - combination[1], - populated_metaregistry, - stable_registry_pool, - max_coins, - ) - - -def test_stable_factory_pools( - populated_metaregistry, stable_factory_pool, max_coins -): - - all_combinations = _get_coin_combinations( - populated_metaregistry, stable_factory_pool - ) - - for combination in all_combinations: - if combination[0] == combination[1]: - continue - _test_coin_indices( - combination[0], - combination[1], - populated_metaregistry, - stable_factory_pool, - max_coins, - ) - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, max_coins -): - - all_combinations = _get_coin_combinations( - populated_metaregistry, crypto_registry_pool - ) - - for combination in all_combinations: - if combination[0] == combination[1]: - continue - _test_coin_indices( - combination[0], - combination[1], - populated_metaregistry, - crypto_registry_pool, - max_coins, - ) - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, max_coins -): - - all_combinations = _get_coin_combinations( - populated_metaregistry, crypto_factory_pool - ) - - for combination in all_combinations: - if combination[0] == combination[1]: - continue - _test_coin_indices( - combination[0], - combination[1], - populated_metaregistry, - crypto_factory_pool, - max_coins, - ) +import itertools +import warnings + +import pytest + +from tests.utils import ZERO_ADDRESS + + +def _reject_pools_with_one_coin(metaregistry, pool): + pool_coins = [ + coin for coin in metaregistry.get_coins(pool) if coin != ZERO_ADDRESS + ] + if len(list(set(pool_coins))) == 1: + warnings.warn(f"Pool {pool} has only one coin!") + pytest.skip("Pool has only one coin") + + +def _get_coin_combinations(metaregistry, pool): + # skip tests if pool has only one coin: + _reject_pools_with_one_coin(metaregistry, pool) + + is_meta = metaregistry.is_meta(pool) + pool_coins = [ + coin for coin in metaregistry.get_coins(pool) if coin != ZERO_ADDRESS + ] + + base_combinations = list(itertools.combinations(pool_coins, 2)) + all_combinations = base_combinations + if is_meta: + underlying_coins = [ + coin + for coin in metaregistry.get_underlying_coins(pool) + if coin != ZERO_ADDRESS + ] + all_combinations = all_combinations + [ + (pool_coins[0], coin) for coin in underlying_coins + ] + + return all_combinations + + +def _get_coin_indices(pool, coin_a, coin_b, metaregistry, max_coins): + # this is the exact same logic as in the crypto factory handler + + _coins = metaregistry.get_coins(pool) + found_market: bool = False + result = [0] * 3 + + # check coin markets + for x in range(max_coins): + coin = _coins[x] + if coin == ZERO_ADDRESS: + # if we reach the end of the coins, reset `found_market` and try again + # with the underlying coins + found_market = False + break + if coin == coin_a: + result[0] = x + elif coin == coin_b: + result[1] = x + else: + continue + + if found_market: + # the second time we find a match, break out of the loop + break + # the first time we find a match, set `found_market` to True + found_market = True + + if not found_market and metaregistry.is_meta(pool): + # check underlying coin markets + underlying_coins = metaregistry.get_underlying_coins(pool) + + for x in range(max_coins): + coin = underlying_coins[x] + if coin == ZERO_ADDRESS: + raise "No available market" + if coin == coin_a: + result[0] = x + elif coin == coin_b: + result[1] = x + else: + continue + + if found_market: + result[2] = 1 + break + found_market = True + + return result[0], result[1], result[2] > 0 + + +def _test_coin_indices(coin_a, coin_b, metaregistry, pool, max_coins): + if coin_a != coin_b: + metaregistry_output = metaregistry.get_coin_indices( + pool, coin_a, coin_b + ) + + actual_output = _get_coin_indices( + pool, + coin_a, + coin_b, + metaregistry, + max_coins, + ) + + assert tuple(actual_output) == metaregistry_output + + +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, max_coins +): + all_combinations = _get_coin_combinations( + populated_metaregistry, stable_registry_pool + ) + + for combination in all_combinations: + if combination[0] == combination[1]: + continue + _test_coin_indices( + combination[0], + combination[1], + populated_metaregistry, + stable_registry_pool, + max_coins, + ) + + +def test_stable_factory_pools( + populated_metaregistry, stable_factory_pool, max_coins +): + all_combinations = _get_coin_combinations( + populated_metaregistry, stable_factory_pool + ) + + for combination in all_combinations: + if combination[0] == combination[1]: + continue + _test_coin_indices( + combination[0], + combination[1], + populated_metaregistry, + stable_factory_pool, + max_coins, + ) + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, max_coins +): + all_combinations = _get_coin_combinations( + populated_metaregistry, crypto_registry_pool + ) + + for combination in all_combinations: + if combination[0] == combination[1]: + continue + _test_coin_indices( + combination[0], + combination[1], + populated_metaregistry, + crypto_registry_pool, + max_coins, + ) + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, max_coins +): + all_combinations = _get_coin_combinations( + populated_metaregistry, crypto_factory_pool + ) + + for combination in all_combinations: + if combination[0] == combination[1]: + continue + _test_coin_indices( + combination[0], + combination[1], + populated_metaregistry, + crypto_factory_pool, + max_coins, + ) diff --git a/tests/mainnet/metaregistry/api/test_get_coins.py b/tests/mainnet/metaregistry/api/test_get_coins.py index 30c164e..f1ef593 100644 --- a/tests/mainnet/metaregistry/api/test_get_coins.py +++ b/tests/mainnet/metaregistry/api/test_get_coins.py @@ -1,42 +1,38 @@ -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - metaregistry_output = populated_metaregistry.get_coins( - stable_registry_pool - ) - actual_output = list(stable_registry.get_coins(stable_registry_pool)) - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] - - -def test_factory_pools( - populated_metaregistry, stable_factory_pool, stable_factory -): - - metaregistry_output = populated_metaregistry.get_coins(stable_factory_pool) - actual_output = list(stable_factory.get_coins(stable_factory_pool)) - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, crypto_registry -): - - metaregistry_output = populated_metaregistry.get_coins( - crypto_registry_pool - ) - actual_output = list(crypto_registry.get_coins(crypto_registry_pool)) - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, crypto_factory -): - - metaregistry_output = populated_metaregistry.get_coins(crypto_factory_pool) - actual_output = list(crypto_factory.get_coins(crypto_factory_pool)) - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + metaregistry_output = populated_metaregistry.get_coins( + stable_registry_pool + ) + actual_output = list(stable_registry.get_coins(stable_registry_pool)) + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] + + +def test_factory_pools( + populated_metaregistry, stable_factory_pool, stable_factory +): + metaregistry_output = populated_metaregistry.get_coins(stable_factory_pool) + actual_output = list(stable_factory.get_coins(stable_factory_pool)) + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, crypto_registry +): + metaregistry_output = populated_metaregistry.get_coins( + crypto_registry_pool + ) + actual_output = list(crypto_registry.get_coins(crypto_registry_pool)) + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, crypto_factory +): + metaregistry_output = populated_metaregistry.get_coins(crypto_factory_pool) + actual_output = list(crypto_factory.get_coins(crypto_factory_pool)) + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] diff --git a/tests/mainnet/metaregistry/api/test_get_decimals.py b/tests/mainnet/metaregistry/api/test_get_decimals.py index 780da92..420854d 100644 --- a/tests/mainnet/metaregistry/api/test_get_decimals.py +++ b/tests/mainnet/metaregistry/api/test_get_decimals.py @@ -1,46 +1,42 @@ -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - metaregistry_output = populated_metaregistry.get_decimals( - stable_registry_pool - ) - actual_output = list(stable_registry.get_decimals(stable_registry_pool)) - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] - - -def test_factory_pools( - populated_metaregistry, stable_factory_pool, stable_factory -): - - metaregistry_output = populated_metaregistry.get_decimals( - stable_factory_pool - ) - actual_output = list(stable_factory.get_decimals(stable_factory_pool)) - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, crypto_registry -): - - metaregistry_output = populated_metaregistry.get_decimals( - crypto_registry_pool - ) - actual_output = list(crypto_registry.get_decimals(crypto_registry_pool)) - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, crypto_factory -): - - metaregistry_output = populated_metaregistry.get_decimals( - crypto_factory_pool - ) - actual_output = list(crypto_factory.get_decimals(crypto_factory_pool)) - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + metaregistry_output = populated_metaregistry.get_decimals( + stable_registry_pool + ) + actual_output = list(stable_registry.get_decimals(stable_registry_pool)) + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] + + +def test_factory_pools( + populated_metaregistry, stable_factory_pool, stable_factory +): + metaregistry_output = populated_metaregistry.get_decimals( + stable_factory_pool + ) + actual_output = list(stable_factory.get_decimals(stable_factory_pool)) + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, crypto_registry +): + metaregistry_output = populated_metaregistry.get_decimals( + crypto_registry_pool + ) + actual_output = list(crypto_registry.get_decimals(crypto_registry_pool)) + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, crypto_factory +): + metaregistry_output = populated_metaregistry.get_decimals( + crypto_factory_pool + ) + actual_output = list(crypto_factory.get_decimals(crypto_factory_pool)) + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] diff --git a/tests/mainnet/metaregistry/api/test_get_fees.py b/tests/mainnet/metaregistry/api/test_get_fees.py index 18647f3..125dd38 100644 --- a/tests/mainnet/metaregistry/api/test_get_fees.py +++ b/tests/mainnet/metaregistry/api/test_get_fees.py @@ -1,85 +1,83 @@ -import boa -import pytest - - -def _check_dissimilar_length_array_elements_are_equal(output_a, output_b): - for i in range(min(len(output_a), len(output_b))): - assert output_a[i] == output_b[i] - - -def test_stable_registry_pools( - populated_metaregistry, - stable_registry_pool, - stable_registry, - stable_registry_handler, # TODO: Check if this is needed -): - actual_output = stable_registry.get_fees(stable_registry_pool) - metaregistry_output = populated_metaregistry.get_fees(stable_registry_pool) - _check_dissimilar_length_array_elements_are_equal( - actual_output, metaregistry_output - ) - - -def test_stable_factory_pools( - populated_metaregistry, - stable_factory_pool, - stable_factory, - stable_factory_handler, # TODO: Check if this is needed -): - actual_output = stable_factory.get_fees(stable_factory_pool) - metaregistry_output = populated_metaregistry.get_fees(stable_factory_pool) - _check_dissimilar_length_array_elements_are_equal( - actual_output, metaregistry_output - ) - - -def test_crypto_registry_pools( - populated_metaregistry, - crypto_registry_pool, - crypto_registry, - curve_pool_v2, -): - - if sum(crypto_registry.get_balances(crypto_registry_pool)) == 0: - with boa.reverts(): - curve_pool_v2(crypto_registry_pool).fee() - pytest.skip( - f"crypto factory pool {crypto_registry_pool} is empty and factory pools tend to " - "revert for `fee()` since calcs are needed and they can't be done " - "for an empty pool" - ) - - actual_output = crypto_registry.get_fees(crypto_registry_pool) - metaregistry_output = populated_metaregistry.get_fees(crypto_registry_pool) - _check_dissimilar_length_array_elements_are_equal( - actual_output, metaregistry_output - ) - - -def test_crypto_factory_pools( - populated_metaregistry, - crypto_factory_pool, - crypto_factory, - curve_pool_v2, -): - - if sum(crypto_factory.get_balances(crypto_factory_pool)) == 0: - with ape.reverts(): - curve_pool_v2(crypto_factory_pool).fee() - pytest.skip( - f"crypto factory pool {crypto_factory_pool} is empty and factory pools tend to " - "revert for `fee()` since calcs are needed and they can't be done " - "for an empty pool" - ) - - curve_contract = curve_pool_v2(crypto_factory_pool) - actual_output = [ - curve_contract.fee(), - curve_contract.admin_fee(), - curve_contract.mid_fee(), - curve_contract.out_fee(), - ] - metaregistry_output = populated_metaregistry.get_fees(crypto_factory_pool) - _check_dissimilar_length_array_elements_are_equal( - actual_output, metaregistry_output - ) +import boa +import pytest + + +def _check_dissimilar_length_array_elements_are_equal(output_a, output_b): + for i in range(min(len(output_a), len(output_b))): + assert output_a[i] == output_b[i] + + +def test_stable_registry_pools( + populated_metaregistry, + stable_registry_pool, + stable_registry, + stable_registry_handler, # TODO: Check if this is needed +): + actual_output = stable_registry.get_fees(stable_registry_pool) + metaregistry_output = populated_metaregistry.get_fees(stable_registry_pool) + _check_dissimilar_length_array_elements_are_equal( + actual_output, metaregistry_output + ) + + +def test_stable_factory_pools( + populated_metaregistry, + stable_factory_pool, + stable_factory, + stable_factory_handler, # TODO: Check if this is needed +): + actual_output = stable_factory.get_fees(stable_factory_pool) + metaregistry_output = populated_metaregistry.get_fees(stable_factory_pool) + _check_dissimilar_length_array_elements_are_equal( + actual_output, metaregistry_output + ) + + +def test_crypto_registry_pools( + populated_metaregistry, + crypto_registry_pool, + crypto_registry, + curve_pool_v2, +): + if sum(crypto_registry.get_balances(crypto_registry_pool)) == 0: + with boa.reverts(): + curve_pool_v2(crypto_registry_pool).fee() + pytest.skip( + f"crypto factory pool {crypto_registry_pool} is empty and factory pools tend to " + "revert for `fee()` since calcs are needed and they can't be done " + "for an empty pool" + ) + + actual_output = crypto_registry.get_fees(crypto_registry_pool) + metaregistry_output = populated_metaregistry.get_fees(crypto_registry_pool) + _check_dissimilar_length_array_elements_are_equal( + actual_output, metaregistry_output + ) + + +def test_crypto_factory_pools( + populated_metaregistry, + crypto_factory_pool, + crypto_factory, + curve_pool_v2, +): + if sum(crypto_factory.get_balances(crypto_factory_pool)) == 0: + with ape.reverts(): + curve_pool_v2(crypto_factory_pool).fee() + pytest.skip( + f"crypto factory pool {crypto_factory_pool} is empty and factory pools tend to " + "revert for `fee()` since calcs are needed and they can't be done " + "for an empty pool" + ) + + curve_contract = curve_pool_v2(crypto_factory_pool) + actual_output = [ + curve_contract.fee(), + curve_contract.admin_fee(), + curve_contract.mid_fee(), + curve_contract.out_fee(), + ] + metaregistry_output = populated_metaregistry.get_fees(crypto_factory_pool) + _check_dissimilar_length_array_elements_are_equal( + actual_output, metaregistry_output + ) diff --git a/tests/mainnet/metaregistry/api/test_get_gauge.py b/tests/mainnet/metaregistry/api/test_get_gauge.py index 08e0230..835cca1 100644 --- a/tests/mainnet/metaregistry/api/test_get_gauge.py +++ b/tests/mainnet/metaregistry/api/test_get_gauge.py @@ -1,139 +1,134 @@ -import boa -from tests.utils import ZERO_ADDRESS - - -def _is_dao_onboarded_gauge(_gauge, gauge_controller, liquidity_gauge): - - try: - gauge_controller.gauge_types(_gauge) - except ape.exceptions.VirtualMachineError: - return False - - if liquidity_gauge(_gauge).is_killed(): - return False - - return True - - -def _get_factory_gauge( - registry, - pool, - gauge_controller, - liquidity_gauge, - default_gauge_type: int = 0, -): - - gauge = registry.get_gauge(pool) - - # we check if the gauge is dao onboarded, else - # gauge_controller.gauge_types(gauge) will revert - # as gauge type is zero. This slows down tests significantly - if _is_dao_onboarded_gauge(gauge, gauge_controller, liquidity_gauge): - return ( - [gauge] + [ZERO_ADDRESS] * 9, - [gauge_controller.gauge_types(gauge)] + [0] * 9, - ) - else: - return ( - [gauge] + [ZERO_ADDRESS] * 9, - [default_gauge_type] * 10, - ) - - -def test_stable_registry_pools( - populated_metaregistry, - stable_registry_pool, - stable_registry, -): - - actual_output = stable_registry.get_gauges(stable_registry_pool) - metaregistry_output_gauge = populated_metaregistry.get_gauge( - stable_registry_pool - ) - metaregistry_output_gauge_type = populated_metaregistry.get_gauge_type( - stable_registry_pool - ) - - assert actual_output[0][0] == metaregistry_output_gauge - assert actual_output[1][0] == metaregistry_output_gauge_type - - -def test_stable_factory_pools( - populated_metaregistry, - stable_factory_pool, - stable_factory, - gauge_controller, - liquidity_gauge, -): - - actual_output = _get_factory_gauge( - stable_factory, stable_factory_pool, gauge_controller, liquidity_gauge - ) - - # lots of stable registry pools were actually factory pools which then got moved - # over to the stable factory's storage. During this process, gauge data was not - # moved over properly. For these pools, the metaregistry automatically goes to - # the stable registry handler (where the correct gauge data is stored), but the - # stable factory will not have the right data. We therefore do a manual check for - # this case: - pool_registry_handlers = ( - populated_metaregistry.get_registry_handlers_from_pool( - stable_factory_pool - ) - ) - num_registry_handlers = len( - list(filter((ZERO_ADDRESS).__ne__, pool_registry_handlers)) - ) - - metaregistry_output_gauge = populated_metaregistry.get_gauge( - stable_factory_pool, 0, num_registry_handlers - 1 - ) - metaregistry_output_gauge_type = populated_metaregistry.get_gauge_type( - stable_factory_pool, 0, num_registry_handlers - 1 - ) - - assert actual_output[0][0] == metaregistry_output_gauge - assert actual_output[1][0] == metaregistry_output_gauge_type - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, crypto_registry -): - - actual_output = crypto_registry.get_gauges(crypto_registry_pool) - metaregistry_output_gauge = populated_metaregistry.get_gauge( - crypto_registry_pool - ) - metaregistry_output_gauge_type = populated_metaregistry.get_gauge_type( - crypto_registry_pool - ) - - assert actual_output[0][0] == metaregistry_output_gauge - assert actual_output[1][0] == metaregistry_output_gauge_type - - -def test_crypto_factory_pools( - populated_metaregistry, - crypto_factory_pool, - crypto_factory, - gauge_controller, - liquidity_gauge, -): - - # warning: gauge_type == 5 : this is true only for crypto pools on ethereum - actual_output = _get_factory_gauge( - crypto_factory, - crypto_factory_pool, - gauge_controller, - liquidity_gauge, - 5, # DEFAULT_GAUGE_TYPE_CRYPTO_FACTORY_POOLS - ) - metaregistry_output_gauge = populated_metaregistry.get_gauge( - crypto_factory_pool - ) - metaregistry_output_gauge_type = populated_metaregistry.get_gauge_type( - crypto_factory_pool - ) - - assert actual_output[0][0] == metaregistry_output_gauge - assert metaregistry_output_gauge_type == 5 +import boa + +from tests.utils import ZERO_ADDRESS + + +def _is_dao_onboarded_gauge(_gauge, gauge_controller, liquidity_gauge): + try: + gauge_controller.gauge_types(_gauge) + except ape.exceptions.VirtualMachineError: + return False + + if liquidity_gauge(_gauge).is_killed(): + return False + + return True + + +def _get_factory_gauge( + registry, + pool, + gauge_controller, + liquidity_gauge, + default_gauge_type: int = 0, +): + gauge = registry.get_gauge(pool) + + # we check if the gauge is dao onboarded, else + # gauge_controller.gauge_types(gauge) will revert + # as gauge type is zero. This slows down tests significantly + if _is_dao_onboarded_gauge(gauge, gauge_controller, liquidity_gauge): + return ( + [gauge] + [ZERO_ADDRESS] * 9, + [gauge_controller.gauge_types(gauge)] + [0] * 9, + ) + else: + return ( + [gauge] + [ZERO_ADDRESS] * 9, + [default_gauge_type] * 10, + ) + + +def test_stable_registry_pools( + populated_metaregistry, + stable_registry_pool, + stable_registry, +): + actual_output = stable_registry.get_gauges(stable_registry_pool) + metaregistry_output_gauge = populated_metaregistry.get_gauge( + stable_registry_pool + ) + metaregistry_output_gauge_type = populated_metaregistry.get_gauge_type( + stable_registry_pool + ) + + assert actual_output[0][0] == metaregistry_output_gauge + assert actual_output[1][0] == metaregistry_output_gauge_type + + +def test_stable_factory_pools( + populated_metaregistry, + stable_factory_pool, + stable_factory, + gauge_controller, + liquidity_gauge, +): + actual_output = _get_factory_gauge( + stable_factory, stable_factory_pool, gauge_controller, liquidity_gauge + ) + + # lots of stable registry pools were actually factory pools which then got moved + # over to the stable factory's storage. During this process, gauge data was not + # moved over properly. For these pools, the metaregistry automatically goes to + # the stable registry handler (where the correct gauge data is stored), but the + # stable factory will not have the right data. We therefore do a manual check for + # this case: + pool_registry_handlers = ( + populated_metaregistry.get_registry_handlers_from_pool( + stable_factory_pool + ) + ) + num_registry_handlers = len( + list(filter((ZERO_ADDRESS).__ne__, pool_registry_handlers)) + ) + + metaregistry_output_gauge = populated_metaregistry.get_gauge( + stable_factory_pool, 0, num_registry_handlers - 1 + ) + metaregistry_output_gauge_type = populated_metaregistry.get_gauge_type( + stable_factory_pool, 0, num_registry_handlers - 1 + ) + + assert actual_output[0][0] == metaregistry_output_gauge + assert actual_output[1][0] == metaregistry_output_gauge_type + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, crypto_registry +): + actual_output = crypto_registry.get_gauges(crypto_registry_pool) + metaregistry_output_gauge = populated_metaregistry.get_gauge( + crypto_registry_pool + ) + metaregistry_output_gauge_type = populated_metaregistry.get_gauge_type( + crypto_registry_pool + ) + + assert actual_output[0][0] == metaregistry_output_gauge + assert actual_output[1][0] == metaregistry_output_gauge_type + + +def test_crypto_factory_pools( + populated_metaregistry, + crypto_factory_pool, + crypto_factory, + gauge_controller, + liquidity_gauge, +): + # warning: gauge_type == 5 : this is true only for crypto pools on ethereum + actual_output = _get_factory_gauge( + crypto_factory, + crypto_factory_pool, + gauge_controller, + liquidity_gauge, + 5, # DEFAULT_GAUGE_TYPE_CRYPTO_FACTORY_POOLS + ) + metaregistry_output_gauge = populated_metaregistry.get_gauge( + crypto_factory_pool + ) + metaregistry_output_gauge_type = populated_metaregistry.get_gauge_type( + crypto_factory_pool + ) + + assert actual_output[0][0] == metaregistry_output_gauge + assert metaregistry_output_gauge_type == 5 diff --git a/tests/mainnet/metaregistry/api/test_get_lp_token.py b/tests/mainnet/metaregistry/api/test_get_lp_token.py index 351b6bc..08f168b 100644 --- a/tests/mainnet/metaregistry/api/test_get_lp_token.py +++ b/tests/mainnet/metaregistry/api/test_get_lp_token.py @@ -1,41 +1,37 @@ -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - actual_output = stable_registry.get_lp_token(stable_registry_pool) - metaregistry_output = populated_metaregistry.get_lp_token( - stable_registry_pool - ) - assert metaregistry_output == actual_output - - -def test_stable_factory_pools(populated_metaregistry, stable_factory_pool): - - metaregistry_output = populated_metaregistry.get_lp_token( - stable_factory_pool - ) - - # pool == lp_token for stable factory - assert stable_factory_pool == metaregistry_output - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, crypto_registry -): - - actual_output = crypto_registry.get_lp_token(crypto_registry_pool) - metaregistry_output = populated_metaregistry.get_lp_token( - crypto_registry_pool - ) - assert metaregistry_output == actual_output - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, crypto_factory -): - - actual_output = crypto_factory.get_token(crypto_factory_pool) - metaregistry_output = populated_metaregistry.get_lp_token( - crypto_factory_pool - ) - assert metaregistry_output == actual_output +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + actual_output = stable_registry.get_lp_token(stable_registry_pool) + metaregistry_output = populated_metaregistry.get_lp_token( + stable_registry_pool + ) + assert metaregistry_output == actual_output + + +def test_stable_factory_pools(populated_metaregistry, stable_factory_pool): + metaregistry_output = populated_metaregistry.get_lp_token( + stable_factory_pool + ) + + # pool == lp_token for stable factory + assert stable_factory_pool == metaregistry_output + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, crypto_registry +): + actual_output = crypto_registry.get_lp_token(crypto_registry_pool) + metaregistry_output = populated_metaregistry.get_lp_token( + crypto_registry_pool + ) + assert metaregistry_output == actual_output + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, crypto_factory +): + actual_output = crypto_factory.get_token(crypto_factory_pool) + metaregistry_output = populated_metaregistry.get_lp_token( + crypto_factory_pool + ) + assert metaregistry_output == actual_output diff --git a/tests/mainnet/metaregistry/api/test_get_n_coins.py b/tests/mainnet/metaregistry/api/test_get_n_coins.py index f858a95..c8113a6 100644 --- a/tests/mainnet/metaregistry/api/test_get_n_coins.py +++ b/tests/mainnet/metaregistry/api/test_get_n_coins.py @@ -1,76 +1,65 @@ -from tests.utils import ZERO_ADDRESS - - -def _get_n_coins_for_pool(registry, pool): - - actual_output = registry.get_n_coins(pool) - # registry returns tuple, we want the first one (since the second) - # index is about basepool n coins - if not isinstance(actual_output, int): - - actual_output = registry.get_n_coins(pool)[0] - - # registry returns 0 value for n coins: something's not right on the - # registry's side. find n_coins via registry.get_coins: - elif actual_output == 0: - - coins = registry.get_coins(pool) - actual_output = sum( - [1 for coin in coins if coin != ZERO_ADDRESS] - ) - - return actual_output - - -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - actual_output = _get_n_coins_for_pool( - stable_registry, stable_registry_pool - ) - - metaregistry_output = populated_metaregistry.get_n_coins( - stable_registry_pool - ) - assert metaregistry_output == actual_output - - -def test_stable_factory_pools( - populated_metaregistry, stable_factory_pool, stable_factory -): - - actual_output = _get_n_coins_for_pool(stable_factory, stable_factory_pool) - - metaregistry_output = populated_metaregistry.get_n_coins( - stable_factory_pool - ) - assert metaregistry_output == actual_output - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, crypto_registry -): - - actual_output = _get_n_coins_for_pool( - crypto_registry, crypto_registry_pool - ) - - metaregistry_output = populated_metaregistry.get_n_coins( - crypto_registry_pool - ) - assert metaregistry_output == actual_output - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, crypto_factory -): - - coins = crypto_factory.get_coins(crypto_factory_pool) - actual_output = sum( - [1 for coin in coins if coin != ZERO_ADDRESS] - ) - metaregistry_output = populated_metaregistry.get_n_coins( - crypto_factory_pool - ) - assert metaregistry_output == actual_output +from tests.utils import ZERO_ADDRESS + + +def _get_n_coins_for_pool(registry, pool): + actual_output = registry.get_n_coins(pool) + # registry returns tuple, we want the first one (since the second) + # index is about basepool n coins + if not isinstance(actual_output, int): + actual_output = registry.get_n_coins(pool)[0] + + # registry returns 0 value for n coins: something's not right on the + # registry's side. find n_coins via registry.get_coins: + elif actual_output == 0: + coins = registry.get_coins(pool) + actual_output = sum([1 for coin in coins if coin != ZERO_ADDRESS]) + + return actual_output + + +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + actual_output = _get_n_coins_for_pool( + stable_registry, stable_registry_pool + ) + + metaregistry_output = populated_metaregistry.get_n_coins( + stable_registry_pool + ) + assert metaregistry_output == actual_output + + +def test_stable_factory_pools( + populated_metaregistry, stable_factory_pool, stable_factory +): + actual_output = _get_n_coins_for_pool(stable_factory, stable_factory_pool) + + metaregistry_output = populated_metaregistry.get_n_coins( + stable_factory_pool + ) + assert metaregistry_output == actual_output + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, crypto_registry +): + actual_output = _get_n_coins_for_pool( + crypto_registry, crypto_registry_pool + ) + + metaregistry_output = populated_metaregistry.get_n_coins( + crypto_registry_pool + ) + assert metaregistry_output == actual_output + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, crypto_factory +): + coins = crypto_factory.get_coins(crypto_factory_pool) + actual_output = sum([1 for coin in coins if coin != ZERO_ADDRESS]) + metaregistry_output = populated_metaregistry.get_n_coins( + crypto_factory_pool + ) + assert metaregistry_output == actual_output diff --git a/tests/mainnet/metaregistry/api/test_get_n_underlying_coins.py b/tests/mainnet/metaregistry/api/test_get_n_underlying_coins.py index 7933411..9d5a243 100644 --- a/tests/mainnet/metaregistry/api/test_get_n_underlying_coins.py +++ b/tests/mainnet/metaregistry/api/test_get_n_underlying_coins.py @@ -1,95 +1,87 @@ -from tests.utils import ZERO_ADDRESS - - -def _get_num_coins(registry, pool, base_pool_registry): - - coins = registry.get_coins(pool) - num_coins = 0 - for coin in coins: - - if coin == ZERO_ADDRESS: - break - - base_pool = base_pool_registry.get_base_pool_for_lp_token(coin) - - if base_pool != ZERO_ADDRESS: - - basepool_coins = base_pool_registry.get_coins(base_pool) - num_bp_coins = sum( - [1 for i in basepool_coins if i != ZERO_ADDRESS] - ) - num_coins += num_bp_coins - - else: - - num_coins += 1 - - return num_coins - - -def test_stable_registry_pools( - populated_metaregistry, - stable_registry_pool, - stable_registry, - populated_base_pool_registry, -): - - metaregistry_output = populated_metaregistry.get_n_underlying_coins( - stable_registry_pool - ) - num_coins = _get_num_coins( - stable_registry, stable_registry_pool, populated_base_pool_registry - ) - - assert metaregistry_output == num_coins - - -def test_stable_factory_pools( - populated_metaregistry, - stable_factory_pool, - stable_factory, - populated_base_pool_registry, -): - - metaregistry_output = populated_metaregistry.get_n_underlying_coins( - stable_factory_pool - ) - num_coins = _get_num_coins( - stable_factory, stable_factory_pool, populated_base_pool_registry - ) - - assert metaregistry_output == num_coins - - -def test_crypto_registry_pools( - populated_metaregistry, - crypto_registry_pool, - crypto_registry, - populated_base_pool_registry, -): - - metaregistry_output = populated_metaregistry.get_n_underlying_coins( - crypto_registry_pool - ) - num_coins = _get_num_coins( - crypto_registry, crypto_registry_pool, populated_base_pool_registry - ) - - assert metaregistry_output == num_coins - - -def test_crypto_factory_pools( - populated_metaregistry, - crypto_factory_pool, - crypto_factory, - populated_base_pool_registry, -): - - metaregistry_output = populated_metaregistry.get_n_underlying_coins( - crypto_factory_pool - ) - num_coins = _get_num_coins( - crypto_factory, crypto_factory_pool, populated_base_pool_registry - ) - - assert metaregistry_output == num_coins +from tests.utils import ZERO_ADDRESS + + +def _get_num_coins(registry, pool, base_pool_registry): + coins = registry.get_coins(pool) + num_coins = 0 + for coin in coins: + if coin == ZERO_ADDRESS: + break + + base_pool = base_pool_registry.get_base_pool_for_lp_token(coin) + + if base_pool != ZERO_ADDRESS: + basepool_coins = base_pool_registry.get_coins(base_pool) + num_bp_coins = sum( + [1 for i in basepool_coins if i != ZERO_ADDRESS] + ) + num_coins += num_bp_coins + + else: + num_coins += 1 + + return num_coins + + +def test_stable_registry_pools( + populated_metaregistry, + stable_registry_pool, + stable_registry, + populated_base_pool_registry, +): + metaregistry_output = populated_metaregistry.get_n_underlying_coins( + stable_registry_pool + ) + num_coins = _get_num_coins( + stable_registry, stable_registry_pool, populated_base_pool_registry + ) + + assert metaregistry_output == num_coins + + +def test_stable_factory_pools( + populated_metaregistry, + stable_factory_pool, + stable_factory, + populated_base_pool_registry, +): + metaregistry_output = populated_metaregistry.get_n_underlying_coins( + stable_factory_pool + ) + num_coins = _get_num_coins( + stable_factory, stable_factory_pool, populated_base_pool_registry + ) + + assert metaregistry_output == num_coins + + +def test_crypto_registry_pools( + populated_metaregistry, + crypto_registry_pool, + crypto_registry, + populated_base_pool_registry, +): + metaregistry_output = populated_metaregistry.get_n_underlying_coins( + crypto_registry_pool + ) + num_coins = _get_num_coins( + crypto_registry, crypto_registry_pool, populated_base_pool_registry + ) + + assert metaregistry_output == num_coins + + +def test_crypto_factory_pools( + populated_metaregistry, + crypto_factory_pool, + crypto_factory, + populated_base_pool_registry, +): + metaregistry_output = populated_metaregistry.get_n_underlying_coins( + crypto_factory_pool + ) + num_coins = _get_num_coins( + crypto_factory, crypto_factory_pool, populated_base_pool_registry + ) + + assert metaregistry_output == num_coins diff --git a/tests/mainnet/metaregistry/api/test_get_pool_asset_type.py b/tests/mainnet/metaregistry/api/test_get_pool_asset_type.py index 73909ee..1a75be7 100644 --- a/tests/mainnet/metaregistry/api/test_get_pool_asset_type.py +++ b/tests/mainnet/metaregistry/api/test_get_pool_asset_type.py @@ -1,37 +1,34 @@ -# pool is asset type 0 on metaregistry at _handler_id == 0 but 3 (correct) -# at _handler_id == 1 -EXCEPTIONS = {"0xFD5dB7463a3aB53fD211b4af195c5BCCC1A03890": 3} - - -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - assert populated_metaregistry.get_pool_asset_type( - stable_registry_pool - ) == stable_registry.get_pool_asset_type(stable_registry_pool) - - -def test_stable_factory_pools( - populated_metaregistry, stable_factory_pool, stable_factory -): - metaregistry_output = populated_metaregistry.get_pool_asset_type( - stable_factory_pool - ) - if stable_factory_pool in EXCEPTIONS: - metaregistry_output = EXCEPTIONS[stable_factory_pool] - assert metaregistry_output == stable_factory.get_pool_asset_type( - stable_factory_pool - ) - - -def test_crypto_registry_pools(populated_metaregistry, crypto_registry_pool): - - assert ( - populated_metaregistry.get_pool_asset_type(crypto_registry_pool) == 4 - ) - - -def test_crypto_factory_pools(populated_metaregistry, crypto_factory_pool): - - assert populated_metaregistry.get_pool_asset_type(crypto_factory_pool) == 4 +# pool is asset type 0 on metaregistry at _handler_id == 0 but 3 (correct) +# at _handler_id == 1 +EXCEPTIONS = {"0xFD5dB7463a3aB53fD211b4af195c5BCCC1A03890": 3} + + +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + assert populated_metaregistry.get_pool_asset_type( + stable_registry_pool + ) == stable_registry.get_pool_asset_type(stable_registry_pool) + + +def test_stable_factory_pools( + populated_metaregistry, stable_factory_pool, stable_factory +): + metaregistry_output = populated_metaregistry.get_pool_asset_type( + stable_factory_pool + ) + if stable_factory_pool in EXCEPTIONS: + metaregistry_output = EXCEPTIONS[stable_factory_pool] + assert metaregistry_output == stable_factory.get_pool_asset_type( + stable_factory_pool + ) + + +def test_crypto_registry_pools(populated_metaregistry, crypto_registry_pool): + assert ( + populated_metaregistry.get_pool_asset_type(crypto_registry_pool) == 4 + ) + + +def test_crypto_factory_pools(populated_metaregistry, crypto_factory_pool): + assert populated_metaregistry.get_pool_asset_type(crypto_factory_pool) == 4 diff --git a/tests/mainnet/metaregistry/api/test_get_pool_from_lp_token.py b/tests/mainnet/metaregistry/api/test_get_pool_from_lp_token.py index 7e99099..2ed2c5d 100644 --- a/tests/mainnet/metaregistry/api/test_get_pool_from_lp_token.py +++ b/tests/mainnet/metaregistry/api/test_get_pool_from_lp_token.py @@ -1,6 +1,6 @@ -def test_all_pools(populated_metaregistry, pool): - lp_token = populated_metaregistry.get_lp_token(pool) - metaregistry_output = populated_metaregistry.get_pool_from_lp_token( - lp_token - ) - assert pool == metaregistry_output +def test_all_pools(populated_metaregistry, pool): + lp_token = populated_metaregistry.get_lp_token(pool) + metaregistry_output = populated_metaregistry.get_pool_from_lp_token( + lp_token + ) + assert pool == metaregistry_output diff --git a/tests/mainnet/metaregistry/api/test_get_pool_name.py b/tests/mainnet/metaregistry/api/test_get_pool_name.py index 1c4018b..1e85b4f 100644 --- a/tests/mainnet/metaregistry/api/test_get_pool_name.py +++ b/tests/mainnet/metaregistry/api/test_get_pool_name.py @@ -1,70 +1,63 @@ -import pytest -from tests.utils import ZERO_ADDRESS - - -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - assert populated_metaregistry.get_pool_name( - stable_registry_pool - ) == stable_registry.get_pool_name(stable_registry_pool) - - -def test_stable_factory_pools(populated_metaregistry, stable_factory_pool): - - # same issues where a pool that was first in a registry got ported over to the - # factory incorrectly. so we try different handler indices to check if we get - # the right result: - pool_registry_handlers = ( - populated_metaregistry.get_registry_handlers_from_pool( - stable_factory_pool - ) - ) - num_registry_handlers = len( - list(filter((ZERO_ADDRESS).__ne__, pool_registry_handlers)) - ) - - if num_registry_handlers == 1: - - assert ( - populated_metaregistry.get_pool_name(stable_factory_pool) - == VyperContract(stable_factory_pool).name() - ) - - elif num_registry_handlers == 2: - - with pytest.raises(AssertionError): - - assert ( - populated_metaregistry.get_pool_name(stable_factory_pool) - == VyperContract(stable_factory_pool).name() - ) - - assert ( - populated_metaregistry.get_pool_name(stable_factory_pool, 1) - == VyperContract(stable_factory_pool).name() - ) - - else: - - raise - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, crypto_registry -): - - assert populated_metaregistry.get_pool_name( - crypto_registry_pool - ) == crypto_registry.get_pool_name(crypto_registry_pool) - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, crypto_factory -): - - assert ( - populated_metaregistry.get_pool_name(crypto_factory_pool) - == VyperContract(crypto_factory.get_token(crypto_factory_pool)).name() - ) +import pytest + +from tests.utils import ZERO_ADDRESS + + +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + assert populated_metaregistry.get_pool_name( + stable_registry_pool + ) == stable_registry.get_pool_name(stable_registry_pool) + + +def test_stable_factory_pools(populated_metaregistry, stable_factory_pool): + # same issues where a pool that was first in a registry got ported over to the + # factory incorrectly. so we try different handler indices to check if we get + # the right result: + pool_registry_handlers = ( + populated_metaregistry.get_registry_handlers_from_pool( + stable_factory_pool + ) + ) + num_registry_handlers = len( + list(filter((ZERO_ADDRESS).__ne__, pool_registry_handlers)) + ) + + if num_registry_handlers == 1: + assert ( + populated_metaregistry.get_pool_name(stable_factory_pool) + == VyperContract(stable_factory_pool).name() + ) + + elif num_registry_handlers == 2: + with pytest.raises(AssertionError): + assert ( + populated_metaregistry.get_pool_name(stable_factory_pool) + == VyperContract(stable_factory_pool).name() + ) + + assert ( + populated_metaregistry.get_pool_name(stable_factory_pool, 1) + == VyperContract(stable_factory_pool).name() + ) + + else: + raise + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, crypto_registry +): + assert populated_metaregistry.get_pool_name( + crypto_registry_pool + ) == crypto_registry.get_pool_name(crypto_registry_pool) + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, crypto_factory +): + assert ( + populated_metaregistry.get_pool_name(crypto_factory_pool) + == VyperContract(crypto_factory.get_token(crypto_factory_pool)).name() + ) diff --git a/tests/mainnet/metaregistry/api/test_get_pool_params.py b/tests/mainnet/metaregistry/api/test_get_pool_params.py index f8c96f0..1cd5896 100644 --- a/tests/mainnet/metaregistry/api/test_get_pool_params.py +++ b/tests/mainnet/metaregistry/api/test_get_pool_params.py @@ -1,67 +1,63 @@ -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - actual_pool_params = [0] * 20 - actual_pool_params[0] = stable_registry.get_A(stable_registry_pool) - metaregistry_output = populated_metaregistry.get_pool_params( - stable_registry_pool - ) - - assert actual_pool_params == metaregistry_output - - -def test_stable_factory_pools( - populated_metaregistry, stable_factory_pool, stable_factory -): - - metaregistry_output = populated_metaregistry.get_pool_params( - stable_factory_pool - ) - actual_pool_params = [0] * 20 - actual_pool_params[0] = stable_factory.get_A(stable_factory_pool) - - assert actual_pool_params == metaregistry_output - - -def test_crypto_registry_pools( - populated_metaregistry, - crypto_registry_pool, - crypto_registry, - curve_pool_v2, -): - - metaregistry_output = populated_metaregistry.get_pool_params( - crypto_registry_pool - ) - v2_pool = curve_pool_v2(crypto_registry_pool) - - actual_pool_params = [0] * 20 - actual_pool_params[0] = crypto_registry.get_A(crypto_registry_pool) - actual_pool_params[1] = crypto_registry.get_D(crypto_registry_pool) - actual_pool_params[2] = crypto_registry.get_gamma(crypto_registry_pool) - actual_pool_params[3] = v2_pool.allowed_extra_profit() - actual_pool_params[4] = v2_pool.fee_gamma() - actual_pool_params[5] = v2_pool.adjustment_step() - actual_pool_params[6] = v2_pool.ma_half_time() - assert actual_pool_params == metaregistry_output - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, curve_pool_v2 -): - - metaregistry_output = populated_metaregistry.get_pool_params( - crypto_factory_pool - ) - v2_pool = curve_pool_v2(crypto_factory_pool) - - actual_pool_params = [0] * 20 - actual_pool_params[0] = v2_pool.A() - actual_pool_params[1] = v2_pool.D() - actual_pool_params[2] = v2_pool.gamma() - actual_pool_params[3] = v2_pool.allowed_extra_profit() - actual_pool_params[4] = v2_pool.fee_gamma() - actual_pool_params[5] = v2_pool.adjustment_step() - actual_pool_params[6] = v2_pool.ma_half_time() - assert actual_pool_params == metaregistry_output +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + actual_pool_params = [0] * 20 + actual_pool_params[0] = stable_registry.get_A(stable_registry_pool) + metaregistry_output = populated_metaregistry.get_pool_params( + stable_registry_pool + ) + + assert actual_pool_params == metaregistry_output + + +def test_stable_factory_pools( + populated_metaregistry, stable_factory_pool, stable_factory +): + metaregistry_output = populated_metaregistry.get_pool_params( + stable_factory_pool + ) + actual_pool_params = [0] * 20 + actual_pool_params[0] = stable_factory.get_A(stable_factory_pool) + + assert actual_pool_params == metaregistry_output + + +def test_crypto_registry_pools( + populated_metaregistry, + crypto_registry_pool, + crypto_registry, + curve_pool_v2, +): + metaregistry_output = populated_metaregistry.get_pool_params( + crypto_registry_pool + ) + v2_pool = curve_pool_v2(crypto_registry_pool) + + actual_pool_params = [0] * 20 + actual_pool_params[0] = crypto_registry.get_A(crypto_registry_pool) + actual_pool_params[1] = crypto_registry.get_D(crypto_registry_pool) + actual_pool_params[2] = crypto_registry.get_gamma(crypto_registry_pool) + actual_pool_params[3] = v2_pool.allowed_extra_profit() + actual_pool_params[4] = v2_pool.fee_gamma() + actual_pool_params[5] = v2_pool.adjustment_step() + actual_pool_params[6] = v2_pool.ma_half_time() + assert actual_pool_params == metaregistry_output + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, curve_pool_v2 +): + metaregistry_output = populated_metaregistry.get_pool_params( + crypto_factory_pool + ) + v2_pool = curve_pool_v2(crypto_factory_pool) + + actual_pool_params = [0] * 20 + actual_pool_params[0] = v2_pool.A() + actual_pool_params[1] = v2_pool.D() + actual_pool_params[2] = v2_pool.gamma() + actual_pool_params[3] = v2_pool.allowed_extra_profit() + actual_pool_params[4] = v2_pool.fee_gamma() + actual_pool_params[5] = v2_pool.adjustment_step() + actual_pool_params[6] = v2_pool.ma_half_time() + assert actual_pool_params == metaregistry_output diff --git a/tests/mainnet/metaregistry/api/test_get_underlying_balances.py b/tests/mainnet/metaregistry/api/test_get_underlying_balances.py index cd1b041..e760d11 100644 --- a/tests/mainnet/metaregistry/api/test_get_underlying_balances.py +++ b/tests/mainnet/metaregistry/api/test_get_underlying_balances.py @@ -1,163 +1,151 @@ -import warnings - -import boa -import pytest -from tests.utils import ZERO_ADDRESS - -EXCEPTION_POOLS = ["0x79a8C46DeA5aDa233ABaFFD40F3A0A2B1e5A4F27"] - - -def pre_test_checks(metaregistry, pool): - - if sum(metaregistry.get_balances(pool)) == 0: - pytest.skip(f"Empty pool: {pool}") - - -def _get_underlying_balances( - metaregistry, pool, registry, base_pool_registry, max_coins -): - - actual_output = [0] * max_coins - - try: - - actual_output = registry.get_underlying_balances(pool) - - # registry getter borks, so we need to get balances the hard way: - except (ape.exceptions.ContractLogicError, AttributeError): - - coins = metaregistry.get_coins(pool) - balances = metaregistry.get_balances(pool) - for idx, coin in enumerate(coins): - - base_pool = base_pool_registry.get_base_pool_for_lp_token(coin) - - if base_pool != ZERO_ADDRESS: - - basepool_lp_token_balance = balances[idx] - coin_contract = VyperContract(coin) - try: - lp_token_supply = coin_contract.totalSupply() - except (ape.exceptions.SignatureError, AttributeError): - assert "totalSupply" not in [ - i.name - for i in coin_contract.contract_type.view_methods - ] - pytest.skip( - f"Token {coin} method totalSupply() is not a view method" - ) - - ratio_in_pool = basepool_lp_token_balance / lp_token_supply - - base_pool_balances = metaregistry.get_balances(base_pool) - - for idy, balance in enumerate(base_pool_balances): - - if coin == ZERO_ADDRESS: - break - actual_output[idx] = balance * ratio_in_pool - - break - - actual_output[idx] = balances[idx] - - return actual_output - - -def _test_underlying_balances_getter( - metaregistry, pool, registry, base_pool_registry, max_coins -): - - actual_output = _get_underlying_balances( - metaregistry, pool, registry, base_pool_registry, max_coins - ) - metaregistry_output = metaregistry.get_underlying_balances(pool) - underlying_decimals = metaregistry.get_underlying_decimals(pool) - - for idx, registry_value in enumerate(actual_output): - - try: - - assert registry_value == pytest.approx( - metaregistry_output[idx] - * 10 ** (18 - underlying_decimals[idx]) - ) - - except AssertionError: - - if pool in EXCEPTION_POOLS: - - warnings.warn("Skipping test for pool: {}".format(pool)) - pytest.skip( - "Unresolved output from Borky pool: {}".format(pool) - ) - - -def test_stable_registry_pools( - populated_metaregistry, - stable_registry_pool, - stable_registry, - populated_base_pool_registry, - max_coins, -): - pre_test_checks(populated_metaregistry, stable_registry_pool) - _test_underlying_balances_getter( - populated_metaregistry, - stable_registry_pool, - stable_registry, - populated_base_pool_registry, - max_coins, - ) - - -def test_stable_factory_pools( - populated_metaregistry, - stable_factory_pool, - stable_factory, - populated_base_pool_registry, - max_coins, -): - pre_test_checks(populated_metaregistry, stable_factory_pool) - _test_underlying_balances_getter( - populated_metaregistry, - stable_factory_pool, - stable_factory, - populated_base_pool_registry, - max_coins, - ) - - -def test_crypto_registry_pools( - populated_metaregistry, - crypto_registry_pool, - crypto_registry, - populated_base_pool_registry, - max_coins, -): - pre_test_checks(populated_metaregistry, crypto_registry_pool) - _test_underlying_balances_getter( - populated_metaregistry, - crypto_registry_pool, - crypto_registry, - populated_base_pool_registry, - max_coins, - ) - - -def test_crypto_factory_pools( - populated_metaregistry, - populated_base_pool_registry, - crypto_factory_pool, - crypto_factory, - max_coins, -): - - pre_test_checks(populated_metaregistry, crypto_factory_pool) - - _test_underlying_balances_getter( - populated_metaregistry, - crypto_factory_pool, - crypto_factory, - populated_base_pool_registry, - max_coins, - ) +import warnings + +import boa +import pytest + +from tests.utils import ZERO_ADDRESS + +EXCEPTION_POOLS = ["0x79a8C46DeA5aDa233ABaFFD40F3A0A2B1e5A4F27"] + + +def pre_test_checks(metaregistry, pool): + if sum(metaregistry.get_balances(pool)) == 0: + pytest.skip(f"Empty pool: {pool}") + + +def _get_underlying_balances( + metaregistry, pool, registry, base_pool_registry, max_coins +): + actual_output = [0] * max_coins + + try: + actual_output = registry.get_underlying_balances(pool) + + # registry getter borks, so we need to get balances the hard way: + except (ape.exceptions.ContractLogicError, AttributeError): + coins = metaregistry.get_coins(pool) + balances = metaregistry.get_balances(pool) + for idx, coin in enumerate(coins): + base_pool = base_pool_registry.get_base_pool_for_lp_token(coin) + + if base_pool != ZERO_ADDRESS: + basepool_lp_token_balance = balances[idx] + coin_contract = VyperContract(coin) + try: + lp_token_supply = coin_contract.totalSupply() + except (ape.exceptions.SignatureError, AttributeError): + assert "totalSupply" not in [ + i.name + for i in coin_contract.contract_type.view_methods + ] + pytest.skip( + f"Token {coin} method totalSupply() is not a view method" + ) + + ratio_in_pool = basepool_lp_token_balance / lp_token_supply + + base_pool_balances = metaregistry.get_balances(base_pool) + + for idy, balance in enumerate(base_pool_balances): + if coin == ZERO_ADDRESS: + break + actual_output[idx] = balance * ratio_in_pool + + break + + actual_output[idx] = balances[idx] + + return actual_output + + +def _test_underlying_balances_getter( + metaregistry, pool, registry, base_pool_registry, max_coins +): + actual_output = _get_underlying_balances( + metaregistry, pool, registry, base_pool_registry, max_coins + ) + metaregistry_output = metaregistry.get_underlying_balances(pool) + underlying_decimals = metaregistry.get_underlying_decimals(pool) + + for idx, registry_value in enumerate(actual_output): + try: + assert registry_value == pytest.approx( + metaregistry_output[idx] + * 10 ** (18 - underlying_decimals[idx]) + ) + + except AssertionError: + if pool in EXCEPTION_POOLS: + warnings.warn("Skipping test for pool: {}".format(pool)) + pytest.skip( + "Unresolved output from Borky pool: {}".format(pool) + ) + + +def test_stable_registry_pools( + populated_metaregistry, + stable_registry_pool, + stable_registry, + populated_base_pool_registry, + max_coins, +): + pre_test_checks(populated_metaregistry, stable_registry_pool) + _test_underlying_balances_getter( + populated_metaregistry, + stable_registry_pool, + stable_registry, + populated_base_pool_registry, + max_coins, + ) + + +def test_stable_factory_pools( + populated_metaregistry, + stable_factory_pool, + stable_factory, + populated_base_pool_registry, + max_coins, +): + pre_test_checks(populated_metaregistry, stable_factory_pool) + _test_underlying_balances_getter( + populated_metaregistry, + stable_factory_pool, + stable_factory, + populated_base_pool_registry, + max_coins, + ) + + +def test_crypto_registry_pools( + populated_metaregistry, + crypto_registry_pool, + crypto_registry, + populated_base_pool_registry, + max_coins, +): + pre_test_checks(populated_metaregistry, crypto_registry_pool) + _test_underlying_balances_getter( + populated_metaregistry, + crypto_registry_pool, + crypto_registry, + populated_base_pool_registry, + max_coins, + ) + + +def test_crypto_factory_pools( + populated_metaregistry, + populated_base_pool_registry, + crypto_factory_pool, + crypto_factory, + max_coins, +): + pre_test_checks(populated_metaregistry, crypto_factory_pool) + + _test_underlying_balances_getter( + populated_metaregistry, + crypto_factory_pool, + crypto_factory, + populated_base_pool_registry, + max_coins, + ) diff --git a/tests/mainnet/metaregistry/api/test_get_underlying_coins.py b/tests/mainnet/metaregistry/api/test_get_underlying_coins.py index 4146bcd..3faae91 100644 --- a/tests/mainnet/metaregistry/api/test_get_underlying_coins.py +++ b/tests/mainnet/metaregistry/api/test_get_underlying_coins.py @@ -1,161 +1,151 @@ -import warnings - -import boa -from boa import BoaError -from tests.utils import ZERO_ADDRESS - - -def _get_underlying_coins( - registry, base_pool_registry_updated, pool, max_coins -): - - coins = registry.get_coins(pool) - underlying_coins = [ZERO_ADDRESS] * max_coins - - for idx, coin in enumerate(coins): - - base_pool = base_pool_registry_updated.get_base_pool_for_lp_token(coin) - - if base_pool == ZERO_ADDRESS: - - underlying_coins[idx] = coin - - else: - - basepool_coins = base_pool_registry_updated.get_coins(base_pool) - - for bp_coin in basepool_coins: - - if bp_coin == ZERO_ADDRESS: - break - - underlying_coins[idx] = bp_coin - idx += 1 - - break - - return underlying_coins - - -def _check_fetched_underlying_coins(registry, pool, underlying_coins): - - try: - - registry_underlying_coins = registry.get_underlying_coins(pool) - if registry_underlying_coins != underlying_coins: - warnings.warn(f"Pool {pool} might be a lending pool.") - return registry_underlying_coins - - except BoaError: # TODO: Make error more specific - # virtual machine errors prop up for registry.get_underlying_coins if pool - # is completely depegged. We check this by setting up a revert check and - # then returning underlying_coins:git - balances = registry.get_balances(pool) - decimals = registry.get_decimals(pool) - - float_balances = [ - balances[i] / 10 ** decimals[i] for i in range(len(decimals)) - ] - if min(float_balances) < 1: - with boa.reverts(): - registry.get_underlying_coins(pool) - return underlying_coins - - return underlying_coins - - -def test_stable_registry_pools( - populated_metaregistry, - populated_base_pool_registry, - stable_registry_pool, - stable_registry, - max_coins, -): - - metaregistry_output = populated_metaregistry.get_underlying_coins( - stable_registry_pool - ) - actual_output = _get_underlying_coins( - stable_registry, - populated_base_pool_registry, - stable_registry_pool, - max_coins, - ) - actual_output = _check_fetched_underlying_coins( - stable_registry, stable_registry_pool, actual_output - ) - - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] - - -def test_stable_factory_pools( - populated_metaregistry, - populated_base_pool_registry, - stable_factory_pool, - stable_factory, - max_coins, -): - - metaregistry_output = populated_metaregistry.get_underlying_coins( - stable_factory_pool - ) - actual_output = _get_underlying_coins( - stable_factory, - populated_base_pool_registry, - stable_factory_pool, - max_coins, - ) - actual_output = _check_fetched_underlying_coins( - stable_factory, stable_factory_pool, actual_output - ) - - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] - - -def test_crypto_registry_pools( - populated_metaregistry, - populated_base_pool_registry, - crypto_registry_pool, - crypto_registry, - max_coins, -): - - metaregistry_output = populated_metaregistry.get_underlying_coins( - crypto_registry_pool - ) - actual_output = _get_underlying_coins( - crypto_registry, - populated_base_pool_registry, - crypto_registry_pool, - max_coins, - ) - actual_output = _check_fetched_underlying_coins( - crypto_registry, crypto_registry_pool, actual_output - ) - - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] - - -def test_crypto_factory_pools( - populated_metaregistry, - populated_base_pool_registry, - crypto_factory_pool, - crypto_factory, - max_coins, -): - - metaregistry_output = populated_metaregistry.get_underlying_coins( - crypto_factory_pool - ) - actual_output = _get_underlying_coins( - crypto_factory, - populated_base_pool_registry, - crypto_factory_pool, - max_coins, - ) - - for idx, coin in enumerate(actual_output): - assert coin == metaregistry_output[idx] +import warnings + +import boa +from boa import BoaError + +from tests.utils import ZERO_ADDRESS + + +def _get_underlying_coins( + registry, base_pool_registry_updated, pool, max_coins +): + coins = registry.get_coins(pool) + underlying_coins = [ZERO_ADDRESS] * max_coins + + for idx, coin in enumerate(coins): + base_pool = base_pool_registry_updated.get_base_pool_for_lp_token(coin) + + if base_pool == ZERO_ADDRESS: + underlying_coins[idx] = coin + + else: + basepool_coins = base_pool_registry_updated.get_coins(base_pool) + + for bp_coin in basepool_coins: + if bp_coin == ZERO_ADDRESS: + break + + underlying_coins[idx] = bp_coin + idx += 1 + + break + + return underlying_coins + + +def _check_fetched_underlying_coins(registry, pool, underlying_coins): + try: + registry_underlying_coins = registry.get_underlying_coins(pool) + if registry_underlying_coins != underlying_coins: + warnings.warn(f"Pool {pool} might be a lending pool.") + return registry_underlying_coins + + except BoaError: # TODO: Make error more specific + # virtual machine errors prop up for registry.get_underlying_coins if pool + # is completely depegged. We check this by setting up a revert check and + # then returning underlying_coins:git + balances = registry.get_balances(pool) + decimals = registry.get_decimals(pool) + + float_balances = [ + balances[i] / 10 ** decimals[i] for i in range(len(decimals)) + ] + if min(float_balances) < 1: + with boa.reverts(): + registry.get_underlying_coins(pool) + return underlying_coins + + return underlying_coins + + +def test_stable_registry_pools( + populated_metaregistry, + populated_base_pool_registry, + stable_registry_pool, + stable_registry, + max_coins, +): + metaregistry_output = populated_metaregistry.get_underlying_coins( + stable_registry_pool + ) + actual_output = _get_underlying_coins( + stable_registry, + populated_base_pool_registry, + stable_registry_pool, + max_coins, + ) + actual_output = _check_fetched_underlying_coins( + stable_registry, stable_registry_pool, actual_output + ) + + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] + + +def test_stable_factory_pools( + populated_metaregistry, + populated_base_pool_registry, + stable_factory_pool, + stable_factory, + max_coins, +): + metaregistry_output = populated_metaregistry.get_underlying_coins( + stable_factory_pool + ) + actual_output = _get_underlying_coins( + stable_factory, + populated_base_pool_registry, + stable_factory_pool, + max_coins, + ) + actual_output = _check_fetched_underlying_coins( + stable_factory, stable_factory_pool, actual_output + ) + + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] + + +def test_crypto_registry_pools( + populated_metaregistry, + populated_base_pool_registry, + crypto_registry_pool, + crypto_registry, + max_coins, +): + metaregistry_output = populated_metaregistry.get_underlying_coins( + crypto_registry_pool + ) + actual_output = _get_underlying_coins( + crypto_registry, + populated_base_pool_registry, + crypto_registry_pool, + max_coins, + ) + actual_output = _check_fetched_underlying_coins( + crypto_registry, crypto_registry_pool, actual_output + ) + + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] + + +def test_crypto_factory_pools( + populated_metaregistry, + populated_base_pool_registry, + crypto_factory_pool, + crypto_factory, + max_coins, +): + metaregistry_output = populated_metaregistry.get_underlying_coins( + crypto_factory_pool + ) + actual_output = _get_underlying_coins( + crypto_factory, + populated_base_pool_registry, + crypto_factory_pool, + max_coins, + ) + + for idx, coin in enumerate(actual_output): + assert coin == metaregistry_output[idx] diff --git a/tests/mainnet/metaregistry/api/test_get_underlying_decimals.py b/tests/mainnet/metaregistry/api/test_get_underlying_decimals.py index 97e0383..7b39729 100644 --- a/tests/mainnet/metaregistry/api/test_get_underlying_decimals.py +++ b/tests/mainnet/metaregistry/api/test_get_underlying_decimals.py @@ -1,97 +1,96 @@ -import boa -import pytest -from tests.utils import ZERO_ADDRESS - -EXCEPTIONS = { - # eth: ankreth pool returns [18, 0] when it should return: - "0xA96A65c051bF88B4095Ee1f2451C2A9d43F53Ae2": [18, 18], - # compound pools. ctokens are 8 decimals. underlying is dai usdc: - "0xA2B47E3D5c44877cca798226B7B8118F9BFb7A56": [18, 6], - # cream-yearn cytokens are 8 decimals, whereas underlying is - # dai usdc usdt: - "0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF": [18, 6, 6], - # usdt pool has cDAI, cUSDC and USDT (which is [8, 8, 6]): - "0x52EA46506B9CC5Ef470C5bf89f17Dc28bB35D85C": [18, 6, 6], -} - - -def _test_underlying_decimals_getter(metaregistry, registry, pool): - - metaregistry_output = metaregistry.get_underlying_decimals(pool) - assert metaregistry_output[1] != 0 # there has to be a second coin! - - pool_is_metapool = metaregistry.is_meta(pool) - if pool in EXCEPTIONS: - actual_output = EXCEPTIONS[pool] - elif pool_is_metapool: - underlying_coins = metaregistry.get_underlying_coins(pool) - actual_output = [] - for i in range(len(underlying_coins)): - - if underlying_coins[i] == ZERO_ADDRESS: - actual_output.append(0) - continue - - try: - token_contract = VyperContract(underlying_coins[i]) - actual_output.append(token_contract.decimals()) - except ape.exceptions.ChainError: - pytest.skip("Unverified contract. Skipping test.") - except ape.exceptions.SignatureError: - if ( - underlying_coins[i] - == "0x6810e776880C02933D47DB1b9fc05908e5386b96" - ): - actual_output.append(18) # Gnosis Token - else: - pytest.skip( - "Unable to get decimals due to SignatureError. Skipping test." - ) - except AttributeError: - view_methods = [ - method.name - for method in token_contract.contract_type.view_methods - ] - if "decimals" not in view_methods: - pytest.skip( - f"no decimals() view method on {token_contract.address}" - ) - - assert actual_output[2] != 0 # there has to be a third coin! - else: - actual_output = list(registry.get_decimals(pool)) - - for idx, decimals in enumerate(actual_output): - assert decimals == metaregistry_output[idx] - - -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - _test_underlying_decimals_getter( - populated_metaregistry, stable_registry, stable_registry_pool - ) - - -def test_stable_factory_pools( - populated_metaregistry, stable_factory_pool, stable_factory -): - _test_underlying_decimals_getter( - populated_metaregistry, stable_factory, stable_factory_pool - ) - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, crypto_registry -): - _test_underlying_decimals_getter( - populated_metaregistry, crypto_registry, crypto_registry_pool - ) - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, crypto_factory -): - _test_underlying_decimals_getter( - populated_metaregistry, crypto_factory, crypto_factory_pool - ) +import boa +import pytest + +from tests.utils import ZERO_ADDRESS + +EXCEPTIONS = { + # eth: ankreth pool returns [18, 0] when it should return: + "0xA96A65c051bF88B4095Ee1f2451C2A9d43F53Ae2": [18, 18], + # compound pools. ctokens are 8 decimals. underlying is dai usdc: + "0xA2B47E3D5c44877cca798226B7B8118F9BFb7A56": [18, 6], + # cream-yearn cytokens are 8 decimals, whereas underlying is + # dai usdc usdt: + "0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF": [18, 6, 6], + # usdt pool has cDAI, cUSDC and USDT (which is [8, 8, 6]): + "0x52EA46506B9CC5Ef470C5bf89f17Dc28bB35D85C": [18, 6, 6], +} + + +def _test_underlying_decimals_getter(metaregistry, registry, pool): + metaregistry_output = metaregistry.get_underlying_decimals(pool) + assert metaregistry_output[1] != 0 # there has to be a second coin! + + pool_is_metapool = metaregistry.is_meta(pool) + if pool in EXCEPTIONS: + actual_output = EXCEPTIONS[pool] + elif pool_is_metapool: + underlying_coins = metaregistry.get_underlying_coins(pool) + actual_output = [] + for i in range(len(underlying_coins)): + if underlying_coins[i] == ZERO_ADDRESS: + actual_output.append(0) + continue + + try: + token_contract = VyperContract(underlying_coins[i]) + actual_output.append(token_contract.decimals()) + except ape.exceptions.ChainError: + pytest.skip("Unverified contract. Skipping test.") + except ape.exceptions.SignatureError: + if ( + underlying_coins[i] + == "0x6810e776880C02933D47DB1b9fc05908e5386b96" + ): + actual_output.append(18) # Gnosis Token + else: + pytest.skip( + "Unable to get decimals due to SignatureError. Skipping test." + ) + except AttributeError: + view_methods = [ + method.name + for method in token_contract.contract_type.view_methods + ] + if "decimals" not in view_methods: + pytest.skip( + f"no decimals() view method on {token_contract.address}" + ) + + assert actual_output[2] != 0 # there has to be a third coin! + else: + actual_output = list(registry.get_decimals(pool)) + + for idx, decimals in enumerate(actual_output): + assert decimals == metaregistry_output[idx] + + +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + _test_underlying_decimals_getter( + populated_metaregistry, stable_registry, stable_registry_pool + ) + + +def test_stable_factory_pools( + populated_metaregistry, stable_factory_pool, stable_factory +): + _test_underlying_decimals_getter( + populated_metaregistry, stable_factory, stable_factory_pool + ) + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, crypto_registry +): + _test_underlying_decimals_getter( + populated_metaregistry, crypto_registry, crypto_registry_pool + ) + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, crypto_factory +): + _test_underlying_decimals_getter( + populated_metaregistry, crypto_factory, crypto_factory_pool + ) diff --git a/tests/mainnet/metaregistry/api/test_get_virtual_price.py b/tests/mainnet/metaregistry/api/test_get_virtual_price.py index 5fe807a..fb7809e 100644 --- a/tests/mainnet/metaregistry/api/test_get_virtual_price.py +++ b/tests/mainnet/metaregistry/api/test_get_virtual_price.py @@ -1,170 +1,162 @@ -import warnings - -import boa -import pytest -from tests.utils import ZERO_ADDRESS - - -# ---- sanity checks since vprice getters can revert for specific pools states ---- - - -def _check_pool_has_no_liquidity(metaregistry, pool, pool_balances, lp_token): - - # skip if pool has little to no liquidity, since vprice queries will most likely bork: - if sum(pool_balances) == 0: - - with ape.reverts(): - metaregistry.get_virtual_price_from_lp_token(lp_token) - - pytest.skip(f"empty pool: {pool}") - - elif sum(pool_balances) < 100: # tiny pool - with ape.reverts(): - metaregistry.get_virtual_price_from_lp_token(lp_token) - - pytest.skip(f"tiny pool: {pool}") - - -def _check_skem_tokens_with_weird_decimals( - metaregistry, pool, lp_token, pool_balances, coins, coin_decimals -): - - # check if pool balances after accounting for decimals is legible. - # some scam tokens can have weird token properties (e.g. ELONX) - pool_balances_float = [] - for i in range(len(pool_balances)): - - if coins[i] == ZERO_ADDRESS: - break - - pool_balances_float.append(pool_balances[i] / 10 ** coin_decimals[i]) - - if ( - coin_decimals[i] == 0 - and VyperContract(metaregistry.get_coins(pool)[0]).decimals() == 0 - ): - with ape.reverts(): - metaregistry.get_virtual_price_from_lp_token(lp_token) - pytest.skip( - f"skem token {coins[i]} in pool {pool} with zero decimals" - ) - - return pool_balances_float - - -def _check_pool_is_depegged( - metaregistry, - pool, - pool_balances, - pool_balances_float, - coin_decimals, - lp_token, -): - - for i in range(len(pool_balances)): - # check if pool balances are skewed: vprice calc will bork if one of the coin - # balances is close to zero. - if ( - max(pool_balances_float) - min(pool_balances_float) - == pytest.approx(max(pool_balances_float)) - and min(pool_balances_float) < 1 - ): - try: - with ape.reverts(): - metaregistry.get_virtual_price_from_lp_token(lp_token) - - pytest.skip( - f"skewed pool: {pool} as num coins (decimals divided) at index {i} is " - f"{pool_balances[i] / 10 ** coin_decimals[i]}" - ) - except AssertionError: # ok to catch this assertion error since we continue testing - warnings.warn( - "pool virtual price getter did not revert. continuing test" - ) - - -def pre_test_checks(metaregistry, pool): - - pool_balances = metaregistry.get_balances(pool) - lp_token = metaregistry.get_lp_token(pool) - - _check_pool_has_no_liquidity(metaregistry, pool, pool_balances, lp_token) - - coin_decimals = metaregistry.get_decimals(pool) - coins = metaregistry.get_coins(pool) - - pool_balances_float = _check_skem_tokens_with_weird_decimals( - metaregistry, pool, lp_token, pool_balances, coins, coin_decimals - ) - - _check_pool_is_depegged( - metaregistry, - pool, - pool_balances, - pool_balances_float, - coin_decimals, - lp_token, - ) - - return lp_token - - -# ---- tests ---- - - -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - # if checks fail, pytest skips, else lp_token is returned: - lp_token = pre_test_checks(populated_metaregistry, stable_registry_pool) - actual_output = stable_registry.get_virtual_price_from_lp_token(lp_token) - metaregistry_output = ( - populated_metaregistry.get_virtual_price_from_lp_token(lp_token) - ) - assert actual_output == metaregistry_output - - -def test_stable_factory_pools( - populated_metaregistry, stable_factory_pool, curve_pool -): - - # if checks fail, pytest skips, else lp_token is returned: - lp_token = pre_test_checks(populated_metaregistry, stable_factory_pool) - - try: - actual_output = curve_pool(stable_factory_pool).get_virtual_price() - metaregistry_output = ( - populated_metaregistry.get_virtual_price_from_lp_token(lp_token) - ) - assert actual_output == metaregistry_output - except ape.exceptions.ContractLogicError: - with ape.reverts(): - populated_metaregistry.get_virtual_price_from_lp_token(lp_token) - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, crypto_registry -): - - # if checks fail, pytest skips, else lp_token is returned: - lp_token = pre_test_checks(populated_metaregistry, crypto_registry_pool) - actual_output = crypto_registry.get_virtual_price_from_lp_token(lp_token) - metaregistry_output = ( - populated_metaregistry.get_virtual_price_from_lp_token(lp_token) - ) - assert actual_output == metaregistry_output - - -def test_crypto_factory_pools( - populated_metaregistry, crypto_factory_pool, curve_pool -): - - # if checks fail, pytest skips, else lp_token is returned: - lp_token = pre_test_checks(populated_metaregistry, crypto_factory_pool) - actual_output = curve_pool(crypto_factory_pool).get_virtual_price() - - metaregistry_output = ( - populated_metaregistry.get_virtual_price_from_lp_token(lp_token) - ) - assert actual_output == metaregistry_output +import warnings + +import boa +import pytest + +from tests.utils import ZERO_ADDRESS + +# ---- sanity checks since vprice getters can revert for specific pools states ---- + + +def _check_pool_has_no_liquidity(metaregistry, pool, pool_balances, lp_token): + # skip if pool has little to no liquidity, since vprice queries will most likely bork: + if sum(pool_balances) == 0: + with ape.reverts(): + metaregistry.get_virtual_price_from_lp_token(lp_token) + + pytest.skip(f"empty pool: {pool}") + + elif sum(pool_balances) < 100: # tiny pool + with ape.reverts(): + metaregistry.get_virtual_price_from_lp_token(lp_token) + + pytest.skip(f"tiny pool: {pool}") + + +def _check_skem_tokens_with_weird_decimals( + metaregistry, pool, lp_token, pool_balances, coins, coin_decimals +): + # check if pool balances after accounting for decimals is legible. + # some scam tokens can have weird token properties (e.g. ELONX) + pool_balances_float = [] + for i in range(len(pool_balances)): + if coins[i] == ZERO_ADDRESS: + break + + pool_balances_float.append(pool_balances[i] / 10 ** coin_decimals[i]) + + if ( + coin_decimals[i] == 0 + and VyperContract(metaregistry.get_coins(pool)[0]).decimals() == 0 + ): + with ape.reverts(): + metaregistry.get_virtual_price_from_lp_token(lp_token) + pytest.skip( + f"skem token {coins[i]} in pool {pool} with zero decimals" + ) + + return pool_balances_float + + +def _check_pool_is_depegged( + metaregistry, + pool, + pool_balances, + pool_balances_float, + coin_decimals, + lp_token, +): + for i in range(len(pool_balances)): + # check if pool balances are skewed: vprice calc will bork if one of the coin + # balances is close to zero. + if ( + max(pool_balances_float) - min(pool_balances_float) + == pytest.approx(max(pool_balances_float)) + and min(pool_balances_float) < 1 + ): + try: + with ape.reverts(): + metaregistry.get_virtual_price_from_lp_token(lp_token) + + pytest.skip( + f"skewed pool: {pool} as num coins (decimals divided) at index {i} is " + f"{pool_balances[i] / 10 ** coin_decimals[i]}" + ) + except ( + AssertionError + ): # ok to catch this assertion error since we continue testing + warnings.warn( + "pool virtual price getter did not revert. continuing test" + ) + + +def pre_test_checks(metaregistry, pool): + pool_balances = metaregistry.get_balances(pool) + lp_token = metaregistry.get_lp_token(pool) + + _check_pool_has_no_liquidity(metaregistry, pool, pool_balances, lp_token) + + coin_decimals = metaregistry.get_decimals(pool) + coins = metaregistry.get_coins(pool) + + pool_balances_float = _check_skem_tokens_with_weird_decimals( + metaregistry, pool, lp_token, pool_balances, coins, coin_decimals + ) + + _check_pool_is_depegged( + metaregistry, + pool, + pool_balances, + pool_balances_float, + coin_decimals, + lp_token, + ) + + return lp_token + + +# ---- tests ---- + + +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + # if checks fail, pytest skips, else lp_token is returned: + lp_token = pre_test_checks(populated_metaregistry, stable_registry_pool) + actual_output = stable_registry.get_virtual_price_from_lp_token(lp_token) + metaregistry_output = ( + populated_metaregistry.get_virtual_price_from_lp_token(lp_token) + ) + assert actual_output == metaregistry_output + + +def test_stable_factory_pools( + populated_metaregistry, stable_factory_pool, curve_pool +): + # if checks fail, pytest skips, else lp_token is returned: + lp_token = pre_test_checks(populated_metaregistry, stable_factory_pool) + + try: + actual_output = curve_pool(stable_factory_pool).get_virtual_price() + metaregistry_output = ( + populated_metaregistry.get_virtual_price_from_lp_token(lp_token) + ) + assert actual_output == metaregistry_output + except ape.exceptions.ContractLogicError: + with ape.reverts(): + populated_metaregistry.get_virtual_price_from_lp_token(lp_token) + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, crypto_registry +): + # if checks fail, pytest skips, else lp_token is returned: + lp_token = pre_test_checks(populated_metaregistry, crypto_registry_pool) + actual_output = crypto_registry.get_virtual_price_from_lp_token(lp_token) + metaregistry_output = ( + populated_metaregistry.get_virtual_price_from_lp_token(lp_token) + ) + assert actual_output == metaregistry_output + + +def test_crypto_factory_pools( + populated_metaregistry, crypto_factory_pool, curve_pool +): + # if checks fail, pytest skips, else lp_token is returned: + lp_token = pre_test_checks(populated_metaregistry, crypto_factory_pool) + actual_output = curve_pool(crypto_factory_pool).get_virtual_price() + + metaregistry_output = ( + populated_metaregistry.get_virtual_price_from_lp_token(lp_token) + ) + assert actual_output == metaregistry_output diff --git a/tests/mainnet/metaregistry/api/test_pool_is_metapool.py b/tests/mainnet/metaregistry/api/test_pool_is_metapool.py index 5393737..ec20c8c 100644 --- a/tests/mainnet/metaregistry/api/test_pool_is_metapool.py +++ b/tests/mainnet/metaregistry/api/test_pool_is_metapool.py @@ -1,48 +1,45 @@ -from tests.utils import ZERO_ADDRESS - - -def test_stable_registry_pools( - populated_metaregistry, stable_registry_pool, stable_registry -): - - actual_output = stable_registry.is_meta(stable_registry_pool) - metaregistry_output = populated_metaregistry.is_meta(stable_registry_pool) - assert actual_output == metaregistry_output - - -def test_stable_factory_pools( - populated_metaregistry, stable_factory_pool, stable_factory -): - - actual_output = stable_factory.is_meta(stable_factory_pool) - metaregistry_output = populated_metaregistry.is_meta(stable_factory_pool) - assert actual_output == metaregistry_output - - -def test_crypto_registry_pools( - populated_metaregistry, crypto_registry_pool, crypto_registry -): - - actual_output = crypto_registry.is_meta(crypto_registry_pool) - metaregistry_output = populated_metaregistry.is_meta(crypto_registry_pool) - assert actual_output == metaregistry_output - - -def test_crypto_factory_pools( - populated_metaregistry, - populated_base_pool_registry, - crypto_factory_pool, - crypto_factory, -): - coins = crypto_factory.get_coins(crypto_factory_pool) - actual_output = False - for i in range(len(coins)): - if ( - populated_base_pool_registry.get_base_pool_for_lp_token(coins[i]) - != ZERO_ADDRESS - ): - actual_output = True - break - - metaregistry_output = populated_metaregistry.is_meta(crypto_factory_pool) - assert actual_output == metaregistry_output +from tests.utils import ZERO_ADDRESS + + +def test_stable_registry_pools( + populated_metaregistry, stable_registry_pool, stable_registry +): + actual_output = stable_registry.is_meta(stable_registry_pool) + metaregistry_output = populated_metaregistry.is_meta(stable_registry_pool) + assert actual_output == metaregistry_output + + +def test_stable_factory_pools( + populated_metaregistry, stable_factory_pool, stable_factory +): + actual_output = stable_factory.is_meta(stable_factory_pool) + metaregistry_output = populated_metaregistry.is_meta(stable_factory_pool) + assert actual_output == metaregistry_output + + +def test_crypto_registry_pools( + populated_metaregistry, crypto_registry_pool, crypto_registry +): + actual_output = crypto_registry.is_meta(crypto_registry_pool) + metaregistry_output = populated_metaregistry.is_meta(crypto_registry_pool) + assert actual_output == metaregistry_output + + +def test_crypto_factory_pools( + populated_metaregistry, + populated_base_pool_registry, + crypto_factory_pool, + crypto_factory, +): + coins = crypto_factory.get_coins(crypto_factory_pool) + actual_output = False + for i in range(len(coins)): + if ( + populated_base_pool_registry.get_base_pool_for_lp_token(coins[i]) + != ZERO_ADDRESS + ): + actual_output = True + break + + metaregistry_output = populated_metaregistry.is_meta(crypto_factory_pool) + assert actual_output == metaregistry_output diff --git a/tests/mainnet/metaregistry/api/test_pool_is_registered.py b/tests/mainnet/metaregistry/api/test_pool_is_registered.py index 095cbe2..3edc834 100644 --- a/tests/mainnet/metaregistry/api/test_pool_is_registered.py +++ b/tests/mainnet/metaregistry/api/test_pool_is_registered.py @@ -1,2 +1,2 @@ -def test_all_pools(populated_metaregistry, pool): - assert populated_metaregistry.is_registered(pool) +def test_all_pools(populated_metaregistry, pool): + assert populated_metaregistry.is_registered(pool) diff --git a/tests/mainnet/metaregistry/test_add_remove_update_registry.py b/tests/mainnet/metaregistry/test_add_remove_update_registry.py index f5a81ab..62c40a1 100644 --- a/tests/mainnet/metaregistry/test_add_remove_update_registry.py +++ b/tests/mainnet/metaregistry/test_add_remove_update_registry.py @@ -1,53 +1,53 @@ -import boa - - -def test_revert_unauthorised_add_registry_handler( - metaregistry, unauthorised_address, random_address -): - with boa.reverts(): - tx = metaregistry.add_registry_handler( - random_address, sender=unauthorised_address - ) - assert tx.revert_msg == "dev: only owner" - - -def test_revert_unauthorised_update_registry_handler( - populated_metaregistry, unauthorised_address, random_address -): - with boa.reverts(): - tx = populated_metaregistry.update_registry_handler( - 0, random_address, sender=unauthorised_address - ) - assert tx.revert_msg == "dev: only owner" - - -def test_update_registry_handler_invalid_registry( - populated_metaregistry, random_address, owner -): - with boa.reverts(): - populated_metaregistry.update_registry_handler( - 10, random_address, sender=owner - ) - - -def test_update_registry_handler( - populated_metaregistry, - stable_registry_handler, - stable_registry_handler_index, - random_address, - owner, -): - assert ( - populated_metaregistry.get_registry(stable_registry_handler_index) - == stable_registry_handler.address - ) - - populated_metaregistry.update_registry_handler( - stable_registry_handler_index, - random_address, - sender=owner, - ) - assert ( - populated_metaregistry.get_registry(stable_registry_handler_index) - == random_address - ) +import boa + + +def test_revert_unauthorised_add_registry_handler( + metaregistry, unauthorised_address, random_address +): + with boa.reverts(): + tx = metaregistry.add_registry_handler( + random_address, sender=unauthorised_address + ) + assert tx.revert_msg == "dev: only owner" + + +def test_revert_unauthorised_update_registry_handler( + populated_metaregistry, unauthorised_address, random_address +): + with boa.reverts(): + tx = populated_metaregistry.update_registry_handler( + 0, random_address, sender=unauthorised_address + ) + assert tx.revert_msg == "dev: only owner" + + +def test_update_registry_handler_invalid_registry( + populated_metaregistry, random_address, owner +): + with boa.reverts(): + populated_metaregistry.update_registry_handler( + 10, random_address, sender=owner + ) + + +def test_update_registry_handler( + populated_metaregistry, + stable_registry_handler, + stable_registry_handler_index, + random_address, + owner, +): + assert ( + populated_metaregistry.get_registry(stable_registry_handler_index) + == stable_registry_handler.address + ) + + populated_metaregistry.update_registry_handler( + stable_registry_handler_index, + random_address, + sender=owner, + ) + assert ( + populated_metaregistry.get_registry(stable_registry_handler_index) + == random_address + ) diff --git a/tests/mainnet/metaregistry/test_base_registry_tracking.py b/tests/mainnet/metaregistry/test_base_registry_tracking.py index 93cbcc8..6a9c0d9 100644 --- a/tests/mainnet/metaregistry/test_base_registry_tracking.py +++ b/tests/mainnet/metaregistry/test_base_registry_tracking.py @@ -1,93 +1,92 @@ -from tests.utils import ZERO_ADDRESS - - -def test_new_crypto_factory_pool( - metaregistry, crypto_factory, tokens, lp_tokens, alice_address -): - test_pool_name = "test_pool" - - assert ( - metaregistry.find_pool_for_coins( - tokens["dai"], lp_tokens["cvxFXSFXS-f"], 0 - ) - == ZERO_ADDRESS - ) - - crypto_factory.deploy_pool( - test_pool_name, - test_pool_name, - [tokens["dai"], lp_tokens["cvxFXSFXS-f"]], - 200000000, - 100000000000000, - 1000000, - 10000000, - 10000000000, - 5000000000000000, - 5500000000000, - 5000000000, - 600, - 994000214704046300, - sender=alice_address, - ) - new_pool = crypto_factory.pool_list(crypto_factory.pool_count() - 1) - lp_token = crypto_factory.get_token(new_pool) - - assert ( - metaregistry.get_coins(new_pool) - == [tokens["dai"], lp_tokens["cvxFXSFXS-f"]] - + [ZERO_ADDRESS] * 6 - ) - assert test_pool_name in metaregistry.get_pool_name(new_pool) - assert metaregistry.get_pool_from_lp_token(lp_token) == new_pool - assert ( - metaregistry.find_pool_for_coins( - tokens["dai"], lp_tokens["cvxFXSFXS-f"], 0 - ) - == new_pool - ) - - -def test_new_stable_factory_pool( - metaregistry, stable_factory, lp_tokens, alice_address -): - test_pool_name = "test_pool" - - assert ( - metaregistry.find_pool_for_coins( - lp_tokens["bveCVX-CVX-f"], lp_tokens["cvxFXSFXS-f"], 0 - ) - == ZERO_ADDRESS - ) - - stable_factory.deploy_plain_pool( - test_pool_name, - test_pool_name, - [ - lp_tokens["bveCVX-CVX-f"], - lp_tokens["cvxFXSFXS-f"], - ZERO_ADDRESS, - ZERO_ADDRESS, - ], - 10000, - 4000000, - 0, - 0, - sender=alice_address, - ) - - new_pool = stable_factory.pool_list(stable_factory.pool_count() - 1) - lp_token = new_pool # pool == lp_token fot stable_factory - - assert ( - metaregistry.get_coins(new_pool) - == [lp_tokens["bveCVX-CVX-f"], lp_tokens["cvxFXSFXS-f"]] - + [ZERO_ADDRESS] * 6 - ) - assert test_pool_name in metaregistry.get_pool_name(new_pool) - assert metaregistry.get_pool_from_lp_token(lp_token) == new_pool - assert ( - metaregistry.find_pool_for_coins( - lp_tokens["bveCVX-CVX-f"], lp_tokens["cvxFXSFXS-f"], 0 - ) - == new_pool - ) +from tests.utils import ZERO_ADDRESS + + +def test_new_crypto_factory_pool( + metaregistry, crypto_factory, tokens, lp_tokens, alice_address +): + test_pool_name = "test_pool" + + assert ( + metaregistry.find_pool_for_coins( + tokens["dai"], lp_tokens["cvxFXSFXS-f"], 0 + ) + == ZERO_ADDRESS + ) + + crypto_factory.deploy_pool( + test_pool_name, + test_pool_name, + [tokens["dai"], lp_tokens["cvxFXSFXS-f"]], + 200000000, + 100000000000000, + 1000000, + 10000000, + 10000000000, + 5000000000000000, + 5500000000000, + 5000000000, + 600, + 994000214704046300, + sender=alice_address, + ) + new_pool = crypto_factory.pool_list(crypto_factory.pool_count() - 1) + lp_token = crypto_factory.get_token(new_pool) + + assert ( + metaregistry.get_coins(new_pool) + == [tokens["dai"], lp_tokens["cvxFXSFXS-f"]] + [ZERO_ADDRESS] * 6 + ) + assert test_pool_name in metaregistry.get_pool_name(new_pool) + assert metaregistry.get_pool_from_lp_token(lp_token) == new_pool + assert ( + metaregistry.find_pool_for_coins( + tokens["dai"], lp_tokens["cvxFXSFXS-f"], 0 + ) + == new_pool + ) + + +def test_new_stable_factory_pool( + metaregistry, stable_factory, lp_tokens, alice_address +): + test_pool_name = "test_pool" + + assert ( + metaregistry.find_pool_for_coins( + lp_tokens["bveCVX-CVX-f"], lp_tokens["cvxFXSFXS-f"], 0 + ) + == ZERO_ADDRESS + ) + + stable_factory.deploy_plain_pool( + test_pool_name, + test_pool_name, + [ + lp_tokens["bveCVX-CVX-f"], + lp_tokens["cvxFXSFXS-f"], + ZERO_ADDRESS, + ZERO_ADDRESS, + ], + 10000, + 4000000, + 0, + 0, + sender=alice_address, + ) + + new_pool = stable_factory.pool_list(stable_factory.pool_count() - 1) + lp_token = new_pool # pool == lp_token fot stable_factory + + assert ( + metaregistry.get_coins(new_pool) + == [lp_tokens["bveCVX-CVX-f"], lp_tokens["cvxFXSFXS-f"]] + + [ZERO_ADDRESS] * 6 + ) + assert test_pool_name in metaregistry.get_pool_name(new_pool) + assert metaregistry.get_pool_from_lp_token(lp_token) == new_pool + assert ( + metaregistry.find_pool_for_coins( + lp_tokens["bveCVX-CVX-f"], lp_tokens["cvxFXSFXS-f"], 0 + ) + == new_pool + ) diff --git a/tests/mainnet/registries/test_add_remove_basepool.py b/tests/mainnet/registries/test_add_remove_basepool.py index abe0e06..479e878 100644 --- a/tests/mainnet/registries/test_add_remove_basepool.py +++ b/tests/mainnet/registries/test_add_remove_basepool.py @@ -1,144 +1,140 @@ -import boa -from tests.utils import ZERO_ADDRESS - - -def test_revert_unauthorised_add_base_pool( - owner, unauthorised_address, base_pools -): - - base_pool_registry = ape.project.BasePoolRegistry.deploy(sender=owner) - - base_pool_data = base_pools["tripool"] - with ape.reverts(): - base_pool_registry.add_base_pool( - base_pool_data["pool"], - base_pool_data["lp_token"], - base_pool_data["num_coins"], - base_pool_data["is_legacy"], - base_pool_data["is_lending"], - base_pool_data["is_v2"], - sender=unauthorised_address, - ) - - -def test_add_basepool(owner, base_pools, tokens): - - base_pool_registry = ape.project.BasePoolRegistry.deploy(sender=owner) - - base_pool_count = base_pool_registry.base_pool_count() - base_pool_data = base_pools["tripool"] - tripool = base_pool_data["pool"] - tripool_lp_token = base_pool_data["lp_token"] - - base_pool_registry.add_base_pool( - base_pool_data["pool"], - base_pool_data["lp_token"], - base_pool_data["num_coins"], - base_pool_data["is_legacy"], - base_pool_data["is_lending"], - base_pool_data["is_v2"], - sender=owner, - ) - - assert base_pool_registry.base_pool_count() == base_pool_count + 1 - assert ( - base_pool_registry.get_base_pool_for_lp_token(tripool_lp_token) - == tripool - ) - assert base_pool_registry.get_lp_token(tripool) == tripool_lp_token - assert not base_pool_registry.is_legacy(tripool) - assert not base_pool_registry.is_v2(tripool) - assert not base_pool_registry.is_lending(tripool) - - base_pool_coins = base_pool_registry.get_coins(tripool) - assert base_pool_coins[0].lower() == tokens["dai"].lower() - assert base_pool_coins[1].lower() == tokens["usdc"].lower() - assert base_pool_coins[2].lower() == tokens["usdt"].lower() - assert base_pool_coins[3] == ZERO_ADDRESS - assert base_pool_registry.get_n_coins(tripool) == 3 - - base_pool_coin_decimals = base_pool_registry.get_decimals(tripool) - assert base_pool_coin_decimals[0] == 18 - assert base_pool_coin_decimals[1] == 6 - assert base_pool_coin_decimals[2] == 6 - - -def test_add_basepool_with_legacy_abi(owner, base_pools, tokens): - - base_pool_registry = ape.project.BasePoolRegistry.deploy(sender=owner) - - base_pool_data = base_pools["sbtc"] - assert base_pool_data["is_legacy"] - - btc_basepool = base_pool_data["pool"] - - base_pool_registry.add_base_pool( - base_pool_data["pool"], - base_pool_data["lp_token"], - base_pool_data["num_coins"], - base_pool_data["is_legacy"], - base_pool_data["is_lending"], - base_pool_data["is_v2"], - sender=owner, - ) - - assert base_pool_registry.is_legacy(btc_basepool) - - base_pool_coins = base_pool_registry.get_coins(btc_basepool) - assert base_pool_coins[0].lower() == tokens["renbtc"].lower() - assert base_pool_coins[1].lower() == tokens["wbtc"].lower() - assert base_pool_coins[2].lower() == tokens["sbtc"].lower() - assert base_pool_coins[3] == ZERO_ADDRESS - assert base_pool_registry.get_n_coins(btc_basepool) == 3 - - -def test_revert_unauthorised_remove_base_pool( - populated_base_pool_registry, unauthorised_address, base_pools -): - - tripool_address = base_pools["tripool"]["pool"] - - assert ( - populated_base_pool_registry.get_lp_token(tripool_address) - != ZERO_ADDRESS - ) - with ape.reverts(): - populated_base_pool_registry.remove_base_pool( - tripool_address, sender=unauthorised_address - ) - - -def test_remove_base_pool(populated_base_pool_registry, owner, base_pools): - - tripool_address = base_pools["tripool"]["pool"] - tripool_lp_token = base_pools["tripool"]["lp_token"] - - base_pool_count = populated_base_pool_registry.base_pool_count() - last_base_pool = populated_base_pool_registry.base_pool_list( - base_pool_count - 1 - ) - base_pool_location = populated_base_pool_registry.get_location( - tripool_address - ) - populated_base_pool_registry.remove_base_pool( - tripool_address, sender=owner - ) - - assert ( - populated_base_pool_registry.base_pool_count() == base_pool_count - 1 - ) - assert ( - populated_base_pool_registry.get_lp_token(tripool_address) - == ZERO_ADDRESS - ) - assert ( - populated_base_pool_registry.get_base_pool_for_lp_token( - tripool_lp_token - ) - == ZERO_ADDRESS - ) - assert ( - populated_base_pool_registry.base_pool_list(base_pool_location) - == last_base_pool - ) - assert populated_base_pool_registry.get_n_coins(tripool_address) == 0 +import boa + +from tests.utils import ZERO_ADDRESS + + +def test_revert_unauthorised_add_base_pool( + owner, unauthorised_address, base_pools +): + base_pool_registry = ape.project.BasePoolRegistry.deploy(sender=owner) + + base_pool_data = base_pools["tripool"] + with ape.reverts(): + base_pool_registry.add_base_pool( + base_pool_data["pool"], + base_pool_data["lp_token"], + base_pool_data["num_coins"], + base_pool_data["is_legacy"], + base_pool_data["is_lending"], + base_pool_data["is_v2"], + sender=unauthorised_address, + ) + + +def test_add_basepool(owner, base_pools, tokens): + base_pool_registry = ape.project.BasePoolRegistry.deploy(sender=owner) + + base_pool_count = base_pool_registry.base_pool_count() + base_pool_data = base_pools["tripool"] + tripool = base_pool_data["pool"] + tripool_lp_token = base_pool_data["lp_token"] + + base_pool_registry.add_base_pool( + base_pool_data["pool"], + base_pool_data["lp_token"], + base_pool_data["num_coins"], + base_pool_data["is_legacy"], + base_pool_data["is_lending"], + base_pool_data["is_v2"], + sender=owner, + ) + + assert base_pool_registry.base_pool_count() == base_pool_count + 1 + assert ( + base_pool_registry.get_base_pool_for_lp_token(tripool_lp_token) + == tripool + ) + assert base_pool_registry.get_lp_token(tripool) == tripool_lp_token + assert not base_pool_registry.is_legacy(tripool) + assert not base_pool_registry.is_v2(tripool) + assert not base_pool_registry.is_lending(tripool) + + base_pool_coins = base_pool_registry.get_coins(tripool) + assert base_pool_coins[0].lower() == tokens["dai"].lower() + assert base_pool_coins[1].lower() == tokens["usdc"].lower() + assert base_pool_coins[2].lower() == tokens["usdt"].lower() + assert base_pool_coins[3] == ZERO_ADDRESS + assert base_pool_registry.get_n_coins(tripool) == 3 + + base_pool_coin_decimals = base_pool_registry.get_decimals(tripool) + assert base_pool_coin_decimals[0] == 18 + assert base_pool_coin_decimals[1] == 6 + assert base_pool_coin_decimals[2] == 6 + + +def test_add_basepool_with_legacy_abi(owner, base_pools, tokens): + base_pool_registry = ape.project.BasePoolRegistry.deploy(sender=owner) + + base_pool_data = base_pools["sbtc"] + assert base_pool_data["is_legacy"] + + btc_basepool = base_pool_data["pool"] + + base_pool_registry.add_base_pool( + base_pool_data["pool"], + base_pool_data["lp_token"], + base_pool_data["num_coins"], + base_pool_data["is_legacy"], + base_pool_data["is_lending"], + base_pool_data["is_v2"], + sender=owner, + ) + + assert base_pool_registry.is_legacy(btc_basepool) + + base_pool_coins = base_pool_registry.get_coins(btc_basepool) + assert base_pool_coins[0].lower() == tokens["renbtc"].lower() + assert base_pool_coins[1].lower() == tokens["wbtc"].lower() + assert base_pool_coins[2].lower() == tokens["sbtc"].lower() + assert base_pool_coins[3] == ZERO_ADDRESS + assert base_pool_registry.get_n_coins(btc_basepool) == 3 + + +def test_revert_unauthorised_remove_base_pool( + populated_base_pool_registry, unauthorised_address, base_pools +): + tripool_address = base_pools["tripool"]["pool"] + + assert ( + populated_base_pool_registry.get_lp_token(tripool_address) + != ZERO_ADDRESS + ) + with ape.reverts(): + populated_base_pool_registry.remove_base_pool( + tripool_address, sender=unauthorised_address + ) + + +def test_remove_base_pool(populated_base_pool_registry, owner, base_pools): + tripool_address = base_pools["tripool"]["pool"] + tripool_lp_token = base_pools["tripool"]["lp_token"] + + base_pool_count = populated_base_pool_registry.base_pool_count() + last_base_pool = populated_base_pool_registry.base_pool_list( + base_pool_count - 1 + ) + base_pool_location = populated_base_pool_registry.get_location( + tripool_address + ) + populated_base_pool_registry.remove_base_pool( + tripool_address, sender=owner + ) + + assert ( + populated_base_pool_registry.base_pool_count() == base_pool_count - 1 + ) + assert ( + populated_base_pool_registry.get_lp_token(tripool_address) + == ZERO_ADDRESS + ) + assert ( + populated_base_pool_registry.get_base_pool_for_lp_token( + tripool_lp_token + ) + == ZERO_ADDRESS + ) + assert ( + populated_base_pool_registry.base_pool_list(base_pool_location) + == last_base_pool + ) + assert populated_base_pool_registry.get_n_coins(tripool_address) == 0 diff --git a/tests/mainnet/registries/test_add_remove_metapool.py b/tests/mainnet/registries/test_add_remove_metapool.py index ae12b1c..fbc8487 100644 --- a/tests/mainnet/registries/test_add_remove_metapool.py +++ b/tests/mainnet/registries/test_add_remove_metapool.py @@ -1,315 +1,300 @@ -import boa -from tests.utils import ZERO_ADDRESS - - -def test_add_metapool( - owner, - gauge_controller, - address_provider, - populated_base_pool_registry, - crypto_registry_pools, - base_pools, - tokens, -): - - crypto_registry = ape.project.CryptoRegistryV1.deploy( - address_provider, populated_base_pool_registry, sender=owner - ) - - pool_count = crypto_registry.pool_count() - assert pool_count == 0 - - pool_data = crypto_registry_pools["eurt3crv"] - - crypto_registry.add_pool( - pool_data["pool"], - pool_data["lp_token"], - pool_data["gauge"], - pool_data["zap"], - pool_data["num_coins"], - pool_data["name"], - pool_data["base_pool"], - pool_data["has_positive_rebasing_tokens"], - sender=owner, - ) - - assert crypto_registry.pool_count() == pool_count + 1 - - assert ( - crypto_registry.pool_list(pool_count).lower() - == pool_data["pool"].lower() - ) - assert ( - crypto_registry.get_zap(pool_data["pool"]).lower() - == pool_data["zap"].lower() - ) - assert ( - crypto_registry.get_lp_token(pool_data["pool"]).lower() - == pool_data["lp_token"].lower() - ) - assert ( - crypto_registry.get_pool_from_lp_token(pool_data["lp_token"]).lower() - == pool_data["pool"].lower() - ) - assert ( - crypto_registry.get_base_pool(pool_data["pool"]).lower() - == base_pools["tripool"]["pool"].lower() - ) - assert ( - crypto_registry.get_pool_name(pool_data["pool"]).lower() - == "eurtusd".lower() - ) - - assert crypto_registry.is_meta(pool_data["pool"]) - assert crypto_registry.get_n_coins(pool_data["pool"]) == 2 - assert crypto_registry.get_n_underlying_coins(pool_data["pool"]) == 4 - assert crypto_registry.get_decimals(pool_data["pool"]) == [6, 18] + [0] * 6 - assert ( - crypto_registry.get_underlying_decimals(pool_data["pool"]) - == [6, 18, 6, 6] + [0] * 4 - ) - - # gauge checks: - assert ( - crypto_registry.get_gauges(pool_data["pool"])[0][0].lower() - == pool_data["gauge"].lower() - ) - # special check: eurtusd has gauge_type 0 but it should be 5! The following check - # will pass regardless: - gauge_type_actual = gauge_controller.gauge_types(pool_data["gauge"]) - assert gauge_type_actual == 0 - # this has no impact since gauge types 0 and 5 are mainnet gauges and have the same - # gauge weight - assert ( - crypto_registry.get_gauges(pool_data["pool"])[1][0] - == gauge_type_actual - ) - - # coin checks: - assert [ - i.lower() for i in crypto_registry.get_coins(pool_data["pool"]) - ] == [ - tokens["eurt"].lower(), - base_pools["tripool"]["lp_token"].lower(), - ] + [ - ZERO_ADDRESS - ] * 6 - assert [ - i.lower() - for i in crypto_registry.get_underlying_coins(pool_data["pool"]) - ] == [ - tokens["eurt"].lower(), - tokens["dai"].lower(), - tokens["usdc"].lower(), - tokens["usdt"].lower(), - ] + [ - ZERO_ADDRESS - ] * 4 - - assert crypto_registry.get_coin_indices( - pool_data["pool"], tokens["eurt"], base_pools["tripool"]["lp_token"] - ) == ( - 0, - 1, - False, - ) - assert crypto_registry.get_coin_indices( - pool_data["pool"], base_pools["tripool"]["lp_token"], tokens["eurt"] - ) == ( - 1, - 0, - False, - ) - - # for exchange_underlying: - assert crypto_registry.get_coin_indices( - pool_data["pool"], tokens["eurt"], tokens["dai"] - ) == ( - 0, - 1, - True, - ) - assert crypto_registry.get_coin_indices( - pool_data["pool"], tokens["eurt"], tokens["usdc"] - ) == ( - 0, - 2, - True, - ) - assert crypto_registry.get_coin_indices( - pool_data["pool"], tokens["eurt"], tokens["usdt"] - ) == ( - 0, - 3, - True, - ) - # the following should revert since we didn't add any basepool lp token <> coin pairs: - for coin in [tokens["dai"], tokens["usdc"], tokens["usdt"]]: - with ape.reverts(): - crypto_registry.get_coin_indices( - pool_data["pool"], base_pools["tripool"]["lp_token"], coin - ) - - # find pool for coins: - coins = [ - tokens["eurt"], - base_pools["tripool"]["lp_token"], - tokens["dai"], - tokens["usdc"], - tokens["usdt"], - ] - for coin_a in coins: - for coin_b in coins: - - # if both coins are the same, then it should return ZERO_ADDRESS: - if coin_a == coin_b: - assert ( - crypto_registry.find_pool_for_coins(coin_a, coin_b, 0) - == ZERO_ADDRESS - ) - - # if basepool lp token <> underlying, then it should return ZERO_ADDRESS: - elif base_pools["tripool"]["lp_token"] in [ - coin_a, - coin_b, - ] and not set( - [tokens["dai"], tokens["usdc"], tokens["usdt"]] - ).isdisjoint( - [coin_a, coin_b] - ): - crypto_registry.find_pool_for_coins( - coin_a, coin_b, 0 - ) == ZERO_ADDRESS - - elif not set( - [tokens["dai"], tokens["usdc"], tokens["usdt"]] - ).isdisjoint([coin_a, coin_b]): - crypto_registry.find_pool_for_coins( - coin_a, coin_b, 0 - ) == ZERO_ADDRESS - - # everything else should go to EURTUSD pool: - else: - assert ( - crypto_registry.find_pool_for_coins( - coin_a, coin_b, 0 - ).lower() - == pool_data["pool"].lower() - ) - - -def test_remove_metapool( - address_provider, - populated_base_pool_registry, - owner, - crypto_registry_pools, - max_coins, - base_pools, - tokens, -): - - crypto_registry = ape.project.CryptoRegistryV1.deploy( - address_provider, populated_base_pool_registry, sender=owner - ) - - # add EURT3CRV pool - eurt3crv = crypto_registry_pools["eurt3crv"] - crypto_registry.add_pool( - eurt3crv["pool"], - eurt3crv["lp_token"], - eurt3crv["gauge"], - eurt3crv["zap"], - eurt3crv["num_coins"], - eurt3crv["name"], - eurt3crv["base_pool"], - eurt3crv["has_positive_rebasing_tokens"], - sender=owner, - ) - - # add tricrypto2 as the last pool: - tricrypto2 = crypto_registry_pools["tricrypto2"] - crypto_registry.add_pool( - tricrypto2["pool"], - tricrypto2["lp_token"], - tricrypto2["gauge"], - tricrypto2["zap"], - tricrypto2["num_coins"], - tricrypto2["name"], - tricrypto2["base_pool"], - tricrypto2["has_positive_rebasing_tokens"], - sender=owner, - ) - - pool_count = crypto_registry.pool_count() - last_pool = crypto_registry.pool_list(pool_count - 1) - - assert crypto_registry.pool_list(0).lower() == eurt3crv["pool"].lower() - - crypto_registry.remove_pool(eurt3crv["pool"], sender=owner) - - assert crypto_registry.pool_list(0).lower() == last_pool.lower() - assert ( - crypto_registry.pool_count() == pool_count - 1 - ) # one pool should be gone - - assert crypto_registry.get_zap(eurt3crv["pool"]) == ZERO_ADDRESS - assert ( - crypto_registry.get_lp_token(eurt3crv["pool"]) - == ZERO_ADDRESS - ) - assert ( - crypto_registry.get_pool_from_lp_token(eurt3crv["lp_token"]) - == ZERO_ADDRESS - ) - assert ( - crypto_registry.get_base_pool(eurt3crv["pool"]) - == ZERO_ADDRESS - ) - assert not crypto_registry.is_meta(eurt3crv["pool"]) - assert crypto_registry.get_pool_name(eurt3crv["pool"]) == "" - - assert crypto_registry.get_n_coins(eurt3crv["pool"]) == 0 - assert crypto_registry.get_n_underlying_coins(eurt3crv["pool"]) == 0 - assert crypto_registry.get_decimals(eurt3crv["pool"]) == [0] * max_coins - assert crypto_registry.get_underlying_decimals(eurt3crv["pool"]) == [0] * 8 - - # gauge checks: - assert ( - crypto_registry.get_gauges(eurt3crv["pool"])[0][0] - == ZERO_ADDRESS - ) - assert crypto_registry.get_gauges(eurt3crv["pool"])[1][0] == 0 - - # coin checks: - assert ( - crypto_registry.get_coins(eurt3crv["pool"]) - == [ZERO_ADDRESS] * 8 - ) - assert ( - crypto_registry.get_underlying_coins(eurt3crv["pool"]) - == [ZERO_ADDRESS] * 8 - ) - - coins = [ - tokens["eurt"], - base_pools["tripool"]["lp_token"], - tokens["dai"], - tokens["usdc"], - tokens["usdt"], - ] - # find pool for coins: - for coin_a in coins: - for coin_b in coins: - - assert crypto_registry.get_coin_indices( - eurt3crv["pool"], coin_a, coin_b - ) == ( - 0, - 0, - False, - ) - - assert ( - crypto_registry.find_pool_for_coins(coin_a, coin_b, 0) - == ZERO_ADDRESS - ) +import boa + +from tests.utils import ZERO_ADDRESS + + +def test_add_metapool( + owner, + gauge_controller, + address_provider, + populated_base_pool_registry, + crypto_registry_pools, + base_pools, + tokens, +): + crypto_registry = ape.project.CryptoRegistryV1.deploy( + address_provider, populated_base_pool_registry, sender=owner + ) + + pool_count = crypto_registry.pool_count() + assert pool_count == 0 + + pool_data = crypto_registry_pools["eurt3crv"] + + crypto_registry.add_pool( + pool_data["pool"], + pool_data["lp_token"], + pool_data["gauge"], + pool_data["zap"], + pool_data["num_coins"], + pool_data["name"], + pool_data["base_pool"], + pool_data["has_positive_rebasing_tokens"], + sender=owner, + ) + + assert crypto_registry.pool_count() == pool_count + 1 + + assert ( + crypto_registry.pool_list(pool_count).lower() + == pool_data["pool"].lower() + ) + assert ( + crypto_registry.get_zap(pool_data["pool"]).lower() + == pool_data["zap"].lower() + ) + assert ( + crypto_registry.get_lp_token(pool_data["pool"]).lower() + == pool_data["lp_token"].lower() + ) + assert ( + crypto_registry.get_pool_from_lp_token(pool_data["lp_token"]).lower() + == pool_data["pool"].lower() + ) + assert ( + crypto_registry.get_base_pool(pool_data["pool"]).lower() + == base_pools["tripool"]["pool"].lower() + ) + assert ( + crypto_registry.get_pool_name(pool_data["pool"]).lower() + == "eurtusd".lower() + ) + + assert crypto_registry.is_meta(pool_data["pool"]) + assert crypto_registry.get_n_coins(pool_data["pool"]) == 2 + assert crypto_registry.get_n_underlying_coins(pool_data["pool"]) == 4 + assert crypto_registry.get_decimals(pool_data["pool"]) == [6, 18] + [0] * 6 + assert ( + crypto_registry.get_underlying_decimals(pool_data["pool"]) + == [6, 18, 6, 6] + [0] * 4 + ) + + # gauge checks: + assert ( + crypto_registry.get_gauges(pool_data["pool"])[0][0].lower() + == pool_data["gauge"].lower() + ) + # special check: eurtusd has gauge_type 0 but it should be 5! The following check + # will pass regardless: + gauge_type_actual = gauge_controller.gauge_types(pool_data["gauge"]) + assert gauge_type_actual == 0 + # this has no impact since gauge types 0 and 5 are mainnet gauges and have the same + # gauge weight + assert ( + crypto_registry.get_gauges(pool_data["pool"])[1][0] + == gauge_type_actual + ) + + # coin checks: + assert [ + i.lower() for i in crypto_registry.get_coins(pool_data["pool"]) + ] == [ + tokens["eurt"].lower(), + base_pools["tripool"]["lp_token"].lower(), + ] + [ + ZERO_ADDRESS + ] * 6 + assert [ + i.lower() + for i in crypto_registry.get_underlying_coins(pool_data["pool"]) + ] == [ + tokens["eurt"].lower(), + tokens["dai"].lower(), + tokens["usdc"].lower(), + tokens["usdt"].lower(), + ] + [ + ZERO_ADDRESS + ] * 4 + + assert crypto_registry.get_coin_indices( + pool_data["pool"], tokens["eurt"], base_pools["tripool"]["lp_token"] + ) == ( + 0, + 1, + False, + ) + assert crypto_registry.get_coin_indices( + pool_data["pool"], base_pools["tripool"]["lp_token"], tokens["eurt"] + ) == ( + 1, + 0, + False, + ) + + # for exchange_underlying: + assert crypto_registry.get_coin_indices( + pool_data["pool"], tokens["eurt"], tokens["dai"] + ) == ( + 0, + 1, + True, + ) + assert crypto_registry.get_coin_indices( + pool_data["pool"], tokens["eurt"], tokens["usdc"] + ) == ( + 0, + 2, + True, + ) + assert crypto_registry.get_coin_indices( + pool_data["pool"], tokens["eurt"], tokens["usdt"] + ) == ( + 0, + 3, + True, + ) + # the following should revert since we didn't add any basepool lp token <> coin pairs: + for coin in [tokens["dai"], tokens["usdc"], tokens["usdt"]]: + with ape.reverts(): + crypto_registry.get_coin_indices( + pool_data["pool"], base_pools["tripool"]["lp_token"], coin + ) + + # find pool for coins: + coins = [ + tokens["eurt"], + base_pools["tripool"]["lp_token"], + tokens["dai"], + tokens["usdc"], + tokens["usdt"], + ] + for coin_a in coins: + for coin_b in coins: + # if both coins are the same, then it should return ZERO_ADDRESS: + if coin_a == coin_b: + assert ( + crypto_registry.find_pool_for_coins(coin_a, coin_b, 0) + == ZERO_ADDRESS + ) + + # if basepool lp token <> underlying, then it should return ZERO_ADDRESS: + elif base_pools["tripool"]["lp_token"] in [ + coin_a, + coin_b, + ] and not set( + [tokens["dai"], tokens["usdc"], tokens["usdt"]] + ).isdisjoint( + [coin_a, coin_b] + ): + crypto_registry.find_pool_for_coins( + coin_a, coin_b, 0 + ) == ZERO_ADDRESS + + elif not set( + [tokens["dai"], tokens["usdc"], tokens["usdt"]] + ).isdisjoint([coin_a, coin_b]): + crypto_registry.find_pool_for_coins( + coin_a, coin_b, 0 + ) == ZERO_ADDRESS + + # everything else should go to EURTUSD pool: + else: + assert ( + crypto_registry.find_pool_for_coins( + coin_a, coin_b, 0 + ).lower() + == pool_data["pool"].lower() + ) + + +def test_remove_metapool( + address_provider, + populated_base_pool_registry, + owner, + crypto_registry_pools, + max_coins, + base_pools, + tokens, +): + crypto_registry = ape.project.CryptoRegistryV1.deploy( + address_provider, populated_base_pool_registry, sender=owner + ) + + # add EURT3CRV pool + eurt3crv = crypto_registry_pools["eurt3crv"] + crypto_registry.add_pool( + eurt3crv["pool"], + eurt3crv["lp_token"], + eurt3crv["gauge"], + eurt3crv["zap"], + eurt3crv["num_coins"], + eurt3crv["name"], + eurt3crv["base_pool"], + eurt3crv["has_positive_rebasing_tokens"], + sender=owner, + ) + + # add tricrypto2 as the last pool: + tricrypto2 = crypto_registry_pools["tricrypto2"] + crypto_registry.add_pool( + tricrypto2["pool"], + tricrypto2["lp_token"], + tricrypto2["gauge"], + tricrypto2["zap"], + tricrypto2["num_coins"], + tricrypto2["name"], + tricrypto2["base_pool"], + tricrypto2["has_positive_rebasing_tokens"], + sender=owner, + ) + + pool_count = crypto_registry.pool_count() + last_pool = crypto_registry.pool_list(pool_count - 1) + + assert crypto_registry.pool_list(0).lower() == eurt3crv["pool"].lower() + + crypto_registry.remove_pool(eurt3crv["pool"], sender=owner) + + assert crypto_registry.pool_list(0).lower() == last_pool.lower() + assert ( + crypto_registry.pool_count() == pool_count - 1 + ) # one pool should be gone + + assert crypto_registry.get_zap(eurt3crv["pool"]) == ZERO_ADDRESS + assert crypto_registry.get_lp_token(eurt3crv["pool"]) == ZERO_ADDRESS + assert ( + crypto_registry.get_pool_from_lp_token(eurt3crv["lp_token"]) + == ZERO_ADDRESS + ) + assert crypto_registry.get_base_pool(eurt3crv["pool"]) == ZERO_ADDRESS + assert not crypto_registry.is_meta(eurt3crv["pool"]) + assert crypto_registry.get_pool_name(eurt3crv["pool"]) == "" + + assert crypto_registry.get_n_coins(eurt3crv["pool"]) == 0 + assert crypto_registry.get_n_underlying_coins(eurt3crv["pool"]) == 0 + assert crypto_registry.get_decimals(eurt3crv["pool"]) == [0] * max_coins + assert crypto_registry.get_underlying_decimals(eurt3crv["pool"]) == [0] * 8 + + # gauge checks: + assert crypto_registry.get_gauges(eurt3crv["pool"])[0][0] == ZERO_ADDRESS + assert crypto_registry.get_gauges(eurt3crv["pool"])[1][0] == 0 + + # coin checks: + assert crypto_registry.get_coins(eurt3crv["pool"]) == [ZERO_ADDRESS] * 8 + assert ( + crypto_registry.get_underlying_coins(eurt3crv["pool"]) + == [ZERO_ADDRESS] * 8 + ) + + coins = [ + tokens["eurt"], + base_pools["tripool"]["lp_token"], + tokens["dai"], + tokens["usdc"], + tokens["usdt"], + ] + # find pool for coins: + for coin_a in coins: + for coin_b in coins: + assert crypto_registry.get_coin_indices( + eurt3crv["pool"], coin_a, coin_b + ) == ( + 0, + 0, + False, + ) + + assert ( + crypto_registry.find_pool_for_coins(coin_a, coin_b, 0) + == ZERO_ADDRESS + ) diff --git a/tests/mainnet/registries/test_add_remove_pool.py b/tests/mainnet/registries/test_add_remove_pool.py index 08cf4d3..92291dc 100644 --- a/tests/mainnet/registries/test_add_remove_pool.py +++ b/tests/mainnet/registries/test_add_remove_pool.py @@ -1,243 +1,227 @@ -import boa -from tests.utils import ZERO_ADDRESS - - -def test_revert_unauthorised_add_pool( - crypto_registry, unauthorised_address, crypto_registry_pools -): - - pool_data = crypto_registry_pools["tricrypto2"] - - with ape.reverts(): - crypto_registry.add_pool( - pool_data["pool"], - pool_data["lp_token"], - pool_data["gauge"], - pool_data["zap"], - pool_data["num_coins"], - pool_data["name"], - pool_data["base_pool"], - pool_data["has_positive_rebasing_tokens"], - sender=unauthorised_address, - ) - - -def test_revert_add_existing_pool( - crypto_registry, owner, crypto_registry_pools -): - - pool_data = crypto_registry_pools["tricrypto2"] - - with ape.reverts(): - crypto_registry.add_pool( - pool_data["pool"], - pool_data["lp_token"], - pool_data["gauge"], - pool_data["zap"], - pool_data["num_coins"], - pool_data["name"], - pool_data["base_pool"], - pool_data["has_positive_rebasing_tokens"], - sender=owner, - ) - - -def test_add_pool( - crypto_registry_pools, - populated_base_pool_registry, - address_provider, - owner, - tokens, -): - - crypto_registry = ape.project.CryptoRegistryV1.deploy( - address_provider.address, populated_base_pool_registry, sender=owner - ) - - pool_count = crypto_registry.pool_count() - assert pool_count == 0 - - pool_data = crypto_registry_pools["tricrypto2"] - - crypto_registry.add_pool( - pool_data["pool"], - pool_data["lp_token"], - pool_data["gauge"], - pool_data["zap"], - pool_data["num_coins"], - pool_data["name"], - pool_data["base_pool"], - pool_data["has_positive_rebasing_tokens"], - sender=owner, - ) - - assert crypto_registry.pool_count() == pool_count + 1 - assert crypto_registry.pool_list(pool_count) == pool_data["pool"] - assert crypto_registry.get_zap(pool_data["pool"]) == pool_data["zap"] - assert ( - crypto_registry.get_lp_token(pool_data["pool"]) - == pool_data["lp_token"] - ) - assert ( - crypto_registry.get_pool_from_lp_token(pool_data["lp_token"]) - == pool_data["pool"] - ) - assert ( - crypto_registry.get_base_pool(pool_data["pool"]) - == ZERO_ADDRESS - ) - assert not crypto_registry.is_meta(pool_data["pool"]) - assert crypto_registry.get_pool_name(pool_data["pool"]) == "tricrypto2" - - assert crypto_registry.get_n_coins(pool_data["pool"]) == 3 - assert crypto_registry.get_decimals(pool_data["pool"]) == [ - 6, - 8, - 18, - 0, - 0, - 0, - 0, - 0, - ] - assert ( - crypto_registry.get_gauges(pool_data["pool"])[0][0] - == pool_data["gauge"] - ) - assert ( - crypto_registry.get_gauges(pool_data["pool"])[1][0] == 5 - ) # gauge type is 5 - assert [ - i.lower() for i in crypto_registry.get_coins(pool_data["pool"]) - ] == [ - tokens["usdt"].lower(), - tokens["wbtc"].lower(), - tokens["weth"].lower(), - ] + [ - ZERO_ADDRESS - ] * 5 - - # check if coins and underlying coins (if any) are added to the underlying market: - assert crypto_registry.get_coin_indices( - pool_data["pool"], tokens["usdt"], tokens["wbtc"] - ) == ( - 0, - 1, - False, - ) - assert crypto_registry.get_coin_indices( - pool_data["pool"], tokens["wbtc"], tokens["weth"] - ) == ( - 1, - 2, - False, - ) - assert ( - crypto_registry.find_pool_for_coins( - tokens["usdt"], tokens["wbtc"], 0 - ).lower() - == pool_data["pool"].lower() - ) - - -def test_revert_unauthorised_remove_pool( - crypto_registry, unauthorised_address, crypto_registry_pools -): - - with ape.reverts(): - crypto_registry.remove_pool( - crypto_registry_pools["tricrypto2"]["pool"], - sender=unauthorised_address, - ) - - -def test_remove_pool( - crypto_registry_pools, - address_provider, - populated_base_pool_registry, - owner, - max_coins, - tokens, -): - - crypto_registry = ape.project.CryptoRegistryV1.deploy( - address_provider.address, populated_base_pool_registry, sender=owner - ) - - # add pool to be removed: - tricrypto2 = crypto_registry_pools["tricrypto2"] - - crypto_registry.add_pool( - tricrypto2["pool"], - tricrypto2["lp_token"], - tricrypto2["gauge"], - tricrypto2["zap"], - tricrypto2["num_coins"], - tricrypto2["name"], - tricrypto2["base_pool"], - tricrypto2["has_positive_rebasing_tokens"], - sender=owner, - ) - - # add EURSUSDC pool as the last pool, since it has no coins overlapping - # and is not a metapool: - eursusdc = crypto_registry_pools["eursusdc"] - - crypto_registry.add_pool( - eursusdc["pool"], - eursusdc["lp_token"], - eursusdc["gauge"], - eursusdc["zap"], - eursusdc["num_coins"], - eursusdc["name"], - eursusdc["base_pool"], - eursusdc["has_positive_rebasing_tokens"], - sender=owner, - ) - - pool_count = crypto_registry.pool_count() - last_pool = crypto_registry.pool_list(pool_count - 1) - - assert crypto_registry.pool_list(0).lower() == tricrypto2["pool"].lower() - crypto_registry.remove_pool(tricrypto2["pool"], sender=owner) - - assert crypto_registry.pool_list(0).lower() == last_pool.lower() - assert ( - crypto_registry.pool_count() == pool_count - 1 - ) # one pool should be gone - assert ( - crypto_registry.get_zap(tricrypto2["pool"]) == ZERO_ADDRESS - ) - assert ( - crypto_registry.get_lp_token(tricrypto2["pool"]) - == ZERO_ADDRESS - ) - assert ( - crypto_registry.get_pool_from_lp_token(tricrypto2["lp_token"]) - == ZERO_ADDRESS - ) - assert crypto_registry.get_pool_name(tricrypto2["pool"]) == "" - - assert crypto_registry.get_n_coins(tricrypto2["pool"]) == 0 - assert crypto_registry.get_decimals(tricrypto2["pool"]) == [0] * max_coins - assert ( - crypto_registry.get_gauges(tricrypto2["pool"])[0][0] - == ZERO_ADDRESS - ) - assert crypto_registry.get_gauges(tricrypto2["pool"])[1][0] == 0 - - assert ( - crypto_registry.get_coins(tricrypto2["pool"]) - == [ZERO_ADDRESS] * max_coins - ) - - for coin_i in [tokens["usdt"], tokens["wbtc"], tokens["weth"]]: - for coin_j in [tokens["usdt"], tokens["wbtc"], tokens["weth"]]: - - assert crypto_registry.get_coin_indices( - tricrypto2["pool"], coin_i, coin_j - ) == ( - 0, - 0, - False, - ) +import boa + +from tests.utils import ZERO_ADDRESS + + +def test_revert_unauthorised_add_pool( + crypto_registry, unauthorised_address, crypto_registry_pools +): + pool_data = crypto_registry_pools["tricrypto2"] + + with ape.reverts(): + crypto_registry.add_pool( + pool_data["pool"], + pool_data["lp_token"], + pool_data["gauge"], + pool_data["zap"], + pool_data["num_coins"], + pool_data["name"], + pool_data["base_pool"], + pool_data["has_positive_rebasing_tokens"], + sender=unauthorised_address, + ) + + +def test_revert_add_existing_pool( + crypto_registry, owner, crypto_registry_pools +): + pool_data = crypto_registry_pools["tricrypto2"] + + with ape.reverts(): + crypto_registry.add_pool( + pool_data["pool"], + pool_data["lp_token"], + pool_data["gauge"], + pool_data["zap"], + pool_data["num_coins"], + pool_data["name"], + pool_data["base_pool"], + pool_data["has_positive_rebasing_tokens"], + sender=owner, + ) + + +def test_add_pool( + crypto_registry_pools, + populated_base_pool_registry, + address_provider, + owner, + tokens, +): + crypto_registry = ape.project.CryptoRegistryV1.deploy( + address_provider.address, populated_base_pool_registry, sender=owner + ) + + pool_count = crypto_registry.pool_count() + assert pool_count == 0 + + pool_data = crypto_registry_pools["tricrypto2"] + + crypto_registry.add_pool( + pool_data["pool"], + pool_data["lp_token"], + pool_data["gauge"], + pool_data["zap"], + pool_data["num_coins"], + pool_data["name"], + pool_data["base_pool"], + pool_data["has_positive_rebasing_tokens"], + sender=owner, + ) + + assert crypto_registry.pool_count() == pool_count + 1 + assert crypto_registry.pool_list(pool_count) == pool_data["pool"] + assert crypto_registry.get_zap(pool_data["pool"]) == pool_data["zap"] + assert ( + crypto_registry.get_lp_token(pool_data["pool"]) + == pool_data["lp_token"] + ) + assert ( + crypto_registry.get_pool_from_lp_token(pool_data["lp_token"]) + == pool_data["pool"] + ) + assert crypto_registry.get_base_pool(pool_data["pool"]) == ZERO_ADDRESS + assert not crypto_registry.is_meta(pool_data["pool"]) + assert crypto_registry.get_pool_name(pool_data["pool"]) == "tricrypto2" + + assert crypto_registry.get_n_coins(pool_data["pool"]) == 3 + assert crypto_registry.get_decimals(pool_data["pool"]) == [ + 6, + 8, + 18, + 0, + 0, + 0, + 0, + 0, + ] + assert ( + crypto_registry.get_gauges(pool_data["pool"])[0][0] + == pool_data["gauge"] + ) + assert ( + crypto_registry.get_gauges(pool_data["pool"])[1][0] == 5 + ) # gauge type is 5 + assert [ + i.lower() for i in crypto_registry.get_coins(pool_data["pool"]) + ] == [ + tokens["usdt"].lower(), + tokens["wbtc"].lower(), + tokens["weth"].lower(), + ] + [ + ZERO_ADDRESS + ] * 5 + + # check if coins and underlying coins (if any) are added to the underlying market: + assert crypto_registry.get_coin_indices( + pool_data["pool"], tokens["usdt"], tokens["wbtc"] + ) == ( + 0, + 1, + False, + ) + assert crypto_registry.get_coin_indices( + pool_data["pool"], tokens["wbtc"], tokens["weth"] + ) == ( + 1, + 2, + False, + ) + assert ( + crypto_registry.find_pool_for_coins( + tokens["usdt"], tokens["wbtc"], 0 + ).lower() + == pool_data["pool"].lower() + ) + + +def test_revert_unauthorised_remove_pool( + crypto_registry, unauthorised_address, crypto_registry_pools +): + with ape.reverts(): + crypto_registry.remove_pool( + crypto_registry_pools["tricrypto2"]["pool"], + sender=unauthorised_address, + ) + + +def test_remove_pool( + crypto_registry_pools, + address_provider, + populated_base_pool_registry, + owner, + max_coins, + tokens, +): + crypto_registry = ape.project.CryptoRegistryV1.deploy( + address_provider.address, populated_base_pool_registry, sender=owner + ) + + # add pool to be removed: + tricrypto2 = crypto_registry_pools["tricrypto2"] + + crypto_registry.add_pool( + tricrypto2["pool"], + tricrypto2["lp_token"], + tricrypto2["gauge"], + tricrypto2["zap"], + tricrypto2["num_coins"], + tricrypto2["name"], + tricrypto2["base_pool"], + tricrypto2["has_positive_rebasing_tokens"], + sender=owner, + ) + + # add EURSUSDC pool as the last pool, since it has no coins overlapping + # and is not a metapool: + eursusdc = crypto_registry_pools["eursusdc"] + + crypto_registry.add_pool( + eursusdc["pool"], + eursusdc["lp_token"], + eursusdc["gauge"], + eursusdc["zap"], + eursusdc["num_coins"], + eursusdc["name"], + eursusdc["base_pool"], + eursusdc["has_positive_rebasing_tokens"], + sender=owner, + ) + + pool_count = crypto_registry.pool_count() + last_pool = crypto_registry.pool_list(pool_count - 1) + + assert crypto_registry.pool_list(0).lower() == tricrypto2["pool"].lower() + crypto_registry.remove_pool(tricrypto2["pool"], sender=owner) + + assert crypto_registry.pool_list(0).lower() == last_pool.lower() + assert ( + crypto_registry.pool_count() == pool_count - 1 + ) # one pool should be gone + assert crypto_registry.get_zap(tricrypto2["pool"]) == ZERO_ADDRESS + assert crypto_registry.get_lp_token(tricrypto2["pool"]) == ZERO_ADDRESS + assert ( + crypto_registry.get_pool_from_lp_token(tricrypto2["lp_token"]) + == ZERO_ADDRESS + ) + assert crypto_registry.get_pool_name(tricrypto2["pool"]) == "" + + assert crypto_registry.get_n_coins(tricrypto2["pool"]) == 0 + assert crypto_registry.get_decimals(tricrypto2["pool"]) == [0] * max_coins + assert crypto_registry.get_gauges(tricrypto2["pool"])[0][0] == ZERO_ADDRESS + assert crypto_registry.get_gauges(tricrypto2["pool"])[1][0] == 0 + + assert ( + crypto_registry.get_coins(tricrypto2["pool"]) + == [ZERO_ADDRESS] * max_coins + ) + + for coin_i in [tokens["usdt"], tokens["wbtc"], tokens["weth"]]: + for coin_j in [tokens["usdt"], tokens["wbtc"], tokens["weth"]]: + assert crypto_registry.get_coin_indices( + tricrypto2["pool"], coin_i, coin_j + ) == ( + 0, + 0, + False, + ) diff --git a/tests/utils.py b/tests/utils.py index d445a28..e7220f2 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,36 +1,46 @@ -from os import path -from typing import Union - -import boa -from boa.vyper.contract import VyperContract -from eth_account.signers.local import LocalAccount - -ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" -BASE_DIR = path.join(path.dirname(path.abspath(__file__)), "..") - - -def get_contract_pools(contract: str, address: str) -> list[str]: - """ - Retrieves the list of pools from a deployed contract with the given address. - :param contract: The name of the contract to load. - :param address: The address of the deployed contract. - """ - registry = get_deployed_contract(contract, address) - return [registry.pool_list(i) for i in range(registry.pool_count())] - - -def get_deployed_contract(contract_abi: str, address: str) -> VyperContract: - """ - Loads a contract and retrieves a deployed instance of it with the given address. - TODO: Refactor calls to use fixtures instead of re-loading multiple times. - :param contract_abi: The name of the contract to load. - :param address: The address of the deployed contract. - """ - file_name = path.join(BASE_DIR, f"contracts/mainnet/abi/{contract_abi}.json") - return boa.load_abi(file_name).at(address) - - -def deploy_contract(contract: str, *args, sender: Union[LocalAccount, str], directory: str = ".", **kwargs) -> VyperContract: - file_name = path.join(BASE_DIR, f"contracts/mainnet/{directory}/{contract}.vy") - boa.env.eoa = sender if isinstance(sender, str) else sender.address - return boa.load(file_name, *args, **kwargs) +from os import path +from typing import Union + +import boa +from boa.vyper.contract import VyperContract +from eth_account.signers.local import LocalAccount + +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" +BASE_DIR = path.join(path.dirname(path.abspath(__file__)), "..") + + +def get_contract_pools(contract: str, address: str) -> list[str]: + """ + Retrieves the list of pools from a deployed contract with the given address. + :param contract: The name of the contract to load. + :param address: The address of the deployed contract. + """ + registry = get_deployed_contract(contract, address) + return [registry.pool_list(i) for i in range(registry.pool_count())] + + +def get_deployed_contract(contract_abi: str, address: str) -> VyperContract: + """ + Loads a contract and retrieves a deployed instance of it with the given address. + TODO: Refactor calls to use fixtures instead of re-loading multiple times. + :param contract_abi: The name of the contract to load. + :param address: The address of the deployed contract. + """ + file_name = path.join( + BASE_DIR, f"contracts/mainnet/abi/{contract_abi}.json" + ) + return boa.load_abi(file_name).at(address) + + +def deploy_contract( + contract: str, + *args, + sender: Union[LocalAccount, str], + directory: str = ".", + **kwargs, +) -> VyperContract: + file_name = path.join( + BASE_DIR, f"contracts/mainnet/{directory}/{contract}.vy" + ) + boa.env.eoa = sender if isinstance(sender, str) else sender.address + return boa.load(file_name, *args, **kwargs)