From 4073e587e64a345c8bd92497cdcc299efd6541cc Mon Sep 17 00:00:00 2001 From: Marius <14898268+mariuspod@users.noreply.github.com> Date: Wed, 19 Jan 2022 03:59:34 +0100 Subject: [PATCH] fix: Requesting ERC-20 or ERC-677 Transfer events in log filter. (#186) * fix: Requesting ERC-20 or ERC-677 Transfer events in log filter. * fix: use brownie version that contains the ability to download the latest solc compiler patch version for contract compilations and remove handling of '(unknown)' events. * fix: don't import relative parts and use encode_* methods to encode the addresses for the log filter. * fix: typo in yaml file * feat: use brownie master branch which has the required changes merged in which fix event decoding for the given chainlink contract. --- brownie-config.yaml | 5 +++ requirements.txt | 2 +- yearn/constants.py | 4 +++ yearn/treasury/treasury.py | 66 +++++++++++++++++++++----------------- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/brownie-config.yaml b/brownie-config.yaml index 8327d37a7..a9f0e2928 100644 --- a/brownie-config.yaml +++ b/brownie-config.yaml @@ -2,3 +2,8 @@ networks: default: mainnet autofetch_sources: true + +compiler: + solc: + use_latest_patch: + - '0x514910771AF9Ca656af840dff83E8264EcF986CA' diff --git a/requirements.txt b/requirements.txt index 6a45fe5f5..860136cad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -eth-brownie>=1.16.4 +git+https://github.com/eth-brownie/brownie.git@master web3>=5.23.1 click>=7.1.2 tabulate>=0.8.7 diff --git a/yearn/constants.py b/yearn/constants.py index 804924e83..e1f5e4dd2 100644 --- a/yearn/constants.py +++ b/yearn/constants.py @@ -125,3 +125,7 @@ "0x7d2aB9CA511EBD6F03971Fb417d3492aA82513f0", # ySwap Multisig "0x2C01B4AD51a67E2d8F02208F54dF9aC4c0B778B6", # yMechs Multisig } + +# EVENTS +ERC20_TRANSFER_EVENT_HASH = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' +ERC677_TRANSFER_EVENT_HASH = '0xe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16' \ No newline at end of file diff --git a/yearn/treasury/treasury.py b/yearn/treasury/treasury.py index fc90f3972..b6e31f5de 100644 --- a/yearn/treasury/treasury.py +++ b/yearn/treasury/treasury.py @@ -5,6 +5,7 @@ from brownie import Contract, chain, web3 from brownie.network.event import EventLookupError from eth_abi import encode_single +from eth_utils import encode_hex from joblib import Parallel, delayed from yearn.events import decode_logs from yearn.multicall2 import fetch_multicall @@ -16,7 +17,7 @@ from yearn.exceptions import PriceError from yearn.utils import contract -from ..constants import TREASURY_WALLETS +from yearn.constants import TREASURY_WALLETS, ERC20_TRANSFER_EVENT_HASH, ERC677_TRANSFER_EVENT_HASH logger = logging.getLogger(__name__) logger_price_magic.setLevel(logging.CRITICAL) @@ -62,7 +63,8 @@ def _get_price(token, block=None): def get_token_from_event(event): try: - address = event['Transfer'][0].address + transfer = event['Transfer'] + address = transfer[0].address # try to download the contract from etherscan contract(address) return address @@ -70,13 +72,8 @@ def get_token_from_event(event): # some tokens have unverified sources with etherscan, skip them! return None except EventLookupError: - logger.critical( - f'One of your cached contracts has an incorrect definition: {event.address}. Please fix this manually' - ) - raise Exception( - f'One of your cached contracts has an incorrect definition: {event.address}. Please fix this manually' - ) - + logger.critical(event) + raise class Treasury: ''' @@ -86,15 +83,26 @@ class Treasury: def __init__(self, watch_events_forever=False): self.addresses = list(TREASURY_WALLETS) self._transfers = [] - self._topics_in = [ - '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', - None, - ['0x000000000000000000000000' + address[2:] for address in self.addresses], - ] # Transfers into Yearn wallets - self._topics_out = [ - '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', - ['0x000000000000000000000000' + address[2:] for address in self.addresses], - ] # Transfers out of Yearn wallets + self._start_block = 10502337 # Treasury didn't exist prior to block 10502337 + + # define transfer signatures for Transfer events from ERC-20 and ERC-677 contracts + transfer_sigs = [ + ERC20_TRANSFER_EVENT_HASH, + ERC677_TRANSFER_EVENT_HASH + ] + treasury_addresses = [encode_hex(encode_single('address', address)) for address in self.addresses] + self._topics = [ + [ + transfer_sigs, + None, + treasury_addresses # Transfers into Treasury wallets + ], + [ + transfer_sigs, + treasury_addresses # Transfers out of Treasury wallets + ] + ] + self._watch_events_forever = watch_events_forever self._done = threading.Event() self._thread = threading.Thread(target=self.watch_transfers, daemon=True) @@ -110,13 +118,15 @@ def assets(self, block=None) -> dict: def token_list(self, address, block=None) -> list: self.load_transfers() tokens = set() - for transfer in self._transfers: - token = get_token_from_event(transfer) + for event in self._transfers: + token = get_token_from_event(event) if token is None: continue - if transfer['Transfer'].values()[1] == address: + + transfer = event['Transfer'] + if transfer.values()[1] == address: if block: - if transfer['Transfer'][0].block_number <= block: + if transfer[0].block_number <= block: tokens.add(token) else: tokens.add(token) @@ -274,14 +284,12 @@ def watch_transfers(self): logger.info( 'pulling treasury transfer events, please wait patiently this takes a while...' ) - # Treasury didn't exist prior to block 10502337 - self.log_filter_in = web3.eth.filter({"fromBlock": 10502337, "topics": self._topics_in}) - self.log_filter_out = web3.eth.filter({"fromBlock": 10502337, "topics": self._topics_out}) for block in chain.new_blocks(height_buffer=12): - logs = self.log_filter_in.get_new_entries() - self.process_transfers(logs) - logs = self.log_filter_out.get_new_entries() - self.process_transfers(logs) + for topics in self._topics: + topic_filter = web3.eth.filter({"fromBlock": self._start_block, "topics": topics}) + logs = topic_filter.get_new_entries() + self.process_transfers(logs) + if not self._done.is_set(): self._done.set() logger.info(