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

generically decode DEX swap transactions, including event log decoding #14

Merged
merged 11 commits into from May 1, 2022

Conversation

spazcoin
Copy link
Contributor

@spazcoin spazcoin commented Apr 21, 2022

Description:

This PR uses @yifei_huang's scripts to decode contract input data as well interpret a transaction log file (to figure out the result of a contract interaction, not just the inputs).
See article explanation: https://towardsdatascience.com/decoding-ethereum-smart-contract-data-eed513a65f76

  • retrieve the ABIs for each contract interface, instead of archiving copies of each one. This allows us to support all APIs without needing to archive each one.
  • Get token name, symbol, and calculate real transaction values. This this required adding support for the Blockscout API also.
  • moonbeam_scraper.py is now able to decode contract input data, and then retrieve transaction receipts for contract interactions so that it can decode the internal dex 'trace' transactions to determine the exact input and output quantities for swap transactions. Previously, we were using the internal 'Swap' transactions, but those were too difficult to match up for a multi-hop swap (i.e. ROME -> MOVR -> SOLAR) and a few implementations were confusing with multiple Swap inputs. So instead the code now only sums up the Transfer input quantities from the source acct. This is done in a generic way without requiring classes for each DEX contract implementation which works as long as DEX contracts all follow general patterns and naming conventions.
  • decode errors for DPS contracts were due to @yifei_huang's initial convert_to_hex functionality not being able to handle more complex data structures. When working down through nested structures, it missed buried byte arrays and didn't convert them to hex. json.dumps(decoded_func_params) was throwing an exception because the bytes weren't JSON serializable. The solution was to look for lists embedded inside a tuple/struct.
  • decode errors for 0xTaylor's puzzle contract were intentionally caused by poor utf8 string handling. Therefore still print out a warning the first time that contract is encountered and can't be decoded. Include full traceback and diagnostic messages instead of swallowing them.
  • add rate limiting to our block explorer API calls, to make sure we always get a valid response from the APIs. Adapt the rate limit for subscan.io depending on whether an API key is provided.
  • support moonscan.io api keys
  • use httpx for GET and POST instead of requests library. Queries to the moonscan.io API started failing. Using Wireshark I tracked it down to use of the "requests" python package which doesn't support HTTPS2. It was submitting the moonscan.io GET request with HTTP/1.1 and then moonscan.io responds with HTTP/1.1 403 Forbidden and the cloudflare error message. Whereas if I hand-crafted the same GET request as a URL string, it would be accepted and I received JSON back with the transaction history. Wireshark showed that these handcrafted URLs were being submitted as HTTP2. The solution was to migrate GET and POST HTTP messages to use the httpx package instead of requests. (and with pip you must install the httpx optional support for http2) I went ahead and changed subscan.io calls to use httpx also, but with minimal testing.
  • update docs to explain how moonbeam_scraper works now, how to interpret its output data, what typical warnings/errors are.

queries to the moonscan.io API started failing. Using Wireshark I
tracked it down to use of the "requests" python package which doesn't
support HTTPS2. It was submitting the moonscan.io GET request with
"HTTP/1.1" and then moonscan.io responds with "HTTP/1.1 403 Forbidden"
and the cloudflare error message. Whereas if I hand-crafted the same
GET request as a URL string, it would be accepted and I received JSON
back with the transaction history. Wireshark showed that these
handcrafted URLs were being submitted as HTTP2.

The solution was to migrate GET and POST HTTP messages to use the
"httpx" package instead of "requests". (and with pip you must install
the httpx optional support for http2)

I went ahead and changed subscan.io calls to use httpx also, but with
minimal testing.
* add rate limiting to our block explorer API calls, to make sure we
always get a valid response from the APIs.
* retrieve the ABIs for each contract interface, instead of archiving
copies of each one. This allows us to support all APIs without needing
to archive each one.
* refactor moonbeam_scraper.py's definition of the params to be passed
to Moonscan.io in an API call. The specific parameter names should be
encapsulated in the wrapper methods.
* detect and log when transaction input data isn't decoded properly
(since we're trying to decode all transactions now).
* Get token name, symbol, and calculate real transaction values. But
this required adding support for the Blockscout API.
* adaptive rate limit for subscan.io depending on whether an API key is
provided.
* migrate URLs to be encapsulated within the block explorer wrappers.

contributes to ChaosDAO-org#8 decoding DEX swap transactions
* Support most dex swap transactions except "swapETHForTokens"
transactions because they don't specify input quantity.

contributes to ChaosDAO-org#8 decoding DEX swap transactions
* decode errors for DPS contracts were due to the initial
"convert_to_hex" functionality not being able to handle more complex
data structures. When working down through nested structures, it missed
buried byte arrays and didn't convert them to hex.
"json.dumps(decoded_func_params)" was throwing an exception because
the bytes weren't JSON serializable. The solution was to look for lists
embedded inside a tuple/struct.
* decode errors for 0xTaylor's puzzle contract were intentionally
caused by poor utf8 string handling. Therefore still print out a
warning the first time that contract is encountered and can't be
decoded. Include full traceback and diagnostic messages instead of
swallowing them. Now able to make the script more generic by removing
references to specific problem contracts.
indicate contributors to each script file
Previously, we were able to decode the input data to a contract
interaction. But in a DEX exchange, there could be slippage so the
actual amount swapped might be slightly different. Therefore, we need
to get the actual event logs to see the exact quantities exchanged.

This commit uses @yifei_huang's script to decode a transaction log file.
Some testing remains, to figure out to handle multiple input values to
a swap.

contributes to ChaosDAO-org#8
moonbeam_scraper.py is now able to retrieve transaction receipts for
contract interactions so that it can decode the internal dex 'trace'
transactions to determine the exact input and output quantities for
swap transactions.
Previously, we were using the internal 'Swap' transactions, but those
were too difficult to match up for a multi-hop swap (i.e. ROME -> MOVR
-> SOLAR). So instead the code now only sums up the Transfer input
quantities from the source acct. This is done in a generic way without
requiring classes for each DEX contract implementation which works as
long as DEX contracts all follow general patterns and naming
conventions.

contributes to ChaosDAO-org#8
@spazcoin spazcoin requested a review from Tomen April 21, 2022 05:17
@spazcoin spazcoin force-pushed the decodeLogs branch 2 times, most recently from 6666b1a to 19304d0 Compare April 27, 2022 04:00
* Include details about Moonscan.io and Blockscout.io API keys and how
they align.
* Include description of the current JSON output format and how to
interpret it.
* Include some common warning messages to see in the console output
while running the tool, just to help users know whether they should be
worried about the messages.
especially for Moonriver/Moonbeam `account_transactions`
processing configuration
@Tomen Tomen merged commit 4483292 into ChaosDAO-org:main May 1, 2022
@spazcoin spazcoin deleted the decodeLogs branch July 12, 2022 03:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants