Deployer API
Liquidity Pools¶
Warning
Transaction will fail if the requirements are not met.
deploy_plain_pool¶
 The pool deployment is permissionless, but it must adhere to certain parameter limitations:
| Parameter | Limitation | 
|---|---|
_fee |  4000000 (0.04%) ≤ _fee ≤ 100000000 (1%) |  
- Valid 
_implementation_idx(cannot beZERO_ADDRESS). - Minimum of 2 coins and maximum of 4 coins.
 - Cannot pair with a coin which is included in a basepool.
 - If paired against plain ETH (0xE...EeE), ETH must be the first coin of the pool (
_coins[0] = plain ETH). - Maximum of 18 decimals for the coins.
 - No duplicate coins.
 
Factory.deploy_plain_pool(_name: String[32], _symbol: String[10], _coins: address[4], _A: uint256, _fee: uint256, _asset_type: uint256 = 0, _implementation_idx: uint256 = 0) → address: nonpayable
Function to deploy a plain pool.
Returns: Deployed pool (address).
Emits: PlainPoolDeployed
| Input | Type | Description | 
|---|---|---|
_name |  String[32] |  Name of the new plain pool | 
_symbol |  String[10] |  Symbol for the new pool’s LP token. This value will be concatenated with the factory symbol | 
_coins |  address[4] |  List of addresses of the coins being used in the pool | 
_A |  uint256 |  Amplification coefficient | 
_fee |  uint256 |  Trade fee, given as an integer with 1e10 precision |  
_asset_type |  uint256 |  Asset type of the pool as an integer. 0 = USD, 1 = ETH, 2 = BTC, 3 = Other |  
_implementation_idx |  uint256 |  Index of the implementation to use. All possible implementations for a pool of N_COINS can be publicly accessed via plain_implementations(N_COINS) |  
Source code
event PlainPoolDeployed:
    coins: address[MAX_PLAIN_COINS]
    A: uint256
    fee: uint256
    deployer: address
MAX_PLAIN_COINS: constant(int128) = 4  # max coins in a plain pool
@external
def deploy_plain_pool(
    _name: String[32],
    _symbol: String[10],
    _coins: address[MAX_PLAIN_COINS],
    _A: uint256,
    _fee: uint256,
    _asset_type: uint256 = 0,
    _implementation_idx: uint256 = 0,
) -> address:
    """
    @notice Deploy a new plain pool
    @param _name Name of the new plain pool
    @param _symbol Symbol for the new plain pool - will be
                   concatenated with factory symbol
    @param _coins List of addresses of the coins being used in the pool.
    @param _A Amplification co-efficient - a lower value here means
              less tolerance for imbalance within the pool's assets.
              Suggested values include:
               * Uncollateralized algorithmic stablecoins: 5-10
               * Non-redeemable, collateralized assets: 100
               * Redeemable assets: 200-400
    @param _fee Trade fee, given as an integer with 1e10 precision. The
                minimum fee is 0.04% (4000000), the maximum is 1% (100000000).
                50% of the fee is distributed to veCRV holders.
    @param _asset_type Asset type for pool, as an integer
                       0 = USD, 1 = ETH, 2 = BTC, 3 = Other
    @param _implementation_idx Index of the implementation to use. All possible
                implementations for a pool of N_COINS can be publicly accessed
                via `plain_implementations(N_COINS)`
    @return Address of the deployed pool
    """
    # fee must be between 0.04% and 1%
    assert _fee >= 4000000 and _fee <= 100000000, "Invalid fee"
    n_coins: uint256 = MAX_PLAIN_COINS
    rate_multipliers: uint256[MAX_PLAIN_COINS] = empty(uint256[MAX_PLAIN_COINS])
    decimals: uint256[MAX_PLAIN_COINS] = empty(uint256[MAX_PLAIN_COINS])
    for i in range(MAX_PLAIN_COINS):
        coin: address = _coins[i]
        if coin == ZERO_ADDRESS:
            assert i > 1, "Insufficient coins"
            n_coins = i
            break
        assert self.base_pool_assets[coin] == False, "Invalid asset, deploy a metapool"
        if _coins[i] == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE:
            assert i == 0, "ETH must be first coin"
            decimals[0] = 18
        else:
            decimals[i] = ERC20(coin).decimals()
            assert decimals[i] < 19, "Max 18 decimals for coins"
        rate_multipliers[i] = 10 ** (36 - decimals[i])
        for x in range(i, i+MAX_PLAIN_COINS):
            if x+1 == MAX_PLAIN_COINS:
                break
            if _coins[x+1] == ZERO_ADDRESS:
                break
            assert coin != _coins[x+1], "Duplicate coins"
    implementation: address = self.plain_implementations[n_coins][_implementation_idx]
    assert implementation != ZERO_ADDRESS, "Invalid implementation index"
    pool: address = create_forwarder_to(implementation)
    CurvePlainPool(pool).initialize(_name, _symbol, _coins, rate_multipliers, _A, _fee)
    length: uint256 = self.pool_count
    self.pool_list[length] = pool
    self.pool_count = length + 1
    self.pool_data[pool].decimals = decimals
    self.pool_data[pool].n_coins = n_coins
    self.pool_data[pool].base_pool = ZERO_ADDRESS
    self.pool_data[pool].implementation = implementation
    if _asset_type != 0:
        self.pool_data[pool].asset_type = _asset_type
    for i in range(MAX_PLAIN_COINS):
        coin: address = _coins[i]
        if coin == ZERO_ADDRESS:
            break
        self.pool_data[pool].coins[i] = coin
        raw_call(
            coin,
            concat(
                method_id("approve(address,uint256)"),
                convert(pool, bytes32),
                convert(MAX_UINT256, bytes32)
            )
        )
        for j in range(MAX_PLAIN_COINS):
            if i < j:
                swappable_coin: address = _coins[j]
                key: uint256 = bitwise_xor(convert(coin, uint256), convert(swappable_coin, uint256))
                length = self.market_counts[key]
                self.markets[key][length] = pool
                self.market_counts[key] = length + 1
    log PlainPoolDeployed(_coins, _A, _fee, msg.sender)
    return pool
deploy_metapool¶
 Limitations when deploying meta pools:
| Parameter | Limitation | 
|---|---|
_fee |  4000000 (0.04%) ≤ _fee ≤ 100000000 (0.1%) |  
- Valid 
_implementation_idx(cannot beZERO_ADDRESS). - Maximum of 18 decimals for the coins.
 
Factory.deploy_metapool(_base_pool: address, _name: String[32], _symbol: String[10], _coin: address, _A: uint256, _fee: uint256, _implementation_idx: uint256 = 0) -> address:
Function to deploy a metapool.
Returns: Deployed metapool (address).
Emits: MetaPoolDeployed
| Input | Type | Description | 
|---|---|---|
_base_pool |  address |  Address of the base pool to pair the token with | 
_name |  String[32] |  Name of the new metapool | 
_symbol |  String[10] |  Symbol for the new metapool’s LP token. This value will be concatenated with the base pool symbol. | 
_coin |  address |  Address of the coin being used in the metapool | 
_A |  uint256 |  Amplification coefficient | 
_fee |  uint256 |  Trade fee, given as an integer with 1e10 precision |  
_implementation_idx |  uint256 |  Index of the implementation to use. All possible implementations for a pool of N_COINS can be publicly accessed via plain_implementations(N_COINS) |  
Source code
event MetaPoolDeployed:
    coin: address
    base_pool: address
    A: uint256
    fee: uint256
    deployer: address
@external
def deploy_metapool(
    _base_pool: address,
    _name: String[32],
    _symbol: String[10],
    _coin: address,
    _A: uint256,
    _fee: uint256,
    _implementation_idx: uint256 = 0,
) -> address:
    """
    @notice Deploy a new metapool
    @param _base_pool Address of the base pool to use
                      within the metapool
    @param _name Name of the new metapool
    @param _symbol Symbol for the new metapool - will be
                   concatenated with the base pool symbol
    @param _coin Address of the coin being used in the metapool
    @param _A Amplification co-efficient - a higher value here means
              less tolerance for imbalance within the pool's assets.
              Suggested values include:
               * Uncollateralized algorithmic stablecoins: 5-10
               * Non-redeemable, collateralized assets: 100
               * Redeemable assets: 200-400
    @param _fee Trade fee, given as an integer with 1e10 precision. The
                minimum fee is 0.04% (4000000), the maximum is 1% (100000000).
                50% of the fee is distributed to veCRV holders.
    @param _implementation_idx Index of the implementation to use. All possible
                implementations for a BASE_POOL can be publicly accessed
                via `metapool_implementations(BASE_POOL)`
    @return Address of the deployed pool
    """
    # fee must be between 0.04% and 1%
    assert _fee >= 4000000 and _fee <= 100000000, "Invalid fee"
    implementation: address = self.base_pool_data[_base_pool].implementations[_implementation_idx]
    assert implementation != ZERO_ADDRESS, "Invalid implementation index"
    # things break if a token has >18 decimals
    decimals: uint256 = ERC20(_coin).decimals()
    assert decimals < 19, "Max 18 decimals for coins"
    pool: address = create_forwarder_to(implementation)
    CurvePool(pool).initialize(_name, _symbol, _coin, 10 ** (36 - decimals), _A, _fee)
    ERC20(_coin).approve(pool, MAX_UINT256)
    # add pool to pool_list
    length: uint256 = self.pool_count
    self.pool_list[length] = pool
    self.pool_count = length + 1
    base_lp_token: address = self.base_pool_data[_base_pool].lp_token
    self.pool_data[pool].decimals = [decimals, 0, 0, 0]
    self.pool_data[pool].n_coins = 2
    self.pool_data[pool].base_pool = _base_pool
    self.pool_data[pool].coins[0] = _coin
    self.pool_data[pool].coins[1] = self.base_pool_data[_base_pool].lp_token
    self.pool_data[pool].implementation = implementation
    is_finished: bool = False
    for i in range(MAX_COINS):
        swappable_coin: address = self.base_pool_data[_base_pool].coins[i]
        if swappable_coin == ZERO_ADDRESS:
            is_finished = True
            swappable_coin = base_lp_token
        key: uint256 = bitwise_xor(convert(_coin, uint256), convert(swappable_coin, uint256))
        length = self.market_counts[key]
        self.markets[key][length] = pool
        self.market_counts[key] = length + 1
        if is_finished:
            break
    log MetaPoolDeployed(_coin, _base_pool, _A, _fee, msg.sender)
    return pool
Liquidity Gauge¶
Info
Liquidity gauges can only be successfully deployed from the same contract from which the pool was deployed!
deploy_gauge¶
 Factory.deploy_gauge(_pool: address) -> address:
Function to deploy a liquidity gauge for a factory pool.
Returns: Deployed gauge (address).
Emits: LiquidityGaugeDeployed
| Input | Type | Description | 
|---|---|---|
_pool |  address |  Factory pool address to deploy a gauge for | 
Source code
event LiquidityGaugeDeployed:
    pool: address
    gauge: address
@external
def deploy_gauge(_pool: address) -> address:
    """
    @notice Deploy a liquidity gauge for a factory pool
    @param _pool Factory pool address to deploy a gauge for
    @return Address of the deployed gauge
    """
    assert self.pool_data[_pool].coins[0] != ZERO_ADDRESS, "Unknown pool"
    assert self.pool_data[_pool].liquidity_gauge == ZERO_ADDRESS, "Gauge already deployed"
    implementation: address = self.gauge_implementation
    assert implementation != ZERO_ADDRESS, "Gauge implementation not set"
    gauge: address = create_forwarder_to(implementation)
    LiquidityGauge(gauge).initialize(_pool)
    self.pool_data[_pool].liquidity_gauge = gauge
    log LiquidityGaugeDeployed(_pool, gauge)
    return gauge