Pool Factory Overview
Curve Pool Factories allow the permissionless deployment of liquidity pools, gauges, and LP tokens.
Every Factory contract from Curve comes with built-in functions designed to feed the MetaRegistry with information about the created pools. These functions will not be documented in this section. For more information, please read here.
Contract Source & Deployment
Factories are deployed on the Ethereum Mainnet as well as on Sidechains/L2. Although it might be the case that some pool types (e.g., cryptoswap pools) are not supported there yet.
A list of all deployed contracts can be found here.
Warning
The methods below might slightly vary depending on the Factory contract being examined. If there are any abnormalities or important standouts, they will be detailed as accurately as possible within the appropriate section!
Supported Pools¶
The various Curve Factories allow the deployment of pools with virtually any kind of asset combination, whether they are stable or volatile, rebasing or not, etc... Some pool variations (e.g., cryptoswap pool) might not be supported on sidechains/L2s yet.
Factory | Description | Supported Pools |
---|---|---|
StableSwap | Regular StableSwap | Plain and metapools |
StableSwap-NG | Improved StableSwap version | Plain pools with up to eight coins and metapools (more here) |
CryptoSwap | Regular CryptoSwap | Two-coin volatile assets (e.g., CRV<>ETH) |
CryptoSwap-NG | CryptoSwap New-Generation | Two-coin volatile assets (e.g., CRV<>ETH) |
Tricrypto-NG | Improved Tricrypto version (here) | Three-coin volatile assets (e.g., ETH<>BTC<>crvUSD) |
For an easy, non-technical explanation of the pool variations, visit: https://resources.curve.fi/lp/pools/
How are contracts deployed?¶
Pool, gauge, or LP token contracts are created according to their implementation contracts set within the Factory. Contracts deployed by newer factories combine both liquidity pool and LP token, whereas for older ones, they are separate contracts.
There are two ways the contracts are deployed:
create_forwarder_to
¶
Earlier factories like the regular stableswap or cryptoswap one use Vyper's built-in create_forwarder_to()
function (renamed to create_minimal_proxy_to
starting from Vyper version 0.3.4) to deploy liquidity pools, LP tokens, or gauge contracts.
The contracts then need to be initialized, which is done automatically.
Blueprint Contracts
¶
Newer factories make use of blueprints (EIP-5202). The contracts are directly created from their corresponding blueprint implementations. This is the most desired and used method for all newly deployed factories.
Fee Receiver¶
The fee receiver is set within the Factory and is a uniform address for all the deployed pools through a factory. The address can be changed by the admin
of the contract by calling the set_fee_receiver
method and setting a new address.
fee_receiver
¶
Factory.fee_receiver() -> address: view
Getter for the fee receiver of the pools admin fees.
Returns: fee receiver (address
).
set_fee_receiver
¶
Factory.set_fee_receiver(_pool: address, _fee_receiver: address)
Guarded Method
This function is only callable by the admin
of the contract.
Function to set a new fee receiver.
Input | Type | Description |
---|---|---|
_pool | address | This variable has no real use; insert a random address, otherwise the transaction will fail. |
_fee_receiver | address | Address of the new fee receiver |
Source code
# fee receiver for all pools
fee_receiver: public(address)
@external
def set_fee_receiver(_pool: address, _fee_receiver: address):
"""
@notice Set fee receiver for all pools
@param _pool Address of pool to set fee receiver for.
@param _fee_receiver Address that fees are sent to
"""
assert msg.sender == self.admin # dev: admin only
self.fee_receiver = _fee_receiver
Factory Contract Ownership¶
The admin
is the owner of the Factory contract and has the ability to call admin-only functions. Ownership can be transferred by first committing to the transfer of ownership (commit_transfer_ownership
), which then needs to be accepted by the future_admin
(accept_transfer_ownership
).
Most contracts are 'owned' by a proxy, which in turn is owned by the DAO. For some factories, the DAO is directly the owner.
admin
¶
Factory.admin() -> address: view
Getter for the admin of the Factory.
Returns: admin (address
).
future_admin
¶
Factory.future_admin() -> address: view
Getter for the future admin.
Returns: future admin (address
).
commit_transfer_ownership
¶
Factory.commit_transfer_ownership(_addr: address):
Guarded Method
This function is only callable by the admin
of the contract.
Function to commit a transfer of ownership. This function sets _addr
as the future admin of the contract. These changes need to be applied via accept_transfer_ownership
by the future admin itself.
Input | Type | Description |
---|---|---|
_addr | address | Address of the future admin |
Source code
accept_transfer_ownership
¶
Factory.accept_transfer_ownership():
Guarded Method
This function is only callable by the future_admin
of the contract.
Function to accept the ownership transfer.
Source code
admin: public(address)
future_admin: public(address)
@external
def accept_transfer_ownership():
"""
@notice Accept a pending ownership transfer
@dev Only callable by the new owner
"""
_admin: address = self.future_admin
assert msg.sender == _admin # dev: future admin only
self.admin = _admin
self.future_admin = empty(address)
Implementations¶
Pool, gauge, or LP token contracts are created according to their implementation contracts set within the Factory.
Technical documentation was done separately for each factory, as they partially vary from each other. Please refer to the corresponding section.
Warning
Implementation contracts are upgradable. They can either be replaced, or additional implementation contracts can be added. Therefore, please always make sure to check the most recent ones.