From bc98aabbfca2077f377ec09f0672aff011ccd976 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 2 Sep 2022 10:41:38 +0200 Subject: [PATCH 01/25] add loops --- .../providers/completion/completionGlobals.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts b/libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts index 4c5285e9ef..a3dd0f05e8 100644 --- a/libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts +++ b/libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts @@ -148,6 +148,27 @@ export function getCompletionSnippets(range: IRange, monaco): monaco.languages.C insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, range }, + { + label: 'while loop', + kind: monaco.languages.CompletionItemKind.Snippet, + insertText: 'while (${1:condition}) \n{\n\t${2:code}\n};', + insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + range + }, + { + label: 'do while loop', + kind: monaco.languages.CompletionItemKind.Snippet, + insertText: 'do {\n\t${2:code}\n} \nwhile (${1:condition});', + insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + range + }, + { + label: 'for loop', + kind: monaco.languages.CompletionItemKind.Snippet, + insertText: 'for (${1:init}; ${2:condition}; ${3:increment}) \n{\n\t${4:code}\n};', + insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + range + }, { label: 'pragma', kind: monaco.languages.CompletionItemKind.Snippet, From b76d5cd8d75a96708fe2059820bca2c3fa841ed6 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 5 Sep 2022 15:02:39 +0200 Subject: [PATCH 02/25] better electron support --- apps/remix-ide/src/app.js | 4 ---- libs/remix-ui/workspace/src/lib/actions/index.ts | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index 0a4f982fa4..b001164e9c 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -354,10 +354,6 @@ class AppComponent { const queryParams = new QueryParams() const params = queryParams.get() - if (isElectron()) { - this.appManager.activatePlugin('remixd') - } - try { this.engine.register(await this.appManager.registeredPlugins()) } catch (e) { diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index afc401c744..8627c25c7e 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -8,6 +8,7 @@ import { createWorkspaceTemplate, getWorkspaces, loadWorkspacePreset, setPlugin, import { QueryParams } from '@remix-project/remix-lib' import { fetchContractFromEtherscan } from '@remix-project/core-plugin' // eslint-disable-line import JSZip from 'jszip' +import isElectron from 'is-electron' export * from './events' export * from './workspace' @@ -111,6 +112,8 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React. await basicWorkspaceInit(workspaces, workspaceProvider) } } else await basicWorkspaceInit(workspaces, workspaceProvider) + } else if (isElectron()) { + await plugin.call('manager', 'activatePlugin', 'remixd') } else if (localStorage.getItem("currentWorkspace")) { const index = workspaces.findIndex(element => element.name == localStorage.getItem("currentWorkspace")) if (index !== -1) { From 5bf47e08b234e66d832012cce329ef271781f804 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Mon, 5 Sep 2022 15:29:03 +0200 Subject: [PATCH 03/25] fix calls --- .../src/app/plugins/parser/code-parser.tsx | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/remix-ide/src/app/plugins/parser/code-parser.tsx b/apps/remix-ide/src/app/plugins/parser/code-parser.tsx index c9caf3b70c..42d7c866bf 100644 --- a/apps/remix-ide/src/app/plugins/parser/code-parser.tsx +++ b/apps/remix-ide/src/app/plugins/parser/code-parser.tsx @@ -87,6 +87,18 @@ export class CodeParser extends Plugin { } } + async handleChangeEvents() { + const completionSettings = await this.call('config', 'getAppParameter', 'auto-completion') + if (completionSettings) { + await this.antlrService.getCurrentFileAST() + } + const showGasSettings = await this.call('config', 'getAppParameter', 'show-gas') + const showErrorSettings = await this.call('config', 'getAppParameter', 'display-errors') + if(showGasSettings || showErrorSettings) { + await this.compilerService.compile() + } + } + async onActivation() { this.gasService = new CodeParserGasService(this) @@ -102,8 +114,7 @@ export class CodeParser extends Plugin { this.on('editor', 'didChangeFile', async (file) => { await this.call('editor', 'discardLineTexts') - await this.antlrService.getCurrentFileAST() - await this.compilerService.compile() + await this.handleChangeEvents() }) this.on('filePanel', 'setWorkspace', async () => { @@ -113,8 +124,7 @@ export class CodeParser extends Plugin { this.on('fileManager', 'currentFileChanged', async () => { await this.call('editor', 'discardLineTexts') - await this.antlrService.getCurrentFileAST() - await this.compilerService.compile() + await this.handleChangeEvents() }) this.on('solidity', 'loadingCompiler', async (url) => { @@ -188,10 +198,10 @@ export class CodeParser extends Plugin { const index = {} const contractName: string = contractNode.name const callback = (node) => { - if(inScope && node.scope !== contractNode.id + if (inScope && node.scope !== contractNode.id && !(node.nodeType === 'EnumDefinition' || node.nodeType === 'EventDefinition' || node.nodeType === 'ModifierDefinition')) return - if(inScope) node.isClassNode = true; + if (inScope) node.isClassNode = true; node.gasEstimate = this._getContractGasEstimate(node, contractName, fileName, compilatioResult) node.functionName = node.name + this._getInputParams(node) node.contractName = contractName @@ -227,11 +237,11 @@ export class CodeParser extends Plugin { if ((node.scope && node.scope === baseContract.id) || node.nodeType === 'EnumDefinition' || node.nodeType === 'EventDefinition' - ) { + ) { baseNodesWithBaseContractScope[node.id] = node } - if(node.members){ - for(const member of node.members){ + if (node.members) { + for (const member of node.members) { member.contractName = (baseContract as any).name member.contractId = (baseContract as any).id member.isBaseNode = true; @@ -249,7 +259,7 @@ export class CodeParser extends Plugin { if (node.nodeType === 'ImportDirective') { const imported = await this.resolveImports(node, {}) - + for (const importedNode of (Object.values(imported) as any)) { if (importedNode.nodes) for (const subNode of importedNode.nodes) { From 06cd09fa83ad5a56ad12fc8d017f09e84b25e86d Mon Sep 17 00:00:00 2001 From: filip mertens Date: Mon, 5 Sep 2022 15:31:08 +0200 Subject: [PATCH 04/25] disable by default --- libs/remix-ui/settings/src/lib/remix-ui-settings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx index 0a24d3b038..55f25bb3d8 100644 --- a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx +++ b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx @@ -148,7 +148,7 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => { const isEditorWrapChecked = props.config.get('settings/text-wrap') || false const isPersonalChecked = props.config.get('settings/personal-mode') || false const isMatomoChecked = props.config.get('settings/matomo-analytics') || false - const isAutoCompleteChecked = props.config.get('settings/auto-completion') === null ? true:props.config.get('settings/auto-completion') + const isAutoCompleteChecked = props.config.get('settings/auto-completion') === null ? false:props.config.get('settings/auto-completion') const isShowGasInEditorChecked = props.config.get('settings/show-gas') === null ? true:props.config.get('settings/show-gas') const displayErrorsChecked = props.config.get('settings/display-errors') === null ? true:props.config.get('settings/display-errors') return ( From 203201449ff5b8dc1ae6bd077a4004dc643ec11e Mon Sep 17 00:00:00 2001 From: filip mertens Date: Mon, 5 Sep 2022 15:40:10 +0200 Subject: [PATCH 05/25] turn off by default --- libs/remix-ui/settings/src/lib/remix-ui-settings.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx index 55f25bb3d8..4b5da79895 100644 --- a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx +++ b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx @@ -41,13 +41,13 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => { if (javascriptVM === null || javascriptVM === undefined) ethereumVM(props.config, true, dispatch) const useAutoComplete = props.config.get('settings/auto-completion') - if (useAutoComplete === null || useAutoComplete === undefined) useAutoCompletion(props.config, true, dispatch) + if (useAutoComplete === null || useAutoComplete === undefined) useAutoCompletion(props.config, false, dispatch) const displayErrors = props.config.get('settings/display-errors') - if (displayErrors === null || displayErrors === undefined) useDisplayErrors(props.config, true, dispatch) + if (displayErrors === null || displayErrors === undefined) useDisplayErrors(props.config, false, dispatch) const useShowGas = props.config.get('settings/show-gas') - if (useShowGas === null || useShowGas === undefined) useShowGasInEditor(props.config, true, dispatch) + if (useShowGas === null || useShowGas === undefined) useShowGasInEditor(props.config, false, dispatch) } useEffect(() => initValue(), [resetState, props.config]) useEffect(() => initValue(), []) @@ -148,7 +148,8 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => { const isEditorWrapChecked = props.config.get('settings/text-wrap') || false const isPersonalChecked = props.config.get('settings/personal-mode') || false const isMatomoChecked = props.config.get('settings/matomo-analytics') || false - const isAutoCompleteChecked = props.config.get('settings/auto-completion') === null ? false:props.config.get('settings/auto-completion') + + const isAutoCompleteChecked = props.config.get('settings/auto-completion') || false const isShowGasInEditorChecked = props.config.get('settings/show-gas') === null ? true:props.config.get('settings/show-gas') const displayErrorsChecked = props.config.get('settings/display-errors') === null ? true:props.config.get('settings/display-errors') return ( From 566fe0d906c48786408682b942b4eecdc0a4ee3c Mon Sep 17 00:00:00 2001 From: filip mertens Date: Mon, 5 Sep 2022 15:41:17 +0200 Subject: [PATCH 06/25] turn off by default --- libs/remix-ui/settings/src/lib/remix-ui-settings.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx index 4b5da79895..e8a15d3a78 100644 --- a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx +++ b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx @@ -150,8 +150,8 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => { const isMatomoChecked = props.config.get('settings/matomo-analytics') || false const isAutoCompleteChecked = props.config.get('settings/auto-completion') || false - const isShowGasInEditorChecked = props.config.get('settings/show-gas') === null ? true:props.config.get('settings/show-gas') - const displayErrorsChecked = props.config.get('settings/display-errors') === null ? true:props.config.get('settings/display-errors') + const isShowGasInEditorChecked = props.config.get('settings/show-gas') || false + const displayErrorsChecked = props.config.get('settings/display-errors') || false return (
From 2f3c68d4d3d857ad7a1bffb27ff13ce67fa40e41 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Mon, 5 Sep 2022 16:15:02 +0200 Subject: [PATCH 07/25] e2e --- apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts | 9 +++++++++ apps/remix-ide-e2e/src/tests/editorHoverContext.test.ts | 8 ++++++++ apps/remix-ide-e2e/src/tests/editorReferences.test.ts | 7 +++++++ apps/remix-ide-e2e/src/tests/editor_error_marker.test.ts | 7 +++++++ apps/remix-ide-e2e/src/tests/editor_line_text.test.ts | 7 +++++++ libs/remix-ui/settings/src/lib/remix-ui-settings.tsx | 6 +++--- 6 files changed, 41 insertions(+), 3 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts b/apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts index d30c942b59..171ad97b6a 100644 --- a/apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts +++ b/apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts @@ -12,6 +12,15 @@ module.exports = { before: function (browser: NightwatchBrowser, done: VoidFunction) { init(browser, done, 'http://127.0.0.1:8080', false) }, + + 'Should enable settings': function (browser: NightwatchBrowser) { + browser + .clickLaunchIcon('settings') + .click('[data-id="settingsAutoCompleteLabel"]') + .click('[data-id="settingsShowGasLabel"]') + .click('[data-id="displayErrorsLabel"]') + }, + 'Should add test and base files #group1': function (browser: NightwatchBrowser) { browser.addFile(examples.testContract.name, examples.testContract) .addFile(examples.baseContract.name, examples.baseContract) diff --git a/apps/remix-ide-e2e/src/tests/editorHoverContext.test.ts b/apps/remix-ide-e2e/src/tests/editorHoverContext.test.ts index db86224b11..f9f5eef0c4 100644 --- a/apps/remix-ide-e2e/src/tests/editorHoverContext.test.ts +++ b/apps/remix-ide-e2e/src/tests/editorHoverContext.test.ts @@ -18,6 +18,14 @@ module.exports = { init(browser, done, 'http://127.0.0.1:8080', false) }, + 'Should enable settings': function (browser: NightwatchBrowser) { + browser + .clickLaunchIcon('settings') + .click('[data-id="settingsAutoCompleteLabel"]') + .click('[data-id="settingsShowGasLabel"]') + .click('[data-id="displayErrorsLabel"]') + }, + 'Should load the test file': function (browser: NightwatchBrowser) { browser.openFile('contracts') .openFile('contracts/3_Ballot.sol') diff --git a/apps/remix-ide-e2e/src/tests/editorReferences.test.ts b/apps/remix-ide-e2e/src/tests/editorReferences.test.ts index 86856a9822..f63837233e 100644 --- a/apps/remix-ide-e2e/src/tests/editorReferences.test.ts +++ b/apps/remix-ide-e2e/src/tests/editorReferences.test.ts @@ -20,6 +20,13 @@ module.exports = { init(browser, done, 'http://127.0.0.1:8080', false) }, + 'Should enable settings': function (browser: NightwatchBrowser) { + browser + .clickLaunchIcon('settings') + .click('[data-id="settingsAutoCompleteLabel"]') + .click('[data-id="settingsShowGasLabel"]') + .click('[data-id="displayErrorsLabel"]') + }, 'Should load the test file': function (browser: NightwatchBrowser) { browser.openFile('contracts') .openFile('contracts/3_Ballot.sol') diff --git a/apps/remix-ide-e2e/src/tests/editor_error_marker.test.ts b/apps/remix-ide-e2e/src/tests/editor_error_marker.test.ts index 8d8cba54e0..daa5456982 100644 --- a/apps/remix-ide-e2e/src/tests/editor_error_marker.test.ts +++ b/apps/remix-ide-e2e/src/tests/editor_error_marker.test.ts @@ -8,6 +8,13 @@ module.exports = { before: function (browser: NightwatchBrowser, done: VoidFunction) { init(browser, done, 'http://127.0.0.1:8080', true) }, + 'Should enable settings': function (browser: NightwatchBrowser) { + browser + .clickLaunchIcon('settings') + .click('[data-id="settingsAutoCompleteLabel"]') + .click('[data-id="settingsShowGasLabel"]') + .click('[data-id="displayErrorsLabel"]') + }, 'Should add error marker': function (browser: NightwatchBrowser) { browser .openFile('contracts') diff --git a/apps/remix-ide-e2e/src/tests/editor_line_text.test.ts b/apps/remix-ide-e2e/src/tests/editor_line_text.test.ts index afff1c8f28..24eb0540e1 100644 --- a/apps/remix-ide-e2e/src/tests/editor_line_text.test.ts +++ b/apps/remix-ide-e2e/src/tests/editor_line_text.test.ts @@ -8,6 +8,13 @@ module.exports = { before: function (browser: NightwatchBrowser, done: VoidFunction) { init(browser, done, 'http://127.0.0.1:8080', true) }, + 'Should enable settings': function (browser: NightwatchBrowser) { + browser + .clickLaunchIcon('settings') + .click('[data-id="settingsAutoCompleteLabel"]') + .click('[data-id="settingsShowGasLabel"]') + .click('[data-id="displayErrorsLabel"]') + }, 'Should add line texts': function (browser: NightwatchBrowser) { browser .openFile('contracts') diff --git a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx index e8a15d3a78..b31313726d 100644 --- a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx +++ b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx @@ -189,19 +189,19 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
-
-
-
From eda9c69b367abf2a6740450573d287f08f7b9ddd Mon Sep 17 00:00:00 2001 From: filip mertens Date: Mon, 5 Sep 2022 16:22:56 +0200 Subject: [PATCH 08/25] fix setting --- apps/remix-ide/src/app/plugins/parser/code-parser.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide/src/app/plugins/parser/code-parser.tsx b/apps/remix-ide/src/app/plugins/parser/code-parser.tsx index 42d7c866bf..b763f81a3c 100644 --- a/apps/remix-ide/src/app/plugins/parser/code-parser.tsx +++ b/apps/remix-ide/src/app/plugins/parser/code-parser.tsx @@ -94,7 +94,7 @@ export class CodeParser extends Plugin { } const showGasSettings = await this.call('config', 'getAppParameter', 'show-gas') const showErrorSettings = await this.call('config', 'getAppParameter', 'display-errors') - if(showGasSettings || showErrorSettings) { + if(showGasSettings || showErrorSettings || completionSettings) { await this.compilerService.compile() } } From a2df3b47897aa6c4a56c5b0a59d0a8def569cbdc Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 5 Sep 2022 16:23:56 +0200 Subject: [PATCH 09/25] create default workspace for desktop --- libs/remix-ui/workspace/src/lib/actions/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index 8627c25c7e..912347a197 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -113,6 +113,7 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React. } } else await basicWorkspaceInit(workspaces, workspaceProvider) } else if (isElectron()) { + await basicWorkspaceInit(workspaces, workspaceProvider) await plugin.call('manager', 'activatePlugin', 'remixd') } else if (localStorage.getItem("currentWorkspace")) { const index = workspaces.findIndex(element => element.name == localStorage.getItem("currentWorkspace")) From ea84447ad36bfbd77ab4597c85032029619b1a2b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 5 Sep 2022 16:32:15 +0200 Subject: [PATCH 10/25] add toast --- libs/remix-ui/workspace/src/lib/actions/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index 912347a197..aa06fb7840 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -113,6 +113,7 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React. } } else await basicWorkspaceInit(workspaces, workspaceProvider) } else if (isElectron()) { + plugin.call('notification', 'toast', `connecting to localhost...`) await basicWorkspaceInit(workspaces, workspaceProvider) await plugin.call('manager', 'activatePlugin', 'remixd') } else if (localStorage.getItem("currentWorkspace")) { From 72244ac01c76b2ec109478ca1b077bca83ff53c8 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 6 Sep 2022 10:49:56 +0200 Subject: [PATCH 11/25] use local version.json for remix live --- apps/remix-ide/src/assets/js/loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide/src/assets/js/loader.js b/apps/remix-ide/src/assets/js/loader.js index ac49d44e3d..4e60dbc36d 100644 --- a/apps/remix-ide/src/assets/js/loader.js +++ b/apps/remix-ide/src/assets/js/loader.js @@ -45,7 +45,7 @@ function isElectron() { return false } -const versionUrl = isElectron() ? 'https://remix.ethereum.org/assets/version.json' : 'assets/version.json' +const versionUrl = 'assets/version.json' fetch(versionUrl, { cache: "no-store" }).then(response => { response.text().then(function (data) { const version = JSON.parse(data); From e2d04177c129fe2a4935415a4596dee343040a4e Mon Sep 17 00:00:00 2001 From: Aniket-Engg Date: Wed, 7 Sep 2022 17:00:31 +0530 Subject: [PATCH 12/25] use oz wizard npm package --- libs/remix-ws-templates/package.json | 3 +++ .../ozerc20/contracts/SampleERC20.sol | 14 -------------- .../src/templates/ozerc20/index.ts | 7 ++++--- .../ozerc20/scripts/deploy_with_ethers.ts | 2 +- .../ozerc20/scripts/deploy_with_web3.ts | 2 +- .../templates/ozerc20/tests/MyToken_test.sol | 18 ++++++++++++++++++ .../ozerc20/tests/SampleERC20_test.sol | 18 ------------------ package.json | 2 ++ yarn.lock | 12 ++++++++++++ 9 files changed, 41 insertions(+), 37 deletions(-) delete mode 100644 libs/remix-ws-templates/src/templates/ozerc20/contracts/SampleERC20.sol create mode 100644 libs/remix-ws-templates/src/templates/ozerc20/tests/MyToken_test.sol delete mode 100644 libs/remix-ws-templates/src/templates/ozerc20/tests/SampleERC20_test.sol diff --git a/libs/remix-ws-templates/package.json b/libs/remix-ws-templates/package.json index 3a27e44a26..16a4d66db1 100644 --- a/libs/remix-ws-templates/package.json +++ b/libs/remix-ws-templates/package.json @@ -22,8 +22,11 @@ "homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-ws-templates#readme", "typings": "./src/index.d.ts", "dependencies": { + "@openzeppelin/contracts": "^4.7.3", + "@openzeppelin/wizard": "^0.1.1", "ethers": "^5.4.2", "web3": "^1.5.1" + }, "gitHead": "0c1957c9b2f890076a5062309bc81b41f93af57c" } \ No newline at end of file diff --git a/libs/remix-ws-templates/src/templates/ozerc20/contracts/SampleERC20.sol b/libs/remix-ws-templates/src/templates/ozerc20/contracts/SampleERC20.sol deleted file mode 100644 index 56a7708413..0000000000 --- a/libs/remix-ws-templates/src/templates/ozerc20/contracts/SampleERC20.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -/** - * @title SampleERC20 - * @dev Create a sample ERC20 standard token - */ -contract SampleERC20 is ERC20 { - - constructor(string memory tokenName, string memory tokenSymbol) ERC20(tokenName, tokenSymbol) {} -} \ No newline at end of file diff --git a/libs/remix-ws-templates/src/templates/ozerc20/index.ts b/libs/remix-ws-templates/src/templates/ozerc20/index.ts index 48ffb45341..f44f812bb2 100644 --- a/libs/remix-ws-templates/src/templates/ozerc20/index.ts +++ b/libs/remix-ws-templates/src/templates/ozerc20/index.ts @@ -1,7 +1,8 @@ +import { erc20 } from '@openzeppelin/wizard'; + export default async () => { return { - // @ts-ignore - 'contracts/SampleERC20.sol': (await import('raw-loader!./contracts/SampleERC20.sol')).default, + 'contracts/MyToken.sol': erc20.print(), // @ts-ignore 'scripts/deploy_with_ethers.ts': (await import('!!raw-loader!./scripts/deploy_with_ethers.ts')).default, // @ts-ignore @@ -11,6 +12,6 @@ export default async () => { // @ts-ignore 'scripts/web3-lib.ts': (await import('!!raw-loader!./scripts/web3-lib.ts')).default, // @ts-ignore - 'tests/SampleERC20_test.sol': (await import('raw-loader!./tests/SampleERC20_test.sol')).default + 'tests/MyToken_test.sol': (await import('raw-loader!./tests/MyToken_test.sol')).default } } \ No newline at end of file diff --git a/libs/remix-ws-templates/src/templates/ozerc20/scripts/deploy_with_ethers.ts b/libs/remix-ws-templates/src/templates/ozerc20/scripts/deploy_with_ethers.ts index c12ce0dfcd..a6c8cf30e5 100644 --- a/libs/remix-ws-templates/src/templates/ozerc20/scripts/deploy_with_ethers.ts +++ b/libs/remix-ws-templates/src/templates/ozerc20/scripts/deploy_with_ethers.ts @@ -2,7 +2,7 @@ import { deploy } from './ethers-lib' (async () => { try { - const result = await deploy('SampleERC20', ['testToken', 'TST']) + const result = await deploy('MyToken', []) console.log(`address: ${result.address}`) } catch (e) { console.log(e.message) diff --git a/libs/remix-ws-templates/src/templates/ozerc20/scripts/deploy_with_web3.ts b/libs/remix-ws-templates/src/templates/ozerc20/scripts/deploy_with_web3.ts index 3a19d6a068..b22b119246 100644 --- a/libs/remix-ws-templates/src/templates/ozerc20/scripts/deploy_with_web3.ts +++ b/libs/remix-ws-templates/src/templates/ozerc20/scripts/deploy_with_web3.ts @@ -2,7 +2,7 @@ import { deploy } from './web3-lib' (async () => { try { - const result = await deploy('SampleERC20', ['testToken', 'TST']) + const result = await deploy('MyToken', []) console.log(`address: ${result.address}`) } catch (e) { console.log(e.message) diff --git a/libs/remix-ws-templates/src/templates/ozerc20/tests/MyToken_test.sol b/libs/remix-ws-templates/src/templates/ozerc20/tests/MyToken_test.sol new file mode 100644 index 0000000000..0fb1d12117 --- /dev/null +++ b/libs/remix-ws-templates/src/templates/ozerc20/tests/MyToken_test.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.7.0 <0.9.0; +import "remix_tests.sol"; +import "../contracts/MyToken.sol"; + +contract MyTokenTest { + + MyToken s; + function beforeAll () public { + s = new MyToken(); + } + + function testTokenNameAndSymbol () public { + Assert.equal(s.name(), "MyToken", "token name did not match"); + Assert.equal(s.symbol(), "MTK", "token symbol did not match"); + } +} \ No newline at end of file diff --git a/libs/remix-ws-templates/src/templates/ozerc20/tests/SampleERC20_test.sol b/libs/remix-ws-templates/src/templates/ozerc20/tests/SampleERC20_test.sol deleted file mode 100644 index 19eb11d97d..0000000000 --- a/libs/remix-ws-templates/src/templates/ozerc20/tests/SampleERC20_test.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; -import "remix_tests.sol"; -import "../contracts/SampleERC20.sol"; - -contract SampleERC20Test { - - SampleERC20 s; - function beforeAll () public { - s = new SampleERC20("TestToken", "TST"); - } - - function testTokenNameAndSymbol () public { - Assert.equal(s.name(), "TestToken", "token name did not match"); - Assert.equal(s.symbol(), "TST", "token symbol did not match"); - } -} \ No newline at end of file diff --git a/package.json b/package.json index b13b797c38..8399c040bc 100644 --- a/package.json +++ b/package.json @@ -154,6 +154,8 @@ "@ethersphere/bee-js": "^3.2.0", "@isomorphic-git/lightning-fs": "^4.4.1", "@monaco-editor/react": "4.4.5", + "@openzeppelin/contracts": "^4.7.3", + "@openzeppelin/wizard": "^0.1.1", "@remixproject/engine": "^0.3.31", "@remixproject/engine-web": "^0.3.31", "@remixproject/plugin": "^0.3.31", diff --git a/yarn.lock b/yarn.lock index e36042dda0..3809c46cb6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3912,6 +3912,18 @@ dependencies: "@octokit/openapi-types" "^11.2.0" +"@openzeppelin/contracts@^4.7.3": + version "4.7.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" + integrity sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw== + +"@openzeppelin/wizard@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@openzeppelin/wizard/-/wizard-0.1.1.tgz#8c183e2c5748869bc3a5317c0330aa36a9ad44fe" + integrity sha512-AGyvn3PIh1vCgAEoRKAXKhtlk4fkA8AHE7G4PyzLnYcASClYCWpSf43WLJCs6S/LORvTZADX1flvF8x2LciJIg== + dependencies: + array.prototype.flatmap "^1.2.4" + "@pmmmwh/react-refresh-webpack-plugin@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz#1eec460596d200c0236bf195b078a5d1df89b766" From e5e17806089804e6c015c4093a624f2d27099808 Mon Sep 17 00:00:00 2001 From: Aniket-Engg Date: Wed, 7 Sep 2022 17:29:11 +0530 Subject: [PATCH 13/25] e2e fix --- apps/remix-ide-e2e/src/tests/workspace.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/workspace.test.ts b/apps/remix-ide-e2e/src/tests/workspace.test.ts index 3e15a18248..d7314e3c5f 100644 --- a/apps/remix-ide-e2e/src/tests/workspace.test.ts +++ b/apps/remix-ide-e2e/src/tests/workspace.test.ts @@ -124,7 +124,7 @@ module.exports = { .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .pause(100) .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/SampleERC20.sol"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') // check js and ts files are not transformed @@ -156,7 +156,7 @@ module.exports = { 'Incorrect content') }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/SampleERC20_test.sol"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/MyToken_test.sol"]') }, 'Should create ERC721 workspace with files #group1': function (browser: NightwatchBrowser) { From 36be826def77e24493bb2e4dc97aad2ce215cf0e Mon Sep 17 00:00:00 2001 From: Aniket-Engg Date: Wed, 7 Sep 2022 19:12:25 +0530 Subject: [PATCH 14/25] generate Erc721 contracts --- .../ozerc721/contracts/SampleERC721.sol | 14 -------------- .../src/templates/ozerc721/index.ts | 7 ++++--- .../ozerc721/scripts/deploy_with_ethers.ts | 2 +- .../ozerc721/scripts/deploy_with_web3.ts | 2 +- .../templates/ozerc721/tests/MyToken_test.sol | 18 ++++++++++++++++++ .../ozerc721/tests/SampleERC721_test.sol | 18 ------------------ 6 files changed, 24 insertions(+), 37 deletions(-) delete mode 100644 libs/remix-ws-templates/src/templates/ozerc721/contracts/SampleERC721.sol create mode 100644 libs/remix-ws-templates/src/templates/ozerc721/tests/MyToken_test.sol delete mode 100644 libs/remix-ws-templates/src/templates/ozerc721/tests/SampleERC721_test.sol diff --git a/libs/remix-ws-templates/src/templates/ozerc721/contracts/SampleERC721.sol b/libs/remix-ws-templates/src/templates/ozerc721/contracts/SampleERC721.sol deleted file mode 100644 index 5a0d40c8e3..0000000000 --- a/libs/remix-ws-templates/src/templates/ozerc721/contracts/SampleERC721.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; - -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; - -/** - * @title SampleERC721 - * @dev Create a sample ERC721 standard token - */ -contract SampleERC721 is ERC721 { - - constructor(string memory tokenName, string memory tokenSymbol) ERC721(tokenName, tokenSymbol) {} -} \ No newline at end of file diff --git a/libs/remix-ws-templates/src/templates/ozerc721/index.ts b/libs/remix-ws-templates/src/templates/ozerc721/index.ts index 53b6d132e7..26a3acd59b 100644 --- a/libs/remix-ws-templates/src/templates/ozerc721/index.ts +++ b/libs/remix-ws-templates/src/templates/ozerc721/index.ts @@ -1,7 +1,8 @@ +import { erc721 } from '@openzeppelin/wizard'; + export default async () => { return { - // @ts-ignore - 'contracts/SampleERC721.sol': (await import('raw-loader!./contracts/SampleERC721.sol')).default, + 'contracts/MyToken.sol': erc721.print(), // @ts-ignore 'scripts/deploy_with_ethers.ts': (await import('!!raw-loader!./scripts/deploy_with_ethers.ts')).default, // @ts-ignore @@ -11,6 +12,6 @@ export default async () => { // @ts-ignore 'scripts/web3-lib.ts': (await import('!!raw-loader!./scripts/web3-lib.ts')).default, // @ts-ignore - 'tests/SampleERC721_test.sol': (await import('raw-loader!./tests/SampleERC721_test.sol')).default + 'tests/MyToken_test.sol': (await import('raw-loader!./tests/MyToken_test.sol')).default } } \ No newline at end of file diff --git a/libs/remix-ws-templates/src/templates/ozerc721/scripts/deploy_with_ethers.ts b/libs/remix-ws-templates/src/templates/ozerc721/scripts/deploy_with_ethers.ts index 185fd7a5fa..a6c8cf30e5 100644 --- a/libs/remix-ws-templates/src/templates/ozerc721/scripts/deploy_with_ethers.ts +++ b/libs/remix-ws-templates/src/templates/ozerc721/scripts/deploy_with_ethers.ts @@ -2,7 +2,7 @@ import { deploy } from './ethers-lib' (async () => { try { - const result = await deploy('SampleERC721', ['testNFT', 'TNFT']) + const result = await deploy('MyToken', []) console.log(`address: ${result.address}`) } catch (e) { console.log(e.message) diff --git a/libs/remix-ws-templates/src/templates/ozerc721/scripts/deploy_with_web3.ts b/libs/remix-ws-templates/src/templates/ozerc721/scripts/deploy_with_web3.ts index 2fec0c3b28..b22b119246 100644 --- a/libs/remix-ws-templates/src/templates/ozerc721/scripts/deploy_with_web3.ts +++ b/libs/remix-ws-templates/src/templates/ozerc721/scripts/deploy_with_web3.ts @@ -2,7 +2,7 @@ import { deploy } from './web3-lib' (async () => { try { - const result = await deploy('SampleERC721', ['testToken', 'TST']) + const result = await deploy('MyToken', []) console.log(`address: ${result.address}`) } catch (e) { console.log(e.message) diff --git a/libs/remix-ws-templates/src/templates/ozerc721/tests/MyToken_test.sol b/libs/remix-ws-templates/src/templates/ozerc721/tests/MyToken_test.sol new file mode 100644 index 0000000000..0fb1d12117 --- /dev/null +++ b/libs/remix-ws-templates/src/templates/ozerc721/tests/MyToken_test.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.7.0 <0.9.0; +import "remix_tests.sol"; +import "../contracts/MyToken.sol"; + +contract MyTokenTest { + + MyToken s; + function beforeAll () public { + s = new MyToken(); + } + + function testTokenNameAndSymbol () public { + Assert.equal(s.name(), "MyToken", "token name did not match"); + Assert.equal(s.symbol(), "MTK", "token symbol did not match"); + } +} \ No newline at end of file diff --git a/libs/remix-ws-templates/src/templates/ozerc721/tests/SampleERC721_test.sol b/libs/remix-ws-templates/src/templates/ozerc721/tests/SampleERC721_test.sol deleted file mode 100644 index 27a4c46826..0000000000 --- a/libs/remix-ws-templates/src/templates/ozerc721/tests/SampleERC721_test.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; -import "remix_tests.sol"; -import "../contracts/SampleERC721.sol"; - -contract SampleERC721Test { - - SampleERC721 s; - function beforeAll () public { - s = new SampleERC721("TestNFT", "TNFT"); - } - - function testTokenNameAndSymbol () public { - Assert.equal(s.name(), "TestNFT", "token name did not match"); - Assert.equal(s.symbol(), "TNFT", "token symbol did not match"); - } -} \ No newline at end of file From e11ac5768a5cec13f9562f7464de43e9b4a56523 Mon Sep 17 00:00:00 2001 From: Aniket-Engg Date: Wed, 7 Sep 2022 19:14:05 +0530 Subject: [PATCH 15/25] e2e update --- apps/remix-ide-e2e/src/tests/workspace.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/workspace.test.ts b/apps/remix-ide-e2e/src/tests/workspace.test.ts index d7314e3c5f..477ed83b7b 100644 --- a/apps/remix-ide-e2e/src/tests/workspace.test.ts +++ b/apps/remix-ide-e2e/src/tests/workspace.test.ts @@ -172,7 +172,7 @@ module.exports = { .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .pause(100) .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/SampleERC721.sol"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') // check js and ts files are not transformed @@ -204,7 +204,7 @@ module.exports = { 'Incorrect content') }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/SampleERC721_test.sol"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/MyToken_test.sol"]') }, // WORKSPACE TEMPLATES E2E END From 67ca3a5d190b005c43450c4c4163c7d351535f88 Mon Sep 17 00:00:00 2001 From: Aniket-Engg Date: Wed, 7 Sep 2022 19:26:11 +0530 Subject: [PATCH 16/25] e2e fix --- apps/remix-ide-e2e/src/tests/erc721.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/erc721.test.ts b/apps/remix-ide-e2e/src/tests/erc721.test.ts index b759d457a8..efc18810b1 100644 --- a/apps/remix-ide-e2e/src/tests/erc721.test.ts +++ b/apps/remix-ide-e2e/src/tests/erc721.test.ts @@ -26,19 +26,19 @@ module.exports = { .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .pause(100) .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/SampleERC721.sol"]') - .openFile('contracts/SampleERC721.sol') - .verifyContracts(['SampleERC721']) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]') + .openFile('contracts/MyToken.sol') + .verifyContracts(['MyToken']) // deploy contract .clickLaunchIcon('udapp') - .selectContract('SampleERC721') - .createContract('E,E') + .selectContract('MyToken') + .createContract('') .testFunction('last', { status: 'true Transaction mined and execution succeed', 'decoded input': { - 'string tokenName': 'E', - 'string tokenSymbol': 'E' + 'string tokenName': 'MyToken', + 'string tokenSymbol': 'MTK' } }).end() } From 0288b250ef72100e63523938721d7d56161f787e Mon Sep 17 00:00:00 2001 From: Aniket-Engg Date: Wed, 7 Sep 2022 19:46:24 +0530 Subject: [PATCH 17/25] fix input in e2e --- apps/remix-ide-e2e/src/tests/erc721.test.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/erc721.test.ts b/apps/remix-ide-e2e/src/tests/erc721.test.ts index efc18810b1..52535ebf3a 100644 --- a/apps/remix-ide-e2e/src/tests/erc721.test.ts +++ b/apps/remix-ide-e2e/src/tests/erc721.test.ts @@ -36,10 +36,7 @@ module.exports = { .testFunction('last', { status: 'true Transaction mined and execution succeed', - 'decoded input': { - 'string tokenName': 'MyToken', - 'string tokenSymbol': 'MTK' - } + 'decoded input': {} }).end() } } From 77d68dea37f0ddbff50492473b51f0ccaf82086f Mon Sep 17 00:00:00 2001 From: David Disu Date: Fri, 2 Sep 2022 15:25:15 +0100 Subject: [PATCH 18/25] Add workflow for running solidity unit tests --- .github/workflows/run-sut.yml | 20 +++++++++++++ .../remix-ide/contracts/tests/Ballot_test.sol | 28 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 .github/workflows/run-sut.yml create mode 100644 apps/remix-ide/contracts/tests/Ballot_test.sol diff --git a/.github/workflows/run-sut.yml b/.github/workflows/run-sut.yml new file mode 100644 index 0000000000..e6b8d98221 --- /dev/null +++ b/.github/workflows/run-sut.yml @@ -0,0 +1,20 @@ + +name: Running Solidity Unit Tests +on: [push] + +jobs: + run_sol_contracts_job: + runs-on: ubuntu-latest + name: A job to run solidity unit tests on github actions CI + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Environment Setup + uses: actions/setup-node@v3 + with: + node-version: 14.17.6 + - name: Run SUT Action + uses: EthereumRemix/sol-test@v1 + with: + test-path: 'apps/remix-ide/contracts/tests' + compiler-version: '0.8.15' \ No newline at end of file diff --git a/apps/remix-ide/contracts/tests/Ballot_test.sol b/apps/remix-ide/contracts/tests/Ballot_test.sol new file mode 100644 index 0000000000..452a5433b4 --- /dev/null +++ b/apps/remix-ide/contracts/tests/Ballot_test.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.7.0 <0.9.0; +import "remix_tests.sol"; // this import is automatically injected by Remix. +import "hardhat/console.sol"; +import "../ballot.sol"; + +contract BallotTest { + + bytes32[] proposalNames; + + Ballot ballotToTest; + function beforeAll () public { + proposalNames.push(bytes32("candidate1")); + ballotToTest = new Ballot(proposalNames); + } + + function checkWinningProposal () public { + console.log("Running checkWinningProposal"); + ballotToTest.vote(0); + Assert.equal(ballotToTest.winningProposal(), uint(0), "proposal at index 0 should be the winning proposal"); + Assert.equal(ballotToTest.winnerName(), bytes32("candidate1"), "candidate1 should be the winner name"); + } + + function checkWinninProposalWithReturnValue () public view returns (bool) { + return ballotToTest.winningProposal() == 0; + } +} \ No newline at end of file From a40839f405d16864e31745f8945a05f804087a6c Mon Sep 17 00:00:00 2001 From: David Disu Date: Fri, 2 Sep 2022 15:28:10 +0100 Subject: [PATCH 19/25] Update ballot contract --- apps/remix-ide/contracts/ballot.sol | 151 ++++++++++++++-------------- 1 file changed, 73 insertions(+), 78 deletions(-) diff --git a/apps/remix-ide/contracts/ballot.sol b/apps/remix-ide/contracts/ballot.sol index d55734ed9a..ffcc6c3609 100644 --- a/apps/remix-ide/contracts/ballot.sol +++ b/apps/remix-ide/contracts/ballot.sol @@ -1,10 +1,13 @@ -pragma solidity ^0.4.0; +// SPDX-License-Identifier: GPL-3.0 -/// @title Voting with delegation. +pragma solidity >=0.7.0 <0.9.0; + +/** + * @title Ballot + * @dev Implements voting process along with vote delegation + */ contract Ballot { - // This declares a new complex type which will - // be used for variables later. - // It will represent a single voter. + struct Voter { uint weight; // weight is accumulated by delegation bool voted; // if true, that person already voted @@ -12,33 +15,31 @@ contract Ballot { uint vote; // index of the voted proposal } - // This is a type for a single proposal. struct Proposal { + // If you can limit the length to a certain number of bytes, + // always use one of bytes1 to bytes32 because they are much cheaper bytes32 name; // short name (up to 32 bytes) uint voteCount; // number of accumulated votes } address public chairperson; - // This declares a state variable that - // stores a \`Voter\` struct for each possible address. mapping(address => Voter) public voters; - // A dynamically-sized array of \`Proposal\` structs. Proposal[] public proposals; - /// Create a new ballot to choose one of \`proposalNames\`. - function Ballot(bytes32[] proposalNames) { + /** + * @dev Create a new ballot to choose one of 'proposalNames'. + * @param proposalNames names of proposals + */ + constructor(bytes32[] memory proposalNames) { chairperson = msg.sender; voters[chairperson].weight = 1; - // For each of the provided proposal names, - // create a new proposal object and add it - // to the end of the array. for (uint i = 0; i < proposalNames.length; i++) { - // \`Proposal({...})\` creates a temporary - // Proposal object and \`proposals.push(...)\` - // appends it to the end of \`proposals\`. + // 'Proposal({...})' creates a temporary + // Proposal object and 'proposals.push(...)' + // appends it to the end of 'proposals'. proposals.push(Proposal({ name: proposalNames[i], voteCount: 0 @@ -46,98 +47,92 @@ contract Ballot { } } - // Give \`voter\` the right to vote on this ballot. - // May only be called by \`chairperson\`. - function giveRightToVote(address voter) { - if (msg.sender != chairperson || voters[voter].voted) { - // \`throw\` terminates and reverts all changes to - // the state and to Ether balances. It is often - // a good idea to use this if functions are - // called incorrectly. But watch out, this - // will also consume all provided gas. - throw; - } + /** + * @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'. + * @param voter address of voter + */ + function giveRightToVote(address voter) public { + require( + msg.sender == chairperson, + "Only chairperson can give right to vote." + ); + require( + !voters[voter].voted, + "The voter already voted." + ); + require(voters[voter].weight == 0); voters[voter].weight = 1; } - /// Delegate your vote to the voter \`to\`. - function delegate(address to) { - // assigns reference - Voter sender = voters[msg.sender]; - if (sender.voted) - throw; - - // Forward the delegation as long as - // \`to\` also delegated. - // In general, such loops are very dangerous, - // because if they run too long, they might - // need more gas than is available in a block. - // In this case, the delegation will not be executed, - // but in other situations, such loops might - // cause a contract to get "stuck" completely. - while ( - voters[to].delegate != address(0) && - voters[to].delegate != msg.sender - ) { + /** + * @dev Delegate your vote to the voter 'to'. + * @param to address to which vote is delegated + */ + function delegate(address to) public { + Voter storage sender = voters[msg.sender]; + require(!sender.voted, "You already voted."); + require(to != msg.sender, "Self-delegation is disallowed."); + + while (voters[to].delegate != address(0)) { to = voters[to].delegate; - } - // We found a loop in the delegation, not allowed. - if (to == msg.sender) { - throw; + // We found a loop in the delegation, not allowed. + require(to != msg.sender, "Found loop in delegation."); } - - // Since \`sender\` is a reference, this - // modifies \`voters[msg.sender].voted\` sender.voted = true; sender.delegate = to; - Voter delegate = voters[to]; - if (delegate.voted) { + Voter storage delegate_ = voters[to]; + if (delegate_.voted) { // If the delegate already voted, // directly add to the number of votes - proposals[delegate.vote].voteCount += sender.weight; + proposals[delegate_.vote].voteCount += sender.weight; } else { // If the delegate did not vote yet, // add to her weight. - delegate.weight += sender.weight; + delegate_.weight += sender.weight; } } - /// Give your vote (including votes delegated to you) - /// to proposal \`proposals[proposal].name\`. - function vote(uint proposal) { - Voter sender = voters[msg.sender]; - if (sender.voted) - throw; + /** + * @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'. + * @param proposal index of proposal in the proposals array + */ + function vote(uint proposal) public { + Voter storage sender = voters[msg.sender]; + require(sender.weight != 0, "Has no right to vote"); + require(!sender.voted, "Already voted."); sender.voted = true; sender.vote = proposal; - // If \`proposal\` is out of the range of the array, + // If 'proposal' is out of the range of the array, // this will throw automatically and revert all // changes. proposals[proposal].voteCount += sender.weight; } - /// @dev Computes the winning proposal taking all - /// previous votes into account. - function winningProposal() constant - returns (uint winningProposal) + /** + * @dev Computes the winning proposal taking all previous votes into account. + * @return winningProposal_ index of winning proposal in the proposals array + */ + function winningProposal() public view + returns (uint winningProposal_) { uint winningVoteCount = 0; for (uint p = 0; p < proposals.length; p++) { if (proposals[p].voteCount > winningVoteCount) { winningVoteCount = proposals[p].voteCount; - winningProposal = p; + winningProposal_ = p; } } } - - // Calls winningProposal() function to get the index - // of the winner contained in the proposals array and then - // returns the name of the winner - function winnerName() constant - returns (bytes32 winnerName) + + /** + * @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then + * @return winnerName_ the name of the winner + */ + function winnerName() public view + returns (bytes32 winnerName_) { - winnerName = proposals[winningProposal()].name; + winnerName_ = proposals[winningProposal()].name; } -} +} \ No newline at end of file From 37283d66683f84ad7b87594e43a324bcaeb615cc Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 8 Sep 2022 16:08:30 +0200 Subject: [PATCH 20/25] "create a new workspace" item --- .../remix-ui/workspace/src/lib/remix-ui-workspace.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index 3eb94b7dee..91aa2c63ff 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -271,7 +271,16 @@ export function Workspace () { - { + { + createWorkspace() + }} + > + { + - create a new workspace - + } + + { global.fs.browser.workspaces.map(({ name, isGitRepo }, index) => ( Date: Mon, 12 Sep 2022 10:38:23 +0200 Subject: [PATCH 21/25] fix resolving function abi with tuple --- libs/remix-lib/src/execution/txHelper.ts | 24 ++++++++++++++++-------- libs/remix-lib/test/txHelper.ts | 13 +++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/libs/remix-lib/src/execution/txHelper.ts b/libs/remix-lib/src/execution/txHelper.ts index 0b50d96463..f3c78930b1 100644 --- a/libs/remix-lib/src/execution/txHelper.ts +++ b/libs/remix-lib/src/execution/txHelper.ts @@ -102,17 +102,25 @@ export function extractSize (type) { return size ? size[2] : '' } +export function getFunctionLiner (fn, detailTuple: boolean = true) { + /* + if detailsTuple is True, this will return something like fnName((uint, string)) + if detailsTuple is False, this will return something like fnName(tuple) + */ + return fn.name + '(' + fn.inputs.map((value) => { + if (detailTuple && value.components) { + const fullType = makeFullTypeDefinition(value) + return fullType.replace(/tuple/g, '') // return of makeFullTypeDefinition might contain `tuple`, need to remove it cause `methodIdentifier` (fnName) does not include `tuple` keyword + } else { + return value.type + } + }).join(',') + ')' +} + export function getFunction (abi, fnName) { for (let i = 0; i < abi.length; i++) { const fn = abi[i] - if (fn.type === 'function' && fnName === fn.name + '(' + fn.inputs.map((value) => { - if (value.components) { - const fullType = makeFullTypeDefinition(value) - return fullType.replace(/tuple/g, '') // return of makeFullTypeDefinition might contain `tuple`, need to remove it cause `methodIdentifier` (fnName) does not include `tuple` keyword - } else { - return value.type - } - }).join(',') + ')') { + if (fn.type === 'function' && (fnName === getFunctionLiner(fn, true) || fnName === getFunctionLiner(fn, false))) { return fn } } diff --git a/libs/remix-lib/test/txHelper.ts b/libs/remix-lib/test/txHelper.ts index 2532bcd34d..9ddd23788e 100644 --- a/libs/remix-lib/test/txHelper.ts +++ b/libs/remix-lib/test/txHelper.ts @@ -21,6 +21,17 @@ tape('getFunction', function (st) { fn = txHelper.getReceiveInterface(JSON.parse(abi)) st.equal(fn.type, 'receive') + + fn = txHelper.getFunction(testTupleAbi, 'setUser(tuple)') // some compiler version might resolve to tuple. + st.equal(fn.name, 'setUser') + st.equal(fn.inputs[0].type, 'tuple') + st.equal(fn.inputs[0].name, 'user') + + fn = txHelper.getFunctionLiner(testTupleAbi[0], true) + st.equal(fn, 'setUser((string,uint256))') + + fn = txHelper.getFunctionLiner(testTupleAbi[0], false) + st.equal(fn, 'setUser(tuple)') }) const abi = `[ @@ -153,3 +164,5 @@ const abi = `[ "type": "receive" } ]` + +const testTupleAbi = [{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"age","type":"uint256"}],"internalType":"struct Example.User","name":"user","type":"tuple"}],"name":"setUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userByAddress","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"age","type":"uint256"}],"stateMutability":"view","type":"function"}] \ No newline at end of file From e53f11cda361f763b0739f91d6fa95890459972a Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 12 Sep 2022 10:57:19 +0200 Subject: [PATCH 22/25] update test count --- libs/remix-lib/test/txHelper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-lib/test/txHelper.ts b/libs/remix-lib/test/txHelper.ts index 9ddd23788e..4d9a46426f 100644 --- a/libs/remix-lib/test/txHelper.ts +++ b/libs/remix-lib/test/txHelper.ts @@ -3,7 +3,7 @@ import tape from 'tape' import * as txHelper from '../src/execution/txHelper' tape('getFunction', function (st) { - st.plan(6) + st.plan(11) let fn = txHelper.getFunction(JSON.parse(abi), 'o((address,uint256))') st.equal(fn.name, 'o') @@ -165,4 +165,4 @@ const abi = `[ } ]` -const testTupleAbi = [{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"age","type":"uint256"}],"internalType":"struct Example.User","name":"user","type":"tuple"}],"name":"setUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userByAddress","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"age","type":"uint256"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +const testTupleAbi = [{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"age","type":"uint256"}],"internalType":"struct Example.User","name":"user","type":"tuple"}],"name":"setUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userByAddress","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"age","type":"uint256"}],"stateMutability":"view","type":"function"}] From d5a758e07c81e97668c6db36fbc9f674cf74a81e Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 13 Sep 2022 09:34:18 +0200 Subject: [PATCH 23/25] move dropdown item --- libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index 91aa2c63ff..0977cee871 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -280,6 +280,7 @@ export function Workspace () { - create a new workspace - } + { switchWorkspace(LOCALHOST) }}>{currentWorkspace === LOCALHOST ? ✓ localhost : { LOCALHOST } } { global.fs.browser.workspaces.map(({ name, isGitRepo }, index) => ( )) } - { switchWorkspace(LOCALHOST) }}>{currentWorkspace === LOCALHOST ? ✓ localhost : { LOCALHOST } } { ((global.fs.browser.workspaces.length <= 0) || currentWorkspace === NO_WORKSPACE) && { switchWorkspace(NO_WORKSPACE) }}>{ NO_WORKSPACE } } From 5c672782d55f4ce977ef90a7f54263a9ae82272a Mon Sep 17 00:00:00 2001 From: lianahus Date: Tue, 6 Sep 2022 15:52:57 +0200 Subject: [PATCH 24/25] do not show localhost explorer if it is not required --- .../workspace/src/lib/remix-ui-workspace.tsx | 151 +++++++++--------- 1 file changed, 74 insertions(+), 77 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index 0977cee871..de157c1feb 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -309,83 +309,80 @@ export function Workspace () {
{ toggleDropdown(false) }}>
{ (global.fs.browser.isRequestingWorkspace || global.fs.browser.isRequestingCloning) &&
} - { !(global.fs.browser.isRequestingWorkspace || - global.fs.browser.isRequestingCloning) && - (global.fs.mode === 'browser') && (currentWorkspace !== NO_WORKSPACE) && -
- -
- } - { - global.fs.localhost.isRequestingLocalhost ?
- :
- { global.fs.mode === 'localhost' && global.fs.localhost.isSuccessfulLocalhost && - - } -
- } + { !(global.fs.browser.isRequestingWorkspace || global.fs.browser.isRequestingCloning) && + (global.fs.mode === 'browser') && (currentWorkspace !== NO_WORKSPACE) && +
+ +
+ } + { global.fs.localhost.isRequestingLocalhost &&
} + { (global.fs.mode === 'localhost' && global.fs.localhost.isSuccessfulLocalhost) && +
+ +
+ }
From 500ce64b5459fa2962c0489d4f96c86d7d5a31b0 Mon Sep 17 00:00:00 2001 From: lianahus Date: Tue, 6 Sep 2022 16:23:13 +0200 Subject: [PATCH 25/25] fixing scroll issue --- libs/remix-ui/app/src/lib/remix-app/style/remix-app.css | 2 +- .../vertical-icons-panel/src/lib/components/IconList.tsx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/remix-ui/app/src/lib/remix-app/style/remix-app.css b/libs/remix-ui/app/src/lib/remix-app/style/remix-app.css index 8c321b9145..d177ce8bcf 100644 --- a/libs/remix-ui/app/src/lib/remix-app/style/remix-app.css +++ b/libs/remix-ui/app/src/lib/remix-app/style/remix-app.css @@ -8,7 +8,7 @@ pre { overflow-x: auto; } .remixIDE { - width : 100vw; + width : 100%; height : 100vh; overflow : hidden; flex-direction : row; diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx b/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx index b41a417ddd..4716ac47f9 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx +++ b/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx @@ -12,7 +12,7 @@ interface OtherIconsProps { function IconList ({ verticalIconsPlugin, itemContextAction, icons, theme }: OtherIconsProps) { return ( -
+
{ icons .map(p => ( @@ -25,7 +25,8 @@ function IconList ({ verticalIconsPlugin, itemContextAction, icons, theme }: Oth p.profile.name } /> - ))} + )) + }
) }