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
Analyzer for fetching bytecode of EVM contracts #448
Conversation
f933cc8
to
5ceb96d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, left some minor/nit comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Peter!
-- Bootstrap the table with the set of addresses we known are contracts because they are the result of an evm.Create tx. | ||
INSERT INTO analysis.evm_contract_code (runtime, contract_candidate, is_contract) | ||
SELECT runtime, contract_address, NULL | ||
FROM chain.evm_contracts | ||
ON CONFLICT (runtime, contract_candidate) DO NOTHING; | ||
|
||
ALTER TABLE chain.evm_contracts | ||
ADD COLUMN runtime_bytecode BYTEA; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our first real migration! Sucks to have users ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
-- TRUE: downloaded runtime bytecode | ||
-- FALSE: download failed because `contract_candidate` is not a contract (= does not have code) | ||
-- NULL: not yet attempted | ||
is_contract bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_contract bool | |
is_contract BOOL |
SapphireEvmTokens *EvmTokensAnalyzerConfig `koanf:"evm_tokens_sapphire"` | ||
EmeraldEvmTokenBalances *EvmTokensAnalyzerConfig `koanf:"evm_token_balances_emerald"` | ||
SapphireEvmTokenBalances *EvmTokensAnalyzerConfig `koanf:"evm_token_balances_sapphire"` | ||
EmeraldEvmTokens *EvmTokensAnalyzerConfig `koanf:"evm_tokens_emerald"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to enable these "evm subanalyzers" in the e2e test config for regressions? I see that Emerald has only the basic block analyzer enabled there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's strongly on my wishlist. It sucks that we don't have visibility into most changes via e2e regressions, especially now that we're working primarily on non-block analyzers.
It's not just a matter of enabling those analyzers though, there's a gotcha. They need to know when to self-terminate, and they need to be run in a separate phase after the block analyzers. See https://app.clickup.com/t/866aak668
2e5a620
to
746a171
Compare
(Note: Also contains the changes of #449 due to bad merge order; that PR was supposed to go in first, but didn't)
This PR adds a new analyzer that fetches the runtime bytecode of EVM contracts. Some details:
runtime_bytecode
column to theevm_contracts
table.getCode()
). Even for contracts created viaevm.Create
(which is not all of them), we only learn the deployment code, which the EVM then interprets to produce the runtime code.getCode()
at the height of the most recent indexer-processed block. This is to keep the call cacheable (which it would not be if we called at thelatestBlock
pseudo-height).evm_contract_code
table to track accounts for which we already tried callinggetCode()
and realized the address was not a contract, and also to track accounts that we've encountered so far that look contract-like (=they were the target of anevm.Call
tx). We need to track non-contracts because we need to try getCode() on every contract-like address because otherwise we won't know about contracts created by other contracts.analysis
DB schema. The goal is to eventually have all*_analysis
tables live there; they're not about the contents of the chain, they're about the internal state of the analyzer(s).Testing:
Ran for 10000 blocks of Emerald. Compared with Blockscout as sanity check. Two contracts had the same runtime bytecode reported by both explorers. Interestingly, I also found an address that we identify as a contract, and show its runtime bytecode (localhost:8008/v1/emerald/accounts/oasis1qrg90d4qlelg5zg4q4sd4y0z8j2lpjpvuspzjlyl) but blockscout does not (https://explorer.emerald.oasis.dev/address/0x6Cb9750a92643382e020eA9a170AbB83Df05F30B/)
Resolves https://app.clickup.com/t/866adz948