From 962c89dfd888d8152c87e03d7c48351f6f9a1b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillermo=20D=C3=ADaz?= Date: Mon, 19 Feb 2024 09:26:37 +0100 Subject: [PATCH] feat: contracts verification scripts --- migrations/addresses.json | 32 ++++++++++++-------------------- migrations/constructorArgs.json | 14 ++++---------- migrations/scripts/1_deployer.js | 9 +++++++++ migrations/scripts/3_core.js | 6 ++++++ package.json | 23 +++++++++++++---------- scripts/verify-core.js | 29 +++++++++++++++++++++++++++++ scripts/verify-impls.js | 32 ++++++++++++++++++++++++++++++++ scripts/verify-libs.js | 28 ++++++++++++++++++++++++++++ src/utils.js | 20 ++++++++++++++------ 9 files changed, 147 insertions(+), 46 deletions(-) create mode 100644 scripts/verify-core.js create mode 100644 scripts/verify-impls.js create mode 100644 scripts/verify-libs.js diff --git a/migrations/addresses.json b/migrations/addresses.json index 2f815dcb..1a3e2bc2 100644 --- a/migrations/addresses.json +++ b/migrations/addresses.json @@ -1,27 +1,19 @@ { "default": { "WitnetDeployer": "0x03232aBE800D1638B30432FeEF300581De323a4E", - "WitnetOracle": "0x00000eBcBDD5B6A1B4f102b165ED2C4d8B6B1000", - "WitnetRequestBytecodes": "0x0000B677d4a6d20C3B087c52A36E4Bed558De000", - "WitnetRequestFactory": "0x0000f7Eb1d08E68C361b8A0c4a36f442c58f1000", - "WitnetPriceFeeds": "0x11111c2cC3f1af92bA0f1f554f2651cEfb858111" + "WitnetOracle": "0x000071F0c823bD30D2Bf4CD1E829Eba5A6070000", + "WitnetPriceFeeds": "0x1111AbA2164AcdC6D291b08DfB374280035E1111", + "WitnetRequestBytecodes": "0x000B61Fe075F545fd37767f40391658275900000", + "WitnetRequestFactory": "0x000F4cCF726c5445626DBD6f2258482f61377000" }, "ethereum:sepolia": { - "WitnetErrorsLib": "0x6A7Db21C42053E5F15aF564fAdfC8E04e5eA5152", - "WitnetEncodingLib": "0x85350c3738864554993EE45b57e9B46d08b80Eec", - "WitnetPriceFeedsLib": "0xd7E19CFd2488B6FE666b1CaE6a93110b78c744B6", - "WitnetRequestBytecodesDefault": "0x93DaB12D00117C3d805fF1042dF31bdA25a06A3B", - "WitnetRequestFactoryDefault": "0x3F654127135E7548a171506Ecc1dfCad70356435", - "WitnetRequestBoardTrustableDefault": "0xbdb6D793CC16d4518ED404D08C133251C877a531", - "WitnetPriceFeedsDefault": "0x075e226222eB03F83Bc36ed9A3cAaeb6d4873660" - }, - "ten:testnet": { - "WitnetErrorsLib": "0x6A7Db21C42053E5F15aF564fAdfC8E04e5eA5152", - "WitnetEncodingLib": "0x85350c3738864554993EE45b57e9B46d08b80Eec", - "WitnetPriceFeedsLib": "0xd7E19CFd2488B6FE666b1CaE6a93110b78c744B6", - "WitnetPriceFeedsDefault": "0x2693977d2fE01542034BE415184d2022250E9B7f", - "WitnetRequestBytecodesDefault": "0xbD8560E02ACd634A0895f340D2EAC3996297630f", - "WitnetRequestFactoryDefault": "0xCcF97F809a4d1b8aC2bF87a2fdfafDFEf576406c", - "WitnetRequestBoardTrustableObscuro": "0x55d78D1fEd850790aDAfFB9BD54A42B9382D7739" + "WitnetErrorsLib": "0x77aac367a921DD2a92dfd0351456839663af248F", + "WitnetEncodingLib": "0x967cfE0Edfc52e027849012E5dA706A9e5e62345", + "WitnetPriceFeedsLib": "0x96013096b1305c4009bfa2C2D3e34fEcB3dD4927", + "WitnetRequestBoardTrustableDefault": "0x8C6F4a0DAa1e3Ea1fAcE58031e76187E61620845", + "WitnetRequestBytecodesDefault": "0x8CE5EF0ab67cdC00D32e09f34f74daFb0d049314", + "WitnetRequestFactoryDefault": "0xdd118b23a2199Bf902e149dE407E205e67932bcb", + "WitnetPriceFeedsDefault": "0x9453CE5217a8688B2318455E82A9Fb4E89eD47b6", + "WitnetProxy": "0x21ac85A6c320E6fC89774A98732eAE733032651C" } } \ No newline at end of file diff --git a/migrations/constructorArgs.json b/migrations/constructorArgs.json index 829039d2..a685248a 100644 --- a/migrations/constructorArgs.json +++ b/migrations/constructorArgs.json @@ -1,14 +1,8 @@ { - "ten:testnet": { - "WitnetPriceFeedsDefault": "00000000000000000000000000000ebcbdd5b6a1b4f102b165ed2c4d8b6b10000000000000000000000000000000000000000000000000000000000000000001322e302e312d3434373063396100000000000000000000000000000000000000", - "WitnetRequestBytecodesDefault": "0000000000000000000000000000000000000000000000000000000000000001322e302e312d3339366564343400000000000000000000000000000000000000", - "WitnetRequestFactoryDefault": "00000000000000000000000000000ebcbdd5b6a1b4f102b165ed2c4d8b6b10000000000000000000000000000000b677d4a6d20c3b087c52a36e4bed558de0000000000000000000000000000000000000000000000000000000000000000001322e302e312d3339366564343400000000000000000000000000000000000000", - "WitnetRequestBoardTrustableObscuro": "0000000000000000000000000000f7eb1d08e68c361b8a0c4a36f442c58f10000000000000000000000000000000b677d4a6d20c3b087c52a36e4bed558de0000000000000000000000000000000000000000000000000000000000000000001322e302e312d3339366564343400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3aa000000000000000000000000000000000000000000000000000000000000fef90000000000000000000000000000000000000000000000000000000000010faa0000000000000000000000000000000000000000000000000000000000004e20" - }, "ethereum:sepolia": { - "WitnetPriceFeedsDefault": "00000000000000000000000000000ebcbdd5b6a1b4f102b165ed2c4d8b6b10000000000000000000000000000000000000000000000000000000000000000001322e302e312d3433663030303800000000000000000000000000000000000000", - "WitnetRequestBytecodesDefault": "0000000000000000000000000000000000000000000000000000000000000001322e302e312d3433663030303800000000000000000000000000000000000000", - "WitnetRequestFactoryDefault": "00000000000000000000000000000ebcbdd5b6a1b4f102b165ed2c4d8b6b10000000000000000000000000000000b677d4a6d20c3b087c52a36e4bed558de0000000000000000000000000000000000000000000000000000000000000000001322e302e312d3433663030303800000000000000000000000000000000000000", - "WitnetRequestBoardTrustableDefault": "0000000000000000000000000000f7eb1d08e68c361b8a0c4a36f442c58f10000000000000000000000000000000b677d4a6d20c3b087c52a36e4bed558de0000000000000000000000000000000000000000000000000000000000000000001322e302e312d3433663030303800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3aa000000000000000000000000000000000000000000000000000000000000fef90000000000000000000000000000000000000000000000000000000000010faa0000000000000000000000000000000000000000000000000000000000004e20" + "WitnetRequestBytecodesDefault": "0000000000000000000000000000000000000000000000000000000000000001322e302e312d3137303438343900000000000000000000000000000000000000", + "WitnetRequestFactoryDefault": "000000000000000000000000000071f0c823bd30d2bf4cd1e829eba5a6070000000000000000000000000000000b61fe075f545fd37767f403916582759000000000000000000000000000000000000000000000000000000000000000000001322e302e312d3332303438366600000000000000000000000000000000000000", + "WitnetRequestBoardTrustableDefault": "000000000000000000000000000f4ccf726c5445626dbd6f2258482f61377000000000000000000000000000000b61fe075f545fd37767f403916582759000000000000000000000000000000000000000000000000000000000000000000001322e302e312d3332303438366600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3aa000000000000000000000000000000000000000000000000000000000000fef90000000000000000000000000000000000000000000000000000000000010faa0000000000000000000000000000000000000000000000000000000000004e20", + "WitnetPriceFeedsDefault": "000000000000000000000000000071f0c823bd30d2bf4cd1e829eba5a60700000000000000000000000000000000000000000000000000000000000000000001322e302e312d3332303438366600000000000000000000000000000000000000" } } \ No newline at end of file diff --git a/migrations/scripts/1_deployer.js b/migrations/scripts/1_deployer.js index 1bf86284..fef03883 100644 --- a/migrations/scripts/1_deployer.js +++ b/migrations/scripts/1_deployer.js @@ -1,6 +1,7 @@ const utils = require("../../src/utils") const WitnetDeployer = artifacts.require("WitnetDeployer") +const WitnetProxy = artifacts.require("WitnetProxy") module.exports = async function (deployer, network, [,,, master]) { @@ -25,4 +26,12 @@ module.exports = async function (deployer, network, [,,, master]) { console.info(" > Contract address:", factory.address) console.info() } + + if (utils.isNullAddress(addresses[network]?.WitnetProxy)) { + await deployer.deploy(WitnetProxy, { from: master }) + addresses[network].WitnetProxy = WitnetProxy.address + if (!utils.isDryRun(network)) { + await utils.overwriteJsonFile("./migrations/addresses.json", addresses) + } + } } diff --git a/migrations/scripts/3_core.js b/migrations/scripts/3_core.js index 41d656a6..ea520809 100644 --- a/migrations/scripts/3_core.js +++ b/migrations/scripts/3_core.js @@ -143,6 +143,12 @@ async function deploy (specs) { utils.traceHeader(`Skipped '${key}'`) } contract.address = addresses[network][key] + for (const index in libs) { + const libname = libs[index] + const lib = artifacts.require(libname) + contract.link(lib) + console.info(" ", "> external library: ", `${libname}@${lib.address}`) + }; console.info(" ", "> contract address: ", contract.address) console.info(" ", "> contract codehash:", web3.utils.soliditySha3(await web3.eth.getCode(contract.address))) console.info() diff --git a/package.json b/package.json index afc436f8..b457285d 100644 --- a/package.json +++ b/package.json @@ -29,29 +29,32 @@ ], "scripts": { "addresses": "node ./scripts/addresses.js 2>&1", - "clean": "npm run clean:build && npm run clean:flattened", + "clean": "pnpm run clean:build && pnpm run clean:flattened", "clean:build": "node ./scripts/clean.js build", "clean:flattened": "node ./scripts/clean.js flattened", "compile": "npx truffle compile --all", "console": "npx truffle console", "coverage": "solidity-coverage", "flatten": "node ./scripts/flatten.js 2>&1", - "flatten:all": "npm run clean && npm run flatten:core && npm run flatten:apps && npm run flatten:libs && npm run flatten:proxy", - "flatten:apps": "npm run flatten contracts/core/apps/", - "flatten:core": "npm run flatten contracts/core/core/", - "flatten:libs": "npm run flatten contracts/libs/WitnetErrorsLib.sol && npm run flatten contracts/libs/WitnetEncodingLib.sol && npm run flatten contracts/libs/WitnetPriceFeedsLib.sol", - "flatten:proxy": "npm run flatten contracts/core/WitnetProxy.sol", + "flatten:all": "pnpm run clean && pnpm run flatten:core && pnpm run flatten:apps && pnpm run flatten:libs && pnpm run flatten:proxy", + "flatten:apps": "pnpm run flatten contracts/core/apps/", + "flatten:core": "pnpm run flatten contracts/core/core/", + "flatten:libs": "pnpm run flatten contracts/libs/WitnetErrorsLib.sol && pnpm run flatten contracts/libs/WitnetEncodingLib.sol && pnpm run flatten contracts/libs/WitnetPriceFeedsLib.sol", + "flatten:proxy": "pnpm run flatten contracts/core/WitnetProxy.sol", "fmt:js": "eslint \"**/*.js\"", "fmt:sol": "solhint --max-warnings 0 \"contracts/**/*.sol\" && solhint \"test/**/*.sol\" && solhint \"flattened/**/*.sol\"", "fmt!:js": "eslint \"**/*.js\" --fix", "fmt!:sol": "solhint --max-warnings 0 \"contracts/**/*.sol\" --fix && solhint \"test/**/*.sol\" --fix && solhint \"flattened/**/*.sol\"", - "fmt!": "npm run fmt!:js && npm run fmt!:sol", - "fmt": "npm run fmt:js && npm run fmt:sol", + "fmt!": "pnpm run fmt!:js && pnpm run fmt!:sol", + "fmt": "pnpm run fmt:js && pnpm run fmt:sol", "migrate": "npx truffle migrate --network", "networks": "node ./scripts/networks.js 2>&1", "ops:rng:sla": "npx truffle migrate --migrations_directory ./migrations/ops/rng/sla --network", "prepare": "npx truffle compile --all && npx hardhat compile && node ./scripts/prepare.js", - "test": "npm run clean && npx truffle test" + "test": "pnpm run clean && npx truffle test", + "verify:core": "node ./scripts/verify-core.js 2>&1", + "verify:libs": "node ./scripts/verify-libs.js 2>&1", + "verify:impls": "node ./scripts/verify-impls.js 2>&1" }, "dependencies": { "dotenv": "^16.4.4", @@ -77,6 +80,6 @@ "truffle": "^5.11.5", "truffle-assertions": "^0.9.2", "truffle-flattener": "^1.6.0", - "typescript": "latest" + "truffle-plugin-verify": "^0.6.7" } } diff --git a/scripts/verify-core.js b/scripts/verify-core.js new file mode 100644 index 00000000..5bb1df42 --- /dev/null +++ b/scripts/verify-core.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node + +const utils = require("../src/utils") + +if (process.argv.length < 3) { + console.error(`\nUsage:\n\n$ node ./scripts/verify-proxies.js : ...OPTIONAL_ARGS\n`) + process.exit(0) +} + +const network = process.argv[2].toLowerCase().replaceAll(".", ":") + +const header = network.toUpperCase() + " CORE"; +console.info() +console.info(header) +console.info("=".repeat(header.length)) +console.info() + +utils.traceVerify(network, "WitnetDeployer"); +utils.traceVerify(network, "WitnetProxy"); + +const singletons = [ + "WitnetOracle", + "WitnetPriceFeeds", + "WitnetRequestBytecodes", + "witnetRequestFactory" +]; +for (const index in singletons) { + utils.traceVerify(network, `${singletons[index]} --custom-proxy WitnetProxy`); +} diff --git a/scripts/verify-impls.js b/scripts/verify-impls.js new file mode 100644 index 00000000..ce1a6f11 --- /dev/null +++ b/scripts/verify-impls.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const settings = require("../settings") +const utils = require("../src/utils") + +if (process.argv.length < 3) { + console.error(`\nUsage:\n\n$ node ./scripts/verify-proxies.js : ...OPTIONAL_ARGS\n`) + process.exit(0) +} + +const network = process.argv[2].toLowerCase().replaceAll(".", ":") + +const header = network.toUpperCase(); +console.info() +console.info(header) +console.info("=".repeat(header.length)) +console.info() + +const artifacts = settings.getArtifacts(network) +const impls = [ + artifacts["WitnetOracle"], + artifacts["WitnetPriceFeeds"], + artifacts["WitnetRequestBytecodes"], + artifacts["WitnetRequestFactory"], +]; +const constructorArgs = require("../migrations/constructorArgs.json") +for (const index in impls) { + utils.traceVerify(network, `${impls[index]} --forceConstructorArgs string:${ + constructorArgs[network][impls[index]] + } --verifiers etherscan`); +} + diff --git a/scripts/verify-libs.js b/scripts/verify-libs.js new file mode 100644 index 00000000..333353de --- /dev/null +++ b/scripts/verify-libs.js @@ -0,0 +1,28 @@ +#!/usr/bin/env node + +const settings = require("../settings") +const utils = require("../src/utils") + +if (process.argv.length < 3) { + console.error(`\nUsage:\n\n$ node ./scripts/verify-proxies.js : ...OPTIONAL_ARGS\n`) + process.exit(0) +} + +const network = process.argv[2].toLowerCase().replaceAll(".", ":") + +const header = network.toUpperCase()+ " LIBS"; +console.info() +console.info(header) +console.info("=".repeat(header.length)) +console.info() + +const artifacts = settings.getArtifacts(network) +const libs = [ + artifacts["WitnetEncodingLib"], + artifacts["WitnetErrorsLib"], + artifacts["WitnetPriceFeedsLib"], +]; +for (const index in libs) { + utils.traceVerify(network, `${libs[index]}`); +} + diff --git a/src/utils.js b/src/utils.js index 4cd0c5d0..9fc25864 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,4 @@ +const execSync = require("child_process").execSync const fs = require("fs") require("dotenv").config() const lockfile = require("proper-lockfile") @@ -17,6 +18,7 @@ module.exports = { overwriteJsonFile, traceHeader, traceTx, + traceVerify, } function fromAscii (str) { @@ -29,7 +31,7 @@ function fromAscii (str) { } function getRealmNetworkFromArgs () { - let networkString = process.argv.includes("test") ? "test" : "development" + let networkString = process.env.WSB_DEFAULT_CHAIN || process.argv.includes("test") ? "test" : "development" // If a `--network` argument is provided, use that instead const args = process.argv.join("=").split("=") const networkIndex = args.indexOf("--network") @@ -136,9 +138,15 @@ function traceTx (tx) { console.info(" ", "> transaction hash: ", tx.receipt.transactionHash) console.info(" ", "> gas used: ", tx.receipt.gasUsed.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")) console.info(" ", "> gas price: ", tx.receipt.effectiveGasPrice / 10 ** 9, "gwei") - // console.info(" ", "> total cost: ", web3.utils.fromWei( - // BigInt(tx.receipt.gasUsed * tx.receipt.effectiveGasPrice).toString(), - // "ether" - // ), "ETH" - // ) + console.info(" ", "> total cost: ", parseFloat(BigInt(tx.receipt.gasUsed) * BigInt(tx.receipt.effectiveGasPrice) / BigInt(10 ** 18)).toString(), "ETH") +} + +function traceVerify(network, verifyArgs) { + console.log( + execSync( + `npx truffle run verify --network ${network} ${verifyArgs} ${process.argv.slice(3)}`, + { stdout: 'inherit' } + ).toString().split("\n") + .join("\n") + ); }