Primitive Interface
- Python implementation of Balancer Weighted Pools ‘broadly’ consists of two main components
- BalancerMath.py: refactor of Balancer V1 Math solidity contract code, and was copied from BalancerPools_Model GH repos
- BalancerExchange.py: refactor of Balancer Pool solidity contract code
- The mapping (contract code -> math refactor -> exchange refactor) is as follows:
- Price
- BMath.calcSpotPrice() -> BalancerMath.calc_spot_price() -> BalancerExchange.get_price()
- Swapping
- BMath.calcOutGivenIn() -> BalancerMath.calc_out_given_in() -> BalancerExchange.get_amount_out()
- BMath.calcInGivenOut() -> BalancerMath.calc_in_given_out() -> BalancerExchange.get_amount_in()
- Adding Liquidity
- BMath.calcPoolOutGivenSingleIn() -> BalancerMath.calc_pool_out_given_single_in() -> BalancerExchange.join_swap_extern_amount_in()
- BMath.calcSingleInGivenPoolOut() -> BalancerMath.calc_single_in_given_pool_out() -> BalancerExchange.join_swap_pool_amount_out()
- Removing Liquidity
- BMath.calcPoolInGivenSingleOut() -> BalancerMath.calc_pool_in_given_single_out() -> BalancerExchange.exit_swap_extern_amount_out()
- BMath.calcSingleOutGivenPoolIn() -> BalancerMath.calc_single_out_given_pool_in() -> BalancerExchange.exit_swap_pool_amount_in()
- Price
import osimport jsonimport numpy as npfrom defipy import *Benchmarks
Section titled “Benchmarks”- Tests extracted from BalancerPools_Model GH repos
cwd = os.getcwd().replace("notebooks","")os.chdir(cwd)actions_json = 'resources/dev/cwpt/0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a-actions-prices.json'with open(actions_json, "r") as f: pool_actions = json.load(f)Parameters
Section titled “Parameters”- Denorm weights are loosely selected as target percentages by the contract deployer
- Percentage weights are normalized (to sum to 1) and are calculated based on denormalized weights
- Shares are typically initialized to 100
USER = 'user_test'
amt_dai = 10000000denorm_wt_dai = 10
amt_eth = 67738.6361731024denorm_wt_eth = 40
init_pool_shares = 100Join balancer pool
Section titled “Join balancer pool”- Join all assets
dai = ERC20("DAI", "0x111")dai.deposit(None, amt_dai)
weth = ERC20("WETH", "0x09")weth.deposit(None, amt_eth)
bgrp = BalancerVault()bgrp.add_token(dai, denorm_wt_dai)bgrp.add_token(weth, denorm_wt_eth)
bfactory = BalancerFactory("WETH pool factory", "0x2")exchg_data = BalancerExchangeData(vault = bgrp, symbol="LP", address="0x011")lp = bfactory.deploy(exchg_data)lp.join_pool(bgrp, init_pool_shares, USER)lp.summary()Balancer Exchange: DAI-WETH (LP)
Reserves: DAI = 10000000, WETH = 67738.6361731024
Weights: DAI = 0.2, WETH = 0.8
Pool Shares: 100
p = lp.get_price(dai, weth)
print(f"The price of {weth.token_name} is {p} {dai.token_name}")The price of WETH is 591.984912776992 DAI
Swap (out-given-in)
Section titled “Swap (out-given-in)”amt_tkn_in = float(pool_actions[3]['action']['token_in']['amount'])tkn_in = daitkn_out = wethres = lp.swap_exact_amount_in(amt_tkn_in, tkn_in, tkn_out, USER)
print(f"{amt_tkn_in} {tkn_in.token_name} was swapped into {res['tkn_out_amt']} {tkn_out.token_name}")11861.328308361 DAI was swapped into 20.021734704865246 WETH
lp.summary()Balancer Exchange: DAI-WETH (LP)
Reserves: DAI = 10011861.32830836, WETH = 67718.61443839753
Weights: DAI = 0.2, WETH = 0.8
Pool Shares: 100
Swap (in-given-out)
Section titled “Swap (in-given-out)”amt_tkn_out = res['tkn_out_amt']tkn_out = wethtkn_in = dai
res = lp.swap_exact_amount_out(amt_tkn_out, tkn_out, tkn_in, USER)
print(f"{amt_tkn_out} {tkn_out.token_name} was swapped into {res['tkn_in_amt']} {tkn_in.token_name}")20.021734704865246 WETH was swapped into 11878.911104285744 DAI
lp.summary()Balancer Exchange: DAI-WETH (LP)
Reserves: DAI = 9999982.417204075, WETH = 67738.6361731024
Weights: DAI = 0.2, WETH = 0.8
Pool Shares: 100
Add liquidity (token amounts)
Section titled “Add liquidity (token amounts)”tkn_in = wethamt_tkn_in = float(pool_actions[336]['action']['token_in']['amount'])
res = lp.join_swap_extern_amount_in(amt_tkn_in, tkn_in, USER)
print(f"{amt_tkn_in} {tkn_in.token_name} was added resulting in anadditional {res['shares_in_amt']} LP shares")26.741601415598677 WETH was added resulting in anadditional 0.03156505964916199 LP shares
lp.summary()Balancer Exchange: DAI-WETH (LP)
Reserves: DAI = 9999982.417204075, WETH = 67765.377774518
Weights: DAI = 0.2, WETH = 0.8
Pool Shares: 100.03156505964917
Add liquidity (LP share amounts)
Section titled “Add liquidity (LP share amounts)”tkn_in = wethamt_shares_in = 10
res = lp.join_swap_pool_amount_out(amt_shares_in, tkn_in, USER)
print(f"{amt_shares_in} LP shares were added resulting in an additional {res['tkn_in_amt']} {tkn_in.token_name}")10 LP shares were added resulting in an additional 8575.568763821291 WETH
lp.summary()Balancer Exchange: DAI-WETH (LP)
Reserves: DAI = 9999982.417204075, WETH = 76340.94653833928
Weights: DAI = 0.2, WETH = 0.8
Pool Shares: 110.03156505964917
Remove liquidity (token amounts)
Section titled “Remove liquidity (token amounts)”tkn_out = wethamt_tkn_out = float(pool_actions[664]['action']['token_out']['amount'])
res = lp.exit_swap_extern_amount_out(amt_tkn_out, tkn_out, USER)
print(f"{amt_tkn_out} {tkn_out.token_name} was removed resulting in the removal of {res['shares_out_amt']} LP shares")27.036668416618735 WETH was removed resulting in the removal of 0.031191445644352424 LP shares
lp.summary()Balancer Exchange: DAI-WETH (LP)
Reserves: DAI = 9999982.417204075, WETH = 76313.90986992266
Weights: DAI = 0.2, WETH = 0.8
Pool Shares: 110.00037361400481
Remove liquidity (LP share amounts)
Section titled “Remove liquidity (LP share amounts)”tkn_out = wethamt_shares_out = 10
res = lp.exit_swap_pool_amount_in(amt_shares_out, tkn_out, USER)
print(f"{amt_shares_out} LP shares were removed resulting in the removal of {res['tkn_out_amt']} {tkn_out.token_name}")10 LP shares were removed resulting in the removal of 8566.8415530723 WETH
lp.summary()Balancer Exchange: DAI-WETH (LP)
Reserves: DAI = 9999982.417204075, WETH = 67747.06831685036
Weights: DAI = 0.2, WETH = 0.8
Pool Shares: 100.00037361400481