Analyze DeFi in Python using DeFiPy

Ian Moore, PhD
DataDrivenInvestor
Published in
7 min readApr 15, 2024

--

1. Introduction

Welcome to the worlds first DeFi Analytics Python package with all major protocols integrated into one! Implement your analytics in one package with DeFiPy. Since DeFiPy is built with a modular design in mind, you can also silo your analytics by protocol using: UniswapPy, BalancerPy and StableswapPy. This suite serves to refactor various DeFi (solidity) frameworks to analyze mock DeFi setups using Python.

Currently, if one would consider testing DeFi designs using these protocols, they may default to testing frameworks such as Brownie or Ape. While frameworks such as these are great for testing on-chain and local deployments, they may not be best suited for running rigorous benchmark tests where Web3 designers may want to stress test their protocols using tens of thousands of mock transactions at a time. This is because these frameworks target raw solidity applications running on the Ethereum Virtual Machine (EVM), hence we can only expect to process 1–5 transactions per second at best, which is not practical for large event data sets. If you are looking to benchmark your ideas on tens of thousands of events, this is not the best approach if you are coming into Web3 from Machine Learning or AI. Hence, we are offering this suite of Python tools for such use cases.

2. The Growing Need for DeFi Analytics

In my opinion, we are in the midst of transitioning to a tokenized economy, see Bettina Warburg TED talk. With this, we believe it is inevitable that finance will experience a full transition into DeFi in the coming years. Thus we will need to build standardized quantitative auditing protocols that are commonplace in our TradFi banking system today. This requires research to build out a suite of tools to handle such. Also, these DeFi protocols stand to gain much improvement in active liquidity management (ALM) using AI and Machine Learning, as opposed to manually, which is common practice with so many yield aggregator systems today.

When it comes to translating complex data science concepts into actionable insights for blockchain development brings in the need for DeFi benchmarking frameworks to test mock designs. The most effective way we have found this possible is via simulation. As mentioned in Warburg’s talk, we see blockchain as an Institutional Technology that will redefine the way our current institutions will be managed. Hence, TradFi will be DeFi in the not so distant future. If that is the case, then we are missing a crucial step in the DeFi development process, and that is quantitative auditing of these protocols to ensure that these protocols contain a certain standard of robustness when handling investor funds. This is why we initiated DeFiPy, to serve as the open source standard for the tooling used to properly test these DeFi protocols

3. Basic Usage

There is a common interface across all protocols within the DeFiPy python suite which are as follows:

  • ERC20 : Mock ERC20 token that used across all mock protocols
  • ExchangeData: Data class of initialization parameters for mock exchange
  • IExchange : All DeFiPy protocol packages come equipped an exchange class (ie, UniswapExchange, BalancerExchange, StableswapExchange)
  • IExchangeFactory: Likewise, all DeFiPy protocol packages also have factories to compliment the exchange class

Uniswap V2 Example

Uniswap is the most commonly known Automated Market Maker (AMM) in DeFi, which utilizes the constant product trading mechanism. To setup a mock liquidity pool (LP), you must first create the tokens in the pair using the ERC20 object. Next, create a LP factory using IFactoryExchange object. Once this is setup, an unlimited amount of LPs can be created; the procedure for such is as follows:

from defipy import *

user_nm = 'user_intro'
eth_amount = 3162.277660168379
dai_amount = 316227.7660168379

dai = ERC20("DAI", "0x09")
eth = ERC20("ETH", "0x111")
exchg_data = UniswapExchangeData(tkn0 = eth, tkn1 = dai, symbol="LP",
address="0x011")

factory = UniswapFactory("ETH pool factory", "0x2")
lp = factory.deploy(exchg_data)
lp.add_liquidity("user0", eth_amount, dai_amount, eth_amount, dai_amount)
lp.summary()


#OUTPUT:
Exchange ETH-DAI (LP)
Reserves: ETH = 3162.277660168379, DAI = 316227.7660168379
Liquidity: 31622.776601683792

Uniswap V3 Example:

See following for basic setup (April 25 update — available ≥ v1.3.0):

from defipy import *

user_nm = 'user_intro'
fee = UniV3Utils.FeeAmount.MEDIUM
tick_spacing = UniV3Utils.TICK_SPACINGS[fee]
lwr_tick = UniV3Utils.getMinTick(tick_spacing)
upr_tick = UniV3Utils.getMaxTick(tick_spacing)
init_price = UniV3Utils.encodePriceSqrt(100, 1)

dai = ERC20("DAI", "0x09")
eth = ERC20("ETH", "0x111")
exchg_data = UniswapExchangeData(tkn0 = eth, tkn1 = dai, symbol="LP",
address="0x011", version = 'V3',
tick_spacing = tick_spacing,
fee = fee)

factory = UniswapFactory("ETH pool factory", "0x2")
lp = factory.deploy(exchg_data)
lp.initialize(init_price)
out = lp.mint(user_nm, lwr_tick, upr_tick, 31622.776601683792)
lp.summary()


#OUTPUT:
Exchange ETH-DAI (LP)
Reserves: ETH = 3162.277660168379, DAI = 316227.7660168379
Liquidity: 31622.776601683792

Balancer Example

This protocol serves as an extension of constant product trading pool (ie, Uniswap) to handle pools with more than two assets, and are known as weighted pools. As both Balancer and Stableswap are muilt-asset protocols, they have what is called a Vault, which is touted as being the defining feature of these protocols. Hence, we also include BalancerVault and StableswapVault as shown in the following basic setups:

from defipy import *

user_nm = 'user_intro'

amt_dai = 10000000
denorm_wt_dai = 10

amt_eth = 67738.6361731024
denorm_wt_eth = 40

init_pool_shares = 100

dai = ERC20("DAI", "0x01")
dai.deposit(None, amt_dai)

weth = ERC20("WETH", "0x02")
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", "0x")
exchg_data = BalancerExchangeData(vault = bgrp, symbol="LP", address="0x1")
lp = bfactory.deploy(exchg_data)
lp.join_pool(bgrp, init_pool_shares, user_nm)
lp.summary()


#OUTPUT:
Balancer Exchange: DAI|WETH (LP)
Reserves: DAI = 10000000, WETH = 67738.6361731024
Weights: DAI = 0.2, WETH = 0.8
Pool Shares: 100

Stableswap Example

This is a lesser known protocol used to implement Composable Stable Pools which are ideal for setting up stable coin pools. See following basic setup:

from defipy import *

USER = 'user_test'

AMPL_COEFF = 2000

amt_dai = 79566307.559825807715868071
decimal_dai = 18

amt_usdc = 81345068.187939
decimal_usdc = 6

amt_usdt = 55663250.772939
decimal_usdt = 6

dai = ERC20("DAI", "0x01", decimal_dai)
dai.deposit(None, amt_dai)

usdc = ERC20("USDC", "0x02", decimal_usdc)
usdc.deposit(None, amt_usdc)

usdt = ERC20("USDT", "0x03", decimal_usdt)
usdt.deposit(None, amt_usdt)

sgrp = StableswapVault()
sgrp.add_token(dai)
sgrp.add_token(usdc)
sgrp.add_token(usdt)

sfactory = StableswapFactory("Pool factory", "0x")
exchg_data = StableswapExchangeData(vault = sgrp, symbol="LP", address="0x11")
lp = sfactory.deploy(exchg_data)
lp.join_pool(sgrp, AMPL_COEFF, USER)
lp.summary()


#OUTPUT:
Stableswap Exchange: DAI-USDC-USDT (LP)
Reserves: DAI = 79566307.55982581, USDC = 81345068.187939, USDT = 55663250.772939
Liquidity: 216573027.91811988

DeFiPy-0x Quant Terminal

This cool little application came out of ETHDenver 2024 BUIDL week, where we place 3rd out of 14 submissions.

DeFiPy team with 0x judges at ETHDenver 2024

By using DeFiPy, and the 0x real time price API, we were able to combine the two into a live paper trading tool that allows users to select from the various blockchains, tokens, and stablecoins that 0x Price API provides to select a live liquidity pool as the basis of the modelling tool. We also added the ability for users to select modelling parameters, such as the maximum swap size allowed by the pool, the randomized trading bias between the selected coin and respective stablecoin in the pool, and the profitability of your position based on liquidity provided.

On top of that we’ve launched a live dashboard so that users can easily interact with the model and visualize relevant activity and parameters, all while tracking the live pool data from the 0x Price API; see README for more info.

These are the first steps necessary to make simple DeFi modelling a norm in the industry by simulating data based on a live price feed so that we can avoid the all too common crash and burns that plague the industry.

Srcreenshot of DeFiPy-0x Quant Terminal

To checkout the DeFiPy-0x Quant terminal, click dashboard.defipy.org for live link, or setup locally via the following shell commands:

> git clone https://github.com/defipy-devs/defipy
> cd defipy
> pip install .
> bokeh serve --show python/application/quant_terminal/bokeh_server.py

5. Upcoming Releases

As we are working diligently to provide open source tooling for DeFi analytics, here is what we are working to include next:

  • Uniswap V3 python refactor: from our perspective, they are no seamless, easy to use, open source python refactors of Uniswap V3; April 25 update — available ≥ v1.3.0
  • Gwei vs decimal: currently all token values in decimal format, we will be providing the ability for users to implement in GWEI (ie, 1 x10^-18)
  • Impermanent loss: plays a major role in assessing risk factors of many AMMs; see survey article
  • Token contract address archive: necessary component to ensure seamless use of 0x Price API without have to manually fetch these contract addresses
  • Historical price data from on-chain: this is a common ask by many analysts, and we are currently investigating the best approach for this
  • Liquidity Trees: this an exciting SYS Labs innovation unique to DeFi and what inspired the creation of DeFiPy, see ETHDenver 2024 talk and more buzz to come regarding this

6. Summary

The work presented in this article is part of a larger body of work for doing things like: (a) simulate the behaviour of a simple liquidity pool [1]; (b) studying the effects of Impermanent Loss in an LP [2]; and (c) analyzing the risk profile and profitability in more advanced DeFi systems for SYS Labs upcoming Pachira protocol. Here, we provide the basic setup for those who are interested in getting into researching LPs. Please be sure to look out for future medium posts on this!

--

--