Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
197f0cf
add beets fee split on OP
franzns Jun 4, 2025
5aa7fea
use cached core pools
franzns Jun 4, 2025
33d48ac
update model
franzns Jun 12, 2025
33c6058
Merge branch 'biweekly-runs' into feat-optimism-beets-split
franzns Jun 12, 2025
907c98f
use PRd fee constant json
franzns Jun 18, 2025
7f020f5
use specific bal_addresses branch
franzns Jun 18, 2025
3e503eb
Merge branch 'biweekly-runs' into feat-optimism-beets-split
franzns Jun 18, 2025
09bdae6
add optimism number to past fee run
franzns Jun 18, 2025
587f9e6
fix recon
franzns Jun 18, 2025
6d129d9
gos comments
franzns Jun 20, 2025
7ac68d7
Merge branch 'biweekly-runs' into feat-optimism-beets-split
franzns Jun 25, 2025
74fd79a
fix: keep `rich` dep
gosuto-inzasheru Jun 26, 2025
5095cd5
fix model
franzns Jun 26, 2025
1dbebfa
add OP fees to latest round
franzns Jun 26, 2025
2d23c9a
Merge branch 'biweekly-runs' into feat-optimism-beets-split
gosuto-inzasheru Jun 26, 2025
e5509c7
fix: input date format requires dashes
gosuto-inzasheru Jun 27, 2025
76ba689
minimal retry
franzns Jul 1, 2025
4a2d222
print retry
franzns Jul 1, 2025
c6ec151
print success
franzns Jul 1, 2025
c98e9cb
integrate beets into the payload visualizer
franzns Jul 1, 2025
0143af7
add markdown
franzns Jul 1, 2025
feecbff
add beets transactions to markdown
franzns Jul 2, 2025
f5634e7
Merge branch 'biweekly-runs' into feat-optimism-beets-split
franzns Jul 7, 2025
e69d82e
add latest fees
franzns Jul 7, 2025
e16159d
task: new fees report ending 2025-07-03
franzns Jul 7, 2025
b38509a
Merge pull request #168 from BalancerMaxis/gha-biweekly-fees-1751887940
franzns Jul 7, 2025
08d47dd
task: new fees report ending 2025-07-03
franzns Jul 8, 2025
4260e50
Merge pull request #169 from BalancerMaxis/gha-biweekly-fees-1751967450
franzns Jul 8, 2025
9b0ee21
add OP to fee run
franzns Jul 9, 2025
c693efc
use prod dept in requirements
franzns Jul 9, 2025
eb86d5d
revert test fee runs
franzns Jul 9, 2025
d8631fe
revert fee constants URL
franzns Jul 9, 2025
9607447
remove retry
franzns Jul 9, 2025
24c3cb4
remove unused import
franzns Jul 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions fee_allocator/accounting/chains.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,20 @@ def total_to_dao_usd(self) -> Decimal:
return sum(
[pool.to_dao_usd for chain in self.all_chains for pool in chain.core_pools]
)

@property
@round(4)
def total_to_beets_usd(self) -> Decimal:
return sum(
[pool.to_beets_usd for chain in self.all_chains for pool in chain.core_pools]
)

@property
@round(4)
def total_to_incentives_usd(self) -> Decimal:
return sum(
[
pool.total_to_incentives_usd + pool.to_dao_usd + pool.to_vebal_usd
pool.total_to_incentives_usd + pool.to_dao_usd + pool.to_vebal_usd + pool.to_beets_usd
for chain in self.all_chains
for pool in chain.core_pools
]
Expand Down Expand Up @@ -263,7 +270,6 @@ def _cache_file_path(self) -> Path:
return self.chains.cache_dir / filename

def _load_core_pools_from_cache(self) -> list[PoolFeeData]:
logger.info(f"loading core pools from cache for {self.name}")
cached_data = joblib.load(self._cache_file_path())
self.alliance_pools = cached_data.get('alliance_pools', [])
self.alliance_noncore_fee_data = cached_data.get('alliance_noncore_fee_data', [])
Expand Down Expand Up @@ -465,12 +471,22 @@ def noncore_fees_collected(self) -> Decimal:
@property
@require_pool_fee_data
def noncore_to_dao_usd(self) -> Decimal:
return self.noncore_fees_collected * self.chains.fee_config.noncore_dao_share_pct
beets_share_pct = self.chains.fee_config.beets_share_pct if self.name == "optimism" else 0
return self.noncore_fees_collected * (1 - beets_share_pct) * self.chains.fee_config.noncore_dao_share_pct

@property
@require_pool_fee_data
def noncore_to_vebal_usd(self) -> Decimal:
return self.noncore_fees_collected * self.chains.fee_config.noncore_vebal_share_pct
beets_share_pct = self.chains.fee_config.beets_share_pct if self.name == "optimism" else 0
return self.noncore_fees_collected * (1 - beets_share_pct) * self.chains.fee_config.noncore_vebal_share_pct

@property
@require_pool_fee_data
def noncore_to_beets_usd(self) -> Decimal:
beets_share_pct = self.chains.fee_config.beets_share_pct if self.name == "optimism" else 0
if beets_share_pct == 0:
return Decimal(0)
return self.noncore_fees_collected * beets_share_pct

@property
@require_pool_fee_data
Expand All @@ -483,11 +499,20 @@ def alliance_noncore_fees_collected(self) -> Decimal:

@property
def alliance_noncore_to_dao_usd(self) -> Decimal:
return self.alliance_noncore_fees_collected * self.chains.alliance_config.alliance_fee_allocations["non_core"].dao_share_pct
beets_share_pct = self.chains.fee_config.beets_share_pct if self.name == "optimism" else 0
return self.alliance_noncore_fees_collected * self.chains.alliance_config.alliance_fee_allocations["non_core"].dao_share_pct * (1 - beets_share_pct)

@property
def alliance_noncore_to_vebal_usd(self) -> Decimal:
return self.alliance_noncore_fees_collected * self.chains.alliance_config.alliance_fee_allocations["non_core"].vebal_share_pct
beets_share_pct = self.chains.fee_config.beets_share_pct if self.name == "optimism" else 0
return self.alliance_noncore_fees_collected * self.chains.alliance_config.alliance_fee_allocations["non_core"].vebal_share_pct * (1 - beets_share_pct)

@property
def alliance_noncore_to_beets_usd(self) -> Decimal:
beets_share_pct = self.chains.fee_config.beets_share_pct if self.name == "optimism" else 0
if beets_share_pct == 0:
return Decimal(0)
return self.alliance_noncore_fees_collected * (1 - self.chains.alliance_config.alliance_fee_allocations["non_core"].partner_share_pct) * beets_share_pct

@property
@round(4)
Expand Down
15 changes: 12 additions & 3 deletions fee_allocator/accounting/core_pools.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def __init__(self, data: PoolFeeData, chain: CorePoolChain):
self.to_dao_usd = self._to_dao_usd()
self.to_vebal_usd = self._to_vebal_usd()
self.to_partner_usd = self._to_partner_usd()
self.to_beets_usd = self._to_beets_usd()
self.redirected_incentives_usd = Decimal(0)

override_cls = overrides.get(self.pool_id)
Expand Down Expand Up @@ -155,21 +156,23 @@ def _to_bal_incentives_usd(self) -> Decimal:

def _to_dao_usd(self) -> Decimal:
core_fees = self._core_pool_allocation()
beets_share_pct = self.chain.chains.fee_config.beets_share_pct if self.chain.name == "optimism" else 0
dao_share_pct = (
self.alliance_fee_config.dao_share_pct
if (self.is_alliance_non_core_pool or self.is_alliance_pool)
else self.chain.chains.fee_config.dao_share_pct
)
return self.earned_fee_share_of_chain_usd * core_fees * dao_share_pct
return self.earned_fee_share_of_chain_usd * core_fees * dao_share_pct * (1 - beets_share_pct)

def _to_vebal_usd(self) -> Decimal:
core_fees = self._core_pool_allocation()
beets_share_pct = self.chain.chains.fee_config.beets_share_pct if self.chain.name == "optimism" else 0
vebal_share_pct = (
self.alliance_fee_config.vebal_share_pct
if (self.is_alliance_non_core_pool or self.is_alliance_pool)
else self.chain.chains.fee_config.vebal_share_pct
)
return self.earned_fee_share_of_chain_usd * core_fees * vebal_share_pct
return self.earned_fee_share_of_chain_usd * core_fees * vebal_share_pct * (1 - beets_share_pct)

def _to_partner_usd(self) -> Decimal:
core_fees = self._core_pool_allocation()
Expand All @@ -179,4 +182,10 @@ def _to_partner_usd(self) -> Decimal:
* core_fees
* self.alliance_fee_config.partner_share_pct
)
return Decimal(0)
return Decimal(0)

def _to_beets_usd(self) -> Decimal:
beets_share_pct = self.chain.chains.fee_config.beets_share_pct if self.chain.name == "optimism" else 0
if beets_share_pct == 0:
return Decimal(0)
return (self.to_dao_usd + self.to_vebal_usd)
3 changes: 3 additions & 0 deletions fee_allocator/accounting/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class GlobalFeeConfig(BaseModel):
# Non-core pool fee splits
noncore_vebal_share_pct: Decimal
noncore_dao_share_pct: Decimal

# Beets fee split (https://forum.balancer.fi/t/bip-800-deploy-balancer-v3-on-op-mainnet)
beets_share_pct: Decimal


class AlliancePool(BaseModel):
Expand Down
27 changes: 24 additions & 3 deletions fee_allocator/fee_allocator.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,21 @@ def generate_bribe_csv(
)

noncore_total_to_dao_usd = sum(chain.noncore_to_dao_usd + chain.alliance_noncore_to_dao_usd for chain in self.run_config.all_chains)
noncore_total_to_beets_usd = sum(chain.noncore_to_beets_usd + chain.alliance_noncore_to_beets_usd for chain in self.run_config.all_chains)
output.append(
{
"target": "0x10A19e7eE7d7F8a52822f6817de8ea18204F2e4f", # DAO msig
"platform": "payment",
"amount": self.run_config.total_to_dao_usd + noncore_total_to_dao_usd,
}
)
output.append(
{
"target": self.book["multisigs/beets_treasury"],
"platform": "beets",
"amount": self.run_config.total_to_beets_usd + noncore_total_to_beets_usd,
}
)

df = pd.DataFrame(output)
datetime_file_header = datetime.datetime.fromtimestamp(
Expand Down Expand Up @@ -300,6 +308,7 @@ def generate_incentives_csv(
"earned_fees": round(core_pool.total_earned_fees_usd_twap, 4),
"fees_to_vebal": round(core_pool.to_vebal_usd, 4),
"fees_to_dao": round(core_pool.to_dao_usd, 4),
"fees_to_beets": round(core_pool.to_beets_usd, 4),
"total_incentives": round(core_pool.total_to_incentives_usd, 4),
"aura_incentives": round(core_pool.to_aura_incentives_usd, 4),
"bal_incentives": round(core_pool.to_bal_incentives_usd, 4),
Expand Down Expand Up @@ -336,17 +345,20 @@ def generate_noncore_csv(
output = []

for chain in self.run_config.all_chains:
beets_share_pct = self.run_config.fee_config.beets_share_pct if chain.name == "optimism" else Decimal(0)
output.append({
"chain": chain.name,
"total_fees_collected": round(chain.fees_collected, 4),
"total_fees_earned_twap": round(chain.total_earned_fees_usd_twap, 4),
"noncore_fees": round(chain.noncore_fees_collected, 4),
"noncore_to_dao": round(chain.noncore_to_dao_usd, 4),
"noncore_to_vebal": round(chain.noncore_to_vebal_usd, 4),
"noncore_to_beets": round(chain.noncore_to_beets_usd, 4),
"dao_share_pct": round(self.run_config.fee_config.noncore_dao_share_pct * 100, 2),
"vebal_share_pct": round(self.run_config.fee_config.noncore_vebal_share_pct * 100, 2)
"vebal_share_pct": round(self.run_config.fee_config.noncore_vebal_share_pct * 100, 2),
"beets_share_pct": round(beets_share_pct * 100, 2)
})

df = pd.DataFrame(output)
start_date = datetime.datetime.fromtimestamp(self.date_range[0]).date()
end_date = datetime.datetime.fromtimestamp(self.date_range[1]).date()
Expand Down Expand Up @@ -428,9 +440,11 @@ def generate_bribe_payload(
df = pd.read_csv(input_csv)
bribe_df = df[df["platform"].isin(["balancer", "aura"])]
payment_df = df[df["platform"] == "payment"].iloc[0]
beets_df = df[df["platform"] == "beets"].iloc[0]

total_bribe_usdc = sum(round(row["amount"] * 1e6) for _, row in bribe_df.iterrows())
dao_fee_usdc = round(payment_df["amount"] * 1e6) - 1000 # round down 0.1 cent
beets_fee_usdc = round(beets_df["amount"] * 1e6) - 1000 # round down 0.1 cent

"""bribe txs"""
usdc.approve(self.book["hidden_hand2/bribe_vault"], total_bribe_usdc + 1) # 1 wei buffer
Expand All @@ -448,6 +462,7 @@ def generate_bribe_payload(

"""transfer txs"""
usdc.transfer(payment_df["target"], dao_fee_usdc)
usdc.transfer(beets_df["target"], beets_fee_usdc)

partner_fee_usdc_spent = 0
if partner_csv:
Expand Down Expand Up @@ -512,6 +527,7 @@ def recon(self) -> None:
total_vebal = Decimal(0)
total_partner = Decimal(0)
total_distributed = Decimal(0)
total_beets = Decimal(0)

for chain in self.run_config.all_chains:
for pool in chain.core_pools:
Expand All @@ -520,21 +536,24 @@ def recon(self) -> None:
assert pool.to_dao_usd >= 0, f"Negative dao share: {pool.to_dao_usd}"
assert pool.to_vebal_usd >= 0, f"Negative vebal share: {pool.to_vebal_usd}"
assert pool.to_partner_usd >= 0, f"Negative partner share: {pool.to_partner_usd}"
assert pool.to_beets_usd >= 0, f"Negative beets share: {pool.to_beets_usd}"

total_aura += pool.to_aura_incentives_usd
total_bal += pool.to_bal_incentives_usd
total_dao += pool.to_dao_usd
total_vebal += pool.to_vebal_usd
total_partner += pool.to_partner_usd
total_beets += pool.to_beets_usd

total_dao += chain.noncore_to_dao_usd + chain.alliance_noncore_to_dao_usd
total_vebal += chain.noncore_to_vebal_usd + chain.alliance_noncore_to_vebal_usd
total_beets += chain.noncore_to_beets_usd + chain.alliance_noncore_to_beets_usd

for noncore_pool in chain.alliance_noncore_fee_data:
total_partner += chain.get_alliance_noncore_partner_fee(noncore_pool.pool_id)

# Total distributed includes all allocations including partner fees
total_distributed = total_aura + total_bal + total_dao + total_vebal + total_partner
total_distributed = total_aura + total_bal + total_dao + total_vebal + total_partner + total_beets

# For percentage calculations, we need to check that everything sums to 100%
if total_distributed > 0:
Expand All @@ -559,12 +578,14 @@ def recon(self) -> None:
"feesToDao": float(round(total_dao, 2)),
"feesToVebal": float(round(total_vebal, 2)),
"feesToPartners": float(round(total_partner, 2)),
"feesToBeets": float(round(total_beets, 2)),
"auravebalShare": float(round(aura_share, 2)),
"auraIncentivesPct": float(round(total_aura / total_distributed, 4)) if total_distributed > 0 else 0,
"balIncentivesPct": float(round(total_bal / total_distributed, 4)) if total_distributed > 0 else 0,
"feesToDaoPct": float(round(total_dao / total_distributed, 4)) if total_distributed > 0 else 0,
"feesToVebalPct": float(round(total_vebal / total_distributed, 4)) if total_distributed > 0 else 0,
"feesToPartnersPct": float(round(total_partner / total_distributed, 4)) if total_distributed > 0 else 0,
"feesToBeetsPct": float(round(total_beets / total_distributed, 4)) if total_distributed > 0 else 0,
"createdAt": int(datetime.datetime.now().timestamp()),
"periodStart": self.date_range[0],
"periodEnd": self.date_range[1]
Expand Down
Loading