diff --git a/.vscode/launch.json b/.vscode/launch.json index 5896086b4..2567a70d4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -190,10 +190,7 @@ // "--grep=v0.6.12", "--exit", ], - "outFiles": [ - "./**/*.js", - "${workspaceFolder}/packages/lib-sourcify/build/**/*.js" - ], + "sourceMaps": true, "smartStep": true, "console": "integratedTerminal", // "internalConsoleOptions": "neverOpen" diff --git a/environments/.env.dev b/environments/.env.dev index aaae137c3..397e7e275 100644 --- a/environments/.env.dev +++ b/environments/.env.dev @@ -79,7 +79,7 @@ MOONSCAN_MOONBEAM_API_KEY= MOONSCAN_MOONRIVER_API_KEY= BOBASCAN_API_KEY= GNOSISSCAN_API_KEY= -OPTIMISTIC_ETHERSCAN_API_KEY= +OPTIMISMSCAN_API_KEY= # Needed to call create2 APIs, format is: TOKEN1,TOKEN2,... CREATE2_CLIENT_TOKENS= diff --git a/environments/.env.latest b/environments/.env.latest index 789eaf4dc..05d34d5e5 100644 --- a/environments/.env.latest +++ b/environments/.env.latest @@ -78,7 +78,7 @@ MOONSCAN_MOONBEAM_API_KEY=xxx MOONSCAN_MOONRIVER_API_KEY=xxx BOBASCAN_API_KEY=xxx GNOSISSCAN_API_KEY=xxx -OPTIMISTIC_ETHERSCAN_API_KEY=xxx +OPTIMISMSCAN_API_KEY=xxx CREATE2_CLIENT_TOKENS=xxx diff --git a/environments/.env.secrets.gpg b/environments/.env.secrets.gpg index 41e9268d4..075fad503 100644 Binary files a/environments/.env.secrets.gpg and b/environments/.env.secrets.gpg differ diff --git a/environments/.env.stable b/environments/.env.stable index e9ef447aa..34200569e 100644 --- a/environments/.env.stable +++ b/environments/.env.stable @@ -76,7 +76,7 @@ MOONSCAN_MOONBEAM_API_KEY=xxx MOONSCAN_MOONRIVER_API_KEY=xxx BOBASCAN_API_KEY=xxx GNOSISSCAN_API_KEY=xxx -OPTIMISTIC_ETHERSCAN_API_KEY=xxx +OPTIMISMSCAN_API_KEY=xxx CREATE2_CLIENT_TOKENS=xxx diff --git a/environments/grafana.yaml b/environments/grafana.yaml index 565042106..400e1402e 100644 --- a/environments/grafana.yaml +++ b/environments/grafana.yaml @@ -92,3 +92,13 @@ services: - "/:/host:ro,rslave" networks: - source-verify + + nginx_exporter: + image: nginx/nginx-prometheus-exporter:0.10.0 + container_name: grafana-nginx_exporter-${TAG} + command: + - -nginx.scrape-uri + - https://sourcify.dev/nginx_status + restart: unless-stopped + networks: + - source-verify diff --git a/package-lock.json b/package-lock.json index 7808bcb8d..32c7c2865 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5295,6 +5295,12 @@ "node": ">=8" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", + "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", + "dev": true + }, "node_modules/ansi-styles": { "version": "3.2.1", "license": "MIT", @@ -14152,6 +14158,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/jsonfile": { "version": "4.0.0", "license": "MIT", @@ -15079,6 +15091,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/macos-release": { "version": "2.5.0", "dev": true, @@ -15169,6 +15187,18 @@ "node": ">=0.10.0" } }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/mcl-wasm": { "version": "0.7.9", "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", @@ -20377,6 +20407,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/shiki": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", + "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", + "dev": true, + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/side-channel": { "version": "1.0.4", "license": "MIT", @@ -22256,6 +22298,51 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typedoc": { + "version": "0.24.6", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.6.tgz", + "integrity": "sha512-c3y3h45xJv3qYwKDAwU6Cl+26CjT0ZvblHzfHJ+SjQDM4p1mZxtgHky4lhmG0+nNarRht8kADfZlbspJWdZarQ==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "4.9.4", "license": "Apache-2.0", @@ -22756,6 +22843,18 @@ "extsprintf": "^1.2.0" } }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "node_modules/wcwidth": { "version": "1.0.1", "dev": true, @@ -29465,8 +29564,8 @@ "prettier": "^2.8.2", "standard-version": "^9.5.0", "ts-node": "^10.9.1", - "typedoc": "^0.23.24", - "typescript": "^4.9.4" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "engines": { "node": ">=10" @@ -29612,6 +29711,20 @@ "node": ">=v14" } }, + "packages/lib-sourcify/node_modules/@commitlint/load/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "optional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "packages/lib-sourcify/node_modules/@commitlint/resolve-extends": { "version": "17.4.0", "dev": true, @@ -36254,11 +36367,6 @@ "version": "5.0.1", "license": "ISC" }, - "packages/lib-sourcify/node_modules/jsonc-parser": { - "version": "3.2.0", - "dev": true, - "license": "MIT" - }, "packages/lib-sourcify/node_modules/jsonfile": { "version": "6.1.0", "dev": true, @@ -36520,11 +36628,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/lib-sourcify/node_modules/lunr": { - "version": "2.3.9", - "dev": true, - "license": "MIT" - }, "packages/lib-sourcify/node_modules/make-dir": { "version": "3.1.0", "dev": true, @@ -36563,17 +36666,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/lib-sourcify/node_modules/marked": { - "version": "4.2.12", - "dev": true, - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, "packages/lib-sourcify/node_modules/md5.js": { "version": "1.3.5", "license": "MIT", @@ -38348,16 +38440,6 @@ "node": ">=8" } }, - "packages/lib-sourcify/node_modules/shiki": { - "version": "0.12.1", - "dev": true, - "license": "MIT", - "dependencies": { - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" - } - }, "packages/lib-sourcify/node_modules/side-channel": { "version": "1.0.4", "license": "MIT", @@ -39369,55 +39451,17 @@ "is-typedarray": "^1.0.0" } }, - "packages/lib-sourcify/node_modules/typedoc": { - "version": "0.23.24", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.2.5", - "minimatch": "^5.1.2", - "shiki": "^0.12.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 14.14" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x" - } - }, - "packages/lib-sourcify/node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "packages/lib-sourcify/node_modules/typedoc/node_modules/minimatch": { - "version": "5.1.4", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "packages/lib-sourcify/node_modules/typescript": { - "version": "4.9.4", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=12.20" } }, "packages/lib-sourcify/node_modules/uglify-js": { @@ -39570,16 +39614,6 @@ "version": "1.0.2", "license": "MIT" }, - "packages/lib-sourcify/node_modules/vscode-oniguruma": { - "version": "1.7.0", - "dev": true, - "license": "MIT" - }, - "packages/lib-sourcify/node_modules/vscode-textmate": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, "packages/lib-sourcify/node_modules/vscode-uri": { "version": "3.0.7", "dev": true, @@ -44050,8 +44084,8 @@ "solc": "^0.8.17", "standard-version": "^9.5.0", "ts-node": "^10.9.1", - "typedoc": "^0.23.24", - "typescript": "^4.9.4", + "typedoc": "^0.24.6", + "typescript": "^5.0.4", "web3": "^1.8.1", "web3-utils": "^1.8.1" }, @@ -44153,6 +44187,15 @@ "resolve-from": "^5.0.0", "ts-node": "^10.8.1", "typescript": "^4.6.4" + }, + "dependencies": { + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "optional": true + } } }, "@commitlint/resolve-extends": { @@ -51887,10 +51930,6 @@ "json-stringify-safe": { "version": "5.0.1" }, - "jsonc-parser": { - "version": "3.2.0", - "dev": true - }, "jsonfile": { "version": "6.1.0", "dev": true, @@ -52073,10 +52112,6 @@ "lowercase-keys": { "version": "3.0.0" }, - "lunr": { - "version": "2.3.9", - "dev": true - }, "make-dir": { "version": "3.1.0", "dev": true, @@ -52098,10 +52133,6 @@ "version": "4.3.0", "dev": true }, - "marked": { - "version": "4.2.12", - "dev": true - }, "md5.js": { "version": "1.3.5", "requires": { @@ -53205,15 +53236,6 @@ "version": "3.0.0", "dev": true }, - "shiki": { - "version": "0.12.1", - "dev": true, - "requires": { - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" - } - }, "side-channel": { "version": "1.0.4", "requires": { @@ -53841,34 +53863,10 @@ "is-typedarray": "^1.0.0" } }, - "typedoc": { - "version": "0.23.24", - "dev": true, - "requires": { - "lunr": "^2.3.9", - "marked": "^4.2.5", - "minimatch": "^5.1.2", - "shiki": "^0.12.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.4", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, "typescript": { - "version": "4.9.4", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true }, "uglify-js": { @@ -53972,14 +53970,6 @@ } } }, - "vscode-oniguruma": { - "version": "1.7.0", - "dev": true - }, - "vscode-textmate": { - "version": "8.0.0", - "dev": true - }, "vscode-uri": { "version": "3.0.7", "dev": true @@ -57938,6 +57928,12 @@ "version": "5.0.1", "dev": true }, + "ansi-sequence-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", + "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "requires": { @@ -64125,6 +64121,12 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "jsonfile": { "version": "4.0.0", "requires": { @@ -64841,6 +64843,12 @@ "version": "2.2.1", "dev": true }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "macos-release": { "version": "2.5.0", "dev": true @@ -64900,6 +64908,12 @@ "object-visit": "^1.0.0" } }, + "marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true + }, "mcl-wasm": { "version": "0.7.9", "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", @@ -68430,6 +68444,18 @@ "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==", "dev": true }, + "shiki": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", + "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", + "dev": true, + "requires": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "side-channel": { "version": "1.0.4", "requires": { @@ -69723,6 +69749,38 @@ "is-typedarray": "^1.0.0" } }, + "typedoc": { + "version": "0.24.6", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.6.tgz", + "integrity": "sha512-c3y3h45xJv3qYwKDAwU6Cl+26CjT0ZvblHzfHJ+SjQDM4p1mZxtgHky4lhmG0+nNarRht8kADfZlbspJWdZarQ==", + "dev": true, + "requires": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "typescript": { "version": "4.9.4" }, @@ -70048,6 +70106,18 @@ "extsprintf": "^1.2.0" } }, + "vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "wcwidth": { "version": "1.0.1", "dev": true, diff --git a/package.json b/package.json index 9de768026..8b44745b6 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "@ethereum-sourcify/bytecode-utils": "*", "@ethereum-sourcify/lib-sourcify": "*", "@types/node-fetch": "^2.5.7", - "abitype": "^0.8.0", + "abitype": "0.8.0", "bunyan": "^1.8.12", "commander": "^9.0.0", "cors": "^2.8.5", diff --git a/packages/lib-sourcify/package-lock.json b/packages/lib-sourcify/package-lock.json index a74aed0fb..899cd82a2 100644 --- a/packages/lib-sourcify/package-lock.json +++ b/packages/lib-sourcify/package-lock.json @@ -16,6 +16,7 @@ "@ethereumjs/statemanager": "^1.0.4", "@ethereumjs/util": "^8.0.5", "@ethereumjs/vm": "^6.4.1", + "@ethersproject/abi": "^5.7.0", "@ethersproject/address": "^5.7.0", "@ethersproject/bignumber": "^5.7.0", "@ethersproject/bytes": "^5.7.0", @@ -55,8 +56,8 @@ "prettier": "^2.8.2", "standard-version": "^9.5.0", "ts-node": "^10.9.1", - "typedoc": "^0.23.24", - "typescript": "^4.9.4" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "engines": { "node": ">=10" @@ -611,6 +612,20 @@ "typescript": ">=3" } }, + "node_modules/@commitlint/load/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "optional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@commitlint/resolve-extends": { "version": "17.4.0", "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.4.0.tgz", @@ -2567,6 +2582,12 @@ "node": ">=8" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", + "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", + "dev": true + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9666,9 +9687,9 @@ } }, "node_modules/marked": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz", - "integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -12222,11 +12243,12 @@ } }, "node_modules/shiki": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.12.1.tgz", - "integrity": "sha512-aieaV1m349rZINEBkjxh2QbBvFFQOlgqYTNtCal82hHj4dDZ76oMlQIX+C7ryerBTDiga3e5NfH6smjdJ02BbQ==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", + "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", "dev": true, "dependencies": { + "ansi-sequence-parser": "^1.1.0", "jsonc-parser": "^3.2.0", "vscode-oniguruma": "^1.7.0", "vscode-textmate": "^8.0.0" @@ -13448,15 +13470,15 @@ } }, "node_modules/typedoc": { - "version": "0.23.24", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.24.tgz", - "integrity": "sha512-bfmy8lNQh+WrPYcJbtjQ6JEEsVl/ce1ZIXyXhyW+a1vFrjO39t6J8sL/d6FfAGrJTc7McCXgk9AanYBSNvLdIA==", + "version": "0.24.6", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.6.tgz", + "integrity": "sha512-c3y3h45xJv3qYwKDAwU6Cl+26CjT0ZvblHzfHJ+SjQDM4p1mZxtgHky4lhmG0+nNarRht8kADfZlbspJWdZarQ==", "dev": true, "dependencies": { "lunr": "^2.3.9", - "marked": "^4.2.5", - "minimatch": "^5.1.2", - "shiki": "^0.12.1" + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" }, "bin": { "typedoc": "bin/typedoc" @@ -13465,7 +13487,7 @@ "node": ">= 14.14" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x" } }, "node_modules/typedoc/node_modules/brace-expansion": { @@ -13478,27 +13500,30 @@ } }, "node_modules/typedoc/node_modules/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=12.20" } }, "node_modules/uglify-js": { @@ -14891,6 +14916,13 @@ "dev": true, "optional": true, "requires": {} + }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "optional": true } } }, @@ -16278,6 +16310,12 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, + "ansi-sequence-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", + "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -21705,9 +21743,9 @@ "dev": true }, "marked": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz", - "integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true }, "mcl-wasm": { @@ -23619,11 +23657,12 @@ "dev": true }, "shiki": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.12.1.tgz", - "integrity": "sha512-aieaV1m349rZINEBkjxh2QbBvFFQOlgqYTNtCal82hHj4dDZ76oMlQIX+C7ryerBTDiga3e5NfH6smjdJ02BbQ==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", + "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", "dev": true, "requires": { + "ansi-sequence-parser": "^1.1.0", "jsonc-parser": "^3.2.0", "vscode-oniguruma": "^1.7.0", "vscode-textmate": "^8.0.0" @@ -24531,15 +24570,15 @@ } }, "typedoc": { - "version": "0.23.24", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.24.tgz", - "integrity": "sha512-bfmy8lNQh+WrPYcJbtjQ6JEEsVl/ce1ZIXyXhyW+a1vFrjO39t6J8sL/d6FfAGrJTc7McCXgk9AanYBSNvLdIA==", + "version": "0.24.6", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.6.tgz", + "integrity": "sha512-c3y3h45xJv3qYwKDAwU6Cl+26CjT0ZvblHzfHJ+SjQDM4p1mZxtgHky4lhmG0+nNarRht8kADfZlbspJWdZarQ==", "dev": true, "requires": { "lunr": "^2.3.9", - "marked": "^4.2.5", - "minimatch": "^5.1.2", - "shiki": "^0.12.1" + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" }, "dependencies": { "brace-expansion": { @@ -24552,9 +24591,9 @@ } }, "minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -24563,9 +24602,9 @@ } }, "typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==" }, "uglify-js": { "version": "3.17.4", diff --git a/packages/lib-sourcify/package.json b/packages/lib-sourcify/package.json index 942c8bb12..313afc332 100644 --- a/packages/lib-sourcify/package.json +++ b/packages/lib-sourcify/package.json @@ -49,6 +49,7 @@ "@ethereumjs/statemanager": "^1.0.4", "@ethereumjs/util": "^8.0.5", "@ethereumjs/vm": "^6.4.1", + "@ethersproject/abi": "^5.7.0", "@ethersproject/address": "^5.7.0", "@ethersproject/bignumber": "^5.7.0", "@ethersproject/bytes": "^5.7.0", @@ -88,8 +89,8 @@ "prettier": "^2.8.2", "standard-version": "^9.5.0", "ts-node": "^10.9.1", - "typedoc": "^0.23.24", - "typescript": "^4.9.4" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "files": [ "build/main", diff --git a/packages/lib-sourcify/src/lib/verification.ts b/packages/lib-sourcify/src/lib/verification.ts index 8ff15b931..e012fd5d8 100644 --- a/packages/lib-sourcify/src/lib/verification.ts +++ b/packages/lib-sourcify/src/lib/verification.ts @@ -4,6 +4,7 @@ import { Create2Args, ImmutableReferences, Match, + Metadata, RecompilationResult, SourcifyChain, StringMap, @@ -27,6 +28,8 @@ import { hexZeroPad, isHexString } from '@ethersproject/bytes'; import { BigNumber } from '@ethersproject/bignumber'; import { getAddress, getContractAddress } from '@ethersproject/address'; import semverSatisfies from 'semver/functions/satisfies'; +import { defaultAbiCoder as abiCoder, ParamType } from '@ethersproject/abi'; +import { AbiConstructor } from 'abitype'; const RPC_TIMEOUT = 5000; @@ -44,6 +47,15 @@ export async function verifyDeployed( }; const recompiled = await checkedContract.recompile(); + if ( + recompiled.deployedBytecode === '0x' || + recompiled.creationBytecode === '0x' + ) { + throw new Error( + `The compiled contract bytecode is "0x". Are you trying to verify an abstract contract?` + ); + } + const deployedBytecode = await getBytecode(sourcifyChain, address); // Can't match if there is no deployed bytecode @@ -114,12 +126,14 @@ export async function verifyDeployed( // Try to match with creationTx, if available if (creatorTxHash) { + const recompiledMetadata: Metadata = JSON.parse(recompiled.metadata); await matchWithCreationTx( match, recompiled.creationBytecode, sourcifyChain, address, - creatorTxHash + creatorTxHash, + recompiledMetadata ); if (isPerfectMatch(match)) { return match; @@ -134,7 +148,8 @@ export async function verifyDeployed( recompiled.creationBytecode, sourcifyChain, address, - creatorTxHash + creatorTxHash, + recompiledMetadata ); } ); @@ -237,6 +252,13 @@ export function matchWithDeployedBytecode( deployedBytecode: string, immutableReferences?: any ) { + // Check if is a library with call protection + // See https://docs.soliditylang.org/en/v0.8.19/contracts.html#call-protection-for-libraries + recompiledDeployedBytecode = checkCallProtectionAndReplaceAddress( + recompiledDeployedBytecode, + deployedBytecode + ); + // Replace the library placeholders in the recompiled bytecode with values from the deployed bytecode const { replaced, libraryMap } = addLibraryAddresses( recompiledDeployedBytecode, @@ -348,8 +370,15 @@ export async function matchWithCreationTx( recompiledCreationBytecode: string, sourcifyChain: SourcifyChain, address: string, - creatorTxHash: string + creatorTxHash: string, + recompiledMetadata: Metadata ) { + if (recompiledCreationBytecode === '0x') { + match.status = null; + match.message = `Failed to match with creation bytecode: recompiled contract's creation bytecode is empty`; + return; + } + const creatorTx = await getTx(creatorTxHash, sourcifyChain); const creatorTxData = creatorTx.input; @@ -380,6 +409,40 @@ export async function matchWithCreationTx( } if (match.status) { + const abiEncodedConstructorArguments = + extractAbiEncodedConstructorArguments( + creatorTxData, + recompiledCreationBytecode + ); + const constructorAbiParamInputs = ( + recompiledMetadata?.output?.abi?.find( + (param) => param.type === 'constructor' + ) as AbiConstructor + )?.inputs as ParamType[]; + if (abiEncodedConstructorArguments) { + if (!constructorAbiParamInputs) { + match.status = null; + match.message = `Failed to match with creation bytecode: constructor ABI Inputs are missing`; + return; + } + // abiCoder doesn't break if called with a wrong `abiEncodedConstructorArguments` + // so in order to successfuly check if the constructor arguments actually match + // we need to re-encode it and compare them + const decodeResult = abiCoder.decode( + constructorAbiParamInputs, + abiEncodedConstructorArguments + ); + const encodeResult = abiCoder.encode( + constructorAbiParamInputs, + decodeResult + ); + if (encodeResult !== abiEncodedConstructorArguments) { + match.status = null; + match.message = `Failed to match with creation bytecode: constructor arguments ABI decoding failed ${encodeResult} vs ${abiEncodedConstructorArguments}`; + return; + } + } + // we need to check if this contract creation tx actually yields the same contract address https://github.com/ethereum/sourcify/issues/887 const createdContractAddress = getContractAddress({ from: creatorTx.from, @@ -391,11 +454,7 @@ export async function matchWithCreationTx( return; } match.libraryMap = libraryMap; - const abiEncodedConstructorArguments = - extractAbiEncodedConstructorArguments( - creatorTxData, - recompiledCreationBytecode - ); + match.abiEncodedConstructorArguments = abiEncodedConstructorArguments; match.creatorTxHash = creatorTxHash; } @@ -506,6 +565,20 @@ export function addLibraryAddresses( }; } +export function checkCallProtectionAndReplaceAddress( + template: string, + real: string +): string { + const push20CodeOp = '73'; + const callProtection = `0x${push20CodeOp}${'00'.repeat(20)}`; + + if (template.startsWith(callProtection)) { + const replacedCallProtection = real.slice(0, 0 + callProtection.length); + return replacedCallProtection + template.substring(callProtection.length); + } + return template; +} + /** * Replaces the values of the immutable variables in the (onchain) deployed bytecode with zeros, so that the bytecode can be compared with the (offchain) recompiled bytecode. * Example immutableReferences: {"97":[{"length":32,"start":137}],"99":[{"length":32,"start":421}]} where 97 and 99 are the AST ids diff --git a/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/metadata.json b/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/metadata.json new file mode 100644 index 000000000..d434360de --- /dev/null +++ b/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/metadata.json @@ -0,0 +1,44 @@ +{ + "compiler": { + "version": "0.6.12+commit.27d51765" + }, + "language": "Solidity", + "output": { + "abi": [], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + }, + "settings": { + "compilationTarget": { + "sources/FFF.sol": "FFF" + }, + "evmVersion": "istanbul", + "libraries": {}, + "metadata": { + "bytecodeHash": "ipfs" + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "remappings": [] + }, + "sources": { + "sources/FFF.sol": { + "keccak256": "0x7ed3554b3f768ad3b3069d7fc8b1a08a24500507fc8a60eb11c726e37f3cd9a3", + "urls": [ + "bzz-raw://6d83c127e075a149ec14c6af579bc7b24955cdb7578ae7da2f253b7142d267cc", + "dweb:/ipfs/QmW6tdCTV7X5dd5LCKDWedbMmkurQTMi4ePx7LY3DNuLn7" + ] + } + }, + "version": 1 +} diff --git a/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/sources/FFF.sol b/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/sources/FFF.sol new file mode 100644 index 000000000..b12b1d274 --- /dev/null +++ b/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/sources/FFF.sol @@ -0,0 +1,6 @@ +pragma solidity 0.6.12; + +abstract contract FFF{ + constructor (uint256 a) public payable { + } +} \ No newline at end of file diff --git a/packages/lib-sourcify/test/sources/CallProtectionForLibraries/artifact.json b/packages/lib-sourcify/test/sources/CallProtectionForLibraries/artifact.json new file mode 100644 index 000000000..a14553168 --- /dev/null +++ b/packages/lib-sourcify/test/sources/CallProtectionForLibraries/artifact.json @@ -0,0 +1,4 @@ +{ + "abi": [], + "bytecode": "0x60bd610039600b82828239805160001a60731461002c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063fe073d11146038575b600080fd5b818015604357600080fd5b50604a604c565b005b60006057600182605b565b5050565b60ff8181168382160190811115608157634e487b7160e01b600052601160045260246000fd5b9291505056fea264697066735822122026efb28b74c882aa2f1f86cbe51d40fba727849fa6113630f5c12c98c1a9eb9b64736f6c63430008130033" +} diff --git a/packages/lib-sourcify/test/sources/CallProtectionForLibraries/metadata.json b/packages/lib-sourcify/test/sources/CallProtectionForLibraries/metadata.json new file mode 100644 index 000000000..2fb60e9be --- /dev/null +++ b/packages/lib-sourcify/test/sources/CallProtectionForLibraries/metadata.json @@ -0,0 +1,27 @@ +{ + "compiler": { "version": "0.8.19+commit.7dd6d404" }, + "language": "Solidity", + "output": { + "abi": [], + "devdoc": { "kind": "dev", "methods": {}, "version": 1 }, + "userdoc": { "kind": "user", "methods": {}, "version": 1 } + }, + "settings": { + "compilationTarget": { "Ballot.sol": "Ballot" }, + "evmVersion": "paris", + "libraries": {}, + "metadata": { "bytecodeHash": "ipfs" }, + "optimizer": { "enabled": true, "runs": 200 }, + "remappings": [] + }, + "sources": { + "Ballot.sol": { + "keccak256": "0x21d251aa06c7fcbb362bca4b1645ef4fbc3d0844f6774f4598588f9045fdfe97", + "urls": [ + "bzz-raw://7464b55b34107bd79040fa11eed489e2d20bde5e15b801e2ba144d7bd10bbeca", + "dweb:/ipfs/Qmbrd7Up3r6Q5JA9NMvZZawsJ5EuuoFfRuMBEjAYk7oDod" + ] + } + }, + "version": 1 +} diff --git a/packages/lib-sourcify/test/sources/CallProtectionForLibraries/sources/Ballot.sol b/packages/lib-sourcify/test/sources/CallProtectionForLibraries/sources/Ballot.sol new file mode 100644 index 000000000..8714a01b0 --- /dev/null +++ b/packages/lib-sourcify/test/sources/CallProtectionForLibraries/sources/Ballot.sol @@ -0,0 +1,7 @@ +pragma solidity 0.8.19; +library Ballot { + function giveRightToVote() public { + uint8 tempnumber = 0; + tempnumber += 1; + } +} \ No newline at end of file diff --git a/packages/lib-sourcify/test/sources/CallProtectionForLibrariesViaIR/artifact.json b/packages/lib-sourcify/test/sources/CallProtectionForLibrariesViaIR/artifact.json new file mode 100644 index 000000000..f7c1d4fb5 --- /dev/null +++ b/packages/lib-sourcify/test/sources/CallProtectionForLibrariesViaIR/artifact.json @@ -0,0 +1,4 @@ +{ + "abi": [], + "bytecode": "0x60808060405234601a57608d90816100208239308160240152f35b600080fdfe6004361015600c57600080fd5b6000803560e01c63fe073d1114602157600080fd5b307f0000000000000000000000000000000000000000000000000000000000000000146054578060031936011260545780f35b80fdfea26469706673582212201104b959cf92e8eead2cb6513fe1d88ee97c7b264a0dea0bd7ccaffd488db72764736f6c63430008130033" +} diff --git a/packages/lib-sourcify/test/sources/CallProtectionForLibrariesViaIR/metadata.json b/packages/lib-sourcify/test/sources/CallProtectionForLibrariesViaIR/metadata.json new file mode 100644 index 000000000..14d67f26e --- /dev/null +++ b/packages/lib-sourcify/test/sources/CallProtectionForLibrariesViaIR/metadata.json @@ -0,0 +1,28 @@ +{ + "compiler": { "version": "0.8.19+commit.7dd6d404" }, + "language": "Solidity", + "output": { + "abi": [], + "devdoc": { "kind": "dev", "methods": {}, "version": 1 }, + "userdoc": { "kind": "user", "methods": {}, "version": 1 } + }, + "settings": { + "compilationTarget": { "Ballot.sol": "Ballot" }, + "evmVersion": "paris", + "libraries": {}, + "metadata": { "bytecodeHash": "ipfs" }, + "optimizer": { "enabled": true, "runs": 200 }, + "remappings": [], + "viaIR": true + }, + "sources": { + "Ballot.sol": { + "keccak256": "0x21d251aa06c7fcbb362bca4b1645ef4fbc3d0844f6774f4598588f9045fdfe97", + "urls": [ + "bzz-raw://7464b55b34107bd79040fa11eed489e2d20bde5e15b801e2ba144d7bd10bbeca", + "dweb:/ipfs/Qmbrd7Up3r6Q5JA9NMvZZawsJ5EuuoFfRuMBEjAYk7oDod" + ] + } + }, + "version": 1 +} diff --git a/packages/lib-sourcify/test/sources/CallProtectionForLibrariesViaIR/sources/Ballot.sol b/packages/lib-sourcify/test/sources/CallProtectionForLibrariesViaIR/sources/Ballot.sol new file mode 100644 index 000000000..8714a01b0 --- /dev/null +++ b/packages/lib-sourcify/test/sources/CallProtectionForLibrariesViaIR/sources/Ballot.sol @@ -0,0 +1,7 @@ +pragma solidity 0.8.19; +library Ballot { + function giveRightToVote() public { + uint8 tempnumber = 0; + tempnumber += 1; + } +} \ No newline at end of file diff --git a/packages/lib-sourcify/test/sources/WithImmutablesCreationBytecodeAttack/artifact.json b/packages/lib-sourcify/test/sources/WithImmutablesCreationBytecodeAttack/artifact.json new file mode 100644 index 000000000..56fc11e2e --- /dev/null +++ b/packages/lib-sourcify/test/sources/WithImmutablesCreationBytecodeAttack/artifact.json @@ -0,0 +1,4 @@ +{ + "bytecode": "60a060405234801561001057600080fd5b506040516103ca0000000000000000000000000000000000000000000000000000000000000001", + "abi": [] +} diff --git a/packages/lib-sourcify/test/sources/WithImmutablesCreationBytecodeAttack/metadata.json b/packages/lib-sourcify/test/sources/WithImmutablesCreationBytecodeAttack/metadata.json new file mode 100644 index 000000000..06a0ba48c --- /dev/null +++ b/packages/lib-sourcify/test/sources/WithImmutablesCreationBytecodeAttack/metadata.json @@ -0,0 +1,44 @@ +{ + "compiler": { + "version": "0.8.19+commit.7dd6d404" + }, + "language": "Solidity", + "output": { + "abi": [], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + }, + "settings": { + "compilationTarget": { + "sources/WithImmutables.sol": "WithImmutables" + }, + "evmVersion": "paris", + "libraries": {}, + "metadata": { + "bytecodeHash": "ipfs" + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "remappings": [] + }, + "sources": { + "sources/WithImmutables.sol": { + "keccak256": "0xa67bac14ebd5956d06bd0f33e2ffd55db729d4ec85bca19ec5b321e6be0b7cc8", + "urls": [ + "bzz-raw://6d83c127e075a149ec14c6af579bc7b24955cdb7578ae7da2f253b7142d267cc", + "dweb:/ipfs/QmW6tdCTV7X5dd5LCKDWedbMmkurQTMi4ePx7LY3DNuLn7" + ] + } + }, + "version": 1 +} diff --git a/packages/lib-sourcify/test/sources/WithImmutablesCreationBytecodeAttack/sources/WithImmutables.sol b/packages/lib-sourcify/test/sources/WithImmutablesCreationBytecodeAttack/sources/WithImmutables.sol new file mode 100644 index 000000000..4f90eb28e --- /dev/null +++ b/packages/lib-sourcify/test/sources/WithImmutablesCreationBytecodeAttack/sources/WithImmutables.sol @@ -0,0 +1,6 @@ +pragma solidity >=0.7.0; + +contract WithImmutables{ + constructor (uint256 a) { + } +} \ No newline at end of file diff --git a/packages/lib-sourcify/test/verification.spec.ts b/packages/lib-sourcify/test/verification.spec.ts index 8a3675638..821bed1bf 100644 --- a/packages/lib-sourcify/test/verification.spec.ts +++ b/packages/lib-sourcify/test/verification.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import path from 'path'; -import { SourcifyChain } from '../src/lib/types'; +import { Metadata, SourcifyChain } from '../src/lib/types'; import Web3 from 'web3'; import Ganache from 'ganache'; import { @@ -398,6 +398,46 @@ describe('lib-sourcify tests', () => { ); expectMatch(match, 'perfect', deployedAddress); }); + + it('should fully verify a library with call protection when viaIR is disabled (legacy compilation placeholder: 0x73 plus 20 zero bytes)', async () => { + const contractFolderPath = path.join( + __dirname, + 'sources', + 'CallProtectionForLibraries' + ); + const [deployedAddress] = await deployFromAbiAndBytecode( + localWeb3Provider, + contractFolderPath, + accounts[0] + ); + + const match = await checkAndVerifyDeployed( + contractFolderPath, + sourcifyChainGanache, + deployedAddress + ); + expectMatch(match, 'perfect', deployedAddress); + }); + + it('should fully verify a library with call protection when viaIR is enabled', async () => { + const contractFolderPath = path.join( + __dirname, + 'sources', + 'CallProtectionForLibrariesViaIR' + ); + const [deployedAddress] = await deployFromAbiAndBytecode( + localWeb3Provider, + contractFolderPath, + accounts[0] + ); + + const match = await checkAndVerifyDeployed( + contractFolderPath, + sourcifyChainGanache, + deployedAddress + ); + expectMatch(match, 'perfect', deployedAddress); + }); }); describe('Unit tests', function () { @@ -524,14 +564,138 @@ describe('lib-sourcify tests', () => { chainId: sourcifyChainGanache.chainId.toString(), status: null, }; + const recompiledMetadata: Metadata = JSON.parse(recompiled.metadata); + await matchWithCreationTx( + match, + recompiled.creationBytecode, + sourcifyChainGanache, + deployedAddress, + wrongCreatorTxHash, + recompiledMetadata + ); + expectMatch(match, null, deployedAddress, undefined); // status is null + }); + + it('should fail to matchWithCreationTx with creatorTxHash having wrong constructor arguments', async () => { + const contractFolderPath = path.join( + __dirname, + 'sources', + 'WithImmutables' + ); + const maliciousContractFolderPath = path.join( + __dirname, + 'sources', + 'WithImmutablesCreationBytecodeAttack' + ); + + const [deployedAddress, wrongCreatorTxHash] = + await deployFromAbiAndBytecode( + localWeb3Provider, + contractFolderPath, + accounts[0], + ['12345'] + ); + const [,] = await deployFromAbiAndBytecode( + localWeb3Provider, + maliciousContractFolderPath, + accounts[0], + ['12345'] + ); + + const checkedContracts = await checkFilesFromContractFolder( + maliciousContractFolderPath + ); + const recompiled = await checkedContracts[0].recompile(); + const match = { + address: deployedAddress, + chainId: sourcifyChainGanache.chainId.toString(), + status: null, + }; + const recompiledMetadata: Metadata = JSON.parse(recompiled.metadata); + await matchWithCreationTx( + match, + '0x60a060405234801561001057600080fd5b506040516103ca', // I force recompiled.creationBytecode because it would take time to generate the right attack, + sourcifyChainGanache, + deployedAddress, + wrongCreatorTxHash, + recompiledMetadata + ); + expectMatch(match, null, deployedAddress, undefined); // status is null + }); + + it('should fail to matchWithCreationTx when passing an abstract contract', async () => { + const contractFolderPath = path.join( + __dirname, + 'sources', + 'WithImmutables' + ); + + const [deployedAddress, creatorTxHash] = await deployFromAbiAndBytecode( + localWeb3Provider, + contractFolderPath, + accounts[0], + ['12345'] + ); + + const maliciousContractFolderPath = path.join( + __dirname, + 'sources', + 'AbstractCreationBytecodeAttack' + ); + const checkedContracts = await checkFilesFromContractFolder( + maliciousContractFolderPath + ); + const recompiled = await checkedContracts[0].recompile(); + const match = { + address: deployedAddress, + chainId: sourcifyChainGanache.chainId.toString(), + status: null, + }; + const recompiledMetadata: Metadata = JSON.parse(recompiled.metadata); + await matchWithCreationTx( match, recompiled.creationBytecode, sourcifyChainGanache, deployedAddress, - wrongCreatorTxHash + creatorTxHash, + recompiledMetadata ); expectMatch(match, null, deployedAddress, undefined); // status is null }); + + it('should successfuly verify with matchWithCreationTx with creationTxHash', async () => { + const contractFolderPath = path.join( + __dirname, + 'sources', + 'WithImmutables' + ); + const [deployedAddress, creatorTxHash] = await deployFromAbiAndBytecode( + localWeb3Provider, + contractFolderPath, + accounts[0], + ['12345'] + ); + + const checkedContracts = await checkFilesFromContractFolder( + contractFolderPath + ); + const recompiled = await checkedContracts[0].recompile(); + const match = { + address: deployedAddress, + chainId: sourcifyChainGanache.chainId.toString(), + status: null, + }; + const recompiledMetadata: Metadata = JSON.parse(recompiled.metadata); + await matchWithCreationTx( + match, + recompiled.creationBytecode, + sourcifyChainGanache, + deployedAddress, + creatorTxHash, + recompiledMetadata + ); + expectMatch(match, 'perfect', deployedAddress, undefined); // status is null + }); }); }); diff --git a/scripts/find_replace.sh b/scripts/find_replace.sh index 7d5d76f00..a859276ad 100755 --- a/scripts/find_replace.sh +++ b/scripts/find_replace.sh @@ -38,7 +38,7 @@ if [ "$CIRCLE_BRANCH" == "staging" ]; then MOONSCAN_MOONRIVER_API_KEY=$MOONSCAN_MOONRIVER_API_KEY_STAGING BOBASCAN_API_KEY=$BOBASCAN_API_KEY_STAGING GNOSISSCAN_API_KEY=$GNOSISSCAN_API_KEY_STAGING - OPTIMISTIC_ETHERSCAN_API_KEY=$OPTIMISTIC_ETHERSCAN_API_KEY_STAGING + OPTIMISMSCAN_API_KEY=$OPTIMISMSCAN_API_KEY_STAGING fi if [ "$CIRCLE_BRANCH" == "master" ]; then @@ -68,14 +68,15 @@ if [ "$CIRCLE_BRANCH" == "master" ]; then MOONSCAN_MOONRIVER_API_KEY=$MOONSCAN_MOONRIVER_API_KEY_MASTER BOBASCAN_API_KEY=$BOBASCAN_API_KEY_MASTER GNOSISSCAN_API_KEY=$GNOSISSCAN_API_KEY_MASTER - OPTIMISTIC_ETHERSCAN_API_KEY=$OPTIMISTIC_ETHERSCAN_API_KEY_MASTER + OPTIMISMSCAN_API_KEY=$OPTIMISMSCAN_API_KEY_MASTER fi -for VAR_NAME in INFURA_ID ALCHEMY_ID AWS_S3_ACCESS_KEY_ID AWS_S3_SECRET_ACCESS_KEY IPFS_SECRET NPM_TOKEN PUBLIC_IP LOCAL_IP SESSION_SECRET ALCHEMY_ID_OPTIMISM ALCHEMY_ID_ARBITRUM CHAINSAFE_S3_ACCESS_KEY_ID CHAINSAFE_S3_SECRET_ACCESS_KEY ESTUARY_PINNING_SECRET WEB3_STORAGE_PINNING_SECRET CREATE2_CLIENT_TOKENS GRAFANA_HTTP_USER GRAFANA_HTTP_PASS ETHERSCAN_API_KEY ARBISCAN_API_KEY POLYGONSCAN_API_KEY BSCSCAN_API_KEY SNOWTRACE_API_KEY CELOSCAN_API_KEY MOONSCAN_MOONBEAM_API_KEY MOONSCAN_MOONRIVER_API_KEY BOBASCAN_API_KEY GNOSISSCAN_API_KEY OPTIMISTIC_ETHERSCAN_API_KEY +for VAR_NAME in INFURA_ID ALCHEMY_ID AWS_S3_ACCESS_KEY_ID AWS_S3_SECRET_ACCESS_KEY IPFS_SECRET NPM_TOKEN PUBLIC_IP LOCAL_IP SESSION_SECRET ALCHEMY_ID_OPTIMISM ALCHEMY_ID_ARBITRUM CHAINSAFE_S3_ACCESS_KEY_ID CHAINSAFE_S3_SECRET_ACCESS_KEY ESTUARY_PINNING_SECRET WEB3_STORAGE_PINNING_SECRET CREATE2_CLIENT_TOKENS GRAFANA_HTTP_USER GRAFANA_HTTP_PASS ETHERSCAN_API_KEY ARBISCAN_API_KEY POLYGONSCAN_API_KEY BSCSCAN_API_KEY SNOWTRACE_API_KEY CELOSCAN_API_KEY MOONSCAN_MOONBEAM_API_KEY MOONSCAN_MOONRIVER_API_KEY BOBASCAN_API_KEY GNOSISSCAN_API_KEY OPTIMISMSCAN_API_KEY do echo "find_repace.sh: replacing $VAR_NAME" VAR_VAL=$(eval "echo \${$VAR_NAME}") # Use @ as delimiter instead of / as values may contain / but @ is unlikely + # sed on MacOS has different syntax. Install "gsed" with brew install gnu-sed and replace when developing on MacOS sed -i "s@${VAR_NAME}=xxx@${VAR_NAME}=${VAR_VAL}@g" ../environments/.env.$TAG done diff --git a/src/config.ts b/src/config.ts index abfa62bfe..9e4ac0cae 100644 --- a/src/config.ts +++ b/src/config.ts @@ -80,11 +80,11 @@ export const etherscanAPIs: EtherscanAPIs = { }, "10": { apiURL: "https://api-optimistic.etherscan.io", - apiKey: process.env.OPTIMISTIC_ETHERSCAN_API_KEY, + apiKey: process.env.OPTIMISMSCAN_API_KEY, }, "420": { apiURL: "https://api-goerli-optimism.etherscan.io", - apiKey: process.env.OPTIMISTIC_ETHERSCAN_API_KEY, + apiKey: process.env.OPTIMISMSCAN_API_KEY, }, "43114": { apiURL: "https://api.snowtrace.io", diff --git a/src/server/controllers/VerificationController-util.ts b/src/server/controllers/VerificationController-util.ts index e9a63aad9..b4411c488 100644 --- a/src/server/controllers/VerificationController-util.ts +++ b/src/server/controllers/VerificationController-util.ts @@ -567,6 +567,12 @@ export const processRequestFromEtherscan = async ( ) { throw new BadRequestError("Etherscan API rate limit reached, try later"); } + + if (resultJson.message === "NOTOK") { + throw new BadRequestError( + "Error in Etherscan API response. Result message: " + resultJson.message + ); + } if (resultJson.result[0].SourceCode === "") { throw new BadRequestError("This contract is not verified on Etherscan"); } diff --git a/src/server/services/RepositoryService.ts b/src/server/services/RepositoryService.ts index 34628f113..0ef87d004 100644 --- a/src/server/services/RepositoryService.ts +++ b/src/server/services/RepositoryService.ts @@ -6,7 +6,6 @@ import { Status, Create2Args, StringMap, - Metadata, /* ContextVariables, */ CheckedContract, } from "@ethereum-sourcify/lib-sourcify"; @@ -631,8 +630,22 @@ export default class RepositoryService implements IRepositoryService { } // This needs to be removed at some point https://github.com/ethereum/sourcify/issues/515 private sanitizePath(originalPath: string): string { - return originalPath + const parsedPath = path.parse(originalPath); + const sanitizedDir = parsedPath.dir + .split(path.sep) + .filter((segment) => segment !== "..") + .join(path.sep) .replace(/[^a-z0-9_./-]/gim, "_") .replace(/(^|\/)[.]+($|\/)/, "_"); + + // Force absolute paths to be relative + if (parsedPath.root) { + parsedPath.root = ""; + parsedPath.dir = sanitizedDir.slice(parsedPath.root.length); + } else { + parsedPath.dir = sanitizedDir; + } + + return path.format(parsedPath); } } diff --git a/src/sourcify-chains.ts b/src/sourcify-chains.ts index 821167f2b..e94dcb654 100644 --- a/src/sourcify-chains.ts +++ b/src/sourcify-chains.ts @@ -196,6 +196,12 @@ const sourcifyChainsExtensions: SourcifyChainsExtensionsObject = { "https://blockscout.com/xdai/mainnet/" + BLOCKSCOUT_SUFFIX, txRegex: getBlockscoutRegex("/xdai/mainnet"), }, + "295": { + // Hedera Mainnet + supported: true, + monitored: false, + contractFetchAddress: "https://hashscan.io/mainnet/" + ETHERSCAN_SUFFIX, + }, "300": { supported: true, monitored: false, @@ -561,6 +567,13 @@ const sourcifyChainsExtensions: SourcifyChainsExtensionsObject = { contractFetchAddress: "https://tuber.build/" + BLOCKSCOUT_SUFFIX, txRegex: getBlockscoutRegex(), }, + "7701": { + // Canto Testnet + supported: true, + monitored: false, + contractFetchAddress: "https://testnet.tuber.build/" + BLOCKSCOUT_SUFFIX, + txRegex: getBlockscoutRegex(), + }, "99": { // POA Network Core supported: true, diff --git a/test/chains/chain-tests.js b/test/chains/chain-tests.js index 58e4909c1..34b1e7d4a 100644 --- a/test/chains/chain-tests.js +++ b/test/chains/chain-tests.js @@ -1071,7 +1071,23 @@ describe("Test Supported Chains", function () { ["shared/WithImmutables.sol"], "shared/withImmutables.metadata.json" ); - + // Canto Testnet + verifyContract( + "0x37e12c98b4663DcE9ab1460073D9Fe82A7bFD0d8", + "7701", + "Canto Testnet", + ["shared/1_Storage.sol"], + "shared/1_Storage.metadata.json" + ); + verifyContractWithImmutables( + "0x652785B4512F7e664448708852e59eF256D3f478", + "7701", + "Canto Testnet", + ["uint256"], + [7700], + ["shared/WithImmutables.sol"], + "shared/withImmutables.metadata.json" + ); // POA Network Core verifyContract( "0x3b2e3383AeE77A58f252aFB3635bCBd842BaeCB3", @@ -1444,6 +1460,24 @@ describe("Test Supported Chains", function () { "shared/withImmutables.metadata.json" ); + // Hedera Mainnet + verifyContract( + "0x00000000000000000000000000000000002265bb", + "295", + "Hedera Mainnet", + ["shared/1_Storage.sol"], + "shared/1_Storage.metadata.json" + ); + verifyContractWithImmutables( + "0x00000000000000000000000000000000002265dd", + "295", + "Hedera Mainnet", + ["uint256"], + [42], + ["shared/WithImmutables.sol"], + "shared/withImmutables.metadata.json" + ); + ////////////////////// // Helper functions // ////////////////////// diff --git a/test/server.js b/test/server.js index 6b211554d..bce28a0ca 100644 --- a/test/server.js +++ b/test/server.js @@ -890,6 +890,60 @@ describe("Server", function () { ); }); }); + + it("should store a contract in /contracts/full_match|partial_match/0xADDRESS despite the files paths in the metadata", async () => { + const artifact = require("./testcontracts/Storage/Storage.json"); + const [address] = await deployFromAbiAndBytecodeForCreatorTxHash( + localWeb3Provider, + artifact.abi, + artifact.bytecode, + accounts[0], + [] + ); + + const metadata = require("./testcontracts/Storage/metadata.upMultipleDirs.json"); + const sourcePath = path.join( + "test", + "testcontracts", + "Storage", + "Storage.sol" + ); + const sourceBuffer = fs.readFileSync(sourcePath); + + // Now pass the creatorTxHash + const res = await chai + .request(server.app) + .post("/") + .send({ + address: address, + chain: defaultContractChain, + files: { + "metadata.json": JSON.stringify(metadata), + "Storage.sol": sourceBuffer.toString(), + }, + }); + assertVerification( + null, + res, + null, + address, + defaultContractChain, + "partial" + ); + const isExist = fs.existsSync( + path.join( + server.repository, + "contracts", + "partial_match", + defaultContractChain, + address, + "sources", + "..contracts", + "Storage.sol" + ) + ); + chai.expect(isExist, "Files saved in the wrong directory").to.be.true; + }); }); describe("solc v0.6.12 and v0.7.0 extra files in compilation causing metadata match but bytecode mismatch", function () { diff --git a/test/testcontracts/Storage/metadata.upMultipleDirs.json b/test/testcontracts/Storage/metadata.upMultipleDirs.json new file mode 100644 index 000000000..e51b7ceac --- /dev/null +++ b/test/testcontracts/Storage/metadata.upMultipleDirs.json @@ -0,0 +1,64 @@ +{ + "compiler": { "version": "0.8.4+commit.c7e474f2" }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [], + "name": "retrieve", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "num", "type": "uint256" } + ], + "name": "store", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "devdoc": { + "details": "Store & retrieve value in a variable", + "kind": "dev", + "methods": { + "retrieve()": { + "details": "Return value ", + "returns": { "_0": "value of 'number'" } + }, + "store(uint256)": { + "details": "Store value in variable", + "params": { "num": "value to store" } + } + }, + "title": "Storage", + "version": 1 + }, + "userdoc": { "kind": "user", "methods": {}, "version": 1 } + }, + "settings": { + "compilationTarget": { + "..contracts/../../../../../Storage.sol": "Storage" + }, + "evmVersion": "istanbul", + "libraries": {}, + "metadata": { "bytecodeHash": "ipfs" }, + "optimizer": { "enabled": false, "runs": 200 }, + "remappings": [] + }, + "sources": { + "..contracts/../../../../../Storage.sol": { + "keccak256": "0x88c47206b5ec3d60ab820e9d126c4ac54cb17fa7396ff49ebe27db2862982ad8", + "license": "GPL-3.0", + "urls": [ + "bzz-raw://5d1eeb01c8c10bed9e290f4a80a8d4081422a7b298a13049d72867022522cf6b", + "dweb:/ipfs/QmaFRC9ZtT7y3t9XNWCbDuMTEwKkyaQJzYFzw3NbeohSn5" + ] + } + }, + "version": 1 +} diff --git a/ui/src/pages/Lookup/Result.tsx b/ui/src/pages/Lookup/Result.tsx index ce2c66ab7..df1b5e08c 100644 --- a/ui/src/pages/Lookup/Result.tsx +++ b/ui/src/pages/Lookup/Result.tsx @@ -49,9 +49,11 @@ type NetworkRowProp = { }; type FoundProp = { response: CheckAllByAddressResult; + goBack: () => void; }; type NotFoundProp = { address: any; + goBack: () => void; }; type MatchStatusProps = { @@ -268,7 +270,7 @@ const Create2Info = (response: CheckAllByAddressResult) => { ); }; -const Found = ({ response }: FoundProp) => { +const Found = ({ response, goBack }: FoundProp) => { const chains = response?.chainIds.filter((chain) => chain.chainId !== "0"); const isCreate2Verified = response?.chainIds.findIndex((chain) => chain.chainId === "0") >= 0; @@ -293,13 +295,22 @@ const Found = ({ response }: FoundProp) => { {isCreate2Verified && <>create2} verified - ,{" "} - - view in Sourcify Repository - + {isCreate2Verified && ( + <> + ,{" "} + + view in Sourcify Repository + + + )}

{isCreate2Verified && Create2Info(response)}

{chains.length > 0 && on the following networks:}

@@ -325,12 +336,15 @@ const Found = ({ response }: FoundProp) => { + ); }; -const NotFound = ({ address }: NotFoundProp) => { +const NotFound = ({ address, goBack }: NotFoundProp) => { return ( <>
@@ -344,6 +358,9 @@ const NotFound = ({ address }: NotFoundProp) => { +
); @@ -366,9 +383,9 @@ const Result = ({ response, goBack }: ResultProp) => {
{verificationIcon(response?.status)} {!!response && response?.status !== "false" ? ( - + ) : ( - + )}
diff --git a/ui/src/pages/Lookup/index.tsx b/ui/src/pages/Lookup/index.tsx index f36c4841d..e7c9d040d 100644 --- a/ui/src/pages/Lookup/index.tsx +++ b/ui/src/pages/Lookup/index.tsx @@ -45,7 +45,7 @@ const Lookup = () => { } }; - const goBack = async () => { + const goBack = () => { setResponse(undefined); navigate(`/lookup`); };