@nomiclabs/hardhat-etherscan
Version:
Hardhat plugin for verifying contracts on etherscan
122 lines • 5.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isAlreadyVerified = exports.EtherscanResponse = exports.getVerificationStatus = exports.verifyContract = exports.delay = void 0;
const constants_1 = require("../constants");
const undici_1 = require("../undici");
const errors_1 = require("../errors");
async function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
exports.delay = delay;
// Used for polling the result of the contract verification.
const verificationIntervalMs = 3000;
async function verifyContract(url, req) {
const parameters = new URLSearchParams({ ...req });
let response;
try {
response = await (0, undici_1.sendPostRequest)(new URL(url), parameters.toString());
}
catch (error) {
throw new errors_1.HardhatEtherscanPluginError(constants_1.pluginName, `Failed to send contract verification request.
Endpoint URL: ${url}
Reason: ${error.message}`, error);
}
if (!(response.statusCode >= 200 && response.statusCode <= 299)) {
// This could be always interpreted as JSON if there were any such guarantee in the Etherscan API.
const responseText = await response.body.text();
throw new errors_1.HardhatEtherscanPluginError(constants_1.pluginName, `Failed to send contract verification request.
Endpoint URL: ${url}
The HTTP server response is not ok. Status code: ${response.statusCode} Response text: ${responseText}`);
}
const etherscanResponse = new EtherscanResponse(await response.body.json());
if (etherscanResponse.isBytecodeMissingInNetworkError()) {
throw new errors_1.HardhatEtherscanPluginError(constants_1.pluginName, `Failed to send contract verification request.
Endpoint URL: ${url}
Reason: The Etherscan API responded that the address ${req.contractaddress} does not have bytecode.
This can happen if the contract was recently deployed and this fact hasn't propagated to the backend yet.
Try waiting for a minute before verifying your contract. If you are invoking this from a script,
try to wait for five confirmations of your contract deployment transaction before running the verification subtask.`);
}
if (!etherscanResponse.isOk()) {
throw new errors_1.HardhatEtherscanPluginError(constants_1.pluginName, etherscanResponse.message);
}
return etherscanResponse;
}
exports.verifyContract = verifyContract;
async function getVerificationStatus(url, req) {
const parameters = new URLSearchParams({ ...req });
const urlWithQuery = new URL(url);
urlWithQuery.search = parameters.toString();
let response;
try {
response = await (0, undici_1.sendGetRequest)(urlWithQuery);
if (!(response.statusCode >= 200 && response.statusCode <= 299)) {
// This could be always interpreted as JSON if there were any such guarantee in the Etherscan API.
const responseText = await response.body.text();
const message = `The HTTP server response is not ok. Status code: ${response.statusCode} Response text: ${responseText}`;
throw new errors_1.HardhatEtherscanPluginError(constants_1.pluginName, message);
}
}
catch (error) {
throw new errors_1.HardhatEtherscanPluginError(constants_1.pluginName, `Failure during etherscan status polling. The verification may still succeed but
should be checked manually.
Endpoint URL: ${urlWithQuery.toString()}
Reason: ${error.message}`, error);
}
const etherscanResponse = new EtherscanResponse(await response.body.json());
if (etherscanResponse.isPending()) {
await delay(verificationIntervalMs);
return getVerificationStatus(url, req);
}
if (etherscanResponse.isVerificationFailure()) {
return etherscanResponse;
}
if (!etherscanResponse.isOk()) {
throw new errors_1.HardhatEtherscanPluginError(constants_1.pluginName, `The Etherscan API responded with a failure status.
The verification may still succeed but should be checked manually.
Reason: ${etherscanResponse.message}`);
}
return etherscanResponse;
}
exports.getVerificationStatus = getVerificationStatus;
class EtherscanResponse {
constructor(response) {
this.status = parseInt(response.status, 10);
this.message = response.result;
}
isPending() {
return this.message === "Pending in queue";
}
isVerificationFailure() {
return this.message === "Fail - Unable to verify";
}
isVerificationSuccess() {
return this.message === "Pass - Verified";
}
isBytecodeMissingInNetworkError() {
return this.message.startsWith("Unable to locate ContractCode at");
}
isOk() {
return this.status === 1;
}
}
exports.EtherscanResponse = EtherscanResponse;
async function isAlreadyVerified(apiURL, apiKey, address) {
const parameters = new URLSearchParams({
module: "contract",
action: "getsourcecode",
address,
apikey: apiKey,
});
const url = new URL(apiURL);
url.search = parameters.toString();
const response = await (0, undici_1.sendGetRequest)(url);
const json = await response.body.json();
if (json.message !== "OK") {
return false;
}
const sourceCode = json?.result?.[0]?.SourceCode;
return sourceCode !== undefined && sourceCode !== "";
}
exports.isAlreadyVerified = isAlreadyVerified;
//# sourceMappingURL=EtherscanService.js.map