Deploying Liquidity Pools
Creating a liquidity pool requires just one transaction as of v0.6
As of v0.6, the Bancor ConverterRegistry contract does most of the hard work deploying new liquidity pools. Developers can still use the manual process to test their converters (see Deploying a Liquidity Pool in the Guides section), but the converter won't be discoverable to the rest of Bancor Network.
The v0.6 release will go live in mid June. Until then, please refer to the Deploying a Liquidity Pool for Testing guide found here. The process described will be deprecated to a testing-only function once v0.6 is live.
This guide is for developers integrating Bancor into their dApp or smart contract. Other pool creators can use one of the community-managed front ends (see: Katana Pools) to customize and deploy their pools.

Step #1 - Deploying a new Liquidity Pool

The newConverter function on the ConverterRegistry contract takes the following parameters:
    _type: converter type
    _name: name of your token or pool
    _symbol: symbol for your token or pool
    _decimals: number of decimals on your pool token
    _maxConversionFee: maximum trading fee in parts per million for transactions passing through your converter
    _reserveTokens: the addresses of the token reserves to be held in your pool
    _reserveWeights: the relative weights of each reserve token in parts per million. The sum of the values in this array must be 1,000,000.
For integration into a smart contract, use the Solidity interfaces below. You'll first need to query for the current address of the ConverterRegistry contract before executing the newConverter function.
1
contract IContractRegistry {
2
function addressOf(
3
bytes32 contractName
4
) external returns(address);
5
}
6
7
contract IConverterRegistry {
8
function newConverter (
9
uint16 _type,
10
string _name,
11
string _symbol,
12
uint8 _decimals,
13
uint32 _maxConversionFee,
14
IERC20Token[] memory _reserveTokens,
15
uint32[] memory _reserveWeights
16
) external returns (IConverter);
17
}
18
19
contract MyContract {
20
// mainnet
21
address contractRegistry = 0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4;
22
bytes32 converterRegistryName = 'BancorConverterRegistry';
23
24
function deployNewConverter(
25
uint16 _type,
26
string _name,
27
string _symbol,
28
uint8 _decimals,
29
uint32 _maxConversionFee,
30
IERC20Token[] memory _reserveTokens,
31
uint32[] memory _reserveWeights
32
) external returns(address) {
33
IContractRegistry contractRegistry = IContractRegistry(contractRegistry);
34
address converterRegistry = contractRegistry.addressOf(converterRegistryName);
35
IConverter converter = IConverterRegistry(converterRegistry).newConverter(
36
_type,
37
_name,
38
_symbol,
39
_decimals,
40
_maxConversionFee,
41
_reserveTokens,
42
_reserveWeights
43
);
44
return address(converter);
45
}
46
}
Copied!
Network
ContractRegistry Address
Mainnet
0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4
Ropsten
0xFD95E724962fCfC269010A0c6700Aa09D5de3074
If you're developing with Web3, you'll first need to copy our ContractRegistry ABI into your project. Find that here.
Then you can copy our ConverterRegistry ABI into your project. Find that here.
And your Web3 implementation would look something like this:
1
const ContractRegistryABI = require('./ContractRegistry.json');
2
const ConverterRegistryABI = require('./ConverterRegistry.json');
3
4
const ContractRegistryAddress = '0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4';
5
const ContractRegistryContract = new web3.eth.Contract(
6
ContractRegistryABI,
7
ContractRegistryAddress
8
)
9
10
const getConverterRegistryAddress = async() => {
11
const converterRegistryName = web3.utils.asciiToHex('ConverterRegistry');
12
const address = await ContractRegistryContract.methods.addressOf(converterRegistryName).call();
13
return address;
14
}
15
16
const deployConverter = async() => {
17
const converterRegistryAddress = await getConverterRegistryAddress();
18
const ConverterRegistryContract = new web3.eth.Contract(
19
ConverterRegistryABI,
20
converterRegistryAddress
21
);
22
23
const type = 1;
24
const name = 'XYZABC Pool Token'
25
const symbol = 'XYZABC';
26
const decimals = 18;
27
const maxConversionFee = 30000;
28
const reserveTokens = [<xyz-address>, <abc-address>];
29
const reserveWeights = [300000, 700000];
30
31
await ConverterRegistryContract.methods.newConverter(
32
type,
33
name,
34
symbol,
35
decimals,
36
maxConversionFee,
37
reserveTokens,
38
reserveWeights
39
);
40
}
Copied!

Step #2 - Adding Oracle and Activating the pool

This step is only relevant for Bancor V2 pools
Following pool creation, Bancor V2 pools require to set the relevant price oracles. Only once this function is called, the pool will be activated and can be used.
1
function activate(
2
address _primaryReserveToken,
3
address _primaryReserveOracle,
4
address _secondaryReserveOracle
5
);
Copied!
_primaryReserveToken
address of the pool's primary reserve token
_primaryReserveOracle
address of a Chainlink price oracle for the primary reserve token
_secondaryReserveOracle
address of a Chainlink price oracle for the secondary reserve token
Make sure you use trusted oracles that are part of the white list
Oracles must use the same pair. It is recommended to use oracles with price to ETH

Step #3 - Accepting Ownership

As the capstone to the pool creation process, make sure to execute the acceptOwnership function on the new converter contract. Etherscan should have automatically verified your contract and this should be easily callable from their UI, or alternatively via your Web3 connection or smart contract interface.
Last modified 5mo ago