curvefi
metaregistry
Vyper

One Registry to Rule Them All

Last updated Jul 30, 2025
24
Stars
8
Forks
11
Issues
0
Stars/day
Attention Score
66
Language breakdown
No language data available.
Files click to expand
README

Curve Metaregistry

The metaregistry is a Curve Finance 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:

  • Curve Stable Registry: A registry of custom pool implementations deployed by Curve Core.
  • Curve Stable Factory: A permissionless StableSwap pool factory, which also acts as a registry for pools that its users create.
  • Curve Crypto Registry: A registry of custom CryptoSwap pool implementations deployed by Curve Core.
  • Curve Crypto Factory: A permissionless CryptoSwap 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.addregistryhandler 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.getregistryhandlersfrompool

Gets registries that a pool has been registered in. Usually, each pool is registered in a single registry.

In [1]: metaregistry.getregistryhandlersfrompool("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.getpoolname

Returns the name of the pool.

In [1]: metaregistry.getpoolname("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7")
Out[1]: '3pool'

MetaRegistry.is_meta

Meta-pools are pools that pair a coin to a base pool comprising multiple coins.

An example is the LUSD-3CRV pool which pairs Liquidity's LUSD against 3CRV, 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.getbasepool

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:

In [1]: metaregistry.getbasepool("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca")
Out[1]: '0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7'

It returns ZERO_ADDRESS if the pool has no base pool:

In [1]: metaregistry.getbasepool("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.getunderlyingcoins

Returns underlying coins in a pool. Returns underlying coins of the base pool if the pool is a metapool.

In [1]: metaregistry.getunderlyingcoins("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca")
Out[1]: [
    '0x5f98805A4E8be255a32880FDeC7F6728C6568bA0',
    '0x6B175474E89094C44Da98b954EedeAC495271d0F',
    '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
    '0xdAC17F958D2ee523a2206206994597C13D831ec7',
    ...
]

MetaRegistry.getncoins

Returns number of coins in a pool.

In [1]: metaregistry.getncoins("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7")
Out[1]: 3

MetaRegistry.getnunderlying_coins

Returns the total number of underlying coins in a pool.

In [1]: metaregistry.getnunderlying_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.getunderlyingdecimals

Returns decimals of coins returned by MetaRegistry.getunderlyingcoins

In [1]: metaregistry.getunderlyingdecimals("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.getunderlyingbalances

Returns a pool's balances of coins returned by MetaRegistry.getunderlyingcoins.

In [25]: populatedmetaregistry.getunderlying_balances("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca")
Out[25]: [5475800032746048063986567, 18068769367677440019648367, 17824609770086, 16989208807146, ...]

MetaRegistry.getadminbalances

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.getadminbalances("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, adminfee percentage, midfee and outfee. The fee is the dynamic fee charged per swap, and depends on the midfee (fee when the CryptoSwap pool is pegged) and the outfee. For understanding the dynamic fee algorithm, the reader is pointed to the CryptoSwap Paper.

In [1]: metaregistry.get_fees("0xd51a44d3fae010294c616388b506acda1bfaae46")
Out[1]: [5954883, 5000000000, 5000000, 30000000, 0, 0, 0, 0, 0, 0]

MetaRegistry.findpoolfor_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.findpoolfor_coins(
            "0x6B175474E89094C44Da98b954EedeAC495271d0F",
            "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
            0
        )
Out[1]: '0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7'

In [2]: metaregistry.findpoolfor_coins( "0x6B175474E89094C44Da98b954EedeAC495271d0F", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 1 ) Out[2]: '0xDeBF20617708857ebe4F679508E7b7863a8A8EeE'

MetaRegistry.findpoolsfor_coins

Returns a list of pools that holds two coins (even if the pool is a metapool).

In [1]: metaregistry.findpoolsfor_coins(
            "0x6B175474E89094C44Da98b954EedeAC495271d0F",
            "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        )
Out[1]:
['0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7',
 '0xDeBF20617708857ebe4F679508E7b7863a8A8EeE',
 '0x79a8C46DeA5aDa233ABaFFD40F3A0A2B1e5A4F27',
 '0xA2B47E3D5c44877cca798226B7B8118F9BFb7A56',
 '0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF',
 '0x06364f10B501e868329afBc005b3492902d6C763',
 '0xA5407eAE9Ba41422680e2e00537571bcC53efBfD',
 '0xA5407eAE9Ba41422680e2e00537571bcC53efBfD',
 '0x52EA46506B9CC5Ef470C5bf89f17Dc28bB35D85C',
 '0x45F783CCE6B7FF23B2ab2D70e416cdb7D6055f51']

MetaRegistry.getcoinindices

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.getcoinindices(
"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.getcoinindices(
"0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca",
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
)
Out[1]: (1, 2, True)

MetaRegistry.getpoolparams

Returns a pool's parameters.

For StableSwap, the getter returns the amplification coefficient (A) of the pool.

In [1]: metaregistry.getpoolparams("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7")
Out[1]: [2000, ... ]

For CryptoSwap, the getter returns:

  • Amplification coefficient (A)
  • Invariant (D)
  • Gamma coefficient (gamma)
  • Allowed extra profit
  • Fee gamma
  • Adjustment step
  • MA (moving average) half-time
In [1]: metaregistry.getpoolparams("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.getgaugetype

Gets the gauge type of the gauge associated with a pool.

In [1]: metaregistry.getgaugetype("0xd51a44d3fae010294c616388b506acda1bfaae46", 0, 0)
Out[1]: 5

MetaRegistry.getlptoken

Gets the address of the liquidity pool token minted by a pool.

In [1]: metaregistry.getlptoken("0xd51a44d3fae010294c616388b506acda1bfaae46")
Out[1]: '0xc4AD29ba4B3c580e6D59105FFf484999997675Ff'

MetaRegistry.getpoolasset_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.getpoolasset_type("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca")
Out[1]: 0

CryptoSwap pool example:

In [1]: metaregistry.getpoolasset_type("0xd51a44d3fae010294c616388b506acda1bfaae46")
Out[1]: 4

MetaRegistry.getpoolfromlptoken

Gets the pool associated with a liquidity pool token.

In [1]: metaregistry.getpoolfromlptoken("0xc4AD29ba4B3c580e6D59105FFf484999997675Ff")
Out[1]: '0xD51a44d3FaE010294C616388b506AcdA1bfAAE46'

MetaRegistry.getvirtualpricefromlp_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.getvirtualpricefromlp_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 for deployment and testing.

Testing

To run tests in interactive mode, please do the following:

> python -m pytest

Deployment and Adding Registries

Various deployment scripts are provided in the scripts folder.

Deployments

Ethereum Mainnet:

Roadmap

  • StableSwap-ng Factory Handler
  • Twocrypto-ng Factory Handler
  • Tricrypto-ng Factory Handler
  • Deployments of Metaregistry with the above handlers across multiple chains.

License

(c) Curve.Fi, 2023 - All rights reserved.

© 2026 GitRepoTrend · curvefi/metaregistry · Updated daily from GitHub