def test_kyber_legacy_old_contract(database, ethereum_manager, eth_transactions): """Data for trade taken from https://etherscan.io/tx/0xe9cc9f27ef2a09fe23abc886a0a0f7ae19d9e2eb73663e1e41e07a3e0c011b87 """ msg_aggregator = MessagesAggregator() tx_hex = '0xe9cc9f27ef2a09fe23abc886a0a0f7ae19d9e2eb73663e1e41e07a3e0c011b87' evmhash = deserialize_evm_tx_hash(tx_hex) transaction = EthereumTransaction( tx_hash=evmhash, timestamp=1591043988, block_number=10182160, from_address='0x6d379cb5BA04c09293b21Bf314E7aba3FfEAaF5b', to_address='0x818E6FECD516Ecc3849DAf6845e3EC868087B755', value=0, gas=600000, gas_price=22990000000, gas_used=527612, input_data=hexstring_to_bytes( '0xcb3c28c7000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000002aea540000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000006d379cb5ba04c09293b21bf314e7aba3ffeaaf5b8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5f611df3b9ac000000000000000000000000f1aa99c69715f423086008eb9d06dc1e35cc504d' ), # noqa: E501 nonce=1, ) receipt = EthereumTxReceipt( tx_hash=evmhash, contract_address=None, status=True, type=0, logs=[ EthereumTxReceiptLog( log_index=87, data=hexstring_to_bytes( '0x0000000000000000000000000000000000000000000000000000000002aea540' ), # noqa: E501 address=string_to_ethereum_address( '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'), removed=False, topics=[ hexstring_to_bytes( '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' ), # noqa: E501 hexstring_to_bytes( '0x0000000000000000000000006d379cb5ba04c09293b21bf314e7aba3ffeaaf5b' ), # noqa: E501 hexstring_to_bytes( '0x00000000000000000000000065bf64ff5f51272f729bdcd7acfb00677ced86cd' ), # noqa: E501 ], ), EthereumTxReceiptLog( log_index=93, data=hexstring_to_bytes( '0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000002aea540000000000000000000000000000000000000000000000000029a80338e28df730000000000000000000000006d379cb5ba04c09293b21bf314e7aba3ffeaaf5b000000000000000000000000000000000000000000000000029a80338e28df730000000000000000000000001670dfb52806de7789d5cf7d5c005cf7083f9a5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000000' ), # noqa: E501 address=string_to_ethereum_address( '0x65bF64Ff5f51272f729BDcD7AcFB00677ced86Cd'), removed=False, topics=[ hexstring_to_bytes( '0xd30ca399cb43507ecec6a629a35cf45eb98cda550c27696dcb0d8c4a3873ce6c' ), # noqa: E501 hexstring_to_bytes( '0x0000000000000000000000006d379cb5ba04c09293b21bf314e7aba3ffeaaf5b' ), # noqa: E501 ], ), ], ) internal_tx = EthereumInternalTransaction( parent_tx_hash=evmhash, trace_id=27, timestamp=Timestamp(1591043988), block_number=10182160, from_address='0x65bF64Ff5f51272f729BDcD7AcFB00677ced86Cd', to_address='0x6d379cb5BA04c09293b21Bf314E7aba3FfEAaF5b', value=187603293406027635, ) dbethtx = DBEthTx(database) dbethtx.add_ethereum_transactions([transaction], relevant_address=None) dbethtx.add_ethereum_internal_transactions( [internal_tx], relevant_address='0x6d379cb5BA04c09293b21Bf314E7aba3FfEAaF5b' ) # noqa: E501 decoder = EVMTransactionDecoder( database=database, ethereum_manager=ethereum_manager, eth_transactions=eth_transactions, msg_aggregator=msg_aggregator, ) events = decoder.decode_transaction(transaction=transaction, tx_receipt=receipt) assert len(events) == 3 expected_events = [ HistoryBaseEntry( event_identifier= '0xe9cc9f27ef2a09fe23abc886a0a0f7ae19d9e2eb73663e1e41e07a3e0c011b87', sequence_index=0, timestamp=1591043988000, location=Location.BLOCKCHAIN, event_type=HistoryEventType.SPEND, event_subtype=HistoryEventSubType.FEE, asset=A_ETH, balance=Balance( amount=FVal(0.01212979988), usd_value=FVal(0), ), location_label='0x6d379cb5BA04c09293b21Bf314E7aba3FfEAaF5b', notes= 'Burned 0.01212979988 ETH in gas from 0x6d379cb5BA04c09293b21Bf314E7aba3FfEAaF5b', # noqa: E501 counterparty=CPT_GAS, ), HistoryBaseEntry( event_identifier= '0xe9cc9f27ef2a09fe23abc886a0a0f7ae19d9e2eb73663e1e41e07a3e0c011b87', sequence_index=1, timestamp=1591043988000, location=Location.BLOCKCHAIN, event_type=HistoryEventType.TRADE, event_subtype=HistoryEventSubType.SPEND, asset=A_USDC, balance=Balance(amount=FVal(45), usd_value=FVal(0)), location_label='0x6d379cb5BA04c09293b21Bf314E7aba3FfEAaF5b', notes='Swap 45 USDC in kyber', counterparty='kyber legacy', ), HistoryBaseEntry( event_identifier= '0xe9cc9f27ef2a09fe23abc886a0a0f7ae19d9e2eb73663e1e41e07a3e0c011b87', sequence_index=89, timestamp=1591043988000, location=Location.BLOCKCHAIN, event_type=HistoryEventType.TRADE, event_subtype=HistoryEventSubType.RECEIVE, asset=A_ETH, balance=Balance( amount=FVal('0.187603293406027635'), usd_value=FVal(0), ), location_label='0x6d379cb5BA04c09293b21Bf314E7aba3FfEAaF5b', notes='Receive 0.187603293406027635 ETH from kyber swap', counterparty='kyber legacy', ) ] assert events == expected_events
def test_liquity_trove_remove_eth(database, ethereum_manager, eth_transactions): """Data for deposit taken from https://etherscan.io/tx/0x6be5312c21855c3cc324b5b6ce9f9f65dbd488e270e84ac5e6fb96c74d83fe4e Deposit 2.1 ether and borrow 4752 LUSD """ msg_aggregator = MessagesAggregator() tx_hex = '0x6be5312c21855c3cc324b5b6ce9f9f65dbd488e270e84ac5e6fb96c74d83fe4e' user_address = '0x648E180e246741363639B1496762763dd25649db' evmhash = deserialize_evm_tx_hash(tx_hex) transaction = EthereumTransaction( tx_hash=evmhash, timestamp=1646375440, block_number=14318825, from_address=user_address, to_address='0x24179cd81c9e782a4096035f7ec97fb8b783e007', value=0, gas=171249, gas_price=22990000000, gas_used=171249, input_data=hexstring_to_bytes('0xc6a6cf2000000000000000000000000000000000000000000000000000238811c2e89e1b000000000000000000000000000000000000000000000001bc16d674ec80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cb926f497763ea5cf993912a442431e6a91d5a64000000000000000000000000c68d61757a9894f34871c0ae733ac034d9abf807'), # noqa: E501 nonce=507, ) receipt = EthereumTxReceipt( tx_hash=evmhash, contract_address=None, status=True, type=0, logs=[ EthereumTxReceiptLog( log_index=204, data=hexstring_to_bytes('0x000000000000000000000000000000000000000000038f9ba4f4e8bb875c546b0000000000000000000000000000000000000000000000aed129e69968ff40000000000000000000000000000000000000000000000000aed129e69968ff40000000000000000000000000000000000000000000000000000000000000000002'), # noqa: E501 address=string_to_ethereum_address('0x24179CD81c9e782A4096035f7eC97fB8B783e007'), removed=False, topics=[ hexstring_to_bytes('0xc3770d654ed33aeea6bf11ac8ef05d02a6a04ed4686dd2f624d853bbec43cc8b'), # noqa: E501 hexstring_to_bytes('0x000000000000000000000000648e180e246741363639b1496762763dd25649db'), # noqa: E501 ], ), EthereumTxReceiptLog( log_index=293, data=hexstring_to_bytes('0x0000000000000000000000000000000000000000000000000000000000000000'), # noqa: E501 address=string_to_ethereum_address('0x5f98805A4E8be255a32880FDeC7F6728C6568bA0'), removed=False, topics=[ hexstring_to_bytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'), # noqa: E501 hexstring_to_bytes('0x000000000000000000000000648e180e246741363639b1496762763dd25649db'), # noqa: E501 hexstring_to_bytes('0x0000000000000000000000000000000000000000000000000000000000000000'), # noqa: E501 ], ), EthereumTxReceiptLog( log_index=208, data=hexstring_to_bytes('0x000000000000000000000000000000000000000000004e927b246c443a2daac9'), # noqa: E501 address=string_to_ethereum_address('0xDf9Eb223bAFBE5c5271415C75aeCD68C21fE3D7F'), removed=False, topics=[ hexstring_to_bytes('0xca232b5abb988c540b959ff6c3bfae3e97fff964fd098c508f9613c0a6bf1a80'), # noqa: E501 ], ), ], ) internal_tx = EthereumInternalTransaction( parent_tx_hash=evmhash, trace_id=19, timestamp=Timestamp(1646375440), block_number=10182160, from_address='0xDf9Eb223bAFBE5c5271415C75aeCD68C21fE3D7F', to_address=user_address, value=FVal(32) * EXP18, ) dbethtx = DBEthTx(database) dbethtx.add_ethereum_transactions([transaction], relevant_address=None) dbethtx.add_ethereum_internal_transactions([internal_tx], relevant_address=user_address) # noqa: E501 decoder = EVMTransactionDecoder( database=database, ethereum_manager=ethereum_manager, eth_transactions=eth_transactions, msg_aggregator=msg_aggregator, ) events = decoder.decode_transaction(transaction=transaction, tx_receipt=receipt) assert len(events) == 3 expected_events = [ HistoryBaseEntry( event_identifier=tx_hex, sequence_index=0, timestamp=1646375440000, location=Location.BLOCKCHAIN, event_type=HistoryEventType.SPEND, event_subtype=HistoryEventSubType.FEE, asset=A_ETH, balance=Balance( amount=FVal(0.00393701451), usd_value=ZERO, ), location_label=user_address, notes=f'Burned 0.00393701451 ETH in gas from {user_address}', counterparty=CPT_GAS, ), HistoryBaseEntry( event_identifier=tx_hex, sequence_index=1, timestamp=1646375440000, location=Location.BLOCKCHAIN, event_type=HistoryEventType.WITHDRAWAL, event_subtype=HistoryEventSubType.REMOVE_ASSET, asset=A_ETH, balance=Balance(amount=FVal('32'), usd_value=ZERO), location_label=user_address, notes='Withdraw 32 ETH collateral from liquity', counterparty='liquity', ), HistoryBaseEntry( event_identifier=tx_hex, sequence_index=295, timestamp=1646375440000, location=Location.BLOCKCHAIN, event_type=HistoryEventType.SPEND, event_subtype=HistoryEventSubType.PAYBACK_DEBT, asset=A_LUSD, balance=Balance(amount=FVal('0'), usd_value=ZERO), location_label=user_address, notes='Return 0 LUSD to liquity', counterparty='liquity', )] assert events == expected_events
def test_curve_remove_liquidity_with_internal(database, ethereum_manager, eth_transactions): """Data for deposit taken from https://etherscan.io/tx/0x30bb99f3e34fb1fbcf009320af7e290caf18b04b207319e15aa8ffbf645f4ad9 This tests uses the steth pool to verify that withdrawals are correctly decoded when an internal transaction is made for eth transfers """ msg_aggregator = MessagesAggregator() tx_hex = '0x30bb99f3e34fb1fbcf009320af7e290caf18b04b207319e15aa8ffbf645f4ad9' location_label = '0xa8005630caE7b7d2AFADD38FD3B3040d13cbE2BC' evmhash = deserialize_evm_tx_hash(tx_hex) transaction = EthereumTransaction( tx_hash=evmhash, timestamp=1650276061, block_number=14647221, from_address=location_label, to_address='0xF178C0b5Bb7e7aBF4e12A4838C7b7c5bA2C623c0', value=0, gas=171249, gas_price=22990000000, gas_used=171249, input_data=hexstring_to_bytes('0x1a4d01d20000000000000000000000000000000000000000000000a8815561fefbe56aa300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a8d15fc942541fea7f'), # noqa: E501 nonce=5, ) receipt = EthereumTxReceipt( tx_hash=evmhash, contract_address=None, status=True, type=0, logs=[ EthereumTxReceiptLog( log_index=191, data=hexstring_to_bytes('0x0000000000000000000000000000000000000000000000000dc335d474901e08'), # noqa: E501 address=string_to_ethereum_address('0x06325440D014e39736583c165C2963BA99fAf14E'), removed=False, topics=[ hexstring_to_bytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'), # noqa: E501 hexstring_to_bytes('0x000000000000000000000000a8005630cae7b7d2afadd38fd3b3040d13cbe2bc'), # noqa: E501 hexstring_to_bytes('0x0000000000000000000000000000000000000000000000000000000000000000'), # noqa: E501 ], ), EthereumTxReceiptLog( log_index=192, data=hexstring_to_bytes('0x0000000000000000000000000000000000000000000000000dc335d474901e080000000000000000000000000000000000000000000000000e48d018621788fa'), # noqa: E501 address=string_to_ethereum_address('0xDC24316b9AE028F1497c275EB9192a3Ea0f67022'), removed=False, topics=[ hexstring_to_bytes('0x9e96dd3b997a2a257eec4df9bb6eaf626e206df5f543bd963682d143300be310'), # noqa: E501 hexstring_to_bytes('0x000000000000000000000000a8005630cae7b7d2afadd38fd3b3040d13cbe2bc'), # noqa: E501 ], ), ], ) internal_tx = EthereumInternalTransaction( parent_tx_hash=evmhash, trace_id=27, timestamp=Timestamp(1591043988), block_number=14647221, from_address='0xDC24316b9AE028F1497c275EB9192a3Ea0f67022', to_address='0xa8005630caE7b7d2AFADD38FD3B3040d13cbE2BC', value=FVal('1.02930131799766041') * EXP18, ) dbethtx = DBEthTx(database) dbethtx.add_ethereum_transactions([transaction], relevant_address=None) dbethtx.add_ethereum_internal_transactions([internal_tx], relevant_address=location_label) # noqa: E501 decoder = EVMTransactionDecoder( database=database, ethereum_manager=ethereum_manager, eth_transactions=eth_transactions, msg_aggregator=msg_aggregator, ) events = decoder.decode_transaction(transaction=transaction, tx_receipt=receipt) expected_events = [ HistoryBaseEntry( event_identifier=tx_hex, sequence_index=0, timestamp=1650276061000, location=Location.BLOCKCHAIN, event_type=HistoryEventType.SPEND, event_subtype=HistoryEventSubType.FEE, asset=A_ETH, balance=Balance( amount=FVal(0.00393701451), usd_value=ZERO, ), location_label=location_label, notes='Burned 0.00393701451 ETH in gas from 0xa8005630caE7b7d2AFADD38FD3B3040d13cbE2BC', # noqa: E501 counterparty=CPT_GAS, ), HistoryBaseEntry( event_identifier=tx_hex, sequence_index=1, timestamp=1650276061000, location=Location.BLOCKCHAIN, event_type=HistoryEventType.WITHDRAWAL, event_subtype=HistoryEventSubType.REMOVE_ASSET, asset=A_ETH, balance=Balance(amount=FVal('1.02930131799766041'), usd_value=ZERO), location_label=location_label, notes='Remove 1.02930131799766041 ETH from the curve pool', counterparty=CPT_CURVE, ), HistoryBaseEntry( event_identifier=tx_hex, sequence_index=193, timestamp=1650276061000, location=Location.BLOCKCHAIN, event_type=HistoryEventType.SPEND, event_subtype=HistoryEventSubType.RETURN_WRAPPED, asset=EthereumToken('0x06325440D014e39736583c165C2963BA99fAf14E'), balance=Balance(amount=FVal('0.991695529556581896'), usd_value=ZERO), location_label=location_label, notes='Return 0.991695529556581896 steCRV', counterparty=CPT_CURVE, )] assert expected_events == events
def _get_internal_transactions_for_ranges( self, address: ChecksumEthAddress, start_ts: Timestamp, end_ts: Timestamp, ) -> None: """Queries etherscan for all internal transactions of address in the given ranges. If any internal transactions are found, they are added in the DB """ location_string = f'{RANGE_PREFIX_ETHINTERNALTX}_{address}' ranges = DBQueryRanges(self.database) ranges_to_query = ranges.get_location_query_ranges( location_string=location_string, start_ts=start_ts, end_ts=end_ts, ) dbethtx = DBEthTx(self.database) new_internal_txs = [] for query_start_ts, query_end_ts in ranges_to_query: log.debug( f'Querying Internal Transactions for {address} -> {query_start_ts} - {query_end_ts}' ) # noqa: E501 try: for new_internal_txs in self.ethereum.etherscan.get_transactions( account=address, from_ts=query_start_ts, to_ts=query_end_ts, action='txlistinternal', ): if len(new_internal_txs) != 0: for internal_tx in new_internal_txs: # make sure all internal transaction parent transactions are in the DB gevent.sleep(0) result = dbethtx.get_ethereum_transactions( ETHTransactionsFilterQuery.make( tx_hash=internal_tx.parent_tx_hash ), # noqa: E501 has_premium=True, # ignore limiting here ) if len( result ) == 0: # parent transaction is not in the DB. Get it transaction = self.ethereum.get_transaction_by_hash( internal_tx.parent_tx_hash) # noqa: E501 gevent.sleep(0) dbethtx.add_ethereum_transactions( ethereum_transactions=[transaction], relevant_address=address, ) timestamp = transaction.timestamp else: timestamp = result[0].timestamp dbethtx.add_ethereum_internal_transactions( transactions=[internal_tx], relevant_address=address, ) log.debug( f'Internal Transactions for {address} -> update range {query_start_ts} - {timestamp}' ) # noqa: E501 ranges.update_used_query_range( # update last queried time for address location_string=location_string, queried_ranges=[(query_start_ts, timestamp)], ) self.msg_aggregator.add_message( message_type=WSMessageType. ETHEREUM_TRANSACTION_STATUS, data={ 'address': address, 'period': [query_start_ts, timestamp], 'status': str(TransactionStatusStep. QUERYING_INTERNAL_TRANSACTIONS ), # noqa: E501 }, ) except RemoteError as e: self.ethereum.msg_aggregator.add_error( f'Got error "{str(e)}" while querying internal ethereum transactions ' f'from Etherscan. Transactions not added to the DB ' f'address: {address} ' f'from_ts: {query_start_ts} ' f'to_ts: {query_end_ts} ', ) return log.debug( f'Internal Transactions for address {address} done. Update range {start_ts} - {end_ts}' ) # noqa: E501 ranges.update_used_query_range( # entire range is now considered queried location_string=location_string, queried_ranges=[(start_ts, end_ts)], )