@solarity/hardhat-migrate
Version:
The simplest way to deploy smart contracts
215 lines • 9.68 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Verifier = void 0;
const ethers_1 = require("ethers");
const etherscan_1 = require("@nomicfoundation/hardhat-verify/etherscan");
const blockscout_1 = require("@nomicfoundation/hardhat-verify/blockscout");
const utils_1 = require("../utils");
const requests_1 = require("../tools/network/requests");
const NetworkManager_1 = require("../tools/network/NetworkManager");
const Reporter_1 = require("../tools/reporters/Reporter");
const etherscan_api_1 = require("../tools/network/etherscan-api");
class Verifier {
_hre;
_config;
_standalone;
_etherscanConfig;
_blockscoutConfig;
constructor(_hre, _config, _standalone = false) {
this._hre = _hre;
this._config = _config;
this._standalone = _standalone;
this._etherscanConfig = _hre.config.etherscan;
this._blockscoutConfig = _hre.config.blockscout;
}
async verifyBatch(verifierBatchArgs) {
const currentChainId = Number(await (0, utils_1.getChainId)());
const toVerify = verifierBatchArgs.filter((args) => args.chainId && currentChainId == args.chainId);
if (!toVerify || toVerify.length === 0) {
Reporter_1.Reporter.reportNothingToVerify();
return;
}
const verificationDelay = this._hre.config.migrate.verification.verificationDelay;
if (verificationDelay > 0 && !this._standalone) {
await Reporter_1.Reporter.startSpinner("verification-delay", () => "Waiting for the explorer to sync up");
await (0, utils_1.sleep)(verificationDelay);
Reporter_1.Reporter.stopSpinner();
}
Reporter_1.Reporter.reportVerificationBatchBegin();
const parallel = this._config.parallel;
for (let i = 0; i < toVerify.length; i += parallel) {
const batch = toVerify.slice(i, i + parallel);
await Promise.all(batch.map((args) => this._verify(args)));
}
}
async _verify(verifierArgs) {
const { contractAddress, contractName, constructorArguments } = verifierArgs;
let instance;
try {
instance = await this._getEtherscanInstance(this._hre);
await this._validateExplorerConfiguration(instance, contractAddress);
}
catch {
instance = await this._getBlockscoutInstance(this._hre);
}
for (let attempts = 0; attempts < this._config.attempts; attempts++) {
try {
await this._tryVerify(instance, contractAddress, contractName, constructorArguments);
break;
}
catch (e) {
this._handleVerificationError(contractAddress, contractName, e);
if (e.message !== undefined &&
typeof e.message === "string" &&
(e.message.includes("HH303: Unrecognized task 'verify:verify'") || e.message.includes("already verified"))) {
break;
}
}
await (0, utils_1.sleep)(2500);
}
}
async _tryVerify(instance, contractAddress, contractName, constructorArguments) {
await this._tryRunVerificationTask(instance, contractAddress, contractName, constructorArguments);
const isVerified = await instance.isVerified(contractAddress);
if (isVerified) {
Reporter_1.Reporter.reportSuccessfulVerification(contractAddress, contractName);
return;
}
else {
Reporter_1.Reporter.reportVerificationError(contractAddress, contractName, "Verification failed");
}
}
_handleVerificationError(contractAddress, contractName, error) {
if (error.message.toLowerCase().includes("already verified")) {
Reporter_1.Reporter.reportAlreadyVerified(contractAddress, contractName);
return;
}
else {
Reporter_1.Reporter.reportVerificationError(contractAddress, contractName, error.message);
}
}
async _getEtherscanInstance(hre) {
const chainConfig = await etherscan_1.Etherscan.getCurrentChainConfig(hre.network.name, hre.network.provider, this._etherscanConfig.customChains ?? []);
return etherscan_1.Etherscan.fromChainConfig(this._etherscanConfig.apiKey, chainConfig);
}
async _getBlockscoutInstance(hre) {
const chainConfig = await blockscout_1.Blockscout.getCurrentChainConfig(hre.network.name, hre.network.provider, this._blockscoutConfig.customChains ?? []);
return blockscout_1.Blockscout.fromChainConfig(chainConfig);
}
async _tryRunVerificationTask(instance, contractAddress, contractName, args) {
if (instance instanceof etherscan_1.Etherscan) {
await this._hre.run("verify:verify", {
address: contractAddress,
constructorArguments: args,
contract: contractName,
force: true,
});
await this._verifyProxy(instance, contractAddress);
}
if (instance instanceof blockscout_1.Blockscout) {
await this._hre.run("verify:blockscout", {
address: contractAddress,
constructorArguments: args,
contract: contractName,
force: true,
});
}
}
async _validateExplorerConfiguration(instance, contractAddress) {
const parameters = new URLSearchParams({
apikey: instance.apiKey,
module: "contract",
action: "getsourcecode",
address: contractAddress,
});
const url = new URL(instance.apiUrl);
url.search = parameters.toString();
const response = await (0, requests_1.sendGetRequest)(url.toString());
if (response.status !== 200) {
console.warn(`The explorer responded with a status code of ${response.status} for the URL "${url.toString().split("?")[0]}".`);
}
}
async _verifyProxy(instance, proxyAddress) {
try {
const implementationAddress = await (0, utils_1.getPossibleImplementationAddress)(proxyAddress);
if (implementationAddress === ethers_1.ethers.ZeroAddress) {
return;
}
await this._linkProxyWithImplementationAbi(instance, proxyAddress, implementationAddress);
}
catch (e) {
/* empty */
}
}
/**
* Calls the Etherscan API to link a proxy with its implementation ABI.
*
* Source: https://github.com/OpenZeppelin/openzeppelin-upgrades
*/
async _linkProxyWithImplementationAbi(instance, proxyAddress, implAddress) {
const params = {
module: "contract",
action: "verifyproxycontract",
address: proxyAddress,
expectedimplementation: implAddress,
};
let verifyProxyResponse = await (0, etherscan_api_1.callEtherscanApi)(instance, params);
if (verifyProxyResponse.status === etherscan_api_1.RESPONSE_OK) {
// initial call was OK, but need to send a status request using the
// returned guid to get the actual verification status
let responseBody = await this._checkProxyVerificationStatus(instance, verifyProxyResponse.result);
while (responseBody.result === "Pending in queue") {
await (0, utils_1.sleep)(5000);
responseBody = await this._checkProxyVerificationStatus(instance, verifyProxyResponse.result);
}
}
if (verifyProxyResponse.status === etherscan_api_1.RESPONSE_OK) {
Reporter_1.Reporter.reportSuccessfulProxyLinking(proxyAddress, implAddress);
}
else {
Reporter_1.Reporter.reportFailedProxyLinking(proxyAddress, implAddress, verifyProxyResponse.result);
}
}
async _checkProxyVerificationStatus(instance, guid) {
const checkProxyVerificationParams = {
module: "contract",
action: "checkproxyverification",
apikey: instance.apiKey,
guid: guid,
};
return (0, etherscan_api_1.callEtherscanApi)(instance, checkProxyVerificationParams);
}
static async buildVerifierTaskDeps(hre) {
(0, NetworkManager_1.buildNetworkDeps)(hre);
await (0, Reporter_1.createAndInitReporter)(hre);
}
}
exports.Verifier = Verifier;
__decorate([
utils_1.catchError
], Verifier.prototype, "verifyBatch", null);
__decorate([
utils_1.catchError
], Verifier.prototype, "_verify", null);
__decorate([
utils_1.catchError
], Verifier.prototype, "_tryVerify", null);
__decorate([
utils_1.catchError
], Verifier.prototype, "_handleVerificationError", null);
__decorate([
utils_1.catchError
], Verifier.prototype, "_getEtherscanInstance", null);
__decorate([
utils_1.catchError
], Verifier.prototype, "_getBlockscoutInstance", null);
__decorate([
utils_1.suppressLogs
], Verifier.prototype, "_tryRunVerificationTask", null);
//# sourceMappingURL=Verifier.js.map