Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
44 changes: 19 additions & 25 deletions .github/workflows/compute-roots.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,54 +24,48 @@ jobs:
run: yarn build

- name: Calculate roots for BAL
run: NETWORK=homestead yarn merkle-roots --outfile ./reports/_roots.json
run: NETWORK=homestead yarn merkle-roots --outfile ./reports/_incident-response/_roots.json

- name: Calculate roots for BAL on arbitrum
run: NETWORK=arbitrum yarn merkle-roots --outfile ./reports/_roots-arbitrum.json
run: NETWORK=arbitrum yarn merkle-roots --outfile ./reports/_incident-response/_roots-arbitrum.json

- name: Calculate roots for BAL on polygon
run: NETWORK=polygon yarn merkle-roots --outfile ./reports/_roots-polygon.json
run: NETWORK=polygon yarn merkle-roots --outfile ./reports/_incident-response/_roots-polygon.json

- name: Calculate roots for BANK
run: NETWORK=homestead-bankless yarn merkle-roots --outfile ./reports/_roots-bankless.json
- name: Calculate roots for LDO
run: NETWORK=homestead-lido yarn merkle-roots --outfile ./reports/_incident-response/_roots-lido.json

- name: Calculate roots for NOTE
run: NETWORK=homestead-note yarn merkle-roots --outfile ./reports/_roots-note.json
- name: Calculate roots for UNN
run: NETWORK=homestead-union yarn merkle-roots --outfile ./reports/_incident-response/_roots-union.json

- name: Calculate roots for VITA
run: NETWORK=homestead-vita yarn merkle-roots --outfile ./reports/_roots-vita.json
- name: Calculate roots for BANK
run: NETWORK=homestead-bankless yarn merkle-roots --outfile ./reports/_incident-response/_roots-bankless.json

- name: Calculate roots for NEXO
run: NETWORK=homestead-nexo yarn merkle-roots --outfile ./reports/_roots-nexo.json
- name: Calculate roots for NOTE
run: NETWORK=homestead-note yarn merkle-roots --outfile ./reports/_incident-response/_roots-note.json

- name: Calculate roots for D2D
run: NETWORK=homestead-d2d yarn merkle-roots --outfile ./reports/_roots-d2d.json
run: NETWORK=homestead-d2d yarn merkle-roots --outfile ./reports/_incident-response/_roots-d2d.json

- name: Calculate roots for TUSD on polygon
run: NETWORK=polygon-tusd yarn merkle-roots --outfile ./reports/_roots-tusd-polygon.json

- name: Calculate roots for TEL on polygon
run: NETWORK=polygon-telcoin yarn merkle-roots --outfile ./reports/_roots-telcoin-polygon.json
run: NETWORK=polygon-tusd yarn merkle-roots --outfile ./reports/_incident-response/_roots-tusd-polygon.json

- name: Calculate roots for QI on polygon
run: NETWORK=polygon-qi yarn merkle-roots --outfile ./reports/_roots-qi-polygon.json
run: NETWORK=polygon-qi yarn merkle-roots --outfile ./reports/_incident-response/_roots-qi-polygon.json

- name: Calculate roots for LDO on polygon
run: NETWORK=polygon-ldo yarn merkle-roots --outfile ./reports/_roots-ldo-polygon.json
run: NETWORK=polygon-ldo yarn merkle-roots --outfile ./reports/_incident-response/_roots-ldo-polygon.json

- name: Calculate roots for WMATIC on polygon
run: NETWORK=polygon-wmatic yarn merkle-roots --outfile ./reports/_roots-wmatic-polygon.json

- name: Calculate roots for MCB on arbitrum
run: NETWORK=arbitrum-mcdex yarn merkle-roots --outfile ./reports/_roots-mcdex-arbitrum.json
run: NETWORK=polygon-wmatic yarn merkle-roots --outfile ./reports/_incident-response/_roots-wmatic-polygon.json

- name: Calculate roots for PICKLE on arbitrum
run: NETWORK=arbitrum-pickle yarn merkle-roots --outfile ./reports/_roots-pickle-arbitrum.json
run: NETWORK=arbitrum-pickle yarn merkle-roots --outfile ./reports/_incident-response/_roots-pickle-arbitrum.json

- name: Commit changes
uses: EndBug/add-and-commit@v7
with:
author_name: Merkle Root Bot
author_email: no-reply@balancer.finance
message: 'Computed roots for reports'
add: './reports/_roots*.json'
message: 'Computed roots for reports/_incident-response'
add: './reports/_incident-response/_roots*.json'
16 changes: 2 additions & 14 deletions .github/workflows/publish-ipfs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Publish reports to ipfs
on:
push:
branches:
- 'master'
- 'incident-response'

jobs:
ipfs-publish:
Expand Down Expand Up @@ -49,21 +49,12 @@ jobs:
- name: Publish ipfs reports for BANK
run: NETWORK=homestead-bankless yarn ipfs-publish

- name: Publish ipfs reports for VITA
run: NETWORK=homestead-vita yarn ipfs-publish

- name: Publish ipfs reports for NOTE
run: NETWORK=homestead-note yarn ipfs-publish

- name: Publish ipfs reports for NEXO
run: NETWORK=homestead-nexo yarn ipfs-publish

- name: Publish ipfs reports for TUSD on polygon
run: NETWORK=polygon-tusd yarn ipfs-publish

- name: Publish ipfs reports for TEL on polygon
run: NETWORK=polygon-telcoin yarn ipfs-publish

- name: Publish ipfs reports for QI on polygon
run: NETWORK=polygon-qi yarn ipfs-publish

Expand All @@ -73,9 +64,6 @@ jobs:
- name: Publish ipfs reports for WMATIC on polygon
run: NETWORK=polygon-wmatic yarn ipfs-publish

- name: Publish ipfs reports for MCB on arbitrum
run: NETWORK=arbitrum-mcdex yarn ipfs-publish

- name: Publish ipfs reports for PICKLE on arbitrum
run: NETWORK=arbitrum-pickle yarn ipfs-publish

Expand All @@ -86,4 +74,4 @@ jobs:
author_email: no-reply@balancer.finance
branch: ipfs-publish
message: 'Updating ipfs links'
add: './reports/_current*.json'
add: './reports/_incident-response/_current*.json'
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ _poolsSeries.json.zip
bal-for-gas-compare-implementations.ipynb
*.pyc
bal-for-gas-v2-test.ipynb

#venv
pyvenv.cfg
bin/*
,/bin/*
137 changes: 80 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,74 +1,97 @@
<h1 align=center><code>BAL Mining</code></h1>
<h1 align=center><code>BAL Mining - incident response</code></h1>

Set of scripts to calculate weekly BAL liquidity mining distributions.
In January 2023, Balancer Labs was notified of a bug in the MerkleOrchard contracts that were used to distribute token incentives before Balancer Protocol migrated to the new ve-tokenomics in 2022. [[1]](https://twitter.com/Balancer/status/1620503172702953475)

On week 26, the process was ported over to Python with the [blockchain-etl](https://github.com/blockchain-etl/) project on Google Bigquery as the source for state data, such as pools' balances, fees, liquidity providers etc. The legacy scripts used up to week 25 can be found in the `js` directory.
Funds were safely transferred to the Balancer DAO treasury to be later distributed by a patched MerkleOrchard contract.

## [Historical Runs](https://github.com/balancer-labs/bal-mining-scripts/blob/aca467d/README.md#historical-runs)
This branch was specifically designed to repurpose the liquidity mining infrastructure so as to address the redistribution of said tokens.

## [Reports](https://github.com/balancer-labs/bal-mining-scripts/tree/master/reports)
For each token recovered from the Merkle Orchard, `run-incident.py` computes the unclaimed distributions belonging to each claimer and aggregates them. The aggregate amounts are output to `reports/_incident-response/1`, in `__<network>_<token>.json` files, containing a list of liquidity providers and the amount of `<token>` left for them to claim.

Starting on week 57 of the liquidity mining program (June 28th 2021), pools can be incentivized with multiple tokens. Each weekly report directory has the following structure:
At the end, the script checks that the sum of all the amounts in each report is equal to the amounts recovered from the faulty Merkle Orchard.

- `__<network>_<token>.json` files, containing a list of liquidity providers and the amount of `<token>` earned by each for providing liquidity in incentivized Balancer pools on `<network>`
- `_totalsLiquidityMining.json`: for consistency with the reports provided in previous weeks, contains a list of liquidity providers and `BAL` earned across all networks
- `_gasResimbursement.json`: results of the _BAL for Gas_ program for the week, if applicable
- `_totals.json`: total amount of `BAL` to be claimed on Ethereum mainnet (`__ethereum_0xba1...` + `_gasResimbursement.json`)
```
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
arbitrum, 0x040d1edc9569d4bab2d15287dc5a4f10f56a56b8 check
17864.43303 recovered
17864.43303 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
arbitrum, 0x965772e0e9c84b6f359c8597c891108dcf1c5b1a check
2265.85941 recovered
2265.85941 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ethereum, 0x226f7b842e0f0120b7e194d05432b3fd14773a9d check
1190799.41399 recovered
1190799.41399 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ethereum, 0x2d94aa3e47d9d5024503ca8491fce9a2fb4da198 check
267578.13838 recovered
267578.13838 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ethereum, 0x43d4a3cd90ddd2f8f4f693170c9c8098163502ad check
14891.48765 recovered
14891.48765 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ethereum, 0x5a98fcbea516cf06857215779fd812ca3bef1b32 check
287507.81357 recovered
287507.81357 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ethereum, 0xba100000625a3754423978a60c9317c58a424e3d check
296749.18133 recovered
296749.18133 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ethereum, 0xcfeaead4947f0705a14ec42ac3d44129e1ef3ed5 check
53281.96362 recovered
53281.96362 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
polygon, 0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270 check
23488.53485 recovered
23488.53485 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
polygon, 0x2e1ad108ff1d8c782fcbbb89aad783ac49586756 check
43359.51599 recovered
43359.51598 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
polygon, 0x580a84c73811e1839f75d86d75d88cca0c241ff4 check
9067.62018 recovered
9067.62018 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
polygon, 0x9a71012b13ca4d3d0cdc72a177df3ef03b0e76a3 check
33852.28964 recovered
33852.28964 redistributed

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
polygon, 0xc3c7d422809852031b44ab29eec9f1eff2a58756 check
462.47457 recovered
462.47457 redistributed
```

`liquidityMiningConfig.json` and the GitHub workflow files have been updated so that:

1. merkle roots are computed from the incident reports and saved to `reports/_incident-response/_roots-*.json`
2. incident reports are published to IPFS and manifests are saved to `reports/_incident-response/_current-*.json`

With this, the existing claim UI can be easily repurposed to enable claims of the redistributed funds.

## Requirements

- Python 3
- A [service account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#iam-service-account-keys-create-console) with read access to Google BigQuery

## Setup

- Install required packages: `pip install -r requirements.txt`
- Configure environment variable:
- `GOOGLE_APPLICATION_CREDENTIALS`: path to a JSON file that contains a service account key with read access to Google BigQuery

## Usage

`python3 run.py`

## Weekly distributions

145,000 BAL will be distributed on a weekly basis.
Liquidity providers must claim their BAL at [app.balancer.fi](https://app.balancer.fi/), [polygon.balancer.fi](https://polygon.balancer.fi/) or [arbitrum.balancer.fi](https://arbitrum.balancer.fi/).

## Redirections

In case smart contracts which cannot receive tokens are liquidity providers (ie. hold the tokens that represent ownership of the pool), owners of those smart contracts can choose to redirect their liquidity mining incentives to a new address. In order to submit a redirection request, submit a pull request to update `config/redirect.json` using `"fromAddress" : "toAddress"` along with some sort of ownership proof. Please reach out to the Balancer team if you need assistance.

## Opting out

Liquidity providers can choose to opt out of liquidity mining incentives. In order to do so, they must submit a pull request as per the instructions below along with some sort of proof of ownership of the address. Please reach out to the Balancer team if you need assistance.

### Opting out of specific pools

Add your address to the file `config/exclude.json`, which has the following structure;

```
{
"chain_id": {
"pool_address": [
"liquidity_provider_a",
"liquidity_provider_b",
...
],
...
},
...
}
```

### Opting out of liquidity mining altogether

Add your address to `BASE_LP_EXCLUSION_LIST` in `src/query_gbq.py`

```
BASE_LP_EXCLUSION_LIST = [
'0x0000000000000000000000000000000000000000',
'0xba12222222228d8ba445958a75a0704d566bf2c8'.
'<insert_address_here>'
]
```
`python3 run-incident.py`
Loading