ethereum / sourcify

Decentralized Solidity contract source code verification service
https://sourcify.dev
MIT License
782 stars 399 forks source link

Monitor only catches contract creations with `tx.to==null` #530

Open kuzdogan opened 3 years ago

kuzdogan commented 3 years ago

Currently, the monitor is only checking for contract creations in blocks by checking if the receiver of the tx is null. This is the usual method when contracts are created by externally owned accounts.

https://github.com/ethereum/sourcify/blob/f5e49e9d5d047421d9efc0b07000c7e8c2a51a14/src/monitor/monitor.ts#L18-L20

However, it is also possible that contracts are created by other contracts in a factory pattern (example)

My initial thought to achieve this was to check tx traces but can we do this for all tx's of all blocks? Also, the contracts that are being created will highly likely not be accessible on IPFS as they will be embedded inside the parent contract. Might be not worth working on this.

View in Huly HI-407

chriseth commented 3 years ago

Why do you think they are not accessible on IPFS? We should at least check how efficient it is to scan transactions for creation opcodes - we might need that anyway at some point.

If we do this, we should maybe do it multiple times like we do it for creation transaction, i.e. for multiple ages of a block.

Also we should protect against tons of copies of the same contract (this could also happen to us for manually verified contracts) - maybe use something like symlinks when two contracts are identically deployed to multiple addresses? Should check if this also still works for the ipfs archive.

kuzdogan commented 3 years ago

My thinking was for such a file there would be one metadata output but yeah there are two different metadata.json's for two contracts linking to the same source file hash.

contract ChildContract {
  address _value;
  constructor (uint256 value) {
    _value=value
  }
}

contract ParentContract {
  ChildContract _contract;
  function createChildContract(uint value) public {
    _contract = new ChildContract(value);
  }
}

So as long as the both metadata files + source file are published we'll be good.

Scanning would mean to run the trace of transactions right? Because to my understanding we can't capture the creation opcodes from the transaction calling createChildContract but within the subsequent internal messages.

chriseth commented 3 years ago

Yes, we need to request the trace. Please check how expensive it is. We could first run without requesting memory and just scan for the create and create2 opcodes and then run it again with memory to get the creation payload. We could also use geth's feature to run a javascript function that could then already analyze everything and extract the creation payload.

JanRuettinger commented 2 years ago

Is anybody working on this? If not, I'd be happy to contribute.

kuzdogan commented 2 years ago

@JanRuettinger It is currently stale but we appreciate contributions. Are you familiar with the trace methods? The first steps would be what @chriseth mentioned above because we need to scan through all tx's of a block and this can be costly.

tjayrush commented 2 years ago

I noticed this issue and thought I'd share. The TrueBlocks index scraper might be an easy way for you'all to find these contract creations in internal traces. We do this naturally as part of our indexing solution. It would be pretty easy to modify the scraper to extract only contract creations (we already see these along with a lot of other things, so it would be a removal of function as opposed to an addition of function -- removal is a lot easier). Let me know if you're interested, and I can show you the exact code you'd have to modify.