Skip to content

Commit

Permalink
Merge pull request #14 from BalancerMaxis/add_updates_from_arbi_grant
Browse files Browse the repository at this point in the history
A number of updares from the arbi grant.
  • Loading branch information
franzns authored Jul 9, 2024
2 parents 75a6443 + 03f1986 commit 689e8c0
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 59 deletions.
25 changes: 12 additions & 13 deletions automation/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import List
from typing import Optional
from typing import Union
from bal_tools import Subgraph

from gql import Client
from gql import gql
Expand All @@ -16,19 +17,17 @@
from web3.exceptions import BadFunctionCallOutput

BAL_GQL_URL = "https://api-v3.balancer.fi/"

BLOCKS_GQL_URL_ARB = (
"https://api.thegraph.com/subgraphs/name/ianlapham/arbitrum-one-blocks"
)

BLOCKS_BY_CHAIN = {
"mainnet": "https://api.thegraph.com/subgraphs/name/blocklytics/ethereum-blocks",
"arbitrum": "https://api.thegraph.com/subgraphs/name/ianlapham/arbitrum-one-blocks",
"polygon": "https://api.thegraph.com/subgraphs/name/ianlapham/polygon-blocks",
"base": "https://api.studio.thegraph.com/query/48427/bleu-base-blocks/version/latest",
"gnosis": "https://api.thegraph.com/subgraphs/name/rebase-agency/gnosis-chain-blocks",
"avalanche": "https://api.thegraph.com/subgraphs/name/iliaazhel/avalanche-blocks",
}
CHAINS = [
"mainnet",
"arbitrum",
"polygon",
"base",
"gnosis",
"avalanche",
]
BLOCKS_BY_CHAIN = {}
for chain in CHAINS:
BLOCKS_BY_CHAIN[chain] = Subgraph(chain).get_subgraph_url("blocks")

VE_BAL_CONTRACT = "0xC128a9954e6c874eA3d62ce62B468bA073093F25"
AURA_VEBAL_HOLDER = "0xaF52695E1bB01A16D33D7194C28C42b10e0Dbec2"
Expand Down
57 changes: 11 additions & 46 deletions automation/lstGrant.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
from automation.helpers import get_abi
from automation.helpers import get_block_by_ts

from .payload_builders import generate_and_save_bal_injector_transaction

# import boost_data, cap_override_data and fixed_emissions_per_pool from the python file specified in POOL_CONFIG
pool_config = importlib.import_module(f"automation.{FILE_PREFIX}")
boost_data = pool_config.boost_data
Expand Down Expand Up @@ -196,45 +198,6 @@ def recur_distribute_unspend_tokens(
recur_distribute_unspend_tokens(max_tokens_per_pool, tokens_gauge_distributions)


def generate_and_save_transaction(
tokens_gauge_distributions: Dict, start_date: datetime, end_date: datetime
) -> Dict:
"""
Take tx template and inject data into it
"""
# Dump into output.json using:
with open(f"{get_root_dir()}/data/output_tx_template.json") as f:
output_data = json.load(f)
# Find transaction with func name `setRecipientList` and dump gauge
gauge_distributions = tokens_gauge_distributions.values()
for tx in output_data["transactions"]:
if tx["contractMethod"]["name"] == "setRecipientList":
# Inject list of gauges addresses:
tx["contractInputsValues"][
"gaugeAddresses"
] = f"[{','.join([gauge['recipientGaugeAddr'] for gauge in gauge_distributions])}]"
# Inject vote weights:
# Dividing by 2 since we are distributing for 2 weeks and 1 week is a period
tx["contractInputsValues"][
"amountsPerPeriod"
] = f"[{','.join([str(int(Decimal(gauge['distribution']) * Decimal(1e18) / 2)) for gauge in gauge_distributions])}]"
tx["contractInputsValues"][
"maxPeriods"
] = f"[{','.join(['2' for gauge in gauge_distributions])}]"
if tx["contractMethod"]["name"] == "transfer":
tx["contractInputsValues"]["amount"] = str(
int(Decimal(TOKENS_TO_FOLLOW_VOTING) * Decimal(1e18))
)

# Dump back to tokens_distribution_for_msig.json
with open(
f"{get_root_dir()}/output/{FILE_PREFIX}_{start_date.date()}_{end_date.date()}.json",
"w",
) as _f:
json.dump(output_data, _f, indent=4)
return output_data


def run_stip_pipeline(end_date: int) -> None:
"""
Main function to execute STIP calculations
Expand Down Expand Up @@ -384,19 +347,19 @@ def run_stip_pipeline(end_date: int) -> None:
mainnet_root_gauge_contract = web3_mainnet.eth.contract(
address=Web3.to_checksum_address(gauge_addr), abi=get_abi("ArbRootGauge")
)
to_distribute = min(to_distribute, max_tokens_per_gauge[gauge_addr])
gauge_distributions[gauge_addr] = {
"recipientGaugeAddr": mainnet_root_gauge_contract.functions.getRecipient().call(),
"poolAddress": gauge_data["poolAddress"],
"symbol": gauge_data["symbol"],
"voteWeight": gauge_data["voteWeight"],
"voteWeightNoBoost": gauge_data["weightNoBoost"],
"distribution": to_distribute
if to_distribute < max_tokens_per_gauge[gauge_addr]
else max_tokens_per_gauge[gauge_addr],
"distribution": to_distribute,
"pctDistribution": to_distribute / TOTAL_TOKENS_PER_EPOCH * 100,
"boost": combined_boost.get(gauge_addr, 1),
"distroToBalancer": to_distribute * pct_to_bal,
"voteWeightNoBoost": gauge_data["weightNoBoost"],
"staticBoost": boost_data.get(gauges[gauge_addr]["id"], 1),
"dynamicBoost": dynamic_boosts.get(gauge_addr, 1),
"boost": combined_boost.get(gauge_addr, 1),
"voteWeight": gauge_data["voteWeight"],
"cap": f"{percent_vote_caps_per_gauge[gauge_addr]}%",
"fixedIncentive": fixed_emissions_per_pool[gauge_data["id"]],
}
Expand Down Expand Up @@ -429,4 +392,6 @@ def run_stip_pipeline(end_date: int) -> None:
index=False,
)

generate_and_save_transaction(gauge_distributions, start_date, end_date)
bal_tx = generate_and_save_bal_injector_transaction(
gauge_distributions, start_date, end_date
)
127 changes: 127 additions & 0 deletions automation/payload_builders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
from bal_tools import Aura
import json
import os
import copy
import math
from datetime import datetime
from decimal import Decimal, ROUND_DOWN
from typing import Dict
from automation.constants import FILE_PREFIX

precision = Decimal(
"0." + "0" * 9 + "1"
) # 10 0s after the dot is insignificant for our purposes and takes care of rounding errors.


def get_root_dir() -> str:
return os.path.abspath(os.path.dirname(os.path.dirname(__file__)))


def generate_and_save_aura_transaction(
tokens_gauge_distributions: Dict,
start_date: datetime,
end_date: datetime,
chain_name: str,
pct_of_distribution: Decimal = Decimal(1),
num_periods: int = 2,
) -> Dict:
"""
Take a set of distributions and send them to aura direct
"""
aura = Aura(chain_name)
# Dump into output.json using:
with open(f"{get_root_dir()}/data/aura_direct_stream.json") as f:
output_data = json.load(f)
# Find transaction with func name `setRecipientList` and dump gauge
gauge_distributions = tokens_gauge_distributions.values()
tx_template = output_data["transactions"][1]
tx_list = []
total_amount = 0
# Inject list of gauges addresses:
for gauge in gauge_distributions:
aura_pid = aura.aura_pids_by_address.get(gauge["recipientGaugeAddr"])
if not aura_pid:
print(
f"WARNING: No aura pid found for gauge {gauge['recipientGaugeAddr']}, using gauge address in payload instead for easy debugging."
)
aura_pid = gauge["recipientGaugeAddr"]
tx = copy.deepcopy(tx_template)
tx["contractInputsValues"]["_pid"] = aura_pid
amount = (
Decimal(gauge["distroToAura"]) * Decimal(pct_of_distribution)
).quantize(precision, rounding=ROUND_DOWN)
wei_amount = (amount * Decimal(1e18)).to_integral_value()
tx["contractInputsValues"]["_amount"] = str(wei_amount)
tx["contractInputsValues"]["_periods"] = str(num_periods)
if wei_amount > 0:
tx_list.append(tx)
total_amount += wei_amount
if not tx_list:
print("No distributions to send to aura direct")
return
# Add approve tx
approve_tx = output_data["transactions"][0]
approve_tx["contractInputsValues"]["amount"] = str(total_amount)
tx_list.insert(0, approve_tx)
output_data["transactions"] = tx_list
with open(
f"{get_root_dir()}/output/{FILE_PREFIX}_{start_date.date()}_{end_date.date()}_aura_direct_stream.json",
"w",
) as _f:
json.dump(output_data, _f, indent=2)
print(f"{total_amount}({total_amount/Decimal(1e18)}) $ARB approved for aura direct")
return output_data


def generate_and_save_bal_injector_transaction(
tokens_gauge_distributions: Dict,
start_date: datetime,
end_date: datetime,
pct_of_distribution: Decimal = Decimal(1),
num_periods: int = 2,
) -> Dict:
"""
Take tx template and inject data into it
"""
# Dump into output.json using:
with open(f"{get_root_dir()}/data/output_tx_template.json") as f:
output_data = json.load(f)

# Find transaction with func name `setRecipientList` and dump gauge
gauge_distributions = tokens_gauge_distributions.values()
claim_tx = output_data["transactions"][0]
tx_template = output_data["transactions"][1]
transfer_tx = output_data["transactions"][2]
tx_list = []
gauges_list = []
amounts_list = []
max_periods_list = []
total_amount = 0
# Inject list of gauges addresses:
for gauge in gauge_distributions:
gauges_list.append(gauge["recipientGaugeAddr"])
epoch_amount = (
Decimal(gauge["distroToBalancer"]) * Decimal(pct_of_distribution)
).quantize(precision, rounding=ROUND_DOWN)
period_amount = epoch_amount / Decimal(num_periods)
wei_amount = (period_amount * Decimal(1e18)).to_integral_value()
total_amount += (epoch_amount * Decimal(1e18)).to_integral_value()
amounts_list.append(str(wei_amount))
max_periods_list.append(str(num_periods))
tx = copy.deepcopy(tx_template)
tx["contractInputsValues"]["gaugeAddresses"] = f"[{','.join(gauges_list)}]"
tx["contractInputsValues"]["amountsPerPeriod"] = f"[{','.join(amounts_list)}]"
tx["contractInputsValues"]["maxPeriods"] = f"[{','.join(max_periods_list)}]"
tx_list.append(tx)

transfer_tx["contractInputsValues"]["amount"] = str(int(total_amount))
tx_list.append(transfer_tx)
tx_list.insert(0, claim_tx)
output_data["transactions"] = tx_list
with open(
f"{get_root_dir()}/output/{FILE_PREFIX}_{start_date.date()}_{end_date.date()}_bal_injector_stream.json",
"w",
) as _f:
json.dump(output_data, _f, indent=2)
print(f"{total_amount} $ARB transferred for balancer injector")
return output_data

0 comments on commit 689e8c0

Please sign in to comment.