|
| 1 | +// Configuration for replacing metadata in sourcify_matches table |
| 2 | +// This configuration targets contracts with partial runtime matches where metadata needs to be updated |
| 3 | +// because it does not match the sources in the database. |
| 4 | +// Only processes contracts where source hashes don't match the existing metadata |
| 5 | + |
| 6 | +const { id: keccak256str } = require("ethers"); |
| 7 | + |
| 8 | +module.exports = { |
| 9 | + query: async (sourcePool, sourcifySchema, currentVerifiedContract, n) => { |
| 10 | + return await sourcePool.query( |
| 11 | + ` |
| 12 | + SELECT |
| 13 | + cd.chain_id, |
| 14 | + cd.address, |
| 15 | + sm.id as verified_contract_id, |
| 16 | + json_build_object( |
| 17 | + 'language', INITCAP(cc.language), |
| 18 | + 'sources', json_object_agg(compiled_contracts_sources.path, json_build_object('content', sources.content)), |
| 19 | + 'settings', cc.compiler_settings |
| 20 | + ) as std_json_input, |
| 21 | + cc.version as compiler_version, |
| 22 | + cc.fully_qualified_name, |
| 23 | + sm.metadata |
| 24 | + FROM ${sourcifySchema}.sourcify_matches sm |
| 25 | + JOIN ${sourcifySchema}.verified_contracts vc ON sm.verified_contract_id = vc.id |
| 26 | + JOIN ${sourcifySchema}.contract_deployments cd ON vc.deployment_id = cd.id |
| 27 | + JOIN ${sourcifySchema}.compiled_contracts cc ON vc.compilation_id = cc.id |
| 28 | + JOIN ${sourcifySchema}.compiled_contracts_sources ON compiled_contracts_sources.compilation_id = cc.id |
| 29 | + LEFT JOIN ${sourcifySchema}.sources ON sources.source_hash = compiled_contracts_sources.source_hash |
| 30 | + WHERE sm.created_at < '2024-08-29 08:58:57 +0200' |
| 31 | + AND sm.runtime_match ='partial' |
| 32 | + AND sm.id >= $1 |
| 33 | + GROUP BY sm.id, vc.id, cc.id, cd.id |
| 34 | + ORDER BY sm.id ASC |
| 35 | + LIMIT $2 |
| 36 | + `, |
| 37 | + [currentVerifiedContract, n], |
| 38 | + ); |
| 39 | + }, |
| 40 | + buildRequestBody: (contract) => { |
| 41 | + return { |
| 42 | + chainId: contract.chain_id.toString(), |
| 43 | + address: `0x${contract.address.toString("hex")}`, |
| 44 | + forceCompilation: true, |
| 45 | + jsonInput: contract.std_json_input, |
| 46 | + compilerVersion: contract.compiler_version, |
| 47 | + compilationTarget: contract.fully_qualified_name, |
| 48 | + forceRPCRequest: false, |
| 49 | + customReplaceMethod: "replace-metadata", |
| 50 | + }; |
| 51 | + }, |
| 52 | + excludeContract: (contract) => { |
| 53 | + const address = `0x${contract.address.toString("hex")}`; |
| 54 | + const sources = contract.std_json_input.sources; |
| 55 | + const currentMetadata = contract.metadata; |
| 56 | + |
| 57 | + if (!sources || !currentMetadata) { |
| 58 | + console.log( |
| 59 | + `Contract address=${address}, chain_id=${contract.chain_id}: Missing sources or metadata -> skipping`, |
| 60 | + ); |
| 61 | + return true; // Exclude if no sources or metadata |
| 62 | + } |
| 63 | + |
| 64 | + if ( |
| 65 | + Object.keys(sources).length !== |
| 66 | + Object.keys(currentMetadata.sources).length |
| 67 | + ) { |
| 68 | + console.log( |
| 69 | + `Contract address=${address}, chain_id=${contract.chain_id}: wrong sources length: ${Object.keys(sources).length} (std json) vs ${Object.keys(currentMetadata.sources).length} (metadata)`, |
| 70 | + ); |
| 71 | + return false; // something is wrong -> replace metadata |
| 72 | + } |
| 73 | + |
| 74 | + for (const [sourcePath, sourceMetadata] of Object.entries( |
| 75 | + currentMetadata.sources, |
| 76 | + )) { |
| 77 | + const expectedHash = sourceMetadata.keccak256; |
| 78 | + |
| 79 | + if (!sources[sourcePath]) { |
| 80 | + console.log( |
| 81 | + `Contract address=${address}, chain_id=${contract.chain_id}: Metadata source ${sourcePath} not in sources`, |
| 82 | + ); |
| 83 | + return false; // something is wrong -> replace metadata |
| 84 | + } |
| 85 | + |
| 86 | + const contentHash = keccak256str(sources[sourcePath].content); |
| 87 | + |
| 88 | + if (contentHash !== expectedHash) { |
| 89 | + console.log( |
| 90 | + `Contract address=${address}, chain_id=${contract.chain_id}: ContentHash does not match metadata hash for source ${sourcePath}: ${contentHash} (std json) vs ${expectedHash} (metadata)`, |
| 91 | + ); |
| 92 | + return false; // something is wrong -> replace metadata |
| 93 | + } |
| 94 | + } |
| 95 | + |
| 96 | + return true; // All sources match the metadata, exclude this contract |
| 97 | + }, |
| 98 | + description: |
| 99 | + "Replaces metadata in sourcify_matches table for contracts where source content hashes don't match the existing metadata hashes.", |
| 100 | +}; |
0 commit comments