diff --git a/apps/contract-verification/.babelrc b/apps/contract-verification/.babelrc new file mode 100644 index 0000000000..e37036ce66 --- /dev/null +++ b/apps/contract-verification/.babelrc @@ -0,0 +1,9 @@ +{ + "presets": ["@babel/preset-env", ["@babel/preset-react", + {"runtime": "automatic"} + ]], + "plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime", "@babel/plugin-proposal-nullish-coalescing-operator"], + "ignore": [ + "**/node_modules/**" + ] +} \ No newline at end of file diff --git a/apps/contract-verification/.browserslistrc b/apps/contract-verification/.browserslistrc new file mode 100644 index 0000000000..f1d12df4fa --- /dev/null +++ b/apps/contract-verification/.browserslistrc @@ -0,0 +1,16 @@ +# This file is used by: +# 1. autoprefixer to adjust CSS to support the below specified browsers +# 2. babel preset-env to adjust included polyfills +# +# For additional information regarding the format and rule options, please see: +# https://github.com/browserslist/browserslist#queries +# +# If you need to support different browsers in production, you may tweak the list below. + +last 1 Chrome version +last 1 Firefox version +last 2 Edge major versions +last 2 Safari major version +last 2 iOS major versions +Firefox ESR +not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file diff --git a/apps/contract-verification/.eslintrc b/apps/contract-verification/.eslintrc new file mode 100644 index 0000000000..2d85f9fa66 --- /dev/null +++ b/apps/contract-verification/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "../../.eslintrc.json", +} \ No newline at end of file diff --git a/apps/contract-verification/.eslintrc.json b/apps/contract-verification/.eslintrc.json new file mode 100644 index 0000000000..a92d0f887a --- /dev/null +++ b/apps/contract-verification/.eslintrc.json @@ -0,0 +1,34 @@ +{ + "extends": [ + "plugin:@nrwl/nx/react", + "../../.eslintrc.json" + ], + "ignorePatterns": [ + "!**/*" + ], + "overrides": [ + { + "files": [ + "*.ts", + "*.tsx", + "*.js", + "*.jsx" + ], + "rules": {} + }, + { + "files": [ + "*.ts", + "*.tsx" + ], + "rules": {} + }, + { + "files": [ + "*.js", + "*.jsx" + ], + "rules": {} + } + ] +} \ No newline at end of file diff --git a/apps/contract-verification/project.json b/apps/contract-verification/project.json new file mode 100644 index 0000000000..dee28fe326 --- /dev/null +++ b/apps/contract-verification/project.json @@ -0,0 +1,69 @@ +{ + "name": "contract-verification", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/contract-verification/src", + "projectType": "application", + "targets": { + "build": { + "executor": "@nrwl/webpack:webpack", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "development", + "options": { + "compiler": "babel", + "outputPath": "dist/apps/contract-verification", + "index": "apps/contract-verification/src/index.html", + "baseHref": "./", + "main": "apps/contract-verification/src/main.tsx", + "polyfills": "apps/contract-verification/src/polyfills.ts", + "tsConfig": "apps/contract-verification/tsconfig.app.json", + "assets": [ + "apps/contract-verification/src/favicon.ico", + "apps/contract-verification/src/assets", + "apps/contract-verification/src/profile.json" + ], + "styles": ["apps/contract-verification/src/styles.css"], + "scripts": [], + "webpackConfig": "apps/contract-verification/webpack.config.js" + }, + "configurations": { + "development": { + }, + "production": { + "fileReplacements": [ + { + "replace": "apps/contract-verification/src/environments/environment.ts", + "with": "apps/contract-verification/src/environments/environment.prod.ts" + } + ] + } + } + }, + "lint": { + "executor": "@nrwl/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["apps/contract-verification/**/*.ts"], + "eslintConfig": "apps/contract-verification/.eslintrc" + } + }, + "serve": { + "executor": "@nrwl/webpack:dev-server", + "defaultConfiguration": "development", + "options": { + "buildTarget": "contract-verification:build", + "hmr": true, + "baseHref": "/" + }, + "configurations": { + "development": { + "buildTarget": "contract-verification:build:development", + "port": 5003 + }, + "production": { + "buildTarget": "contract-verification:build:production" + } + } + } + }, + "tags": [] +} diff --git a/apps/contract-verification/src/app/App.css b/apps/contract-verification/src/app/App.css new file mode 100644 index 0000000000..74a89ee342 --- /dev/null +++ b/apps/contract-verification/src/app/App.css @@ -0,0 +1,7 @@ +body { + margin: 0; +} + +#root { + padding: 8px 14px; +} \ No newline at end of file diff --git a/apps/contract-verification/src/app/AppContext.tsx b/apps/contract-verification/src/app/AppContext.tsx new file mode 100644 index 0000000000..69d967534d --- /dev/null +++ b/apps/contract-verification/src/app/AppContext.tsx @@ -0,0 +1,25 @@ +import React from 'react' +import {PluginClient} from '@remixproject/plugin' + +import {Receipt, ThemeType} from './types' + +export const AppContext = React.createContext({ + apiKey: '', + setAPIKey: (value: string) => { + console.log('Set API Key from Context') + }, + clientInstance: {} as PluginClient, + receipts: [] as Receipt[], + setReceipts: (receipts: Receipt[]) => { + console.log('Calling Set Receipts') + }, + contracts: [] as string[], + setContracts: (contracts: string[]) => { + console.log('Calling Set Contract Names') + }, + themeType: 'dark' as ThemeType, + setThemeType: (themeType: ThemeType) => { + console.log('Calling Set Theme Type') + }, + networkName: '' +}) diff --git a/apps/contract-verification/src/app/EtherscanPluginClient.ts b/apps/contract-verification/src/app/EtherscanPluginClient.ts new file mode 100644 index 0000000000..3d1bf22d94 --- /dev/null +++ b/apps/contract-verification/src/app/EtherscanPluginClient.ts @@ -0,0 +1,70 @@ +import { PluginClient } from '@remixproject/plugin' +import { createClient } from '@remixproject/plugin-webview' +import { verify, EtherScanReturn } from './utils/verify' +import { getReceiptStatus, getEtherScanApi, getNetworkName, getProxyContractReceiptStatus } from './utils' +import EventManager from 'events' + +export class EtherscanPluginClient extends PluginClient { + public internalEvents: EventManager + + constructor() { + super() + this.internalEvents = new EventManager() + createClient(this) + this.onload() + } + + onActivation(): void { + this.internalEvents.emit('etherscan_activated') + } + + async verify( + apiKey: string, + contractAddress: string, + contractArguments: string, + contractName: string, + compilationResultParam: any, + chainRef?: number | string, + isProxyContract?: boolean, + expectedImplAddress?: string + ) { + const result = await verify( + apiKey, + contractAddress, + contractArguments, + contractName, + compilationResultParam, + chainRef, + isProxyContract, + expectedImplAddress, + this, + (value: EtherScanReturn) => {}, + (value: string) => {} + ) + return result + } + + async receiptStatus(receiptGuid: string, apiKey: string, isProxyContract: boolean) { + try { + const { network, networkId } = await getNetworkName(this) + if (network === 'vm') { + throw new Error('Cannot check the receipt status in the selected network') + } + const etherscanApi = getEtherScanApi(networkId) + let receiptStatus + + if (isProxyContract) receiptStatus = await getProxyContractReceiptStatus(receiptGuid, apiKey, etherscanApi) + else receiptStatus = await getReceiptStatus(receiptGuid, apiKey, etherscanApi) + return { + message: receiptStatus.result, + succeed: receiptStatus.status === '0' ? false : true + } + } catch (e: any) { + return { + status: 'error', + message: e.message, + succeed: false + } + } + } +} diff --git a/apps/contract-verification/src/app/app.tsx b/apps/contract-verification/src/app/app.tsx new file mode 100644 index 0000000000..bf553d8319 --- /dev/null +++ b/apps/contract-verification/src/app/app.tsx @@ -0,0 +1,136 @@ +import React, {useState, useEffect, useRef} from 'react' + +import {CompilationFileSources, CompilationResult} from '@remixproject/plugin-api' + +import { EtherscanPluginClient } from './EtherscanPluginClient' + +import {AppContext} from './AppContext' +import {DisplayRoutes} from './routes' + +import {useLocalStorage} from './hooks/useLocalStorage' + +import {getReceiptStatus, getEtherScanApi, getNetworkName, getProxyContractReceiptStatus} from './utils' +import {Receipt, ThemeType} from './types' + +import './App.css' + +export const getNewContractNames = (compilationResult: CompilationResult) => { + const compiledContracts = compilationResult.contracts + let result: string[] = [] + + for (const file of Object.keys(compiledContracts)) { + const newContractNames = Object.keys(compiledContracts[file]) + + result = [...result, ...newContractNames] + } + + return result +} + +const plugin = new EtherscanPluginClient() + +const App = () => { + const [apiKey, setAPIKey] = useLocalStorage('apiKey', '') + const [receipts, setReceipts] = useLocalStorage('receipts', []) + const [contracts, setContracts] = useState([]) + const [themeType, setThemeType] = useState('dark') + const [networkName, setNetworkName] = useState('Loading...') + const timer = useRef(null) + const contractsRef = useRef(contracts) + + contractsRef.current = contracts + + const setListeners = () => { + plugin.on('solidity', 'compilationFinished', (fileName: string, source: CompilationFileSources, languageVersion: string, data: CompilationResult) => { + const newContractsNames = getNewContractNames(data) + + const newContractsToSave: string[] = [...contractsRef.current, ...newContractsNames] + + const uniqueContracts: string[] = [...new Set(newContractsToSave)] + + setContracts(uniqueContracts) + }) + plugin.on('blockchain' as any, 'networkStatus', (result) => { + setNetworkName(`${result.network.name} ${result.network.id !== '-' ? `(Chain id: ${result.network.id})` : '(Not supported)'}`) + }) + // @ts-ignore + plugin.call('blockchain', 'getCurrentNetworkStatus').then((result: any) => setNetworkName(`${result.network.name} ${result.network.id !== '-' ? `(Chain id: ${result.network.id})` : '(Not supported)'}`)) + + } + + useEffect(() => { + plugin.onload(() => { + setListeners() + }) + }, []) + + useEffect(() => { + let receiptsNotVerified: Receipt[] = receipts.filter((item: Receipt) => item.status === 'Pending in queue' || item.status === 'Max rate limit reached') + + if (receiptsNotVerified.length > 0) { + if (timer.current) { + clearInterval(timer.current) + timer.current = null + } + timer.current = setInterval(async () => { + const {network, networkId} = await getNetworkName(plugin) + + if (!plugin) return + if (network === 'vm') return + let newReceipts = receipts + + for (const item of receiptsNotVerified) { + await new Promise((r) => setTimeout(r, 500)) // avoid api rate limit exceed. + let status + if (item.isProxyContract) { + status = await getProxyContractReceiptStatus(item.guid, apiKey, getEtherScanApi(networkId)) + if (status.status === '1') { + status.message = status.result + status.result = 'Successfully Updated' + } + } else status = await getReceiptStatus(item.guid, apiKey, getEtherScanApi(networkId)) + if (status.result === 'Pass - Verified' || status.result === 'Already Verified' || status.result === 'Successfully Updated') { + newReceipts = newReceipts.map((currentReceipt: Receipt) => { + if (currentReceipt.guid === item.guid) { + const res = { + ...currentReceipt, + status: status.result + } + if (currentReceipt.isProxyContract) res.message = status.message + return res + } + return currentReceipt + }) + } + } + receiptsNotVerified = newReceipts.filter((item: Receipt) => item.status === 'Pending in queue' || item.status === 'Max rate limit reached') + if (timer.current && receiptsNotVerified.length === 0) { + clearInterval(timer.current) + timer.current = null + } + setReceipts(newReceipts) + }, 10000) + } + }, [receipts]) + + return ( + + { plugin && } + + ) +} + +export default App diff --git a/apps/contract-verification/src/app/components/HeaderWithSettings.tsx b/apps/contract-verification/src/app/components/HeaderWithSettings.tsx new file mode 100644 index 0000000000..5818b2bc7e --- /dev/null +++ b/apps/contract-verification/src/app/components/HeaderWithSettings.tsx @@ -0,0 +1,81 @@ +import React from 'react' + +import {NavLink} from 'react-router-dom' +import {CustomTooltip} from '@remix-ui/helper' +import {AppContext} from '../AppContext' + +interface Props { + title?: string + from: string +} + +interface IconProps { + from: string +} + +const HomeIcon = ({from}: IconProps) => { + return ( + (isActive ? 'border border-secondary shadow-none btn p-1 m-0' : 'border-0 shadow-none btn p-1 m-0')} + style={({isActive}) => (!isActive ? {width: '1.8rem', filter: 'contrast(0.5)'} : {width: '1.8rem'})} + state={from} + > + + + + + ) +} + +const ReceiptsIcon = ({from}: IconProps) => { + return ( + (isActive ? 'border border-secondary shadow-none btn p-1 m-0' : 'border-0 shadow-none btn p-1 m-0')} + style={({isActive}) => (!isActive ? {width: '1.8rem', filter: 'contrast(0.5)'} : {width: '1.8rem'})} + state={from} + > + + + + + ) +} + +const SettingsIcon = ({from}: IconProps) => { + return ( + (isActive ? 'border border-secondary shadow-none btn p-1 m-0' : 'border-0 shadow-none btn p-1 m-0')} + style={({isActive}) => (!isActive ? {width: '1.8rem', filter: 'contrast(0.5)'} : {width: '1.8rem'})} + state={from} + > + + + + + ) +} + +export const HeaderWithSettings = ({title = '', from}) => { + return ( +
+
{title}
+
+ + + +
+
+ ) +} diff --git a/apps/contract-verification/src/app/components/SubmitButton.tsx b/apps/contract-verification/src/app/components/SubmitButton.tsx new file mode 100644 index 0000000000..9f4bed6200 --- /dev/null +++ b/apps/contract-verification/src/app/components/SubmitButton.tsx @@ -0,0 +1,34 @@ +import React from 'react' +import {CustomTooltip} from '@remix-ui/helper' + +interface Props { + text: string + isSubmitting?: boolean + dataId?: string + disable?: boolean +} + +export const SubmitButton = ({text, dataId, isSubmitting = false, disable = true}) => { + return ( +
+ +
+ ) +} diff --git a/apps/contract-verification/src/app/components/index.ts b/apps/contract-verification/src/app/components/index.ts new file mode 100644 index 0000000000..c52e3712f0 --- /dev/null +++ b/apps/contract-verification/src/app/components/index.ts @@ -0,0 +1,2 @@ +export { HeaderWithSettings } from "./HeaderWithSettings" +export { SubmitButton } from "./SubmitButton" diff --git a/apps/contract-verification/src/app/hooks/useLocalStorage.tsx b/apps/contract-verification/src/app/hooks/useLocalStorage.tsx new file mode 100644 index 0000000000..85d30c849d --- /dev/null +++ b/apps/contract-verification/src/app/hooks/useLocalStorage.tsx @@ -0,0 +1,36 @@ +import {useState} from 'react' + +export function useLocalStorage(key: string, initialValue: any) { + // State to store our value + // Pass initial state function to useState so logic is only executed once + const [storedValue, setStoredValue] = useState(() => { + try { + // Get from local storage by key + const item = window.localStorage.getItem(key) + // Parse stored json or if none return initialValue + return item ? JSON.parse(item) : initialValue + } catch (error) { + // If error also return initialValue + console.error(error) + return initialValue + } + }) + + // Return a wrapped version of useState's setter function that ... + // ... persists the new value to localStorage. + const setValue = (value: any) => { + try { + // Allow value to be a function so we have same API as useState + const valueToStore = value instanceof Function ? value(storedValue) : value + // Save state + setStoredValue(valueToStore) + // Save to local storage + window.localStorage.setItem(key, JSON.stringify(valueToStore)) + } catch (error) { + // A more advanced implementation would handle the error case + console.error(error) + } + } + + return [storedValue, setValue] +} diff --git a/apps/contract-verification/src/app/layouts/Default.tsx b/apps/contract-verification/src/app/layouts/Default.tsx new file mode 100644 index 0000000000..fa9a1111e5 --- /dev/null +++ b/apps/contract-verification/src/app/layouts/Default.tsx @@ -0,0 +1,17 @@ +import React, {PropsWithChildren} from 'react' + +import {HeaderWithSettings} from '../components' + +interface Props { + from: string + title?: string +} + +export const DefaultLayout = ({children, from, title}) => { + return ( +
+ + {children} +
+ ) +} diff --git a/apps/contract-verification/src/app/layouts/index.ts b/apps/contract-verification/src/app/layouts/index.ts new file mode 100644 index 0000000000..9b8e6166d5 --- /dev/null +++ b/apps/contract-verification/src/app/layouts/index.ts @@ -0,0 +1 @@ +export { DefaultLayout } from "./Default" diff --git a/apps/contract-verification/src/app/routes.tsx b/apps/contract-verification/src/app/routes.tsx new file mode 100644 index 0000000000..165b5ae5a7 --- /dev/null +++ b/apps/contract-verification/src/app/routes.tsx @@ -0,0 +1,37 @@ +import React from 'react' +import {HashRouter as Router, Route, Routes, RouteProps} from 'react-router-dom' + +import {ErrorView, HomeView, ReceiptsView, CaptureKeyView} from './views' +import {DefaultLayout} from './layouts' + +export const DisplayRoutes = () => ( + + + + + + } + /> + } /> + + + + } + /> + + + + } + /> + + +) diff --git a/apps/contract-verification/src/app/types/Receipt.ts b/apps/contract-verification/src/app/types/Receipt.ts new file mode 100644 index 0000000000..2dd501651d --- /dev/null +++ b/apps/contract-verification/src/app/types/Receipt.ts @@ -0,0 +1,9 @@ +export type ReceiptStatus = "Pending in queue" | "Pass - Verified" | "Already Verified" | "Max rate limit reached" | "Successfully Updated" + +export interface Receipt { + guid: string + status: ReceiptStatus + isProxyContract: boolean + message?: string + succeed?: boolean +} diff --git a/apps/contract-verification/src/app/types/ThemeType.ts b/apps/contract-verification/src/app/types/ThemeType.ts new file mode 100644 index 0000000000..13b3710cd0 --- /dev/null +++ b/apps/contract-verification/src/app/types/ThemeType.ts @@ -0,0 +1 @@ +export type ThemeType = "dark" | "light" diff --git a/apps/contract-verification/src/app/types/index.ts b/apps/contract-verification/src/app/types/index.ts new file mode 100644 index 0000000000..1a8733d6ff --- /dev/null +++ b/apps/contract-verification/src/app/types/index.ts @@ -0,0 +1,2 @@ +export * from "./Receipt" +export * from "./ThemeType" diff --git a/apps/contract-verification/src/app/utils/index.ts b/apps/contract-verification/src/app/utils/index.ts new file mode 100644 index 0000000000..b23d52e6e0 --- /dev/null +++ b/apps/contract-verification/src/app/utils/index.ts @@ -0,0 +1 @@ +export * from "./utilities" diff --git a/apps/contract-verification/src/app/utils/networks.ts b/apps/contract-verification/src/app/utils/networks.ts new file mode 100644 index 0000000000..fdb28e50a8 --- /dev/null +++ b/apps/contract-verification/src/app/utils/networks.ts @@ -0,0 +1,42 @@ +export const scanAPIurls = { + // all mainnet + 1: 'https://api.etherscan.io/api', + 56: 'https://api.bscscan.com/api', + 137: 'https://api.polygonscan.com/api', + 250: 'https://api.ftmscan.com/api', + 42161: 'https://api.arbiscan.io/api', + 43114: 'https://api.snowtrace.io/api', + 1285: 'https://api-moonriver.moonscan.io/api', + 1284: 'https://api-moonbeam.moonscan.io/api', + 25: 'https://api.cronoscan.com/api', + 199: 'https://api.bttcscan.com/api', + 10: 'https://api-optimistic.etherscan.io/api', + 42220: 'https://api.celoscan.io/api', + 288: 'https://api.bobascan.com/api', + 100: 'https://api.gnosisscan.io/api', + 1101: 'https://api-zkevm.polygonscan.com/api', + 59144: 'https://api.lineascan.build/api', + 8453: 'https://api.basescan.org/api', + 534352: 'https://api.scrollscan.com/api', + + // all testnet + 17000: 'https://api-holesky.etherscan.io/api', + 11155111: 'https://api-sepolia.etherscan.io/api', + 97: 'https://api-testnet.bscscan.com/api', + 80001: 'https://api-testnet.polygonscan.com/api', + 4002: 'https://api-testnet.ftmscan.com/api', + 421611: 'https://api-testnet.arbiscan.io/api', + 42170: 'https://api-nova.arbiscan.io/api', + 43113: 'https://api-testnet.snowtrace.io/api', + 1287: 'https://api-moonbase.moonscan.io/api', + 338: 'https://api-testnet.cronoscan.com/api', + 1028: 'https://api-testnet.bttcscan.com/api', + 420: 'https://api-goerli-optimistic.etherscan.io/api', + 44787: 'https://api-alfajores.celoscan.io/api', + 2888: 'https://api-testnet.bobascan.com/api', + 84531: 'https://api-goerli.basescan.org/api', + 84532: "https://api-sepolia.basescan.org/api", + 1442: 'https://api-testnet-zkevm.polygonscan.com/api', + 59140: 'https://api-testnet.lineascan.build/api', + 534351: 'https://api-sepolia.scrollscan.com/api', +} diff --git a/apps/contract-verification/src/app/utils/scripts.ts b/apps/contract-verification/src/app/utils/scripts.ts new file mode 100644 index 0000000000..0d204d8d55 --- /dev/null +++ b/apps/contract-verification/src/app/utils/scripts.ts @@ -0,0 +1,30 @@ +export const verifyScript = ` +/** + * @param {string} apikey - etherscan api key + * @param {string} contractAddress - Address of the contract to verify + * @param {string} contractArguments - Parameters used in the contract constructor during the initial deployment. It should be the hex encoded value + * @param {string} contractName - Name of the contract + * @param {string} contractFile - File where the contract is located + * @param {number | string} chainRef - Network chain id or API URL (optional) + * @param {boolean} isProxyContract - true, if contract is a proxy contract (optional) + * @param {string} expectedImplAddress - Implementation contract address, in case of proxy contract verification (optional) + * @returns {{ guid, status, message, succeed }} verification result + */ +export const verify = async (apikey: string, contractAddress: string, contractArguments: string, contractName: string, contractFile: string, chainRef?: number | string, isProxyContract?: boolean, expectedImplAddress?: string) => { + const compilationResultParam = await remix.call('compilerArtefacts' as any, 'getCompilerAbstract', contractFile) + console.log('verifying.. ' + contractName) + // update apiKey and chainRef to verify contract on multiple networks + return await remix.call('etherscan' as any, 'verify', apikey, contractAddress, contractArguments, contractName, compilationResultParam, chainRef, isProxyContract, expectedImplAddress) +}` + +export const receiptGuidScript = ` +/** + * @param {string} apikey - etherscan api key + * @param {string} guid - receipt id + * @param {boolean} isProxyContract - true, if contract is a proxy contract (optional) + * @returns {{ status, message, succeed }} receiptStatus + */ +export const receiptStatus = async (apikey: string, guid: string, isProxyContract?: boolean) => { + return await remix.call('etherscan' as any, 'receiptStatus', guid, apikey, isProxyContract) +} +` \ No newline at end of file diff --git a/apps/contract-verification/src/app/utils/utilities.ts b/apps/contract-verification/src/app/utils/utilities.ts new file mode 100644 index 0000000000..048b6e2335 --- /dev/null +++ b/apps/contract-verification/src/app/utils/utilities.ts @@ -0,0 +1,69 @@ +import { PluginClient } from "@remixproject/plugin" +import axios from 'axios' +import { scanAPIurls } from "./networks" +type RemixClient = PluginClient + +/* + status: 0=Error, 1=Pass + message: OK, NOTOK + result: explanation +*/ +export type receiptStatus = { + result: string + message: string + status: string +} + +export const getEtherScanApi = (networkId: any) => { + if (!(networkId in scanAPIurls)) { + throw new Error("no known network to verify against") + } + const apiUrl = (scanAPIurls as any)[networkId] + return apiUrl +} + +export const getNetworkName = async (client: RemixClient) => { + const network = await client.call("network", "detectNetwork") + if (!network) { + throw new Error("no known network to verify against") + } + return { network: network.name!.toLowerCase(), networkId: network.id } +} + +export const getReceiptStatus = async ( + receiptGuid: string, + apiKey: string, + etherscanApi: string +): Promise => { + const params = `guid=${receiptGuid}&module=contract&action=checkverifystatus&apiKey=${apiKey}` + try { + const response = await axios.get(`${etherscanApi}?${params}`) + const { result, message, status } = response.data + return { + result, + message, + status, + } + } catch (error) { + console.error(error) + } +} + +export const getProxyContractReceiptStatus = async ( + receiptGuid: string, + apiKey: string, + etherscanApi: string +): Promise => { + const params = `guid=${receiptGuid}&module=contract&action=checkproxyverification&apiKey=${apiKey}` + try { + const response = await axios.get(`${etherscanApi}?${params}`) + const { result, message, status } = response.data + return { + result, + message, + status, + } + } catch (error) { + console.error(error) + } +} diff --git a/apps/contract-verification/src/app/utils/verify.ts b/apps/contract-verification/src/app/utils/verify.ts new file mode 100644 index 0000000000..a459fb5499 --- /dev/null +++ b/apps/contract-verification/src/app/utils/verify.ts @@ -0,0 +1,206 @@ +import { getNetworkName, getEtherScanApi, getReceiptStatus, getProxyContractReceiptStatus } from "." +import { CompilationResult } from "@remixproject/plugin-api" +import { CompilerAbstract } from '@remix-project/remix-solidity' +import axios from 'axios' +import { PluginClient } from "@remixproject/plugin" + +const resetAfter10Seconds = (client: PluginClient, setResults: (value: string) => void) => { + setTimeout(() => { + client.emit("statusChanged", { key: "none" }) + setResults("") + }, 10000) +} + +export type EtherScanReturn = { + guid: any, + status: any, +} +export const verify = async ( + apiKeyParam: string, + contractAddress: string, + contractArgumentsParam: string, + contractName: string, + compilationResultParam: CompilerAbstract, + chainRef: number | string, + isProxyContract: boolean, + expectedImplAddress: string, + client: PluginClient, + onVerifiedContract: (value: EtherScanReturn) => void, + setResults: (value: string) => void +) => { + let networkChainId + let etherscanApi + if (chainRef) { + if (typeof chainRef === 'number') { + networkChainId = chainRef + etherscanApi = getEtherScanApi(networkChainId) + } else if (typeof chainRef === 'string') etherscanApi = chainRef + } else { + const { network, networkId } = await getNetworkName(client) + if (network === "vm") { + return { + succeed: false, + message: "Cannot verify in the selected network" + } + } else { + networkChainId = networkId + etherscanApi = getEtherScanApi(networkChainId) + } + } + + try { + const contractMetadata = getContractMetadata( + // cast from the remix-plugin interface to the solidity one. Should be fixed when remix-plugin move to the remix-project repository + compilationResultParam.data as unknown as CompilationResult, + contractName + ) + + if (!contractMetadata) { + return { + succeed: false, + message: "Please recompile contract" + } + } + + const contractMetadataParsed = JSON.parse(contractMetadata) + + const fileName = getContractFileName( + // cast from the remix-plugin interface to the solidity one. Should be fixed when remix-plugin move to the remix-project repository + compilationResultParam.data as unknown as CompilationResult, + contractName + ) + + const jsonInput = { + language: 'Solidity', + sources: compilationResultParam.source.sources, + settings: { + optimizer: { + enabled: contractMetadataParsed.settings.optimizer.enabled, + runs: contractMetadataParsed.settings.optimizer.runs + } + } + } + + const data: { [key: string]: string | any } = { + apikey: apiKeyParam, // A valid API-Key is required + module: "contract", // Do not change + action: "verifysourcecode", // Do not change + codeformat: "solidity-standard-json-input", + sourceCode: JSON.stringify(jsonInput), + contractname: fileName + ':' + contractName, + compilerversion: `v${contractMetadataParsed.compiler.version}`, // see http://etherscan.io/solcversions for list of support versions + constructorArguements: contractArgumentsParam ? contractArgumentsParam.replace('0x', '') : '', // if applicable + } + + if (isProxyContract) { + data.action = "verifyproxycontract" + data.expectedimplementation = expectedImplAddress + data.address = contractAddress + } else { + data.contractaddress = contractAddress + } + + const body = new FormData() + Object.keys(data).forEach((key) => body.append(key, data[key])) + + client.emit("statusChanged", { + key: "loading", + type: "info", + title: "Verifying ...", + }) + const response = await axios.post(etherscanApi, body) + const { message, result, status } = await response.data + + if (message === "OK" && status === "1") { + resetAfter10Seconds(client, setResults) + let receiptStatus + if (isProxyContract) { + receiptStatus = await getProxyContractReceiptStatus( + result, + apiKeyParam, + etherscanApi + ) + if (receiptStatus.status === '1') { + receiptStatus.message = receiptStatus.result + receiptStatus.result = 'Successfully Updated' + } + } else receiptStatus = await getReceiptStatus( + result, + apiKeyParam, + etherscanApi + ) + + const returnValue = { + guid: result, + status: receiptStatus.result, + message: `Verification request submitted successfully. Use this receipt GUID ${result} to track the status of your submission`, + succeed: true, + isProxyContract + } + onVerifiedContract(returnValue) + return returnValue + } else if (message === "NOTOK") { + client.emit("statusChanged", { + key: "failed", + type: "error", + title: result, + }) + const returnValue = { + message: result, + succeed: false, + isProxyContract + } + resetAfter10Seconds(client, setResults) + return returnValue + } + return { + message: 'unknown reason ' + result, + succeed: false + } + } catch (error: any) { + console.error(error) + setResults("Something wrong happened, try again") + return { + message: error.message, + succeed: false + } + } +} + +export const getContractFileName = ( + compilationResult: CompilationResult, + contractName: string +) => { + const compiledContracts = compilationResult.contracts + let fileName = "" + + for (const file of Object.keys(compiledContracts)) { + for (const contract of Object.keys(compiledContracts[file])) { + if (contract === contractName) { + fileName = file + break + } + } + } + return fileName +} + +export const getContractMetadata = ( + compilationResult: CompilationResult, + contractName: string +) => { + const compiledContracts = compilationResult.contracts + let contractMetadata = "" + + for (const file of Object.keys(compiledContracts)) { + for (const contract of Object.keys(compiledContracts[file])) { + if (contract === contractName) { + contractMetadata = compiledContracts[file][contract].metadata + if (contractMetadata) { + break + } + } + } + } + return contractMetadata +} diff --git a/apps/contract-verification/src/app/views/CaptureKeyView.tsx b/apps/contract-verification/src/app/views/CaptureKeyView.tsx new file mode 100644 index 0000000000..e63ec4278d --- /dev/null +++ b/apps/contract-verification/src/app/views/CaptureKeyView.tsx @@ -0,0 +1,63 @@ +import React, {useState, useEffect} from 'react' + +import {Formik, ErrorMessage, Field} from 'formik' +import {useNavigate, useLocation} from 'react-router-dom' + +import {AppContext} from '../AppContext' +import {SubmitButton} from '../components' + +export const CaptureKeyView = () => { + const location = useLocation() + const navigate = useNavigate() + const [msg, setMsg] = useState('') + const context = React.useContext(AppContext) + + useEffect(() => { + if (!context.apiKey) setMsg('Please provide a 34-character API key to continue') + }, [context.apiKey]) + + return ( +
+ { + const errors = {} as any + if (!values.apiKey) { + errors.apiKey = 'Required' + } else if (values.apiKey.length !== 34) { + errors.apiKey = 'API key should be 34 characters long' + } + return errors + }} + onSubmit={(values) => { + const apiKey = values.apiKey + if (apiKey.length === 34) { + context.setAPIKey(values.apiKey) + navigate(location && location.state ? location.state : '/') + } + }} + > + {({errors, touched, handleSubmit}) => ( +
+
+ + + +
+ +
+ +
+
+ )} +
+ +
+
+ ) +} diff --git a/apps/contract-verification/src/app/views/ErrorView.tsx b/apps/contract-verification/src/app/views/ErrorView.tsx new file mode 100644 index 0000000000..90ee41e62a --- /dev/null +++ b/apps/contract-verification/src/app/views/ErrorView.tsx @@ -0,0 +1,16 @@ +import React from 'react' + +export const ErrorView = () => { + return ( +
+ Error page +
Sorry, something unexpected happened.
+
+ Please raise an issue:{' '} + + Here + +
+
+ ) +} diff --git a/apps/contract-verification/src/app/views/HomeView.tsx b/apps/contract-verification/src/app/views/HomeView.tsx new file mode 100644 index 0000000000..d0cda503d6 --- /dev/null +++ b/apps/contract-verification/src/app/views/HomeView.tsx @@ -0,0 +1,31 @@ +import React from 'react' + +import {Navigate} from 'react-router-dom' + +import {AppContext} from '../AppContext' +import {Receipt} from '../types' + +import {VerifyView} from './VerifyView' + +export const HomeView = () => { + const context = React.useContext(AppContext) + + return !context.apiKey ? ( + + ) : ( + { + const newReceipts = [...context.receipts, receipt] + context.setReceipts(newReceipts) + }} + networkName={context.networkName} + /> + ) +} diff --git a/apps/contract-verification/src/app/views/ReceiptsView.tsx b/apps/contract-verification/src/app/views/ReceiptsView.tsx new file mode 100644 index 0000000000..9a2c345462 --- /dev/null +++ b/apps/contract-verification/src/app/views/ReceiptsView.tsx @@ -0,0 +1,170 @@ +import React, {useState} from 'react' + +import {Formik, ErrorMessage, Field} from 'formik' +import {getEtherScanApi, getNetworkName, getReceiptStatus, getProxyContractReceiptStatus} from '../utils' +import {Receipt} from '../types' +import {AppContext} from '../AppContext' +import {SubmitButton} from '../components' +import {Navigate} from 'react-router-dom' +import {Button} from 'react-bootstrap' +import {CustomTooltip} from '@remix-ui/helper' + +interface FormValues { + receiptGuid: string +} + +export const ReceiptsView = () => { + const [results, setResults] = useState({succeed: false, message: ''}) + const [isProxyContractReceipt, setIsProxyContractReceipt] = useState(false) + const context = React.useContext(AppContext) + + const onGetReceiptStatus = async (values: FormValues, clientInstance: any, apiKey: string) => { + try { + const {network, networkId} = await getNetworkName(clientInstance) + if (network === 'vm') { + setResults({ + succeed: false, + message: 'Cannot verify in the selected network' + }) + return + } + const etherscanApi = getEtherScanApi(networkId) + let result + if (isProxyContractReceipt) { + result = await getProxyContractReceiptStatus(values.receiptGuid, apiKey, etherscanApi) + if (result.status === '1') { + result.message = result.result + result.result = 'Successfully Updated' + } + } else result = await getReceiptStatus(values.receiptGuid, apiKey, etherscanApi) + setResults({ + succeed: result.status === '1' ? true : false, + message: result.result || (result.status === '0' ? 'Verification failed' : result.message) + }) + } catch (error: any) { + setResults({ + succeed: false, + message: error.message + }) + } + } + + return !context.apiKey ? ( + + ) : ( +
+ { + const errors = {} as any + if (!values.receiptGuid) { + errors.receiptGuid = 'Required' + } + return errors + }} + onSubmit={(values) => onGetReceiptStatus(values, context.clientInstance, context.apiKey)} + > + {({errors, touched, handleSubmit, handleChange}) => ( +
+
+ + + +
+ +
+ { + handleChange(e) + if (e.target.checked) setIsProxyContractReceipt(true) + else setIsProxyContractReceipt(false) + }} + /> + +
+ + + )} +
+ +
+ + +
+ + + +
+ ) +} + +const ReceiptsTable = ({receipts}) => { + return ( +
+
Receipts
+ + + + + + + + + {receipts && + receipts.length > 0 && + receipts.map((item: Receipt, index) => { + return ( + + + + + ) + })} + +
StatusGUID
+ {item.status} + {item.status === 'Successfully Updated' && ( + + + + )} + {item.guid}
+
+ ) +} diff --git a/apps/contract-verification/src/app/views/VerifyView.tsx b/apps/contract-verification/src/app/views/VerifyView.tsx new file mode 100644 index 0000000000..ca70dba74c --- /dev/null +++ b/apps/contract-verification/src/app/views/VerifyView.tsx @@ -0,0 +1,235 @@ +import React, {useEffect, useRef, useState} from 'react' +import Web3 from 'web3' + +import {PluginClient} from '@remixproject/plugin' +import {CustomTooltip} from '@remix-ui/helper' +import {Formik, ErrorMessage, Field} from 'formik' + +import {SubmitButton} from '../components' +import {Receipt} from '../types' +import {verify} from '../utils/verify' +import {etherscanScripts} from '@remix-project/remix-ws-templates' + +interface Props { + client: PluginClient + apiKey: string + onVerifiedContract: (receipt: Receipt) => void + contracts: string[], + networkName: string +} + +interface FormValues { + contractName: string + contractAddress: string + expectedImplAddress?: string +} + +export const VerifyView = ({apiKey, client, contracts, onVerifiedContract, networkName}) => { + const [results, setResults] = useState('') + const [selectedContract, setSelectedContract] = useState('') + const [showConstructorArgs, setShowConstructorArgs] = useState(false) + const [isProxyContract, setIsProxyContract] = useState(false) + const [constructorInputs, setConstructorInputs] = useState([]) + const verificationResult = useRef({}) + + useEffect(() => { + if (contracts.includes(selectedContract)) updateConsFields(selectedContract) + }, [contracts]) + + const updateConsFields = (contractName) => { + client.call('compilerArtefacts' as any, 'getArtefactsByContractName', contractName).then((result) => { + const {artefact} = result + if (artefact && artefact.abi && artefact.abi[0] && artefact.abi[0].type && artefact.abi[0].type === 'constructor' && artefact.abi[0].inputs.length > 0) { + setConstructorInputs(artefact.abi[0].inputs) + setShowConstructorArgs(true) + } else { + setConstructorInputs([]) + setShowConstructorArgs(false) + } + }) + } + + const onVerifyContract = async (values: FormValues) => { + const compilationResult = (await client.call('solidity', 'getCompilationResult')) as any + + if (!compilationResult) { + throw new Error('no compilation result available') + } + + const constructorValues = [] + for (const key in values) { + if (key.startsWith('contractArgValue')) constructorValues.push(values[key]) + } + const web3 = new Web3() + const constructorTypes = constructorInputs.map((e) => e.type) + let contractArguments = web3.eth.abi.encodeParameters(constructorTypes, constructorValues) + contractArguments = contractArguments.replace('0x', '') + + verificationResult.current = await verify( + apiKey, + values.contractAddress, + contractArguments, + values.contractName, + compilationResult, + null, + isProxyContract, + values.expectedImplAddress, + client, + onVerifiedContract, + setResults + ) + setResults(verificationResult.current['message']) + } + + return ( +
+ { + const errors = {} as any + if (!values.contractName) { + errors.contractName = 'Required' + } + if (!values.contractAddress) { + errors.contractAddress = 'Required' + } + if (values.contractAddress.trim() === '' || !values.contractAddress.startsWith('0x') || values.contractAddress.length !== 42) { + errors.contractAddress = 'Please enter a valid contract address' + } + return errors + }} + onSubmit={(values) => onVerifyContract(values)} + > + {({errors, touched, handleSubmit, handleChange, isSubmitting}) => { + return ( +
+
+ + + + +
+
+ + { + handleChange(e) + setSelectedContract(e.target.value) + updateConsFields(e.target.value) + }} + > + + {contracts.map((item) => ( + + ))} + + +
+
+ + {constructorInputs.map((item, index) => { + return ( +
+ + + + +
+ ) + })} +
+
+ + + +
+ { + handleChange(e) + if (e.target.checked) setIsProxyContract(true) + else setIsProxyContract(false) + }} + /> + +
+
+
+ + + + + + +
+ +
+ + + + + ) + }} +
+
+ {/*
+ View Receipts +
*/} +
+ ) +} diff --git a/apps/contract-verification/src/app/views/index.ts b/apps/contract-verification/src/app/views/index.ts new file mode 100644 index 0000000000..c483228ece --- /dev/null +++ b/apps/contract-verification/src/app/views/index.ts @@ -0,0 +1,4 @@ +export { HomeView } from "./HomeView" +export { ErrorView } from "./ErrorView" +export { ReceiptsView } from "./ReceiptsView" +export { CaptureKeyView } from "./CaptureKeyView" diff --git a/apps/contract-verification/src/assets/.gitkeep b/apps/contract-verification/src/assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/contract-verification/src/environments/environment.prod.ts b/apps/contract-verification/src/environments/environment.prod.ts new file mode 100644 index 0000000000..3612073bc3 --- /dev/null +++ b/apps/contract-verification/src/environments/environment.prod.ts @@ -0,0 +1,3 @@ +export const environment = { + production: true +}; diff --git a/apps/contract-verification/src/environments/environment.ts b/apps/contract-verification/src/environments/environment.ts new file mode 100644 index 0000000000..d9370e924b --- /dev/null +++ b/apps/contract-verification/src/environments/environment.ts @@ -0,0 +1,6 @@ +// This file can be replaced during build by using the `fileReplacements` array. +// When building for production, this file is replaced with `environment.prod.ts`. + +export const environment = { + production: false +}; diff --git a/apps/contract-verification/src/favicon.ico b/apps/contract-verification/src/favicon.ico new file mode 100644 index 0000000000..317ebcb233 Binary files /dev/null and b/apps/contract-verification/src/favicon.ico differ diff --git a/apps/contract-verification/src/index.html b/apps/contract-verification/src/index.html new file mode 100644 index 0000000000..b0ff6f5784 --- /dev/null +++ b/apps/contract-verification/src/index.html @@ -0,0 +1,17 @@ + + + + + Etherscan + + + + + + + +
+ + + diff --git a/apps/contract-verification/src/main.tsx b/apps/contract-verification/src/main.tsx new file mode 100644 index 0000000000..077b7ac8f4 --- /dev/null +++ b/apps/contract-verification/src/main.tsx @@ -0,0 +1,14 @@ +import React from 'react' +import * as ReactDOM from 'react-dom' +import { createRoot } from 'react-dom/client'; +import App from './app/app' + + +const container = document.getElementById('root'); + +if (container) { + createRoot(container).render( + + ); +} + diff --git a/apps/contract-verification/src/polyfills.ts b/apps/contract-verification/src/polyfills.ts new file mode 100644 index 0000000000..2adf3d05b6 --- /dev/null +++ b/apps/contract-verification/src/polyfills.ts @@ -0,0 +1,7 @@ +/** + * Polyfill stable language features. These imports will be optimized by `@babel/preset-env`. + * + * See: https://github.com/zloirock/core-js#babel + */ +import 'core-js/stable'; +import 'regenerator-runtime/runtime'; diff --git a/apps/contract-verification/src/profile.json b/apps/contract-verification/src/profile.json new file mode 100644 index 0000000000..f2feb39afa --- /dev/null +++ b/apps/contract-verification/src/profile.json @@ -0,0 +1,16 @@ +{ + "name": "contreact-verification", + "displayName": "[NEW] Contract verification", + "description": "VERIFY CODE", + "version": "0.1.0", + "events": [], + "methods": ["verify", "receiptStatus"], + "kind": "none", + "icon": "data:image/png;base64,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", + "location": "sidePanel", + "url": "https://ipfs-cluster.ethdevops.io/ipfs/QmQsZbBSYCVBVpz2mVRbPRVTrcz59oJEpuuoxiT9otu3mh", + "repo": "https://github.com/ethereum/remix-project/tree/master/apps/etherscan", + "documentation": "https://remix-ide.readthedocs.io/en/latest/contract_verification.html#etherscan", + "maintainedBy": "Remix", + "authorContact": "remix@ethereum.org" +} \ No newline at end of file diff --git a/apps/contract-verification/src/styles.css b/apps/contract-verification/src/styles.css new file mode 100644 index 0000000000..90d4ee0072 --- /dev/null +++ b/apps/contract-verification/src/styles.css @@ -0,0 +1 @@ +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/contract-verification/tsconfig.app.json b/apps/contract-verification/tsconfig.app.json new file mode 100644 index 0000000000..252904bb73 --- /dev/null +++ b/apps/contract-verification/tsconfig.app.json @@ -0,0 +1,22 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node"] + }, + "files": [ + "../../node_modules/@nrwl/react/typings/cssmodule.d.ts", + "../../node_modules/@nrwl/react/typings/image.d.ts" + ], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/apps/contract-verification/tsconfig.json b/apps/contract-verification/tsconfig.json new file mode 100644 index 0000000000..5aab5e7911 --- /dev/null +++ b/apps/contract-verification/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/apps/contract-verification/webpack.config.js b/apps/contract-verification/webpack.config.js new file mode 100644 index 0000000000..5564f25b94 --- /dev/null +++ b/apps/contract-verification/webpack.config.js @@ -0,0 +1,90 @@ +const {composePlugins, withNx} = require('@nrwl/webpack') +const webpack = require('webpack') +const TerserPlugin = require('terser-webpack-plugin') +const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') + +const versionData = { + timestamp: Date.now(), + mode: process.env.NODE_ENV === 'production' ? 'production' : 'development' +} +// Nx plugins for webpack. +module.exports = composePlugins(withNx(), (config) => { + // Update the webpack config as needed here. + // e.g. `config.plugins.push(new MyPlugin())` + + // add fallback for node modules + config.resolve.fallback = { + ...config.resolve.fallback, + crypto: require.resolve('crypto-browserify'), + stream: require.resolve('stream-browserify'), + path: require.resolve('path-browserify'), + http: require.resolve('stream-http'), + https: require.resolve('https-browserify'), + constants: require.resolve('constants-browserify'), + os: false, //require.resolve("os-browserify/browser"), + timers: false, // require.resolve("timers-browserify"), + zlib: require.resolve('browserify-zlib'), + fs: false, + module: false, + tls: false, + net: false, + readline: false, + child_process: false, + buffer: require.resolve('buffer/'), + vm: require.resolve('vm-browserify') + } + + // add externals + config.externals = { + ...config.externals, + solc: 'solc' + } + + // add public path + config.output.publicPath = '/' + + // set filename + config.output.filename = `[name].plugin-etherscan.${versionData.timestamp}.js` + config.output.chunkFilename = `[name].plugin-etherscan.${versionData.timestamp}.js` + + // add copy & provide plugin + config.plugins.push( + new webpack.ProvidePlugin({ + Buffer: ['buffer', 'Buffer'], + url: ['url', 'URL'], + process: 'process/browser' + }) + ) + + // souce-map loader + config.module.rules.push({ + test: /\.js$/, + use: ['source-map-loader'], + enforce: 'pre' + }) + + config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings + + // set minimizer + config.optimization.minimizer = [ + new TerserPlugin({ + parallel: true, + terserOptions: { + ecma: 2015, + compress: false, + mangle: false, + format: { + comments: false + } + }, + extractComments: false + }), + new CssMinimizerPlugin() + ] + + config.watchOptions = { + ignored: /node_modules/ + } + + return config +}) diff --git a/apps/remix-ide/project.json b/apps/remix-ide/project.json index 563c6d2910..d53fdd6e33 100644 --- a/apps/remix-ide/project.json +++ b/apps/remix-ide/project.json @@ -3,7 +3,7 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "apps/remix-ide/src", "projectType": "application", - "implicitDependencies": ["doc-gen", "doc-viewer", "etherscan", "vyper", "solhint", "walletconnect", "circuit-compiler", "learneth", "quick-dapp", "remix-dapp"], + "implicitDependencies": ["doc-gen", "doc-viewer", "etherscan", "contract-verification", "vyper", "solhint", "walletconnect", "circuit-compiler", "learneth", "quick-dapp", "remix-dapp"], "targets": { "build": { "executor": "@nrwl/webpack:webpack", diff --git a/apps/remix-ide/src/assets/list.json b/apps/remix-ide/src/assets/list.json new file mode 100644 index 0000000000..6a55fff4f7 --- /dev/null +++ b/apps/remix-ide/src/assets/list.json @@ -0,0 +1,1123 @@ +{ + "builds": [ + { + "path": "soljson-v0.3.6+commit.3fc68da5.js", + "version": "0.3.6", + "build": "commit.3fc68da5", + "longVersion": "0.3.6+commit.3fc68da5", + "keccak256": "0x4a1c2a6a4896edefd3a4178a6c3ed8f1de625bd7c00dd7cc5781a9f36236e7db", + "sha256": "0xee7ba01680ed3a1c1cda236189a51c1e6ff99f6dca602a580e5b16441772b50b", + "urls": [ + "dweb:/ipfs/Qme9brfZS3XhbiRbbNDKhBpgFknyD92omMmYa7XSf56bJP" + ] + }, + { + "path": "soljson-v0.4.0+commit.acd334c9.js", + "version": "0.4.0", + "build": "commit.acd334c9", + "longVersion": "0.4.0+commit.acd334c9", + "keccak256": "0x07994ad8c59c498bf44ca8e84914e27b79be964d98a9556226db377819d67387", + "sha256": "0xb83d2025e0bbc7f7f0dc9e47f5aa22eacb548b42c55add8f5f6822c105163500", + "urls": [ + "dweb:/ipfs/QmcBZ6Q2iHmrf9omvD7Jyy8kgrqyPmZFwvKWqvVDaxo1Ta" + ] + }, + { + "path": "soljson-v0.4.1+commit.4fc6fc2c.js", + "version": "0.4.1", + "build": "commit.4fc6fc2c", + "longVersion": "0.4.1+commit.4fc6fc2c", + "keccak256": "0x4c358c2e90447ad9e7c1816b5be8edde1172f67dedf16755a6c7373ede46b245", + "sha256": "0x9825565e1f199dbed6de01d27e10f83a9180300acab80f8469bf427e3cf92e96", + "urls": [ + "dweb:/ipfs/QmcEK5gvWNeHUtjsF3B6j5AXb9uNoG3aHbPrCMJDx7C8TM" + ] + }, + { + "path": "soljson-v0.4.2+commit.af6afb04.js", + "version": "0.4.2", + "build": "commit.af6afb04", + "longVersion": "0.4.2+commit.af6afb04", + "keccak256": "0xb67df5c37e8255e0de7918b6d3261f0f29e277d121bf5f414b66157a5b1070cd", + "sha256": "0x67f8a94b60278cfb80d505c47a1a5e67ec2caf20167ef85f2bdf2a80a692bd1b", + "urls": [ + "dweb:/ipfs/QmVumPvgQVFLZvDvQddcDGcdxjbVWTTzxoQvJAECBBZ6Ju" + ] + }, + { + "path": "soljson-v0.4.3+commit.2353da71.js", + "version": "0.4.3", + "build": "commit.2353da71", + "longVersion": "0.4.3+commit.2353da71", + "keccak256": "0x62a65d0a951617f022524fc844ca11d90266f64e693343a2f41107183bf364c1", + "sha256": "0x66da311056ec26c9c3fb501350ee22187c30e79c41bf2713eeff7d84479948c5", + "urls": [ + "dweb:/ipfs/QmXf2cKYJ26tXAU6A6tmUk2dn4tuX3CWNaXJVnGLuoe15y" + ] + }, + { + "path": "soljson-v0.4.4+commit.4633f3de.js", + "version": "0.4.4", + "build": "commit.4633f3de", + "longVersion": "0.4.4+commit.4633f3de", + "keccak256": "0x06afcb6dc23efb1482545b63c5e3983dded0c383ecc46c3ae319f7b868201e47", + "sha256": "0x9e386edb2ee759ad65792f7d62c10ae7edf65c5b874a5451f1e695e586b69eea", + "urls": [ + "dweb:/ipfs/QmSJFaZhpXQ2EPF2koyiTNAiiuJRykv1Q8yubhkmBhvYyu" + ] + }, + { + "path": "soljson-v0.4.5+commit.b318366e.js", + "version": "0.4.5", + "build": "commit.b318366e", + "longVersion": "0.4.5+commit.b318366e", + "keccak256": "0xcdf7c4d4c6b9331b755170fa927692019c94088f87f100d2c3c920bcc3740d0b", + "sha256": "0x7184dae0b761485a5dce66b50075e17857c5b55fe3fa71fe22d4d5acc0839741", + "urls": [ + "dweb:/ipfs/QmYJuZgMbeMiotHAFNWEXdxjTa5yi7GaV4UkgBYABomFpj" + ] + }, + { + "path": "soljson-v0.4.6+commit.2dabbdf0.js", + "version": "0.4.6", + "build": "commit.2dabbdf0", + "longVersion": "0.4.6+commit.2dabbdf0", + "keccak256": "0x52ca702b8ed4b1e6d43d8a006b3d27f6dba611bac118c523711bfd209fb1cc9d", + "sha256": "0x8db9466df3b91c52e3412cebd13176ea9fe16d3239d000828a081c34ce899337", + "urls": [ + "dweb:/ipfs/QmZZ9hNntBxJw3G7LGW3e8nXtnGxLnaSMM44K4BbLrkELs" + ] + }, + { + "path": "soljson-v0.4.7+commit.822622cf.js", + "version": "0.4.7", + "build": "commit.822622cf", + "longVersion": "0.4.7+commit.822622cf", + "keccak256": "0xcd8a6a8b2626de75ef6ff73fb724f3ad5693a8902f86e88290f048b56182e7cc", + "sha256": "0xd28a58fbc3ce56ff650d4daf3a1d8092e25cadf2a5b2769fd333b321dfc6a22d", + "urls": [ + "dweb:/ipfs/QmfHjv4nYKuv3yFpWZqBYyiYEYmkQGydQmFT5b6mJkFpWp" + ] + }, + { + "path": "soljson-v0.4.8+commit.60cc1668.js", + "version": "0.4.8", + "build": "commit.60cc1668", + "longVersion": "0.4.8+commit.60cc1668", + "keccak256": "0x43c96fc79cf288cecda12b23a17f30b1cf0427a19dc7c1c094bb461eabefe0df", + "sha256": "0x9af176f42b63eaec838999a07e80484f92f41a0fc497adefa65baf88d8fbecaf", + "urls": [ + "dweb:/ipfs/Qmf7WYJJ8y6oHr4RQ7HC4tXgFPGvsnp3Qf6TrMBdK52Y5Z" + ] + }, + { + "path": "soljson-v0.4.9+commit.364da425.js", + "version": "0.4.9", + "build": "commit.364da425", + "longVersion": "0.4.9+commit.364da425", + "keccak256": "0xbe94ff397be2a951cbeb6c9c1a60ddf531d0ce76f45d51755386b6fa42cc2e2c", + "sha256": "0x6ff1683eb76dc58c31043fea474be6da8535ec625d1cd8331a3daead84fd5564", + "urls": [ + "dweb:/ipfs/QmeBWFbK1aAxnB6muXWStZJWndrFvMJt4xfAzEJD7AqaY3" + ] + }, + { + "path": "soljson-v0.4.10+commit.f0d539ae.js", + "version": "0.4.10", + "build": "commit.f0d539ae", + "longVersion": "0.4.10+commit.f0d539ae", + "keccak256": "0x178e51ad0c6a350ec4ed6fd07675dfd4d2581ee07b14b4954dd0b0f6d8633ca5", + "sha256": "0xd70ca2f656a88a9be7a3f7d602f03b30149b3bda0d1057cfa3a3c5e3d6e07453", + "urls": [ + "dweb:/ipfs/QmarthW41sfbrdkMmCK6jicXFZDGgvALzdgzygtUqEauae" + ] + }, + { + "path": "soljson-v0.4.11+commit.68ef5810.js", + "version": "0.4.11", + "build": "commit.68ef5810", + "longVersion": "0.4.11+commit.68ef5810", + "keccak256": "0xb8c3f5654b323cea016c0cc1a4584069714cdf796489efe2496a13f8f83a0e63", + "sha256": "0xdeb3c274f8b840d657e2f9b1dba602e89f58b1bf3fd7178c48c9033310a1f006", + "urls": [ + "dweb:/ipfs/QmNUf8dTW9xANAvJmV1ho279AyWSCCvDp6bXet1QTcS2z5" + ] + }, + { + "path": "soljson-v0.4.12+commit.194ff033.js", + "version": "0.4.12", + "build": "commit.194ff033", + "longVersion": "0.4.12+commit.194ff033", + "keccak256": "0x598af6fec02a6783d6a438a6bb0f7d3012716d003f7bf6c9ac5a4d2bc911941b", + "sha256": "0xd522b307a014a32ed5815b05045c4396abc047e70c8a53c1e3ef92e14daa61c6", + "urls": [ + "dweb:/ipfs/QmWGK9FbQiNWNeqysvCNCBw3q7cR1dzpnD1EKtNija2zyK" + ] + }, + { + "path": "soljson-v0.4.13+commit.0fb4cb1a.js", + "version": "0.4.13", + "build": "commit.0fb4cb1a", + "longVersion": "0.4.13+commit.0fb4cb1a", + "keccak256": "0x93f7046d6e0ea2492ec5229936821b3b020dbe9eb2e1193953389293d64a190b", + "sha256": "0x68ace74ca809ff47b09449d4054c77907d9412f14f6003d5475b60f4fec13709", + "urls": [ + "dweb:/ipfs/Qmco9fGHM6mdaPVYqeDQ11GB3BrCbwRcEzM5XzHpAdAVWc" + ] + }, + { + "path": "soljson-v0.4.14+commit.c2215d46.js", + "version": "0.4.14", + "build": "commit.c2215d46", + "longVersion": "0.4.14+commit.c2215d46", + "keccak256": "0x7def3c264883cbe6ffbfc54894e48f9a0d2984ddbd1145eb898758d2a41d1559", + "sha256": "0x54f3dc64f2ff5a5350410f6157a537d96fb4aeec90476e90a951ddfbd1fe4bca", + "urls": [ + "dweb:/ipfs/QmXyyuEWhexuez2rzAeFjunpiAhncD1AfcXitGNHxpRWha" + ] + }, + { + "path": "soljson-v0.4.15+commit.bbb8e64f.js", + "version": "0.4.15", + "build": "commit.bbb8e64f", + "longVersion": "0.4.15+commit.bbb8e64f", + "keccak256": "0x9ffa9ee890ec483580c0b4ed72270b16e92eb0b7a8a97fb00c257f8809aa4023", + "sha256": "0x3e64525797e0b2d9abaeb022688cc02d63fc5820327e382fc6574a7de650dc97", + "urls": [ + "dweb:/ipfs/QmW2rPbEtiVAbWJxtizzDqTjwpRpXCxkpSR696g9GxAYKT" + ] + }, + { + "path": "soljson-v0.4.16+commit.d7661dd9.js", + "version": "0.4.16", + "build": "commit.d7661dd9", + "longVersion": "0.4.16+commit.d7661dd9", + "keccak256": "0xf0a6c32af3eaa2f8c6d9e6c8b90f3bac5e775c7f1c90a61c1e72b593fbb1528d", + "sha256": "0x0e6d842e941cd8b76280c59f28f6d020af1afdea8e4be9d9da677ac5dbe860c6", + "urls": [ + "dweb:/ipfs/QmSwumWbYwYe4xLcqpi38VNtw7xCgbNaUkRhiZro9EnqLt" + ] + }, + { + "path": "soljson-v0.4.17+commit.bdeb9e52.js", + "version": "0.4.17", + "build": "commit.bdeb9e52", + "longVersion": "0.4.17+commit.bdeb9e52", + "keccak256": "0xeb8c3c474b5fa792f9b1b2ac6be945c32f835ccdc059deb562da4e99a031eab9", + "sha256": "0x7fe677e8214d0486fa7164f797862fae0a0fefb7b72cf6ad8e728faa54f12b60", + "urls": [ + "dweb:/ipfs/QmbgEAtdmSoxH4cfRJXj7mVpKv9rT5Cq2YmXmAnjgsyqBC" + ] + }, + { + "path": "soljson-v0.4.18+commit.9cf6e910.js", + "version": "0.4.18", + "build": "commit.9cf6e910", + "longVersion": "0.4.18+commit.9cf6e910", + "keccak256": "0xf824e695e8e66079b4b6063622c7dd80ed056d29969c8c3babac4fb572f3dfec", + "sha256": "0x5bb50839ba5116bf31669f3de8dad72eaec298ba32a643be7d0dc2d1392c54d6", + "urls": [ + "dweb:/ipfs/Qmf5RrLbWeMykvWJbCyyThCLQ9YVmU8uWagMdSp9nNzZMc" + ] + }, + { + "path": "soljson-v0.4.19+commit.c4cbbb05.js", + "version": "0.4.19", + "build": "commit.c4cbbb05", + "longVersion": "0.4.19+commit.c4cbbb05", + "keccak256": "0xa60eadfddbfda0daebb8a1b883b89d33b800cff7ce7e12458170ea17cd5ede58", + "sha256": "0x8c2a69fbab9bdf503538028c697e09e51a7e699323ae7100c375cb35c415a819", + "urls": [ + "dweb:/ipfs/QmSZEQEGuVJ7hudg8FzfDMXKVtn5AVGKaxbhSSDXwpX73K" + ] + }, + { + "path": "soljson-v0.4.20+commit.3155dd80.js", + "version": "0.4.20", + "build": "commit.3155dd80", + "longVersion": "0.4.20+commit.3155dd80", + "keccak256": "0x6c6dfa967526b7060634474ef730761711e5be662abf5ee02dc05985abfadec9", + "sha256": "0x9852ad94048600cc5a1458b4a7ab625996844c809b314422693bdc81d953fcc0", + "urls": [ + "dweb:/ipfs/QmcsCpg6kfp7Vea4y9qPtfDXcaQJbDidb65n3t9f2MFDpR" + ] + }, + { + "path": "soljson-v0.4.21+commit.dfe3193c.js", + "version": "0.4.21", + "build": "commit.dfe3193c", + "longVersion": "0.4.21+commit.dfe3193c", + "keccak256": "0xd0f9a689670184ad874ca6a2cb40dfe57e9cf539d9330ca3f2501951478eace8", + "sha256": "0x4197bb1cb0ea7e637ed8a0e7810f1bfe32c90d0151d6f423bb3dfeef9f6777c4", + "urls": [ + "dweb:/ipfs/QmY7UN95hdfFSD1jwFANegze5eLX8PgP5BfWFH1usTB8Sw" + ] + }, + { + "path": "soljson-v0.4.22+commit.4cb486ee.js", + "version": "0.4.22", + "build": "commit.4cb486ee", + "longVersion": "0.4.22+commit.4cb486ee", + "keccak256": "0x50972c5b966188341d133aa58fbf895c54655d7bd733fb5ad58852e85f9f9444", + "sha256": "0x73458d16a3e34fc7b489d2399b3680cccfc968d01abc9f1b61e438b6fb0c24a1", + "urls": [ + "dweb:/ipfs/QmPUJNa1LYaThwLQsw6fF5DMYyDfEg57gmD5wCsazkLS8c" + ] + }, + { + "path": "soljson-v0.4.23+commit.124ca40d.js", + "version": "0.4.23", + "build": "commit.124ca40d", + "longVersion": "0.4.23+commit.124ca40d", + "keccak256": "0x74f927b4f520d8d31863996a100ebc7827f919c77f777f6d4d416c6e613a03c7", + "sha256": "0x98c350cc41f873af84a78d1e24cbc8449045ee54923af0a39440e4d84600dc50", + "urls": [ + "dweb:/ipfs/QmZbo5YkSbcenWrUDjiCvUZdQe4UrNBw9vtx9nbgcMdRAs" + ] + }, + { + "path": "soljson-v0.4.24+commit.e67f0147.js", + "version": "0.4.24", + "build": "commit.e67f0147", + "longVersion": "0.4.24+commit.e67f0147", + "keccak256": "0x4cc2bb4c8894ad4349a88f330ba74d7ea643030d3f68037d1c94c370b6a25dd7", + "sha256": "0xf83e8f7014ad6b8bc801dc3684c644e372673ed678425c35aea5d4b4fe37e922", + "urls": [ + "dweb:/ipfs/QmauztXLDUdwJitA4Uc9MQYCTttUcivR5foTZYgwt4aAeC" + ] + }, + { + "path": "soljson-v0.4.25+commit.59dbf8f1.js", + "version": "0.4.25", + "build": "commit.59dbf8f1", + "longVersion": "0.4.25+commit.59dbf8f1", + "keccak256": "0x92b9c5de10bd908527e9cfba3f04bbe637163b4a5313c5a69179ccddd5fa6685", + "sha256": "0x782a999d3e1227c86854e7e29954ee856c6ae684124b9facf09f4f1724dc4e85", + "urls": [ + "dweb:/ipfs/QmUtwmzqqCftcubfyGwAefLBQ8ffp8EFhW7HCEQfhaviFs" + ] + }, + { + "path": "soljson-v0.4.26+commit.4563c3fc.js", + "version": "0.4.26", + "build": "commit.4563c3fc", + "longVersion": "0.4.26+commit.4563c3fc", + "keccak256": "0xc9c60203789ef778b9104ae7a39e9090b3d1256b24983d49e40e7d1e3c3ed65d", + "sha256": "0x264d0d25e31cb32f4369f82ba3ad0b6a84a8a1975b10bd738123ddf947618840", + "urls": [ + "dweb:/ipfs/QmRd1uRbHRvpybQk5TQ11zyqmG4wQqHnefgvYdJ14V5D8x" + ] + }, + { + "path": "soljson-v0.5.0+commit.1d4f565a.js", + "version": "0.5.0", + "build": "commit.1d4f565a", + "longVersion": "0.5.0+commit.1d4f565a", + "keccak256": "0x2921f518cf5a0627d96e07e8c3d2b5482dbbf14d7dc6bbb055481c46d98903f3", + "sha256": "0xaf811843add541705ff65f0c20fd864bd0387116544524fa1830cf67a14af6c4", + "urls": [ + "dweb:/ipfs/QmYLhaeGbq3tFdCUC2pvtA8QdGnCbA8kn24z3C741k5TUE" + ] + }, + { + "path": "soljson-v0.5.1+commit.c8a2cb62.js", + "version": "0.5.1", + "build": "commit.c8a2cb62", + "longVersion": "0.5.1+commit.c8a2cb62", + "keccak256": "0x1980cf8a81c6bd2b371bf7d9145c819a7fb2d72e9aa462aaff0c10b4eccd595c", + "sha256": "0x69cb1300b5f72eb128604507991d9ada97180d31afde7c59aa3fa3ae9ad5200d", + "urls": [ + "dweb:/ipfs/QmPfxPYsYysRR8HFkWr47FMQ8ardmfmtrmdYc2ogT9Gfp9" + ] + }, + { + "path": "soljson-v0.5.2+commit.1df8f40c.js", + "version": "0.5.2", + "build": "commit.1df8f40c", + "longVersion": "0.5.2+commit.1df8f40c", + "keccak256": "0x3efd0585a3c00a1a2c62e590e22a69aa981d1b5148af2ebdbe1610dff93cea78", + "sha256": "0xaff4ca62ac0b03cb4b9c50f8250e2e7307b5c75fefc9847f269bd05c20367148", + "urls": [ + "dweb:/ipfs/QmaZrQSg8njYzFXH2PzwxHDLKxkBhKmYmLm43DJWnurPeJ" + ] + }, + { + "path": "soljson-v0.5.3+commit.10d17f24.js", + "version": "0.5.3", + "build": "commit.10d17f24", + "longVersion": "0.5.3+commit.10d17f24", + "keccak256": "0x9b7a39606c3c27a8619b3eb493efca512cbd26c5ab7fc95489564239aab32a50", + "sha256": "0x24b4cbc28d68bde8455c14a46b55e4f292c3c295271e09991b2176a487cb4487", + "urls": [ + "dweb:/ipfs/QmQmkd5FGiKKg8eRmo3L7Cn62nuV1M6GRDUGiq5bAx4AWx" + ] + }, + { + "path": "soljson-v0.5.4+commit.9549d8ff.js", + "version": "0.5.4", + "build": "commit.9549d8ff", + "longVersion": "0.5.4+commit.9549d8ff", + "keccak256": "0x4a6244b03de1968f0a48800e75640921d62b7602d0301093e1c5c318d1effb36", + "sha256": "0x91ed0cf4390f33174a4aaf49d1ce7cd9c72e28b95d2f9422314a29b2144b2042", + "urls": [ + "dweb:/ipfs/QmRPchg1b5ofkLnLTPuunfSMKnxbXcZyzSR4NkyJAYUTrR" + ] + }, + { + "path": "soljson-v0.5.5+commit.47a71e8f.js", + "version": "0.5.5", + "build": "commit.47a71e8f", + "longVersion": "0.5.5+commit.47a71e8f", + "keccak256": "0xf46cb35b3aefb9b3d59a1fb4c151eb23a0f0a05387b379b3e7fbed1c01c861df", + "sha256": "0xaf812445476c101ae5ef92941c79eaebf57b39d455bdfb54a6a86b4ab6ca498c", + "urls": [ + "dweb:/ipfs/QmPYEmgLWDjk7kPGovojurz7fzdGv8Ti3H66nEzRzdiGwh" + ] + }, + { + "path": "soljson-v0.5.6+commit.b259423e.js", + "version": "0.5.6", + "build": "commit.b259423e", + "longVersion": "0.5.6+commit.b259423e", + "keccak256": "0x66669372d2d958bfeb5129a387dbc3882a96e260fc12e2910a7eb148b8ea5dd6", + "sha256": "0x9ffc04d0aee2c817ae6a897b1ba5aaca2bcd860416aaddfaa4de553fc1ad6e8e", + "urls": [ + "dweb:/ipfs/QmYWL8Z3yXfCuhrprimdLhYFkjR74TjFHULxcABbUipetv" + ] + }, + { + "path": "soljson-v0.5.7+commit.6da8b019.js", + "version": "0.5.7", + "build": "commit.6da8b019", + "longVersion": "0.5.7+commit.6da8b019", + "keccak256": "0x27e324f75dd52eb180569e7a8865048253e5fcdaacc52e7c998ecaeb78dcdabd", + "sha256": "0xfd7c4e652d5891c84d93b28c90b8ac58c9253d2a3677935883a337ee96087b8f", + "urls": [ + "dweb:/ipfs/QmdEr1zJrD2UYawZzeE6zPuYiYaSHdpLtKeHYixHgRp9ko" + ] + }, + { + "path": "soljson-v0.5.8+commit.23d335f2.js", + "version": "0.5.8", + "build": "commit.23d335f2", + "longVersion": "0.5.8+commit.23d335f2", + "keccak256": "0x05c00863784c63220704197d8446ac1e277fe53c42b5264093960b7bb70b9792", + "sha256": "0x25cfdd733e9c780ab85373268fde7bfa2e4b22093af57422ca3b586c7af7cd60", + "urls": [ + "dweb:/ipfs/QmSUakgiWEffZ82RrN7hgLaemdqtLSCD7pfGAKxGhDUJxB" + ] + }, + { + "path": "soljson-v0.5.9+commit.e560f70d.js", + "version": "0.5.9", + "build": "commit.e560f70d", + "longVersion": "0.5.9+commit.e560f70d", + "keccak256": "0x7c967d9dc0fdca0db88a7cee22cf5886f65e8fa8b4a145eccd910fc81a1c949d", + "sha256": "0x7d40c6325c0aa4635babdb8913626b7c4bac6a4f41e1c383de5f398e1fc98e1b", + "urls": [ + "dweb:/ipfs/QmZcHLPfa2Dz8M3justKYyDmDnaNo4pseTgAeQbtJNYywe" + ] + }, + { + "path": "soljson-v0.5.10+commit.5a6ea5b1.js", + "version": "0.5.10", + "build": "commit.5a6ea5b1", + "longVersion": "0.5.10+commit.5a6ea5b1", + "keccak256": "0x012ae146ebdd510b31c1e44a8d60071a66cdebc77f0e743a6ebc2fe68e67d297", + "sha256": "0x566601442deff058d393359df59ed72b41e1f6a65b0aa371fab7f903c189b59d", + "urls": [ + "dweb:/ipfs/Qmej9jEnSsD2LqGnL4jgbUvHTxTwiFiHqeMpqyuPLaX1uw" + ] + }, + { + "path": "soljson-v0.5.11+commit.c082d0b4.js", + "version": "0.5.11", + "build": "commit.c082d0b4", + "longVersion": "0.5.11+commit.c082d0b4", + "keccak256": "0x4ba5500559a9ad03e4c1d3866ba9d915cdb5d7f2e326b4cb1fa0fe7bdf90dc27", + "sha256": "0x89978dcef86244b8e7af95298abe26aaf4825df819d6c556e4323dc152c988ad", + "urls": [ + "dweb:/ipfs/QmdgDj3bPSKU1xKMY8FRHj8E6z9BQefeuaVuF27RpvZMXJ" + ] + }, + { + "path": "soljson-v0.5.12+commit.7709ece9.js", + "version": "0.5.12", + "build": "commit.7709ece9", + "longVersion": "0.5.12+commit.7709ece9", + "keccak256": "0xcda83fe69ce2a319d0caa20c98b53ff36ea1886054ab3dab23fa80ede3dcdea0", + "sha256": "0x1784f89fcfffccddaa94273a58e452682f61dea05d142406775f099c6ef5d61f", + "urls": [ + "dweb:/ipfs/QmPA1Uf4iwkr2ouguzxxFepVxaRg36XFXxiwqYUuwafQzQ" + ] + }, + { + "path": "soljson-v0.5.13+commit.5b0b510c.js", + "version": "0.5.13", + "build": "commit.5b0b510c", + "longVersion": "0.5.13+commit.5b0b510c", + "keccak256": "0x432dd5d662d88c2316b4df503f693ae9e6e8ed4216726db2fdb3e7f628523fe5", + "sha256": "0x6e095eefc48dfc21fec18d0b63f229e929f881b5d6e8a999e1622c6b707a7f54", + "urls": [ + "dweb:/ipfs/QmSgJ8Ru6vraz9CyCDPMifVxpckkoooVSBj9vYcQqG4wG4" + ] + }, + { + "path": "soljson-v0.5.14+commit.01f1aaa4.js", + "version": "0.5.14", + "build": "commit.01f1aaa4", + "longVersion": "0.5.14+commit.01f1aaa4", + "keccak256": "0x98e1027fbf3acb279f740c3b38df69d79ad3f2e6171414508d50604dc2dfc13e", + "sha256": "0x43b85bc9941814b018065da5c6c8d40e2af49264d0d1f06bdefbfbe628e65ff8", + "urls": [ + "dweb:/ipfs/QmeXatGB9MdWA2NBLSNQbcKvuZpa4Sxem51vCrqyQGfXnU" + ] + }, + { + "path": "soljson-v0.5.15+commit.6a57276f.js", + "version": "0.5.15", + "build": "commit.6a57276f", + "longVersion": "0.5.15+commit.6a57276f", + "keccak256": "0x6f9251f86fd798a3ae25688307ffc7a9984dcf0d809a1aef54f5c68b6cf9fb6a", + "sha256": "0x0d34e4ed048bbf67daacdf36cd5ce0f553a32962967b52edab6afccaa071878b", + "urls": [ + "dweb:/ipfs/Qmdx3AHUB8bN6ZZs1XsTV3Gz9FV3gAB7x7JbYeUsn43Azu" + ] + }, + { + "path": "soljson-v0.5.16+commit.9c3226ce.js", + "version": "0.5.16", + "build": "commit.9c3226ce", + "longVersion": "0.5.16+commit.9c3226ce", + "keccak256": "0x6abf17bdb1b934d072739e0e083ecfd579c523d200d45184b8d3987924ca0454", + "sha256": "0xa09c9cc2672678d461dc71100600bb58802db87be4de9424769241712ccbec03", + "urls": [ + "dweb:/ipfs/QmQjodGav6KhMDjuoyJ1ag8osgKLBsFC1E9LmaGP7qCRZ2" + ] + }, + { + "path": "soljson-v0.5.17+commit.d19bba13.js", + "version": "0.5.17", + "build": "commit.d19bba13", + "longVersion": "0.5.17+commit.d19bba13", + "keccak256": "0x936e6bfbf4ea9ac32997adb893b0aeecd050cfef8b475f297dca1add0a1ff934", + "sha256": "0x7fd1d3f1fddc615e117f7fb7586acabd60c649c390cf110c8fdc5ce159fa5734", + "urls": [ + "dweb:/ipfs/QmNrRJwVHaJSZ3aAQZWZKjV9o8BqWKFP3RPYL6hKU65PAE" + ] + }, + { + "path": "soljson-v0.6.0+commit.26b70077.js", + "version": "0.6.0", + "build": "commit.26b70077", + "longVersion": "0.6.0+commit.26b70077", + "keccak256": "0xea559c55bf7046cb48378fe9b43eaab6e345700aa22d701fcf946a42ec6b1008", + "sha256": "0xf22c63511a85230f7640ff5a77433db643d8d32be8b7c7f1dc24c1301a5158e9", + "urls": [ + "dweb:/ipfs/QmTQPQb6br2VEzKTiXBEE6z69xRXEk24xi2R2gn8EsvGD9" + ] + }, + { + "path": "soljson-v0.6.1+commit.e6f7d5a4.js", + "version": "0.6.1", + "build": "commit.e6f7d5a4", + "longVersion": "0.6.1+commit.e6f7d5a4", + "keccak256": "0xb2657b5ce7a9b405a65e4a88845a51216cd7371e8f84861eef9cb0cb20d78081", + "sha256": "0x3628fdefd6971ea9cc16acbf91e5f6d6cfb2079181784b47e4d24f4c5d92e4e4", + "urls": [ + "dweb:/ipfs/QmYWAkYAJo59kc5dHWaLuQqEm7xusESdu5meDzjpxnyXKt" + ] + }, + { + "path": "soljson-v0.6.2+commit.bacdbe57.js", + "version": "0.6.2", + "build": "commit.bacdbe57", + "longVersion": "0.6.2+commit.bacdbe57", + "keccak256": "0x7dc96455c864b49abc7dd5f38ba6a47904709ad132ea36babbfce98d42e962e6", + "sha256": "0x25f564cbecc5bfe95d6d358e0e7543c31ece0ab1332c555ff323ca163711bd2b", + "urls": [ + "dweb:/ipfs/QmaLUM18c7ecA911ig5u2HY6fAu4AiUbhJpnZwwCMc9cWi" + ] + }, + { + "path": "soljson-v0.6.3+commit.8dda9521.js", + "version": "0.6.3", + "build": "commit.8dda9521", + "longVersion": "0.6.3+commit.8dda9521", + "keccak256": "0x39ae8b2f3ba05ed7d4a7c16f0a9f4f5118180a209379cfc9bdd2d4fb5d015dff", + "sha256": "0xf89514dedd8cfb3c4d351580ff80b8444acde702f8be0e5fad710fe6e906c687", + "urls": [ + "dweb:/ipfs/Qmd9JfFpUXsUQrJad1u2QDuMxBMeVrcG8mrpfJVV9jiBXB" + ] + }, + { + "path": "soljson-v0.6.4+commit.1dca32f3.js", + "version": "0.6.4", + "build": "commit.1dca32f3", + "longVersion": "0.6.4+commit.1dca32f3", + "keccak256": "0x435820544c2598d4ffbfb6f11003364c883a0766c8ac2a03215dd73022b34679", + "sha256": "0xa4fd5bb021259cdde001b03dac0e66353a3b066b47eb2476acb58b2610a224ca", + "urls": [ + "dweb:/ipfs/QmTxzbPN4HwcK5YX7n3PNkb1BzKFiRwStsmBfgC9VwrtFt" + ] + }, + { + "path": "soljson-v0.6.5+commit.f956cc89.js", + "version": "0.6.5", + "build": "commit.f956cc89", + "longVersion": "0.6.5+commit.f956cc89", + "keccak256": "0x6262768243c1ceaf91418e52dc6f52d2ce94d19c6e1065d54499b7bc4d6e14dc", + "sha256": "0xf8f83757e73f33f44389d1fa72d013fb266454a8dd9bb6897c7776f8fc3b0231", + "urls": [ + "dweb:/ipfs/QmRUoBQeA5zpun1NK7BvBhQk6pTT4uZw7Jn2wZnWQETH9W" + ] + }, + { + "path": "soljson-v0.6.6+commit.6c089d02.js", + "version": "0.6.6", + "build": "commit.6c089d02", + "longVersion": "0.6.6+commit.6c089d02", + "keccak256": "0x3c9cfccc78bf352f4c7901d7af76757bd228f93af2634af4cd16b4916c13e44e", + "sha256": "0x09f6098026622c5c334c7798c3ad2b8f7c0ebc62f87846c7d5e7e725c3d1cbc2", + "urls": [ + "dweb:/ipfs/QmRj2pxXxvmJ96i57maVjLMfs4DUtCuptM8vSVvvDweJ74" + ] + }, + { + "path": "soljson-v0.6.7+commit.b8d736ae.js", + "version": "0.6.7", + "build": "commit.b8d736ae", + "longVersion": "0.6.7+commit.b8d736ae", + "keccak256": "0xb463b6a61fc027247655a32cbfd50bf543eafa3a6b42ceacdda7293e3ada8866", + "sha256": "0xb795f1b20f065a0aee492c24071fc1efa1633c3caab77cff20278a9ae822f04e", + "urls": [ + "dweb:/ipfs/QmShUrNZf1dZFjziorJYE8fMGNUSMFsbaR3ipSvsCMvExM" + ] + }, + { + "path": "soljson-v0.6.8+commit.0bbfe453.js", + "version": "0.6.8", + "build": "commit.0bbfe453", + "longVersion": "0.6.8+commit.0bbfe453", + "keccak256": "0x537cefc0579dd9631ec952cae951b3df0a50a3e557b5638107a67275f7aacc07", + "sha256": "0x3e8b01cbd194e40971b41017ada7c8b2fa941b0458cb701bdfb6a82257ca971b", + "urls": [ + "dweb:/ipfs/Qmdq9AfwdmKfEGP8u7H9E4VYrKLVinRZPZD1EWRnXSn1oe" + ] + }, + { + "path": "soljson-v0.6.9+commit.3e3065ac.js", + "version": "0.6.9", + "build": "commit.3e3065ac", + "longVersion": "0.6.9+commit.3e3065ac", + "keccak256": "0xa2d4d3ebe5d52bfa7ddf1a1fcd9bfed81eaa8678e6a1dd5a1c84954dd064422c", + "sha256": "0xf1724fd46b7a353561b3f8d473b0dc8c855b6d84b5af559d7e3326ac79b9d758", + "urls": [ + "dweb:/ipfs/Qmad6iesaR5FQ45RRtMrt2Fa1EYDuq1oGoMJJB6beMHESn" + ] + }, + { + "path": "soljson-v0.6.10+commit.00c0fcaf.js", + "version": "0.6.10", + "build": "commit.00c0fcaf", + "longVersion": "0.6.10+commit.00c0fcaf", + "keccak256": "0x620163da7ee7b2622c9ee48b06110a52739f633189555148a3b5ecf767e60cfb", + "sha256": "0xfa27ce9d23bddaa76a4aefbafa48e48affde9a1ee7c8a5e8784cf8d4c390f655", + "urls": [ + "dweb:/ipfs/QmUinsRZvs2zFNG6FMWy7ngTYUnZccXq7MRtgpj1dPfxu4" + ] + }, + { + "path": "soljson-v0.6.11+commit.5ef660b1.js", + "version": "0.6.11", + "build": "commit.5ef660b1", + "longVersion": "0.6.11+commit.5ef660b1", + "keccak256": "0xf0abd02c495a0b4c5c9a7ff20de8b932e11fc3066d0b754422035ecd96fcdbbc", + "sha256": "0x9778e4a7667d5fd7632caf3ef3791d390a7cc217f94f96e919a31e3be332386a", + "urls": [ + "dweb:/ipfs/QmXyjgFNMyFD4fdf8wt9uvUU92MGdDVGmcPdMZhNEo1g8N" + ] + }, + { + "path": "soljson-v0.6.12+commit.27d51765.js", + "version": "0.6.12", + "build": "commit.27d51765", + "longVersion": "0.6.12+commit.27d51765", + "keccak256": "0xe1412d909a0dae79b13c0066b9bf08831c522daec00b273bbc19a799af213d6a", + "sha256": "0x3e1956c550ca48e289044c7c0bd892403081b4b5e17e77ce707c815ce6c4228f", + "urls": [ + "dweb:/ipfs/QmTs8PnAGr1ijXtWvMjoWraefAtVv2Y5ZnwkArz6NqJ93w" + ] + }, + { + "path": "soljson-v0.7.0+commit.9e61f92b.js", + "version": "0.7.0", + "build": "commit.9e61f92b", + "longVersion": "0.7.0+commit.9e61f92b", + "keccak256": "0x0c7a4386781683c327fde95363535f377941e14feffad5bb1134c7aa7eba726f", + "sha256": "0xe7e1be3d0a67469f6a37cd676a22314c4faa8a22ff9d5ebde11302db754453eb", + "urls": [ + "dweb:/ipfs/QmQFhTptWdDzhemjGpa7Q65HKWGphs4nKKS13nzkcVE8pM" + ] + }, + { + "path": "soljson-v0.7.1+commit.f4a555be.js", + "version": "0.7.1", + "build": "commit.f4a555be", + "longVersion": "0.7.1+commit.f4a555be", + "keccak256": "0x3502cf7933fbce9f1fe1d87a83d5b9df12eee36c03997c3b9821493ce03fcf3e", + "sha256": "0x7fcc983c5149840a47b946fc51fc14f1c21cda07c01d650e4a1f814319cb1423", + "urls": [ + "dweb:/ipfs/Qmdw9c3usmqgdV2w4JoNWJqscHzscKNVWsWtos1engJa1o" + ] + }, + { + "path": "soljson-v0.7.2+commit.51b20bc0.js", + "version": "0.7.2", + "build": "commit.51b20bc0", + "longVersion": "0.7.2+commit.51b20bc0", + "keccak256": "0x0c80a0bf9e17700249a04a80d7729ccb012a55a82cb0f9e412fa32cc14b09c2b", + "sha256": "0xdfa3f2bb4589bdc9c054292173c82ee70e65af8d1971598f6e13b9b79ba94185", + "urls": [ + "dweb:/ipfs/QmTNWY4vkVLgtNdfGXyH6CY8URmzr33VzMJNN37z5dsAgu" + ] + }, + { + "path": "soljson-v0.7.3+commit.9bfce1f6.js", + "version": "0.7.3", + "build": "commit.9bfce1f6", + "longVersion": "0.7.3+commit.9bfce1f6", + "keccak256": "0xcf099e7057d6c3d5acac1f4e349798ad5a581b6cb7ffcebdf5b37b86eac4872d", + "sha256": "0xcaf4b1f3e01fcf946aad2d22bbe046b9dc4fd50049a05c3458ff239e2c93a785", + "urls": [ + "dweb:/ipfs/QmQMH2o7Nz3DaQ31hNYyHVAgejqTyZouvA35Zzzwe2UBPt" + ] + }, + { + "path": "soljson-v0.7.4+commit.3f05b770.js", + "version": "0.7.4", + "build": "commit.3f05b770", + "longVersion": "0.7.4+commit.3f05b770", + "keccak256": "0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3", + "sha256": "0x2b55ed5fec4d9625b6c7b3ab1abd2b7fb7dd2a9c68543bf0323db2c7e2d55af2", + "urls": [ + "dweb:/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS" + ] + }, + { + "path": "soljson-v0.7.5+commit.eb77ed08.js", + "version": "0.7.5", + "build": "commit.eb77ed08", + "longVersion": "0.7.5+commit.eb77ed08", + "keccak256": "0xfe223dd264421f9b96c3dd3c835a3d0d4d9cfa4c61f75ca0761860c9ae8906ca", + "sha256": "0x2ee1c6434a32a40b137ac28be12ceeba64701bfad5e80239690803d9c139908e", + "urls": [ + "dweb:/ipfs/Qmf5fpJmeHdwgmSjQPqdu25XtA9akTotakkNmrh4axgo8N" + ] + }, + { + "path": "soljson-v0.7.6+commit.7338295f.js", + "version": "0.7.6", + "build": "commit.7338295f", + "longVersion": "0.7.6+commit.7338295f", + "keccak256": "0xc68517effed7163db0c7f4559931a4c5530fe6f2a8a20596361640d9d7eff655", + "sha256": "0xb94e69dfb056b3e26080f805ab43b668afbc0ac70bf124bfb7391ecfc0172ad2", + "urls": [ + "dweb:/ipfs/QmWjG6PLzF5M6kxkHujhEMg5znQCgf2m1cM1UptKA719Hy" + ] + }, + { + "path": "soljson-v0.8.0+commit.c7dfd78e.js", + "version": "0.8.0", + "build": "commit.c7dfd78e", + "longVersion": "0.8.0+commit.c7dfd78e", + "keccak256": "0x08dd57a5cf5fd59accbd5b601909ffa22d28da756b5367c29b523ff17bbc2f99", + "sha256": "0xc596765f9b3dce486cf596ea35676f37124d54f3ada0fcbc02f094c392066a59", + "urls": [ + "dweb:/ipfs/QmYh5C2rgDAx452f7HyHA8soLhnoL1GeeNNEWEuw9jKY8w" + ] + }, + { + "path": "soljson-v0.8.1+commit.df193b15.js", + "version": "0.8.1", + "build": "commit.df193b15", + "longVersion": "0.8.1+commit.df193b15", + "keccak256": "0x84a0e9282047512eeec499d55c83dbb6981430b08692d81d6c09730bb18e6cd8", + "sha256": "0xf77f141e5fed9594b28342e2c630ac6d48f2a724e4383a457881acd7fa62b1cf", + "urls": [ + "dweb:/ipfs/QmQ6W5VedQpZAwuGTtp1BhmNkvVheLnJq4xwN9Qmt9bAbH" + ] + }, + { + "path": "soljson-v0.8.2+commit.661d1103.js", + "version": "0.8.2", + "build": "commit.661d1103", + "longVersion": "0.8.2+commit.661d1103", + "keccak256": "0xd0c15275c5b0d03871332719def9b0f17e8860c7db60e0e71f18b971458a7391", + "sha256": "0x015e83fb0b72ccdafb0c217961b21a0321adb2d3f2ad992f5e79635c2086e6dd", + "urls": [ + "dweb:/ipfs/QmdfVfa2mhyosaJVeV7rbfnvQ95GTHPeRPzmvxcds7RYej" + ] + }, + { + "path": "soljson-v0.8.3+commit.8d00100c.js", + "version": "0.8.3", + "build": "commit.8d00100c", + "longVersion": "0.8.3+commit.8d00100c", + "keccak256": "0x51777116af58223a41aa3016d0bf733bbb0f78ad9ba4bcc36487eba175f65015", + "sha256": "0xb5cedfa8de5f9421fbdaccf9fd5038652c2632344b3b68e5278de81e9aeac210", + "urls": [ + "dweb:/ipfs/QmWbNMzJryhiZmyifLDQteGPwN4aTgXQB6barBvXYVw975" + ] + }, + { + "path": "soljson-v0.8.4+commit.c7e474f2.js", + "version": "0.8.4", + "build": "commit.c7e474f2", + "longVersion": "0.8.4+commit.c7e474f2", + "keccak256": "0x7e0bca960d11fb095798ff65d029436f23358ac060b25a0938acfcb4652da2ec", + "sha256": "0x4a14c7bcaf0d988a829db2174b8f7731898aa8633216490603ad74bff64eca3c", + "urls": [ + "dweb:/ipfs/QmPYDf4qYtZLNEAicW7hcvpUJ69FoHiXmUypipDpTKo9hU" + ] + }, + { + "path": "soljson-v0.8.5+commit.a4f2e591.js", + "version": "0.8.5", + "build": "commit.a4f2e591", + "longVersion": "0.8.5+commit.a4f2e591", + "keccak256": "0x6d6d75b033717aae0a728e527005d8d2cc7dbd0a835c8873c630a2a9689a2976", + "sha256": "0x4af595f976235d33a22ffe223e9e3210b4ca510f6a93f153b3daed60f2b11fbc", + "urls": [ + "dweb:/ipfs/QmNWkyirqXy3gDHNXpPuVUbExMGWjMqPR82Xzs64RzgQzy" + ] + }, + { + "path": "soljson-v0.8.6+commit.11564f7e.js", + "version": "0.8.6", + "build": "commit.11564f7e", + "longVersion": "0.8.6+commit.11564f7e", + "keccak256": "0x070e41c7f761ff1a8383a2c0d54c22aab0f115ca8c3790ecea27d6dde11611ca", + "sha256": "0x06a671efd8865a6ecc0ad648076177b35abcd06a7059888ea65111272e33a57f", + "urls": [ + "dweb:/ipfs/QmQre11ZPgWSx79Jzca1tkTYFyMbXz8H4kcrhfpWSj4qs8" + ] + }, + { + "path": "soljson-v0.8.7+commit.e28d00a7.js", + "version": "0.8.7", + "build": "commit.e28d00a7", + "longVersion": "0.8.7+commit.e28d00a7", + "keccak256": "0x8d6be9e58c33d265b5a8b1132a27fce126067419f3f4f15d3ef6b7147593b61d", + "sha256": "0x663ba99f7c7ee907f0f03227502d48a78256c3c292ace3b79a5d3eb510665306", + "urls": [ + "dweb:/ipfs/QmYv3Rsi9pL6PZAtc4XLHezPqti8yCRGEdDBqzEsQv57GV" + ] + }, + { + "path": "soljson-v0.8.8+commit.dddeac2f.js", + "version": "0.8.8", + "build": "commit.dddeac2f", + "longVersion": "0.8.8+commit.dddeac2f", + "keccak256": "0x56cb2f6978bf1213982ef217ee76b39dc97b6e66c92a7be7a1b44079c0236e5c", + "sha256": "0x534b7d4079d13bb4cd10b7559dc105c2adec625df4105f20ebce47e6da60bfda", + "urls": [ + "dweb:/ipfs/QmZaSrn3TPvPVoShtjSonQLFd3BV6RdgRMqw8GTzhnKYpm" + ] + }, + { + "path": "soljson-v0.8.9+commit.e5eed63a.js", + "version": "0.8.9", + "build": "commit.e5eed63a", + "longVersion": "0.8.9+commit.e5eed63a", + "keccak256": "0xbc470ab3442e78bb4d3f16c01c39b2f160f4f34eb4373efed11c234e1c7f6ca0", + "sha256": "0x5b25f987aae32a0275fdc6c1be36cc47cf126024a04dafd8e4be39a1d1d1422c", + "urls": [ + "dweb:/ipfs/QmfFq3MvisCSUJy8N8EVsBribgPbdpTZb7tQ2eHYw7dwag" + ] + }, + { + "path": "soljson-v0.8.10+commit.fc410830.js", + "version": "0.8.10", + "build": "commit.fc410830", + "longVersion": "0.8.10+commit.fc410830", + "keccak256": "0x3820aae0de50f10f62819d65f0b5a236ccffed11ab465a3295a5408fa47e24f5", + "sha256": "0x5eaee3240a06891abf5ac70c75caf9a0c33ebe9a2736abdaa22a337f86c22933", + "urls": [ + "dweb:/ipfs/QmcsfYpEWbPXfVptzi1YvGokxi2FYCUzUr8rQYJCc5fEiB" + ] + }, + { + "path": "soljson-v0.8.11+commit.d7f03943.js", + "version": "0.8.11", + "build": "commit.d7f03943", + "longVersion": "0.8.11+commit.d7f03943", + "keccak256": "0x798b23086ce1339e3d47b3648a1f3ae40561e2c9f66ffcc98e71fc14a7f77584", + "sha256": "0x64117d4b13bfc5bc6e5f80823519b140e753a0c09e99edd756772dc3029bc1f8", + "urls": [ + "dweb:/ipfs/QmNQTFQmfnjxnDmbguVSnZ5DiHGFQHCsffccW5c2DMcSsT" + ] + }, + { + "path": "soljson-v0.8.12+commit.f00d7308.js", + "version": "0.8.12", + "build": "commit.f00d7308", + "longVersion": "0.8.12+commit.f00d7308", + "keccak256": "0xdd4ae95607655404b769fab5f949ac95c6a1a506330f512aef0d92974c390431", + "sha256": "0xc2c4738c96ad329cbb9baea615ed50ffb5a53d93fed8e00785e47242581d3c60", + "urls": [ + "dweb:/ipfs/QmVdW2ygaT2vecoSUog3HUn8hZqXU4XXQZvuRSdpV6DJPL" + ] + }, + { + "path": "soljson-v0.8.13+commit.abaa5c0e.js", + "version": "0.8.13", + "build": "commit.abaa5c0e", + "longVersion": "0.8.13+commit.abaa5c0e", + "keccak256": "0x9afa714859d1c8f8ed2fded497b83a7a420474282494d25d4c9f592667729f21", + "sha256": "0x387343bcf8f2b77fe4cdcddcaa84361fabf8e1c3508f874fbbcbb9c313542f56", + "urls": [ + "dweb:/ipfs/Qma9V9dJwmkim98H6DQX4f7RH395vsUuqHCDxbKetcbj18" + ] + }, + { + "path": "soljson-v0.8.14+commit.80d49f37.js", + "version": "0.8.14", + "build": "commit.80d49f37", + "longVersion": "0.8.14+commit.80d49f37", + "keccak256": "0xb0f7f19a8590e5c0aaf779019c1deaafed170d8c26bec9bfd782d212e097619e", + "sha256": "0x7c3b3d0066fd381283b1d8d9a86153b2ddb5c01da14a1ae015c05cfa484e81b6", + "urls": [ + "dweb:/ipfs/QmcM1TcDB4ta8ttNLWZ4d24M4Qs35rc91sQkdNmJMNbuvV" + ] + }, + { + "path": "soljson-v0.8.15+commit.e14f2714.js", + "version": "0.8.15", + "build": "commit.e14f2714", + "longVersion": "0.8.15+commit.e14f2714", + "keccak256": "0x4f6cdc0f25e734bcb977bb6a3e22fa41d8a82cbd5f220a2e4238c2d233526d1a", + "sha256": "0x71135e459d691767ce3453bab4564ef4a640dd50182da36517cbc1f96c1d4c7c", + "urls": [ + "dweb:/ipfs/QmPiBrYZxxpNZPQ98GNyL7Xa1F9Dq7uHtdt9ESwhPNkHhc" + ] + }, + { + "path": "soljson-v0.8.16+commit.07a7930e.js", + "version": "0.8.16", + "build": "commit.07a7930e", + "longVersion": "0.8.16+commit.07a7930e", + "keccak256": "0x331f4bc6de3d44d87b68629e83f711105325b482da7e9ca9bdbdd01371fee438", + "sha256": "0x27b2820ef93805a65c76b7945a49432582d306fd17a28985709a51e6403677c2", + "urls": [ + "dweb:/ipfs/QmWzBJ8gdccvRSSB5YsMKiF2qt3RFmAP2X25QEWqqQnR4y" + ] + }, + { + "path": "soljson-v0.8.17+commit.8df45f5f.js", + "version": "0.8.17", + "build": "commit.8df45f5f", + "longVersion": "0.8.17+commit.8df45f5f", + "keccak256": "0x3f2be218cf4545b4d2e380417c6da1e008fdc4255ab38c9ee12f64c0e3f55ea9", + "sha256": "0x617828e63be485c7cc2dbcbdd5a22b582b40fafaa41016ad595637b83c90656c", + "urls": [ + "dweb:/ipfs/QmTedx1wBKSUaLatuqXYngjfKQLD2cGqPKjdLYCnbMYwiz" + ] + }, + { + "path": "soljson-v0.8.18+commit.87f61d96.js", + "version": "0.8.18", + "build": "commit.87f61d96", + "longVersion": "0.8.18+commit.87f61d96", + "keccak256": "0x9a8fa4183ef95496045189b80dfb39f745db89a903b398e40131f500953e5d57", + "sha256": "0xd82bdcba2c386d60b33aca148a9cfdf097551f68c5e45d8ec01aebbafacf5075", + "urls": [ + "dweb:/ipfs/QmcKzrqRBy7PeFQxzJDs1AZZzNHKaKbJces6zUDysXZofJ" + ] + }, + { + "path": "soljson-v0.8.19+commit.7dd6d404.js", + "version": "0.8.19", + "build": "commit.7dd6d404", + "longVersion": "0.8.19+commit.7dd6d404", + "keccak256": "0x6be35b86f5656c06ae897ef311c28da375bdcbded68c4a81e124f2cb36adf830", + "sha256": "0xe0b74e0a16e783a35169f74d1a615ecb48d07c30f97346b83cd587949268681e", + "urls": [ + "dweb:/ipfs/QmPnhNtzrEBeWWQMXdAByQTDPoKXXV9NFXLk3YL4QbghMP" + ] + }, + { + "path": "soljson-v0.8.20+commit.a1b79de6.js", + "version": "0.8.20", + "build": "commit.a1b79de6", + "longVersion": "0.8.20+commit.a1b79de6", + "keccak256": "0x3a420fa9963772eee5b9221ebb8cf9548eea8f88b09537390960ea9b440f333c", + "sha256": "0x5c509f760dc110a695c8b39bbc21e08c17dee431aa14d606f59e623d7c3cc657", + "urls": [ + "dweb:/ipfs/QmciAxUX2kfuoxitmMdkKSfWn2SfxQdieLRa3S5S2munot" + ] + }, + { + "path": "soljson-v0.8.21+commit.d9974bed.js", + "version": "0.8.21", + "build": "commit.d9974bed", + "longVersion": "0.8.21+commit.d9974bed", + "keccak256": "0x370efd28e2d28b6d0ba55e20d8994f3d286c3772552ed63586b5fe157c0d3c57", + "sha256": "0x45bea352b41d04039e19439962ddef1d3e10cf2bc9526feba39f2cc79e3c5a17", + "urls": [ + "dweb:/ipfs/QmXLgy6oexvCBWYS5pTpJWohsDNGqgdNFLRKX7JrE3NxYt" + ] + }, + { + "path": "soljson-v0.8.22+commit.4fc1097e.js", + "version": "0.8.22", + "build": "commit.4fc1097e", + "longVersion": "0.8.22+commit.4fc1097e", + "keccak256": "0x907eeba6e6e0d6977ac5a8f50e4dd2762539ca827ceab1afb1f5a4f0f3ce3e0c", + "sha256": "0x92d283c545395b91a656fa1ec94d567a464bca55aebcdbb99debf42b43026845", + "urls": [ + "dweb:/ipfs/Qma6o4e57YtWj8cQLQs12r2Enx9qmRA7VHtupCauXjYTAk" + ] + }, + { + "path": "soljson-v0.8.23+commit.f704f362.js", + "version": "0.8.23", + "build": "commit.f704f362", + "longVersion": "0.8.23+commit.f704f362", + "keccak256": "0x743aaafac24d9740a0b71215f55a132f89336a662487944767ca4bfd66400769", + "sha256": "0x9c681b165c8647867589c0a5ecdc8692637a935928a2b1bbea2ff4a1f4976985", + "urls": [ + "dweb:/ipfs/QmZy5ho8W943FMGwppXZFS1WFrVwV3UXhUUwcD7oH5vrYe" + ] + }, + { + "path": "soljson-v0.8.24+commit.e11b9ed9.js", + "version": "0.8.24", + "build": "commit.e11b9ed9", + "longVersion": "0.8.24+commit.e11b9ed9", + "keccak256": "0x1b6ceeabad21bbb2011ba13373160f7c4d46c11371a354243ee1be07159345f3", + "sha256": "0x11b054b55273ec55f6ab3f445eb0eb2c83a23fed43d10079d34ac3eabe6ed8b1", + "urls": [ + "dweb:/ipfs/QmW2SQbEhiz3n2qV5iL8WBgzapv6cXjkLStvTMpCZhvr2x" + ] + }, + { + "path": "soljson-v0.8.25+commit.b61c2a91.js", + "version": "0.8.25", + "build": "commit.b61c2a91", + "longVersion": "0.8.25+commit.b61c2a91", + "keccak256": "0x4639103a26b2f669bd3ecc22b1a1665819f2a2956f917ab91380bd9565dbcd01", + "sha256": "0xf8c9554471ff2db3843167dffb7a503293b5dc728c8305b044ef9fd37d626ca7", + "urls": [ + "dweb:/ipfs/QmdduJxmPXungjJk2FBDw1bdDQ6ucHxYGLXRMBJqMFW7h9" + ] + }, + { + "path": "soljson-v0.8.26+commit.8a97fa7a.js", + "version": "0.8.26", + "build": "commit.8a97fa7a", + "longVersion": "0.8.26+commit.8a97fa7a", + "keccak256": "0x34ffb570dd3b2041e3df86cb1f9190256cd28ee5a6f3d4200fe4b9747d33f901", + "sha256": "0xdb85e5396f523cc1a53c4c4d742e204f6dcba1a05842623d73be946809e11cd6", + "urls": [ + "dweb:/ipfs/QmS5JdeXtYhGBvdgNTLWuBNHupyP623X4sf43fRbrgiTaA" + ] + } + ], + "releases": { + "0.8.26": "soljson-v0.8.26+commit.8a97fa7a.js", + "0.8.25": "soljson-v0.8.25+commit.b61c2a91.js", + "0.8.24": "soljson-v0.8.24+commit.e11b9ed9.js", + "0.8.23": "soljson-v0.8.23+commit.f704f362.js", + "0.8.22": "soljson-v0.8.22+commit.4fc1097e.js", + "0.8.21": "soljson-v0.8.21+commit.d9974bed.js", + "0.8.20": "soljson-v0.8.20+commit.a1b79de6.js", + "0.8.19": "soljson-v0.8.19+commit.7dd6d404.js", + "0.8.18": "soljson-v0.8.18+commit.87f61d96.js", + "0.8.17": "soljson-v0.8.17+commit.8df45f5f.js", + "0.8.16": "soljson-v0.8.16+commit.07a7930e.js", + "0.8.15": "soljson-v0.8.15+commit.e14f2714.js", + "0.8.14": "soljson-v0.8.14+commit.80d49f37.js", + "0.8.13": "soljson-v0.8.13+commit.abaa5c0e.js", + "0.8.12": "soljson-v0.8.12+commit.f00d7308.js", + "0.8.11": "soljson-v0.8.11+commit.d7f03943.js", + "0.8.10": "soljson-v0.8.10+commit.fc410830.js", + "0.8.9": "soljson-v0.8.9+commit.e5eed63a.js", + "0.8.8": "soljson-v0.8.8+commit.dddeac2f.js", + "0.8.7": "soljson-v0.8.7+commit.e28d00a7.js", + "0.8.6": "soljson-v0.8.6+commit.11564f7e.js", + "0.8.5": "soljson-v0.8.5+commit.a4f2e591.js", + "0.8.4": "soljson-v0.8.4+commit.c7e474f2.js", + "0.8.3": "soljson-v0.8.3+commit.8d00100c.js", + "0.8.2": "soljson-v0.8.2+commit.661d1103.js", + "0.8.1": "soljson-v0.8.1+commit.df193b15.js", + "0.8.0": "soljson-v0.8.0+commit.c7dfd78e.js", + "0.7.6": "soljson-v0.7.6+commit.7338295f.js", + "0.7.5": "soljson-v0.7.5+commit.eb77ed08.js", + "0.7.4": "soljson-v0.7.4+commit.3f05b770.js", + "0.7.3": "soljson-v0.7.3+commit.9bfce1f6.js", + "0.7.2": "soljson-v0.7.2+commit.51b20bc0.js", + "0.7.1": "soljson-v0.7.1+commit.f4a555be.js", + "0.7.0": "soljson-v0.7.0+commit.9e61f92b.js", + "0.6.12": "soljson-v0.6.12+commit.27d51765.js", + "0.6.11": "soljson-v0.6.11+commit.5ef660b1.js", + "0.6.10": "soljson-v0.6.10+commit.00c0fcaf.js", + "0.6.9": "soljson-v0.6.9+commit.3e3065ac.js", + "0.6.8": "soljson-v0.6.8+commit.0bbfe453.js", + "0.6.7": "soljson-v0.6.7+commit.b8d736ae.js", + "0.6.6": "soljson-v0.6.6+commit.6c089d02.js", + "0.6.5": "soljson-v0.6.5+commit.f956cc89.js", + "0.6.4": "soljson-v0.6.4+commit.1dca32f3.js", + "0.6.3": "soljson-v0.6.3+commit.8dda9521.js", + "0.6.2": "soljson-v0.6.2+commit.bacdbe57.js", + "0.6.1": "soljson-v0.6.1+commit.e6f7d5a4.js", + "0.6.0": "soljson-v0.6.0+commit.26b70077.js", + "0.5.17": "soljson-v0.5.17+commit.d19bba13.js", + "0.5.16": "soljson-v0.5.16+commit.9c3226ce.js", + "0.5.15": "soljson-v0.5.15+commit.6a57276f.js", + "0.5.14": "soljson-v0.5.14+commit.01f1aaa4.js", + "0.5.13": "soljson-v0.5.13+commit.5b0b510c.js", + "0.5.12": "soljson-v0.5.12+commit.7709ece9.js", + "0.5.11": "soljson-v0.5.11+commit.c082d0b4.js", + "0.5.10": "soljson-v0.5.10+commit.5a6ea5b1.js", + "0.5.9": "soljson-v0.5.9+commit.e560f70d.js", + "0.5.8": "soljson-v0.5.8+commit.23d335f2.js", + "0.5.7": "soljson-v0.5.7+commit.6da8b019.js", + "0.5.6": "soljson-v0.5.6+commit.b259423e.js", + "0.5.5": "soljson-v0.5.5+commit.47a71e8f.js", + "0.5.4": "soljson-v0.5.4+commit.9549d8ff.js", + "0.5.3": "soljson-v0.5.3+commit.10d17f24.js", + "0.5.2": "soljson-v0.5.2+commit.1df8f40c.js", + "0.5.1": "soljson-v0.5.1+commit.c8a2cb62.js", + "0.5.0": "soljson-v0.5.0+commit.1d4f565a.js", + "0.4.26": "soljson-v0.4.26+commit.4563c3fc.js", + "0.4.25": "soljson-v0.4.25+commit.59dbf8f1.js", + "0.4.24": "soljson-v0.4.24+commit.e67f0147.js", + "0.4.23": "soljson-v0.4.23+commit.124ca40d.js", + "0.4.22": "soljson-v0.4.22+commit.4cb486ee.js", + "0.4.21": "soljson-v0.4.21+commit.dfe3193c.js", + "0.4.20": "soljson-v0.4.20+commit.3155dd80.js", + "0.4.19": "soljson-v0.4.19+commit.c4cbbb05.js", + "0.4.18": "soljson-v0.4.18+commit.9cf6e910.js", + "0.4.17": "soljson-v0.4.17+commit.bdeb9e52.js", + "0.4.16": "soljson-v0.4.16+commit.d7661dd9.js", + "0.4.15": "soljson-v0.4.15+commit.bbb8e64f.js", + "0.4.14": "soljson-v0.4.14+commit.c2215d46.js", + "0.4.13": "soljson-v0.4.13+commit.0fb4cb1a.js", + "0.4.12": "soljson-v0.4.12+commit.194ff033.js", + "0.4.11": "soljson-v0.4.11+commit.68ef5810.js", + "0.4.10": "soljson-v0.4.10+commit.f0d539ae.js", + "0.4.9": "soljson-v0.4.9+commit.364da425.js", + "0.4.8": "soljson-v0.4.8+commit.60cc1668.js", + "0.4.7": "soljson-v0.4.7+commit.822622cf.js", + "0.4.6": "soljson-v0.4.6+commit.2dabbdf0.js", + "0.4.5": "soljson-v0.4.5+commit.b318366e.js", + "0.4.4": "soljson-v0.4.4+commit.4633f3de.js", + "0.4.3": "soljson-v0.4.3+commit.2353da71.js", + "0.4.2": "soljson-v0.4.2+commit.af6afb04.js", + "0.4.1": "soljson-v0.4.1+commit.4fc6fc2c.js", + "0.4.0": "soljson-v0.4.0+commit.acd334c9.js", + "0.3.6": "soljson-v0.3.6+commit.3fc68da5.js" + }, + "latestRelease": "0.8.26" +} \ No newline at end of file diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js index 9dab012bd5..7c333fd0cc 100644 --- a/apps/remix-ide/src/remixAppManager.js +++ b/apps/remix-ide/src/remixAppManager.js @@ -7,7 +7,8 @@ import {Registry} from '@remix-project/remix-lib' const _paq = (window._paq = window._paq || []) // requiredModule removes the plugin from the plugin manager list on UI -let requiredModules = [ // services + layout views + system views +let requiredModules = [ + // services + layout views + system views 'manager', 'config', 'compilerArtefacts', @@ -92,14 +93,14 @@ let requiredModules = [ // services + layout views + system views // dependentModules shouldn't be manually activated (e.g hardhat is activated by remixd) const dependentModules = ['foundry', 'hardhat', 'truffle', 'slither'] -const loadLocalPlugins = ['doc-gen', 'doc-viewer', 'etherscan', 'vyper', 'solhint', 'walletconnect', 'circuit-compiler', 'learneth', 'quick-dapp'] +const loadLocalPlugins = ['doc-gen', 'doc-viewer', 'etherscan', 'contract-verification', 'vyper', 'solhint', 'walletconnect', 'circuit-compiler', 'learneth', 'quick-dapp'] const partnerPlugins = ['cookbookdev'] const sensitiveCalls = { fileManager: ['writeFile', 'copyFile', 'rename', 'copyDir'], contentImport: ['resolveAndSave'], - web3Provider: ['sendAsync'] + web3Provider: ['sendAsync'], } const isInjectedProvider = (name) => { @@ -316,7 +317,7 @@ export class RemixAppManager extends PluginManager { path: [], pattern: [], sticky: true, - group: 5 + group: 5, }) await this.call('filePanel', 'registerContextMenuItem', { id: 'nahmii-compiler', @@ -327,7 +328,7 @@ export class RemixAppManager extends PluginManager { path: [], pattern: [], sticky: true, - group: 6 + group: 6, }) await this.call('filePanel', 'registerContextMenuItem', { id: 'solidityumlgen', @@ -338,7 +339,7 @@ export class RemixAppManager extends PluginManager { path: [], pattern: [], sticky: true, - group: 7 + group: 7, }) await this.call('filePanel', 'registerContextMenuItem', { id: 'doc-gen', @@ -349,7 +350,7 @@ export class RemixAppManager extends PluginManager { path: [], pattern: [], sticky: true, - group: 7 + group: 7, }) await this.call('filePanel', 'registerContextMenuItem', { id: 'vyper', @@ -360,7 +361,7 @@ export class RemixAppManager extends PluginManager { path: [], pattern: [], sticky: true, - group: 7 + group: 7, }) if (Registry.getInstance().get('platform').api.isDesktop()) { await this.call('filePanel', 'registerContextMenuItem', { @@ -372,7 +373,7 @@ export class RemixAppManager extends PluginManager { path: [], pattern: [], sticky: true, - group: 8 + group: 8, }) await this.call('filePanel', 'registerContextMenuItem', { id: 'fs', @@ -383,7 +384,7 @@ export class RemixAppManager extends PluginManager { path: [], pattern: [], sticky: true, - group: 8 + group: 8, }) } } @@ -418,7 +419,7 @@ class PluginLoader { }, get: () => { return JSON.parse(localStorage.getItem('workspace')) - } + }, } this.loaders.queryParams = { @@ -429,7 +430,7 @@ class PluginLoader { const {activate} = queryParams.get() if (!activate) return [] return activate.split(',') - } + }, } this.current = queryParams.get().activate ? 'queryParams' : 'localStorage'