Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Requesting ERC-20 or ERC-677 Transfer events in log filter. #186

Merged
merged 5 commits into from
Jan 19, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions yearn/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,7 @@
"0x7d2aB9CA511EBD6F03971Fb417d3492aA82513f0", # ySwap Multisig
"0x2C01B4AD51a67E2d8F02208F54dF9aC4c0B778B6", # yMechs Multisig
}

# EVENTS
ERC20_TRANSFER_EVENT_HASH = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
ERC677_TRANSFER_EVENT_HASH = '0xe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16'
72 changes: 43 additions & 29 deletions yearn/treasury/treasury.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from yearn.exceptions import PriceError
from yearn.utils import contract

from ..constants import TREASURY_WALLETS
from ..constants import TREASURY_WALLETS, ERC20_TRANSFER_EVENT_HASH, ERC677_TRANSFER_EVENT_HASH
mariuspod marked this conversation as resolved.
Show resolved Hide resolved

logger = logging.getLogger(__name__)
logger_price_magic.setLevel(logging.CRITICAL)
Expand Down Expand Up @@ -62,21 +62,24 @@ def _get_price(token, block=None):

def get_token_from_event(event):
try:
address = event['Transfer'][0].address
if '(unknown)' in event:
mariuspod marked this conversation as resolved.
Show resolved Hide resolved
# Depending on the contract's internal topic_map the event will be unknown if it couldn't be decoded by brownie based on the provided transfer event signature of the given log filter.
# ERC-20 events are matched with '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' in the first topic.
# ERC-677 events are matched with '0xe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16' in the first topic.
# As each log is matched against exactly one topic-0 although we're passing an union of topics-0 we will still get some unknown events from brownie which can be skipped as it should be matched on the next log.
return None

transfer = event['Transfer']
address = transfer[0].address
# try to download the contract from etherscan
contract(address)
return address
except ValueError:
# 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:
'''
Expand All @@ -86,15 +89,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 = ['0x000000000000000000000000' + address[2:] for address in self.addresses]
self._topics = [
mariuspod marked this conversation as resolved.
Show resolved Hide resolved
[
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)
Expand All @@ -110,13 +124,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)
Expand Down Expand Up @@ -274,14 +290,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(
Expand Down