Software I wrote to monitor USDC depegging risk

Software I wrote to monitor USDC depegging risk
Photo by Safar Safarov / Unsplash

Update 30 June 2022: Defi Llama API is not working for the time being. I do not know when it will be restored.

After UST stablecoin depegged and crashed 2 weeks ago, fear spread to other stablecoins. The most dominant stablecoin, USDT, was briefly depegged. If the biggest stablecoin is in danger, the risk to the other smaller stablecoins cannot be ignored.

Some will say there is no need to worry about USDC. USDC was one of the beneficiaries after the stablecoins turmoil. Investors took out funds from USDT and transferred them to USDC because of its perceived higher safety. Market capitalization of USDT has declined almost 12% versus growth of almost 7% in USDC in the past 1 month.

Recent changes in stablecoin market cap (24May2022)

If there is one thing that the 2008 financial crisis and Anchor/Luna/UST total collapse has taught me, it is that the thing that causes the greatest financial damage is what we think is safe but turns out otherwise. Therefore, prudent risk management means we should monitor what is deemed safe, even though the probability of a bad event happening is extremely low.

The metrics I use for monitoring USDC de-pegging risk

  • Curve 3pool balance proportion
    If the USDC proportion exceeds 50% of the 3pool liquidity pool, go to risk-on mode. Risk-on means getting ready to sell if conditions deteriorate.
  • Market price of USDC
    If USDC price falls to $0.995, go to risk-on mode. Usually, when a stablecoin depegs, the rebound action will be quick. Be extra alert if the rebound is slow in response.
  • Market capitalization of USDC
    If USDC market capitalization suffers a weekly decline of more than 5%, start paying more attention.

I wrote software (source code to be provided) to monitor the de-pegging risk of USDC. When the criteria are met, a telegram message will be sent to myself.

I will explain the workings of the source code in the following paragraphs. You can ignore them if you are not into programming or are already an experienced Web3 programmer.

The 3pool balance data is extracted on-chain using Web3.py (python library for interacting with Ethereum smart contracts). Only Ethereum nodes can interact with Ethereum smart contract. Setting up an Ethereum node on your PC is difficult and costly. The solution is to use a middleman node. Thankfully, Infuria provides this service.

Before the script can interact with Ethereum smart contract, one has to set up an account with Infuria, and then obtain a URL endpoint. You can watch this video on how to do it.

Assign the URL endpoint intoinfuria_url variable in the function get_3pool_liquidity_balance_percentage().

The next step before one can interact with a smart contract is to find out its address and ABI (Application Binary Interface). I found out the address of the 3pool smart contract on Curve Finance. There are several smart contracts on Curve. Don't choose the wrong one. From the address, the smart contract source code and ABI can usually be found on Etherscan.

This is the link where you can read the Curve smart contract source code which runs 3pool.
https://etherscan.io/address/0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7#code

Reading the source code will be useful if one needs to interact with the smart contract. From the source code, the relevant function to call in our context is balances() which returns the stablecoin balance in the liquidity pool.

def get_3pool_liquidity_balance_percentage() -> Dict:
    import json
    from web3 import Web3

    infuria_url = "YOUR_OWN_INFURIA_URL"  # register an account with Infuria
    web3 = Web3(Web3.HTTPProvider(infuria_url))

    # https://curve.fi/contracts        https://etherscan.io/address/0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7#code
    curve3pool_smart_contract_address = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7"
    curve3pool_abi = json.loads("SMART_CONTRACT_ABI. Too long. Can't paste here")

    contract = web3.eth.contract(address=curve3pool_smart_contract_address, abi=curve3pool_abi)

    balance_DAI = contract.functions.balances(0).call() / (pow(10, 18))
    balance_DAI = round(balance_DAI, 2)
    balance_USDC = contract.functions.balances(1).call() / (pow(10, 6))
    balance_USDC = round(balance_USDC, 2)
    balance_USDT = contract.functions.balances(2).call() / (pow(10, 6))
    balance_USDT = round(balance_USDT, 2)

    total_balance = round(balance_DAI + balance_USDC + balance_USDT, 2)
    pct_DAI = round(balance_DAI / total_balance * 100, 2)
    pct_USDC = round(balance_USDC / total_balance * 100, 2)
    pct_USDT = round(balance_USDT / total_balance * 100, 2)

    stablecoin_3pool_pct = {}
    stablecoin_3pool_pct = {
        "DAI": pct_DAI,
        "USDC": pct_USDC,
        "USDT": pct_USDT,
    }

    return stablecoin_3pool_pct
Function for extracting on-chain 3pool balance data

The market cap and price data is extracted from Defi Llama through REST API. I love Defi Llama APIs because they are free of charge. The source of the price data feed is Chainlink. Chainlink data have to be reliable and accurate because smart contracts run on them. Inaccurate data can lead to wrong decisions made by smart contracts. The consequences can be disastrous if huge sums of money are involved. Imagine your funds getting liquidated by a DeFi smart contract because of an inaccurate price feed.

def get_stablecoin_marketcap(stablecoin_symbol) -> Dict:
    import json
    import requests
    # import pprint

    defi_llama_stablecoins_data = "https://uemu821wp6.execute-api.us-east-1.amazonaws.com/dev/peggeds?includeChains=false&includePrices=true"
    response = requests.get(defi_llama_stablecoins_data)
    stablecoin_data = json.loads(response.text)

    coin_price = 0
    circulating_amount = 0
    circulating_prev_day = 0
    circulating_prev_week = 0

    for dict_item in stablecoin_data["peggedAssets"]:
        for key in dict_item:
            if dict_item["symbol"] == stablecoin_symbol:
                coin_price = dict_item["price"]
                circulating_amount = dict_item["circulating"]["peggedUSD"]
                circulating_prev_day = dict_item["circulatingPrevDay"]["peggedUSD"]
                circulating_prev_week = dict_item["circulatingPrevWeek"]["peggedUSD"]

    stablecoin_market_cap = {
        "coin_price": coin_price,
        "circulating_amount": circulating_amount,
        "circulating_prev_day": circulating_prev_day,
        "circulating_prev_week": circulating_prev_week,
    }
    return stablecoin_market_cap

The software will send a telegram message to alert me when the risk criteria is met. send_telegram_message() uses the python-telegram-bot library. I created my own telegram bot. My telegram user account will send the alert message to this bot which will instantly notify me on receiving this alert. Visit the links for instructions on extracting the bot token and user chat_id in order to send the telegram message through `send_telegram_message().

def send_telegram_message(bot_token: str, chat_id: str, message: str) -> None:
    import telegram
    bot = telegram.Bot(token=bot_token)
    bot.send_message(chat_id=chat_id, text=message)
    return None

Finally, the source code can be downloaded here.


I put my idle money with Moomoo Cash Plus while waiting for investment opportunities. Cash Plus yields around 2.5% interest and is giving cashback gift of up to S$60 to new customers. If you are keen, please read my review and sign up if you like it.