Skip to content

Instantly share code, notes, and snippets.

@rafaelugolini
Created May 18, 2023 20:20
Show Gist options
  • Save rafaelugolini/e8e578da1a38889d885dd79a125f65cf to your computer and use it in GitHub Desktop.
Save rafaelugolini/e8e578da1a38889d885dd79a125f65cf to your computer and use it in GitHub Desktop.
Calculate available rewards on convex
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"from ctc import evm, rpc\n",
"import aiohttp\n",
"\n",
"\n",
"from mdata.abis.base_reward_pool import base_reward_pool_functions\n",
"from mdata.abis.cvx_mining import cvx_mining_functions\n",
"from mdata.abis.virtual_balance_reward_pool import virtual_balance_reward_pool_functions\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"CVX_MINING_ADDR = \"0x3c75BFe6FbfDa3A94E7E7E8c2216AFc684dE5343\"\n",
"OETH_VAULT_ADDR = \"0x1827F9eA98E0bf96550b2FC20F7233277FcD7E63\"\n",
"\n",
"OETH_REWARD_POOL = \"0x24b65DC1cf053A8D96872c323d29e86ec43eB33A\""
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[4.64, 0.810901]"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"async def get_mainnet_token_price(addrs: list[str], currency: str) -> list[str]:\n",
" addrs = [addr.lower() for addr in addrs]\n",
" contract_addresses = \",\".join(addrs)\n",
"\n",
" url = f\"https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses={contract_addresses}&vs_currencies={currency}\"\n",
"\n",
" async with aiohttp.ClientSession() as session:\n",
" res = await session.get(url)\n",
" data = await res.json()\n",
"\n",
" return [data[addr][currency.lower()] for addr in addrs]\n"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>earned</th>\n",
" <th>token</th>\n",
" <th>name</th>\n",
" <th>symbol</th>\n",
" <th>decimals</th>\n",
" <th>vault_addr</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>12376298516071205333</td>\n",
" <td>0xD533a949740bb3306d119CC777fa900bA034cd52</td>\n",
" <td>Curve DAO Token</td>\n",
" <td>CRV</td>\n",
" <td>18</td>\n",
" <td>0x1827F9eA98E0bf96550b2FC20F7233277FcD7E63</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>235149671805352901</td>\n",
" <td>0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B</td>\n",
" <td>Convex Token</td>\n",
" <td>CVX</td>\n",
" <td>18</td>\n",
" <td>0x1827F9eA98E0bf96550b2FC20F7233277FcD7E63</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0</td>\n",
" <td>0x4e12e132c5fbce39a4b1a0ae2659d58af982cb6d</td>\n",
" <td>Convex Token</td>\n",
" <td>CVX</td>\n",
" <td>18</td>\n",
" <td>0x1827F9eA98E0bf96550b2FC20F7233277FcD7E63</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" earned token \\\n",
"0 12376298516071205333 0xD533a949740bb3306d119CC777fa900bA034cd52 \n",
"1 235149671805352901 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B \n",
"2 0 0x4e12e132c5fbce39a4b1a0ae2659d58af982cb6d \n",
"\n",
" name symbol decimals \\\n",
"0 Curve DAO Token CRV 18 \n",
"1 Convex Token CVX 18 \n",
"2 Convex Token CVX 18 \n",
"\n",
" vault_addr \n",
"0 0x1827F9eA98E0bf96550b2FC20F7233277FcD7E63 \n",
"1 0x1827F9eA98E0bf96550b2FC20F7233277FcD7E63 \n",
"2 0x1827F9eA98E0bf96550b2FC20F7233277FcD7E63 "
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"async def get_extra_reward(\n",
" reward_addr: str, source_addr: str, extra_id: int, block_number: int | None = None\n",
") -> dict:\n",
" virtual_reward_addr = await rpc.async_eth_call(\n",
" to_address=reward_addr,\n",
" function_abi=base_reward_pool_functions[\"extraRewards\"],\n",
" function_parameters=[extra_id],\n",
" )\n",
" earned = await rpc.async_eth_call(\n",
" to_address=virtual_reward_addr,\n",
" function_abi=virtual_balance_reward_pool_functions[\"earned\"],\n",
" function_parameters=[source_addr],\n",
" )\n",
" token = await rpc.async_eth_call(\n",
" to_address=virtual_reward_addr,\n",
" function_abi=virtual_balance_reward_pool_functions[\"rewardToken\"],\n",
" function_parameters=[source_addr],\n",
" )\n",
" name = await evm.async_get_erc20_name(token)\n",
" symbol = await evm.async_get_erc20_symbol(token)\n",
" decimals = await evm.async_get_erc20_decimals(token)\n",
"\n",
" return {\n",
" \"earned\": earned,\n",
" \"token\": token,\n",
" \"name\": name,\n",
" \"symbol\": symbol,\n",
" \"decimals\": decimals,\n",
" }\n",
"\n",
"\n",
"async def get_reward(\n",
" reward_addr: str, source_addr: str, block_number: int | None = None\n",
"):\n",
" # assume all earnings from base reward pool are CRV\n",
" earned_crv = await rpc.async_eth_call(\n",
" to_address=reward_addr,\n",
" function_abi=base_reward_pool_functions[\"earned\"],\n",
" function_parameters=[source_addr],\n",
" )\n",
" crv = {\n",
" \"earned\": earned_crv,\n",
" \"token\": \"0xD533a949740bb3306d119CC777fa900bA034cd52\",\n",
" \"name\": \"Curve DAO Token\",\n",
" \"symbol\": \"CRV\",\n",
" \"decimals\": 18,\n",
" }\n",
" # get earned CVX from cvx mining contract\n",
" earned_cvx = await rpc.async_eth_call(\n",
" to_address=CVX_MINING_ADDR,\n",
" function_abi=cvx_mining_functions[\"ConvertCrvToCvx\"],\n",
" function_parameters=[earned_crv],\n",
" )\n",
" cvx = {\n",
" \"earned\": earned_cvx,\n",
" \"token\": \"0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B\",\n",
" \"name\": \"Convex Token\",\n",
" \"symbol\": \"CVX\",\n",
" \"decimals\": 18,\n",
" }\n",
"\n",
" extra_rewards_len = await rpc.async_eth_call(\n",
" to_address=reward_addr,\n",
" function_abi=base_reward_pool_functions[\"extraRewardsLength\"],\n",
" )\n",
" extra_rewards = [\n",
" await get_extra_reward(reward_addr, source_addr, i, block_number)\n",
" for i in range(0, extra_rewards_len)\n",
" ]\n",
" rewards = [\n",
" crv,\n",
" cvx,\n",
" *extra_rewards,\n",
" ]\n",
"\n",
" tokens = pd.DataFrame(rewards)\n",
" tokens['vault_addr'] = source_addr\n",
"\n",
" return tokens\n",
"\n",
"\n",
"df_rewards = await get_reward(OETH_REWARD_POOL, OETH_VAULT_ADDR)\n",
"df_rewards.fillna(0, inplace=True)\n",
"df_rewards"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"\n",
"async def get_rewards(currency: str, decimals: int = 18):\n",
" # Get currency value of each token unit\n",
" tokens = df_rewards.groupby('symbol')['token'].first()\n",
" # token_series\n",
" tokens[:] = await get_mainnet_token_price(tokens.values, currency)\n",
" # Get currency value per token\n",
" df_rewards_enhanced = df_rewards.copy()\n",
" df_rewards_enhanced = df_rewards.groupby('symbol')['earned'].sum()\n",
" df_rewards_enhanced = df_rewards_enhanced.apply(lambda x: x / (10 ** decimals))\n",
" return df_rewards_enhanced.multiply(tokens).sum()\n",
"\n",
"rewards_in_usd = await get_rewards('USD')\n",
"rewards_in_eth = await get_rewards('ETH')"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Rewards in USD: 11.127047320157493\n",
"Rewards in ETH: 0.006195283327789222\n"
]
}
],
"source": [
"print(f\"Rewards in USD: {rewards_in_usd}\")\n",
"print(f\"Rewards in ETH: {rewards_in_eth}\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.6"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "ce62bb1dac75b4e84d17d3036d4747b188264174b843468d2ca39ccf440dd0d3"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment