|
| 1 | +/* eslint-disable @typescript-eslint/no-explicit-any */ |
| 2 | +import axios from 'axios' |
| 3 | +import FormData from 'form-data' |
| 4 | +import { HardhatRuntimeEnvironment } from 'hardhat/types' |
| 5 | +import { Readable } from 'stream' |
| 6 | + |
| 7 | +// Inspired by: |
| 8 | +// - https://github.com/wighawag/hardhat-deploy/blob/9c8cd433a37188e793181b727222e2d22aef34b0/src/sourcify.ts |
| 9 | +// - https://github.com/zoey-t/hardhat-sourcify/blob/26f10a08eb6cf97700c78989bf42b009c9cb3275/src/sourcify.ts |
| 10 | +export async function submitSourcesToSourcify( |
| 11 | + hre: HardhatRuntimeEnvironment, |
| 12 | + contract: { |
| 13 | + source: string |
| 14 | + name: string |
| 15 | + address: string |
| 16 | + fqn: string |
| 17 | + }, |
| 18 | +): Promise<void> { |
| 19 | + const chainId = hre.network.config.chainId |
| 20 | + const sourcifyUrl = 'https://sourcify.dev/server/' |
| 21 | + |
| 22 | + // Get contract metadata |
| 23 | + const contractBuildInfo = await hre.artifacts.getBuildInfo(contract.fqn) |
| 24 | + const contractMetadata = ( |
| 25 | + contractBuildInfo.output.contracts[contract.source][contract.name] as any |
| 26 | + ).metadata |
| 27 | + |
| 28 | + if (contractMetadata === undefined) { |
| 29 | + console.error( |
| 30 | + `Contract ${contract.name} was deployed without saving metadata. Cannot submit to sourcify, skipping.`, |
| 31 | + ) |
| 32 | + return |
| 33 | + } |
| 34 | + |
| 35 | + // Check if contract already verified |
| 36 | + try { |
| 37 | + const checkResponse = await axios.get( |
| 38 | + `${sourcifyUrl}checkByAddresses?addresses=${contract.address.toLowerCase()}&chainIds=${chainId}`, |
| 39 | + ) |
| 40 | + const { data: checkData } = checkResponse |
| 41 | + if (checkData[0].status === 'perfect') { |
| 42 | + console.log(`already verified: ${contract.name} (${contract.address}), skipping.`) |
| 43 | + return |
| 44 | + } |
| 45 | + } catch (e) { |
| 46 | + console.error(((e as any).response && JSON.stringify((e as any).response.data)) || e) |
| 47 | + } |
| 48 | + |
| 49 | + console.log(`verifying ${contract.name} (${contract.address} on chain ${chainId}) ...`) |
| 50 | + |
| 51 | + // Build form data |
| 52 | + const formData = new FormData() |
| 53 | + formData.append('address', contract.address) |
| 54 | + formData.append('chain', chainId) |
| 55 | + |
| 56 | + const fileStream = new Readable() |
| 57 | + fileStream.push(contractMetadata) |
| 58 | + fileStream.push(null) |
| 59 | + formData.append('files', fileStream) |
| 60 | + |
| 61 | + // Verify contract |
| 62 | + try { |
| 63 | + const submissionResponse = await axios.post(sourcifyUrl, formData, { |
| 64 | + headers: formData.getHeaders(), |
| 65 | + }) |
| 66 | + const { status } = submissionResponse.data.result[0] |
| 67 | + if (status === 'perfect') { |
| 68 | + console.log(` => contract ${contract.name} is now verified`) |
| 69 | + } else if (status === 'partial') { |
| 70 | + console.log(` => contract ${contract.name} is partially verified`) |
| 71 | + } else { |
| 72 | + console.error(` => contract ${contract.name} is not verified`) |
| 73 | + } |
| 74 | + } catch (e) { |
| 75 | + console.error(((e as any).response && JSON.stringify((e as any).response.data)) || e) |
| 76 | + } |
| 77 | +} |
0 commit comments