From 7d62c550bb2422db32a8e9d59d6855b966edfb58 Mon Sep 17 00:00:00 2001 From: Shahul Hameed <10547529+shahthepro@users.noreply.github.com> Date: Wed, 9 Aug 2023 18:01:05 +0400 Subject: [PATCH] Add Flux Governance monitoring --- eagleproject/core/blockchain/addresses.py | 7 ++++- eagleproject/core/blockchain/const.py | 6 +++- .../compound_governorbravo_implementation.py | 17 +++++++---- .../compound_governorbravo_proposals.py | 29 ++++++++++++------- .../compound_governorbravo_votingparams.py | 29 ++++++++++++------- .../triggers/compound_timelock_admin.py | 24 ++++++++++----- .../triggers/compound_timelock_delay.py | 15 +++++++--- .../compound_timelock_transactions.py | 21 +++++++++----- 8 files changed, 100 insertions(+), 48 deletions(-) diff --git a/eagleproject/core/blockchain/addresses.py b/eagleproject/core/blockchain/addresses.py index 10877ec2..ba3f6b19 100644 --- a/eagleproject/core/blockchain/addresses.py +++ b/eagleproject/core/blockchain/addresses.py @@ -166,6 +166,10 @@ # This contract needs 60% support to pass CURVE_ARAGON_60 = "0xbcff8b0b9419b9a88c44546519b1e909cf330399" +# Flux Finance Governance +FLUX_TIMELOCK = "0x2c5898da4df1d45eab2b7b192a361c3b9eb18d9c" +FLUX_DAO = "0x336505ec1bcc1a020eede459f57581725d23465a" + # Name resolution CONTRACT_ADDR_TO_NAME = { OUSD: "OUSD Token", @@ -222,7 +226,8 @@ OGV_BUYBACK_LEGACY: "OGV BuyBack (Legacy)", OGV_BUYBACK_PROXY: "OGV BuyBack", REWARDS_SOURCE: "RewardsSource", - + FLUX_DAO: "Flux DAO", + FLUX_TIMELOCK: "Flux Timelock", # OETH Contracts OETH: "OETH Token", diff --git a/eagleproject/core/blockchain/const.py b/eagleproject/core/blockchain/const.py index 4898df2f..1ecec2e4 100644 --- a/eagleproject/core/blockchain/const.py +++ b/eagleproject/core/blockchain/const.py @@ -47,7 +47,9 @@ RETH, STETH, WETH, - ETH + ETH, + FLUX_DAO, + FLUX_TIMELOCK ) from core.blockchain.strategies import OUSD_STRATEGIES, OETH_STRATEGIES @@ -177,6 +179,8 @@ CURVE_ARAGON_51, CURVE_ARAGON_60, CHAINLINK_KEEPER_REGISTRY, + FLUX_DAO, + FLUX_TIMELOCK ] ETHERSCAN_CONTRACTS = [ diff --git a/eagleproject/notify/triggers/compound_governorbravo_implementation.py b/eagleproject/notify/triggers/compound_governorbravo_implementation.py index d5e24192..ec0ff345 100644 --- a/eagleproject/notify/triggers/compound_governorbravo_implementation.py +++ b/eagleproject/notify/triggers/compound_governorbravo_implementation.py @@ -2,16 +2,19 @@ from eth_utils import decode_hex from eth_abi import decode_single -from core.blockchain.addresses import COMPOUND_GOVERNOR_BRAVO +from core.blockchain.addresses import ( + COMPOUND_GOVERNOR_BRAVO, + FLUX_DAO, + CONTRACT_ADDR_TO_NAME, +) from core.blockchain.sigs import SIG_EVENT_NEW_IMPLEMENTATION_BRAVO from notify.events import event_high DISCORD_EMBED_DESCRIPTION_LIMIT = 2048 - def get_events(logs): """ Get Mint/Redeem events """ - return logs.filter(address=COMPOUND_GOVERNOR_BRAVO).filter( + return logs.filter(address__in=[COMPOUND_GOVERNOR_BRAVO, FLUX_DAO]).filter( topic_0=SIG_EVENT_NEW_IMPLEMENTATION_BRAVO ).order_by('block_number') @@ -27,10 +30,12 @@ def run_trigger(new_logs): ) new_link = 'https://etherscan.io/address/{}'.format(new_address) + contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address) + events.append(event_high( - "Compound GovernorBravo implementation upgraded 🗳️ ⏫", - "Compound GovernorBravo implementation changed from {} to [{}]({})".format( - old_address, new_address, new_link + "{} implementation upgraded 🗳️ ⏫".format(contract_name), + "{} implementation changed from {} to [{}]({})".format( + contract_name, old_address, new_address, new_link ), log_model=ev )) diff --git a/eagleproject/notify/triggers/compound_governorbravo_proposals.py b/eagleproject/notify/triggers/compound_governorbravo_proposals.py index 60e6b3fe..ead18f66 100644 --- a/eagleproject/notify/triggers/compound_governorbravo_proposals.py +++ b/eagleproject/notify/triggers/compound_governorbravo_proposals.py @@ -7,6 +7,7 @@ from core.blockchain.addresses import ( CONTRACT_ADDR_TO_NAME, COMPOUND_GOVERNOR_BRAVO, + FLUX_DAO, ) from core.blockchain.decode import decode_calls from core.blockchain.sigs import ( @@ -24,7 +25,7 @@ def get_events(logs): """ Get Mint/Redeem events """ - return logs.filter(address=COMPOUND_GOVERNOR_BRAVO).filter( + return logs.filter(address__in=[COMPOUND_GOVERNOR_BRAVO,FLUX_DAO]).filter( Q(topic_0=SIG_EVENT_PROPOSAL_CREATED) | Q(topic_0=SIG_EVENT_PROPOSAL_CANCELED) | Q(topic_0=SIG_EVENT_PROPOSAL_QUEUED) @@ -33,10 +34,10 @@ def get_events(logs): ).order_by('block_number') -def create_prop_details(proposal_id, description, proposer, targets, +def create_prop_details(contract_name, proposal_id, description, proposer, targets, signatures, calldatas, start_block, end_block): return ( - "A new proposal ({}) has been submitted for Compound Governor" + "A new proposal ({}) has been submitted for {}" "\n\n" "**Description**: \n\n{}\n\n" "**Proposer**: {}\n" @@ -44,6 +45,7 @@ def create_prop_details(proposal_id, description, proposer, targets, "**Calls**: \n - {}\n" "**Block Range**: {}".format( proposal_id, + contract_name, description, proposer, ', '.join([ @@ -61,6 +63,7 @@ def run_trigger(new_logs): events = [] for ev in get_events(new_logs): + contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address) if ev.topic_0 == SIG_EVENT_PROPOSAL_CREATED: # ProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint startBlock, uint endBlock, string description) @@ -80,6 +83,7 @@ def run_trigger(new_logs): ) details = create_prop_details( + contract_name, proposal_id, description, proposer, @@ -94,6 +98,7 @@ def run_trigger(new_logs): if len(details) > DISCORD_EMBED_DESCRIPTION_LIMIT: diff = len(details) - DISCORD_EMBED_DESCRIPTION_LIMIT details = create_prop_details( + contract_name, proposal_id, truncate_elipsis( description, @@ -108,7 +113,8 @@ def run_trigger(new_logs): ) events.append(event_high( - "Compound Governor Proposal Created ({}) 🗳️ 🆕".format( + "{} Proposal Created ({}) 🗳️ 🆕".format( + contract_name, proposal_id ), details, @@ -119,8 +125,9 @@ def run_trigger(new_logs): proposal_id = decode_single("(uint256)", decode_hex(ev.data))[0] events.append(event_high( - "Compound GovernorBravo proposed cancelled 🗳️ ❌", - "Compound GovernorBravo proposal #{} has been canceled".format( + "{} proposed cancelled 🗳️ ❌".format(contract_name), + "{} proposal #{} has been canceled".format( + contract_name, proposal_id ), log_model=ev @@ -135,9 +142,10 @@ def run_trigger(new_logs): eta = datetime.utcfromtimestamp(eta_stamp) events.append(event_high( - "Compound GovernorBravo proposed queued 🗳️ 📥", - "Compound GovernorBravo proposal #{} has been queued " + "{} proposed queued 🗳️ 📥".format(contract_name), + "{} proposal #{} has been queued " "for {} UTC".format( + contract_name, proposal_id, eta, ), @@ -148,8 +156,9 @@ def run_trigger(new_logs): proposal_id = decode_single("(uint256)", decode_hex(ev.data))[0] events.append(event_high( - "Compound GovernorBravo proposed executed 🗳️ ⚙️", - "Compound GovernorBravo proposal #{} has been executed".format( + "{} proposed executed 🗳️ ⚙️".format(contract_name), + "{} proposal #{} has been executed".format( + contract_name, proposal_id, ), log_model=ev diff --git a/eagleproject/notify/triggers/compound_governorbravo_votingparams.py b/eagleproject/notify/triggers/compound_governorbravo_votingparams.py index ef6267a7..72e8f0d1 100644 --- a/eagleproject/notify/triggers/compound_governorbravo_votingparams.py +++ b/eagleproject/notify/triggers/compound_governorbravo_votingparams.py @@ -4,7 +4,11 @@ from eth_utils import decode_hex from eth_abi import decode_single -from core.blockchain.addresses import COMPOUND_GOVERNOR_BRAVO +from core.blockchain.addresses import ( + COMPOUND_GOVERNOR_BRAVO, + FLUX_DAO, + CONTRACT_ADDR_TO_NAME, +) from core.blockchain.const import E_18 from core.blockchain.sigs import ( SIG_EVENT_VOTING_DELAY_SET, @@ -18,7 +22,7 @@ def get_events(logs): """ Get Mint/Redeem events """ - return logs.filter(address=COMPOUND_GOVERNOR_BRAVO).filter( + return logs.filter(address__in=[COMPOUND_GOVERNOR_BRAVO, FLUX_DAO]).filter( Q(topic_0=SIG_EVENT_VOTING_DELAY_SET) | Q(topic_0=SIG_EVENT_VOTING_PERIOD_SET) | Q(topic_0=SIG_EVENT_PROPOSAL_THRESHOLD_SET) @@ -29,6 +33,9 @@ def run_trigger(new_logs): """ Compound Timelock changes """ events = [] + contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address) + token_name = "ONDO" if ev.address == FLUX_DAO else "COMP" + for ev in get_events(new_logs): if ev.topic_0 == SIG_EVENT_VOTING_DELAY_SET: old_delay, new_delay = decode_single( @@ -37,9 +44,9 @@ def run_trigger(new_logs): ) events.append(event_normal( - "Compound GovernorBravo voting delay changed 🗳️ 🕖", - "Compound GovernorBravo voting delay changed from {} blocks to {} blocks".format( - old_delay, new_delay + "{} voting delay changed 🗳️ 🕖".format(contract_name), + "{} voting delay changed from {} blocks to {} blocks".format( + contract_name, old_delay, new_delay ), log_model=ev )) @@ -51,9 +58,9 @@ def run_trigger(new_logs): ) events.append(event_normal( - "Compound GovernorBravo voting delay changed 🗳️ 🕗", - "Compound GovernorBravo voting period changed from {} blocks to {} blocks".format( - old_period, new_period + "{} voting delay changed 🗳️ 🕗".format(contract_name), + "{} voting period changed from {} blocks to {} blocks".format( + contract_name, old_period, new_period ), log_model=ev )) @@ -68,9 +75,9 @@ def run_trigger(new_logs): new_human = Decimal(new_threshold) / E_18 events.append(event_normal( - "Compound GovernorBravo voting threshold changed 🗳️ 🪙", - "Compound GovernorBravo voting threshold changed from {} COMP to {} COMP".format( - old_human, new_human + "{} voting threshold changed 🗳️ 🪙".format(contract_name), + "{} voting threshold changed from {} {} to {} {}".format( + contract_name, old_human, token_name, new_human, token_name ), log_model=ev )) diff --git a/eagleproject/notify/triggers/compound_timelock_admin.py b/eagleproject/notify/triggers/compound_timelock_admin.py index 632e7914..c5ee3812 100644 --- a/eagleproject/notify/triggers/compound_timelock_admin.py +++ b/eagleproject/notify/triggers/compound_timelock_admin.py @@ -3,7 +3,11 @@ from eth_utils import decode_hex from eth_abi import decode_single -from core.blockchain.addresses import COMPOUND_TIMELOCK +from core.blockchain.addresses import ( + CONTRACT_ADDR_TO_NAME, + COMPOUND_TIMELOCK, + FLUX_TIMELOCK, +) from core.blockchain.sigs import ( SIG_EVENT_NEW_ADMIN, SIG_EVENT_NEW_PENDING_ADMIN, @@ -13,7 +17,7 @@ def get_events(logs): """ Get Mint/Redeem events """ - return logs.filter(address=COMPOUND_TIMELOCK).filter( + return logs.filter(address__in=[COMPOUND_TIMELOCK, FLUX_TIMELOCK]).filter( Q(topic_0=SIG_EVENT_NEW_ADMIN) | Q(topic_0=SIG_EVENT_NEW_PENDING_ADMIN) ).order_by('block_number') @@ -26,11 +30,14 @@ def run_trigger(new_logs): for ev in get_events(new_logs): admin_address = decode_single("(address)", decode_hex(ev.topic_1))[0] + contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address) + if ev.topic_0 == SIG_EVENT_NEW_ADMIN: events.append(event_high( - "Compound Timelock admin claimed 👮", - "A new admin has been set for the Compound Timelock " + "{} admin claimed 👮".form(contract_name), + "A new admin has been set for the {} " "contract: {}".format( + contract_name, admin_address ), log_model=ev @@ -38,11 +45,12 @@ def run_trigger(new_logs): elif ev.topic_0 == SIG_EVENT_NEW_PENDING_ADMIN: events.append(event_high( - "New Compound Timelock admin proposed 👮", - "{} has been proposed as the new admin for the Compound " - "Timelock governor contract and is currently waiting to be " + "New {} admin proposed 👮".format(contract_name), + "{} has been proposed as the new admin for the {} " + "governor contract and is currently waiting to be " "claimed.".format( - admin_address + admin_address, + contract_name ), log_model=ev )) diff --git a/eagleproject/notify/triggers/compound_timelock_delay.py b/eagleproject/notify/triggers/compound_timelock_delay.py index ab3822ef..5bbd416f 100644 --- a/eagleproject/notify/triggers/compound_timelock_delay.py +++ b/eagleproject/notify/triggers/compound_timelock_delay.py @@ -3,14 +3,18 @@ from eth_utils import decode_hex from eth_abi import decode_single -from core.blockchain.addresses import COMPOUND_TIMELOCK +from core.blockchain.addresses import ( + CONTRACT_ADDR_TO_NAME, + COMPOUND_TIMELOCK, + FLUX_TIMELOCK, +) from core.blockchain.sigs import SIG_EVENT_DELAY from notify.events import event_high def get_events(logs): """ Get NewDelay events """ - return logs.filter(address=COMPOUND_TIMELOCK).filter( + return logs.filter(address__in=[COMPOUND_TIMELOCK, FLUX_TIMELOCK]).filter( topic_0=SIG_EVENT_DELAY ).order_by('block_number') @@ -20,12 +24,15 @@ def run_trigger(new_logs): events = [] for ev in get_events(new_logs): + contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address) + delay_seconds = decode_single("(uint256)", decode_hex(ev.topic_1))[0] delay = timedelta(seconds=delay_seconds) events.append(event_high( - "Compound Timelock delay changed 👮", - "Compound Timelock delay has been changed to {}".format( + "{} delay changed 👮".format(contract_name), + "{} delay has been changed to {}".format( + contract_name, delay ), log_model=ev diff --git a/eagleproject/notify/triggers/compound_timelock_transactions.py b/eagleproject/notify/triggers/compound_timelock_transactions.py index 0aea45c3..61e50728 100644 --- a/eagleproject/notify/triggers/compound_timelock_transactions.py +++ b/eagleproject/notify/triggers/compound_timelock_transactions.py @@ -4,7 +4,11 @@ from eth_abi import decode_single from django.db.models import Q -from core.blockchain.addresses import CONTRACT_ADDR_TO_NAME, COMPOUND_TIMELOCK +from core.blockchain.addresses import ( + CONTRACT_ADDR_TO_NAME, + COMPOUND_TIMELOCK, + FLUX_TIMELOCK, +) from core.blockchain.decode import decode_call from core.blockchain.sigs import ( SIG_EVENT_CANCEL_TRANSACTION, @@ -16,7 +20,7 @@ def get_events(logs): """ Get events """ - return logs.filter(address=COMPOUND_TIMELOCK).filter( + return logs.filter(address__in=[COMPOUND_TIMELOCK, FLUX_TIMELOCK]).filter( Q(topic_0=SIG_EVENT_CANCEL_TRANSACTION) | Q(topic_0=SIG_EVENT_EXECUTE_TRANSACTION) | Q(topic_0=SIG_EVENT_QUEUE_TRANSACTION) @@ -24,21 +28,23 @@ def get_events(logs): def run_trigger(new_logs): - """ Trigger events on Compound Timelock transaction events """ + """ Trigger events on Compound and Flux Timelock transaction events """ events = [] for ev in get_events(new_logs): summary = "ERROR" action = "ERROR" + contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address) + if ev.topic_0 == SIG_EVENT_QUEUE_TRANSACTION: - summary = "Compound Timelock transaction queued ⏲️ 📥" + summary = "{} transaction queued ⏲️ 📥".format(contract_name) action = "queued" elif ev.topic_0 == SIG_EVENT_CANCEL_TRANSACTION: - summary = "Compound Timelock transaction canceled ⏲️ ❌" + summary = "{} transaction canceled ⏲️ ❌".format(contract_name) action = "canceled" elif ev.topic_0 == SIG_EVENT_EXECUTE_TRANSACTION: - summary = "Compound Timelock transaction executed ⏲️ 🏃‍♀️" + summary = "{} transaction executed ⏲️ 🏃‍♀️".format(contract_name) action = "executed" # They all have the same args so most of thise can be reused @@ -54,10 +60,11 @@ def run_trigger(new_logs): events.append(event_high( summary, - "Compound Timelock transaction has been {}\n\n" + "{} transaction has been {}\n\n" "**Target**: {}\n" "**ETA**: {} UTC\n" "**Call**: {}".format( + contract_name, action, CONTRACT_ADDR_TO_NAME.get(target, target), eta,