mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
First iteration of a Polygon block explorer smart contract verifier
This commit is contained in:
parent
d9026b7122
commit
d673d54f75
|
@ -24,7 +24,8 @@ import { Artifact } from 'hardhat/types';
|
||||||
import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types';
|
import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types';
|
||||||
import { verifyContract } from './etherscan-verification';
|
import { verifyContract } from './etherscan-verification';
|
||||||
import { getIErc20Detailed } from './contracts-getters';
|
import { getIErc20Detailed } from './contracts-getters';
|
||||||
import { usingTenderly } from './tenderly-utils';
|
import { usingTenderly, verifyAtTenderly } from './tenderly-utils';
|
||||||
|
import { usingPolygon, verifyAtPolygon } from './polygon-utils';
|
||||||
|
|
||||||
export type MockTokenMap = { [symbol: string]: MintableERC20 };
|
export type MockTokenMap = { [symbol: string]: MintableERC20 };
|
||||||
|
|
||||||
|
@ -99,17 +100,14 @@ export const withSaveAndVerify = async <ContractType extends Contract>(
|
||||||
await waitForTx(instance.deployTransaction);
|
await waitForTx(instance.deployTransaction);
|
||||||
await registerContractInJsonDb(id, instance);
|
await registerContractInJsonDb(id, instance);
|
||||||
if (usingTenderly()) {
|
if (usingTenderly()) {
|
||||||
console.log();
|
await verifyAtTenderly(id, instance);
|
||||||
console.log('Doing Tenderly contract verification of', id);
|
|
||||||
await (DRE as any).tenderlyRPC.verify({
|
|
||||||
name: id,
|
|
||||||
address: instance.address,
|
|
||||||
});
|
|
||||||
console.log(`Verified ${id} at Tenderly!`);
|
|
||||||
console.log();
|
|
||||||
}
|
}
|
||||||
if (verify) {
|
if (verify) {
|
||||||
await verifyContract(instance.address, args);
|
if (usingPolygon()) {
|
||||||
|
await verifyAtPolygon(id, instance, args);
|
||||||
|
} else {
|
||||||
|
await verifyContract(instance.address, args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|
103
helpers/polygon-utils.ts
Normal file
103
helpers/polygon-utils.ts
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
import { Contract } from 'ethers/lib/ethers';
|
||||||
|
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
||||||
|
import { source } from 'lowdb/adapters/FileSync';
|
||||||
|
import { file } from 'tmp-promise';
|
||||||
|
import { DRE } from './misc-utils';
|
||||||
|
import { ePolygonNetwork } from './types';
|
||||||
|
|
||||||
|
const TASK_FLATTEN_GET_FLATTENED_SOURCE = 'flatten:get-flattened-sources';
|
||||||
|
const TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS = 'compile:solidity:get-source-paths';
|
||||||
|
|
||||||
|
/* Polygon Helpers */
|
||||||
|
|
||||||
|
export const usingPolygon = () =>
|
||||||
|
DRE && Object.keys(ePolygonNetwork).includes((DRE as HardhatRuntimeEnvironment).network.name);
|
||||||
|
|
||||||
|
/* Polygon Verifier */
|
||||||
|
|
||||||
|
const SOLIDITY_PRAGMA = 'pragma solidity';
|
||||||
|
const LICENSE_IDENTIFIER = 'License-Identifier';
|
||||||
|
const EXPERIMENTAL_ABIENCODER = 'pragma experimental ABIEncoderV2;';
|
||||||
|
|
||||||
|
// Remove lines at "text" that includes "matcher" string, but keeping first "keep" lines
|
||||||
|
const removeLines = (text: string, matcher: string, keep = 0): string => {
|
||||||
|
let counter = keep;
|
||||||
|
return text
|
||||||
|
.split('\n')
|
||||||
|
.filter((line) => {
|
||||||
|
const match = !line.includes(matcher);
|
||||||
|
if (match === false && counter > 0) {
|
||||||
|
counter--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
})
|
||||||
|
.join('\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try to find the path of a Contract by name of the file without ".sol"
|
||||||
|
const findPath = async (id: string): Promise<string> => {
|
||||||
|
const paths = await DRE.run(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS);
|
||||||
|
const path = paths.find((x) => {
|
||||||
|
const t = x.split('/');
|
||||||
|
return t[t.length - 1].split('.')[0] == id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!path) {
|
||||||
|
throw Error('Missing path for contract name: ${id}');
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hardhat Flattener, similar to truffle flattener
|
||||||
|
const hardhatFlattener = async (filePath: string) =>
|
||||||
|
await DRE.run(TASK_FLATTEN_GET_FLATTENED_SOURCE, { files: [filePath] });
|
||||||
|
|
||||||
|
// Verify a smart contract at Polygon Matic network via a GET request to the block explorer
|
||||||
|
export const verifyAtPolygon = async (
|
||||||
|
id: string,
|
||||||
|
instance: Contract,
|
||||||
|
args: (string | string[])[]
|
||||||
|
) => {
|
||||||
|
/*
|
||||||
|
${net == mumbai or mainnet}
|
||||||
|
https://explorer-${net}.maticvigil.com/api
|
||||||
|
?module=contract
|
||||||
|
&action=verify
|
||||||
|
&addressHash={addressHash}
|
||||||
|
&name={name}
|
||||||
|
&compilerVersion={compilerVersion}
|
||||||
|
&optimization={false}
|
||||||
|
&contractSourceCode={contractSourceCode}
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
const net = (DRE as HardhatRuntimeEnvironment).network.name;
|
||||||
|
const filePath = await findPath(id);
|
||||||
|
const flattenSourceCode = await hardhatFlattener(filePath);
|
||||||
|
|
||||||
|
// Remove pragmas and license identifier after first match, required by block explorers like explorer-mainnet.maticgivil.com or Etherscan
|
||||||
|
const cleanedSourceCode = removeLines(
|
||||||
|
removeLines(removeLines(flattenSourceCode, LICENSE_IDENTIFIER, 1), SOLIDITY_PRAGMA, 1),
|
||||||
|
EXPERIMENTAL_ABIENCODER,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
const response = await axios.get(`https://explorer-${net}.maticvigil.com/api`, {
|
||||||
|
params: {
|
||||||
|
module: 'contract',
|
||||||
|
action: 'verify',
|
||||||
|
addressHash: instance.address,
|
||||||
|
name: id,
|
||||||
|
compilerVersion: 'v0.6.12+commit.27d51765',
|
||||||
|
optimization: 'true',
|
||||||
|
contractSourceCode: cleanedSourceCode,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(response);
|
||||||
|
console.log(JSON.stringify(response, null, 2));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[Polygon Verify] Error:', error.toString());
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Contract } from 'ethers';
|
||||||
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
||||||
import { DRE } from './misc-utils';
|
import { DRE } from './misc-utils';
|
||||||
|
|
||||||
|
@ -5,3 +6,14 @@ export const usingTenderly = () =>
|
||||||
DRE &&
|
DRE &&
|
||||||
((DRE as HardhatRuntimeEnvironment).network.name.includes('tenderly') ||
|
((DRE as HardhatRuntimeEnvironment).network.name.includes('tenderly') ||
|
||||||
process.env.TENDERLY === 'true');
|
process.env.TENDERLY === 'true');
|
||||||
|
|
||||||
|
export const verifyAtTenderly = async (id: string, instance: Contract) => {
|
||||||
|
console.log();
|
||||||
|
console.log('Doing Tenderly contract verification of', id);
|
||||||
|
await (DRE as any).tenderlyRPC.verify({
|
||||||
|
name: id,
|
||||||
|
address: instance.address,
|
||||||
|
});
|
||||||
|
console.log(`Verified ${id} at Tenderly!`);
|
||||||
|
console.log();
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user