Merge branch 'master' into intl

pull/2581/head
drafish 2 years ago
commit 618d8f7f1c
  1. 470
      .circleci/config.yml
  2. 20
      .github/workflows/run-sut.yml
  3. 40
      README.md
  4. 2
      apps/remix-ide-e2e/.eslintrc
  5. 6
      apps/remix-ide-e2e/src/commands/addAtAddressInstance.ts
  6. 40
      apps/remix-ide-e2e/src/commands/addFile.ts
  7. 49
      apps/remix-ide-e2e/src/commands/checkVariableDebug.ts
  8. 5
      apps/remix-ide-e2e/src/commands/clickLaunchIcon.ts
  9. 19
      apps/remix-ide-e2e/src/commands/debugTransaction.ts
  10. 5
      apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts
  11. 16
      apps/remix-ide-e2e/src/commands/refreshPage.ts
  12. 16
      apps/remix-ide-e2e/src/commands/setSolidityCompilerVersion.ts
  13. 6
      apps/remix-ide-e2e/src/commands/switchWorkspace.ts
  14. 38
      apps/remix-ide-e2e/src/commands/verifyLoad.ts
  15. 587
      apps/remix-ide-e2e/src/helpers/foundry_compilation.json
  16. 113556
      apps/remix-ide-e2e/src/helpers/hardhat_compilation_8a7ab689ec618720f53ce867a3031c03.json
  17. 38
      apps/remix-ide-e2e/src/helpers/init.ts
  18. 878
      apps/remix-ide-e2e/src/helpers/truffle_compilation.json
  19. 2
      apps/remix-ide-e2e/src/select_tests.sh
  20. 145
      apps/remix-ide-e2e/src/tests/ballot.test.ts
  21. 45
      apps/remix-ide-e2e/src/tests/ballot_0_4_14.test.ts
  22. 48
      apps/remix-ide-e2e/src/tests/debugger.test.ts
  23. 40
      apps/remix-ide-e2e/src/tests/erc721.test.ts
  24. 2
      apps/remix-ide-e2e/src/tests/fileExplorer.test.ts
  25. 6
      apps/remix-ide-e2e/src/tests/generalSettings.test.ts
  26. 2
      apps/remix-ide-e2e/src/tests/gist.test.ts
  27. 2
      apps/remix-ide-e2e/src/tests/migrateFileSystem.test.ts
  28. 2
      apps/remix-ide-e2e/src/tests/pluginManager.test.ts
  29. 51
      apps/remix-ide-e2e/src/tests/proxy.test.ts
  30. 2
      apps/remix-ide-e2e/src/tests/publishContract.test.ts
  31. 5
      apps/remix-ide-e2e/src/tests/recorder.test.ts
  32. 66
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  33. 6
      apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts
  34. 39
      apps/remix-ide-e2e/src/tests/solidityImport.test.ts
  35. 16
      apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts
  36. 2
      apps/remix-ide-e2e/src/tests/stressEditor.test.ts
  37. 2
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  38. 2
      apps/remix-ide-e2e/src/tests/transactionExecution.test.ts
  39. 149
      apps/remix-ide-e2e/src/tests/url.test.ts
  40. 13
      apps/remix-ide-e2e/src/tests/usingWebWorker.test.ts
  41. 134
      apps/remix-ide-e2e/src/tests/workspace.test.ts
  42. 2
      apps/remix-ide-e2e/src/types/index.d.ts
  43. 3
      apps/remix-ide-e2e/tsconfig.e2e.json
  44. 3
      apps/remix-ide-e2e/tsconfig.json
  45. 3
      apps/remix-ide/.gitignore
  46. 9
      apps/remix-ide/ci/browser_test.sh
  47. 1
      apps/remix-ide/ci/browser_tests_etherscan_plugin.sh
  48. 1
      apps/remix-ide/ci/browser_tests_vyper_plugin.sh
  49. 63
      apps/remix-ide/ci/download_e2e_assets.js
  50. 27
      apps/remix-ide/ci/splice_tests.js
  51. 0
      apps/remix-ide/contracts/artifacts/build-info/.gitgnore
  52. 151
      apps/remix-ide/contracts/ballot.sol
  53. 1
      apps/remix-ide/contracts/build/contracts/.gitignore
  54. 6
      apps/remix-ide/contracts/foundry.toml
  55. 1
      apps/remix-ide/contracts/hardhat.config.js
  56. 266
      apps/remix-ide/contracts/out/Counter.s.sol/CounterScript.json
  57. 121
      apps/remix-ide/contracts/out/Counter.s.sol/CounterScript.metadata.json
  58. 587
      apps/remix-ide/contracts/out/Counter.sol/Counter.json
  59. 82
      apps/remix-ide/contracts/out/Counter.sol/Counter.metadata.json
  60. 1310
      apps/remix-ide/contracts/out/Counter.t.sol/CounterTest.json
  61. 561
      apps/remix-ide/contracts/out/Counter.t.sol/CounterTest.metadata.json
  62. 3630
      apps/remix-ide/contracts/out/Script.sol/Script.json
  63. 99
      apps/remix-ide/contracts/out/Script.sol/Script.metadata.json
  64. 37681
      apps/remix-ide/contracts/out/Test.sol/Test.json
  65. 505
      apps/remix-ide/contracts/out/Test.sol/Test.metadata.json
  66. 37401
      apps/remix-ide/contracts/out/Test.sol/stdError.json
  67. 219
      apps/remix-ide/contracts/out/Test.sol/stdError.metadata.json
  68. 37259
      apps/remix-ide/contracts/out/Test.sol/stdMath.json
  69. 88
      apps/remix-ide/contracts/out/Test.sol/stdMath.metadata.json
  70. 37336
      apps/remix-ide/contracts/out/Test.sol/stdStorage.json
  71. 163
      apps/remix-ide/contracts/out/Test.sol/stdStorage.metadata.json
  72. 9179
      apps/remix-ide/contracts/out/Vm.sol/Vm.json
  73. 1669
      apps/remix-ide/contracts/out/Vm.sol/Vm.metadata.json
  74. 110819
      apps/remix-ide/contracts/out/console.sol/console.json
  75. 48
      apps/remix-ide/contracts/out/console.sol/console.metadata.json
  76. 110818
      apps/remix-ide/contracts/out/console2.sol/console2.json
  77. 48
      apps/remix-ide/contracts/out/console2.sol/console2.metadata.json
  78. 23370
      apps/remix-ide/contracts/out/test.sol/DSTest.json
  79. 343
      apps/remix-ide/contracts/out/test.sol/DSTest.metadata.json
  80. 28
      apps/remix-ide/contracts/tests/Ballot_test.sol
  81. 1
      apps/remix-ide/contracts/truffle-config.js
  82. 28
      apps/remix-ide/src/app.js
  83. 47
      apps/remix-ide/src/app/editor/editor.js
  84. 18
      apps/remix-ide/src/app/files/foundry-handle.js
  85. 2
      apps/remix-ide/src/app/panels/file-panel.js
  86. 82
      apps/remix-ide/src/app/plugins/code-format.ts
  87. 61
      apps/remix-ide/src/app/plugins/code-format/index.ts
  88. 197
      apps/remix-ide/src/app/plugins/code-format/parser.ts
  89. 66
      apps/remix-ide/src/app/plugins/parser/code-parser.tsx
  90. 54
      apps/remix-ide/src/app/plugins/parser/services/antlr-worker.ts
  91. 193
      apps/remix-ide/src/app/plugins/parser/services/code-parser-antlr-service.ts
  92. 132
      apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts
  93. 82
      apps/remix-ide/src/app/plugins/parser/services/code-parser-imports.ts
  94. 2
      apps/remix-ide/src/app/plugins/remixd-handle.tsx
  95. 3
      apps/remix-ide/src/app/tabs/compile-tab.js
  96. 2
      apps/remix-ide/src/app/tabs/web3-provider.js
  97. 8
      apps/remix-ide/src/assets/css/themes/bootstrap-cyborg.min.css
  98. 4
      apps/remix-ide/src/assets/css/themes/bootstrap-flatly.min.css
  99. 4
      apps/remix-ide/src/assets/css/themes/bootstrap-spacelab.min.css
  100. 2
      apps/remix-ide/src/assets/css/themes/remix-dark_tvx1s2.css
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,63 +1,41 @@
# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2.1 version: 2.1
parameters: parameters:
run_flaky_tests: run_flaky_tests:
type: boolean type: boolean
default: false default: false
orbs: orbs:
browser-tools: circleci/browser-tools@1.3.0 browser-tools: circleci/browser-tools@1.4.0
jobs: jobs:
build: build:
docker: docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers - image: cimg/node:14.17.6-browsers
# Specify service dependencies here if necessary resource_class:
# CircleCI maintains a library of pre-built images xlarge
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project working_directory: ~/remix-project
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
keys: keys:
- v1-deps-{{ checksum "yarn.lock" }} - v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install - run: yarn
- save_cache: - save_cache:
key: v1-deps-{{ checksum "yarn.lock" }} key: v1-deps-{{ checksum "yarn.lock" }}
paths: paths:
- node_modules - node_modules
- run: yarn run downloadsolc_assets - run: NX_BIN_URL=http://127.0.0.1:8080/assets/js NX_WASM_URL=http://127.0.0.1:8080/assets/js yarn build:production
- run: npx nx build remix-ide - run: npx nx build remix-ide-e2e-src-local-plugin & yarn run build:libs
- run: npx nx build remix-ide-e2e-src-local-plugin - run: mkdir persist && zip -0 -r persist/dist.zip dist
- run: yarn run build:libs
- run: mkdir persist && zip -r persist/dist.zip dist
- persist_to_workspace: - persist_to_workspace:
root: . root: .
paths: paths:
- 'persist' - "persist"
lint: lint:
docker: docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers - image: cimg/node:14.17.6-browsers
resource_class:
# Specify service dependencies here if necessary xlarge
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project working_directory: ~/remix-project
parallelism: 35 parallelism: 35
steps: steps:
@ -65,334 +43,116 @@ jobs:
- restore_cache: - restore_cache:
keys: keys:
- v1-deps-{{ checksum "yarn.lock" }} - v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install - run: yarn
- run: - run:
name: Remix Libs Linting name: Remix Libs Linting
command: ./apps/remix-ide/ci/lint.sh command: ./apps/remix-ide/ci/lint.sh
remix-libs: remix-libs:
docker: docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers - image: cimg/node:14.17.6-browsers
resource_class:
# Specify service dependencies here if necessary xlarge
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project working_directory: ~/remix-project
steps: steps:
- checkout - checkout
- attach_workspace: - attach_workspace:
at: . at: .
- run: unzip ./persist/dist.zip - run: unzip ./persist/dist.zip
- restore_cache: - restore_cache:
keys: keys:
- v1-deps-{{ checksum "yarn.lock" }} - v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install - run: yarn
- run: cd dist/libs/remix-tests && yarn install - run: cd dist/libs/remix-tests && yarn
- run: yarn run test:libs - run: yarn run test:libs
remix-ide-chrome:
docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project
parallelism: 80 remix-ide-browser:
steps:
- browser-tools/install-chrome
- browser-tools/install-chromedriver
- run:
command: |
google-chrome --version
chromedriver --version
java -jar /usr/local/bin/selenium.jar --version
name: Check install
- checkout
- attach_workspace:
at: .
- run: unzip ./persist/dist.zip
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install
- run:
name: Start Selenium
command: java -jar /usr/local/bin/selenium.jar
background: true
- run: ./apps/remix-ide/ci/browser_test.sh chrome
- store_test_results:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
flaky-chrome:
docker: docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers - image: cimg/node:14.17.6-browsers
resource_class:
# Specify service dependencies here if necessary xlarge
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project working_directory: ~/remix-project
parameters:
parallelism: 80 browser:
type: string
script:
type: string
job:
type: string
jobsize:
type: string
parallelism: 10
steps: steps:
- browser-tools/install-chrome - browser-tools/install-browser-tools
- browser-tools/install-chromedriver
- run: - run:
command: | command: |
google-chrome --version google-chrome --version
chromedriver --version firefox --version
java -jar /usr/local/bin/selenium.jar --version geckodriver --version
name: Check install chromedriver --version
- checkout - checkout
- attach_workspace: - attach_workspace:
at: . at: .
- run: unzip ./persist/dist.zip - run: unzip ./persist/dist.zip
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install
- run:
name: Start Selenium
command: java -jar /usr/local/bin/selenium.jar
background: true
- run: ./apps/remix-ide/ci/flaky.sh chrome
- store_test_results:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
remix-ide-firefox:
docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project
parallelism: 80
steps:
- browser-tools/install-firefox
- browser-tools/install-geckodriver
- run:
command: |
firefox --version
geckodriver --version
java -jar /usr/local/bin/selenium.jar --version
name: Check install
- checkout
- attach_workspace:
at: .
- run: unzip ./persist/dist.zip
- restore_cache: - restore_cache:
keys: keys:
- v1-deps-{{ checksum "yarn.lock" }} - v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install - run: yarn
- run: yarn run downloadsolc_assets_e2e && yarn run downloadsolc_assets_dist
- run: ls -la ./dist/apps/remix-ide/assets/js
- run: yarn run selenium-install
- run: - run:
name: Start Selenium name: Start Selenium
command: java -jar /usr/local/bin/selenium.jar command: yarn run selenium
background: true background: true
- run: ./apps/remix-ide/ci/browser_test.sh firefox - run: ./apps/remix-ide/ci/<< parameters.script >> << parameters.browser >> << parameters.jobsize >> << parameters.job >>
- store_test_results: - store_test_results:
path: ./reports/tests path: ./reports/tests
- store_artifacts: - store_artifacts:
path: ./reports/screenshots path: ./reports/screenshots
flaky-firefox:
docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project
parallelism: 80 tests-passed:
machine:
image: ubuntu-2004:202010-01
steps: steps:
- browser-tools/install-firefox - run: echo done
- browser-tools/install-geckodriver
- run:
command: |
firefox --version
geckodriver --version
java -jar /usr/local/bin/selenium.jar --version
name: Check install
- checkout
- attach_workspace:
at: .
- run: unzip ./persist/dist.zip
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install
- run:
name: Start Selenium
command: java -jar /usr/local/bin/selenium.jar
background: true
- run: ./apps/remix-ide/ci/flaky.sh firefox
- store_test_results:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
remix-ide-vyper-plugin: remix-test-plugins:
docker: docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers - image: cimg/node:14.17.6-browsers
resource_class:
# Specify service dependencies here if necessary xlarge
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project working_directory: ~/remix-project
parameters:
script:
type: string
parallelism: 10 parallelism: 10
steps: steps:
- browser-tools/install-chrome - browser-tools/install-browser-tools
- browser-tools/install-chromedriver
- run: - run:
command: | command: |
google-chrome --version google-chrome --version
chromedriver --version firefox --version
java -jar /usr/local/bin/selenium.jar --version geckodriver --version
chromedriver --version
name: Check install name: Check install
- checkout - checkout
- checkout
- attach_workspace: - attach_workspace:
at: . at: .
- run: unzip ./persist/dist.zip
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install
- run:
name: Start Selenium
command: java -jar /usr/local/bin/selenium.jar
background: true
- run: npx nx build vyper
- run: ./apps/remix-ide/ci/browser_tests_vyper_plugin.sh
- store_test_results:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
remix-ide-etherscan-plugin:
docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project
parallelism: 10
steps:
- browser-tools/install-chrome
- browser-tools/install-chromedriver
- run:
command: |
google-chrome --version
chromedriver --version
java -jar /usr/local/bin/selenium.jar --version
name: Check install
- checkout
- checkout
- attach_workspace:
at: .
- run: unzip ./persist/dist.zip
- restore_cache: - restore_cache:
keys: keys:
- v1-deps-{{ checksum "yarn.lock" }} - v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install - run: yarn
- run:
name: Start Selenium
command: java -jar /usr/local/bin/selenium.jar
background: true
- run: npx nx build etherscan
- run: ./apps/remix-ide/ci/browser_tests_etherscan_plugin.sh
- store_test_results:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
remix-ide-plugin-api:
docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
working_directory: ~/remix-project
parallelism: 10
steps:
- browser-tools/install-chrome
- browser-tools/install-chromedriver
- run:
command: |
google-chrome --version
chromedriver --version
java -jar /usr/local/bin/selenium.jar --version
name: Check install
- checkout
- checkout
- attach_workspace:
at: .
- run: unzip ./persist/dist.zip - run: unzip ./persist/dist.zip
- restore_cache: - run: yarn run downloadsolc_assets_e2e && yarn run downloadsolc_assets_dist
keys: - run: yarn run selenium-install
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn install
- run: - run:
name: Start Selenium name: Start Selenium
command: java -jar /usr/local/bin/selenium.jar command: yarn run selenium
background: true background: true
- run: ./apps/remix-ide/ci/browser_tests_plugin_api.sh - run: ./apps/remix-ide/ci/<< parameters.script >>
- store_test_results: - store_test_results:
path: ./reports/tests path: ./reports/tests
- store_artifacts: - store_artifacts:
@ -400,14 +160,10 @@ jobs:
deploy-remix-live: deploy-remix-live:
docker: docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers - image: cimg/node:14.17.6-browsers
# Specify service dependencies here if necessary resource_class:
# CircleCI maintains a library of pre-built images xlarge
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment: environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org" - COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI" - COMMIT_AUTHOR: "Circle CI"
@ -416,27 +172,22 @@ jobs:
steps: steps:
- checkout - checkout
- run: yarn install - run: yarn
- run: yarn run downloadsolc_assets - run: yarn run downloadsolc_assets
- run: yarn run build:production - run: yarn run build:production
- run: - run:
name: Deploy name: Deploy
command: | command: |
if [ "${CIRCLE_BRANCH}" == "remix_live" ]; then if [ "${CIRCLE_BRANCH}" == "remix_live" ]; then
./apps/remix-ide/ci/deploy_from_travis_remix-live.sh; ./apps/remix-ide/ci/deploy_from_travis_remix-live.sh;
fi fi
deploy-remix-alpha: deploy-remix-alpha:
docker: docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers - image: cimg/node:14.17.6-browsers
# Specify service dependencies here if necessary resource_class:
# CircleCI maintains a library of pre-built images xlarge
resource_class: xlarge
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/mongo:3.4.4
environment: environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org" - COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI" - COMMIT_AUTHOR: "Circle CI"
@ -445,10 +196,10 @@ jobs:
steps: steps:
- checkout - checkout
- run: yarn install - run: yarn
- run: yarn run downloadsolc_assets - run: yarn run downloadsolc_assets
- run: yarn run build:production - run: yarn run build:production
- run: - run:
name: Deploy name: Deploy
command: | command: |
if [ "${CIRCLE_BRANCH}" == "master" ]; then if [ "${CIRCLE_BRANCH}" == "master" ]; then
@ -457,14 +208,10 @@ jobs:
deploy-remix-beta: deploy-remix-beta:
docker: docker:
# specify the version you desire here
- image: cimg/node:14.17.6-browsers - image: cimg/node:14.17.6-browsers
# Specify service dependencies here if necessary resource_class:
# CircleCI maintains a library of pre-built images xlarge
resource_class: xlarge
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/mongo:3.4.4
environment: environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org" - COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI" - COMMIT_AUTHOR: "Circle CI"
@ -473,11 +220,11 @@ jobs:
steps: steps:
- checkout - checkout
- run: yarn install - run: yarn
- run: yarn run build:libs - run: yarn run build:libs
- run: yarn run downloadsolc_assets - run: yarn run downloadsolc_assets
- run: yarn run build:production - run: yarn run build:production
- run: - run:
name: Deploy name: Deploy
command: | command: |
if [ "${CIRCLE_BRANCH}" == "remix_beta" ]; then if [ "${CIRCLE_BRANCH}" == "remix_beta" ]; then
@ -489,12 +236,15 @@ workflows:
when: << pipeline.parameters.run_flaky_tests >> when: << pipeline.parameters.run_flaky_tests >>
jobs: jobs:
- build - build
- flaky-chrome: - remix-ide-browser:
requires:
- build
- flaky-firefox:
requires: requires:
- build - build
matrix:
parameters:
browser: ["chrome", "firefox"]
script: ["flaky.sh"]
job: ["nogroup"]
jobsize: ["1"]
build_all: build_all:
unless: << pipeline.parameters.run_flaky_tests >> unless: << pipeline.parameters.run_flaky_tests >>
jobs: jobs:
@ -505,55 +255,51 @@ workflows:
- remix-libs: - remix-libs:
requires: requires:
- build - build
- remix-ide-plugin-api: - remix-test-plugins:
requires:
- build
- remix-ide-vyper-plugin:
requires: requires:
- build - build
- remix-ide-etherscan-plugin: matrix:
parameters:
script: ["browser_tests_plugin_api.sh", "browser_tests_etherscan_plugin.sh", "browser_tests_vyper_plugin.sh"]
- remix-ide-browser:
requires: requires:
- build - build
- remix-ide-chrome: matrix:
parameters:
browser: ["chrome", "firefox"]
script: ["browser_test.sh"]
job: ["0","1","2","3","4","5","6","7","8","9"]
jobsize: ["10"]
- tests-passed:
requires: requires:
- build - lint
- remix-ide-firefox: - remix-libs
requires: - remix-ide-browser
- build - remix-test-plugins
- deploy-remix-live: - deploy-remix-live:
requires: requires:
- lint - lint
- remix-libs - remix-libs
- remix-ide-chrome - remix-ide-browser
- remix-ide-firefox - remix-test-plugins
- remix-ide-plugin-api
- remix-ide-vyper-plugin
- remix-ide-etherscan-plugin
filters: filters:
branches: branches:
only: remix_live only: remix_live
- deploy-remix-alpha: - deploy-remix-alpha:
requires: requires:
- lint - lint
- remix-libs - remix-libs
- remix-ide-chrome - remix-ide-browser
- remix-ide-firefox - remix-test-plugins
- remix-ide-plugin-api
- remix-ide-vyper-plugin
- remix-ide-etherscan-plugin
filters: filters:
branches: branches:
only: master only: master
- deploy-remix-beta: - deploy-remix-beta:
requires: requires:
- lint - lint
- remix-libs - remix-libs
- remix-ide-chrome - remix-ide-browser
- remix-ide-firefox - remix-test-plugins
- remix-ide-plugin-api
- remix-ide-vyper-plugin
- remix-ide-etherscan-plugin
filters: filters:
branches: branches:
only: remix_beta only: remix_beta

@ -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'

@ -22,7 +22,7 @@
**Remix Project** is a rich toolset including Remix IDE, a comprehensive smart contract development tool. The Remix Project also includes Remix Plugin Engine and Remix Libraries which are low-level tools for wider use. **Remix Project** is a rich toolset including Remix IDE, a comprehensive smart contract development tool. The Remix Project also includes Remix Plugin Engine and Remix Libraries which are low-level tools for wider use.
## Remix IDE ## Remix IDE
**Remix IDE** is used for the entire journey of contract development by users of any knowledge level. It fosters a fast development cycle and has a rich set of plugins with intuitive GUIs. The IDE comes in 2 flavors and a VSCode extension: **Remix IDE** is used for the entire journey of contract development by users of any knowledge level. It fosters a fast development cycle and has a rich set of plugins with intuitive GUIs. The IDE comes in 2 flavors and a VSCode extension:
**Remix Online IDE**, see: [https://remix.ethereum.org](https://remix.ethereum.org) **Remix Online IDE**, see: [https://remix.ethereum.org](https://remix.ethereum.org)
@ -58,7 +58,7 @@ Note: It contains the latest supported version of Solidity available at the time
```bash ```bash
yarn global add nx yarn global add nx
``` ```
* Clone the github repository (`wget` need to be installed first): * Clone the GitHub repository (`wget` need to be installed first):
```bash ```bash
git clone https://github.com/ethereum/remix-project.git git clone https://github.com/ethereum/remix-project.git
@ -74,7 +74,7 @@ nx serve
Open `http://127.0.0.1:8080` in your browser to load Remix IDE locally. Open `http://127.0.0.1:8080` in your browser to load Remix IDE locally.
Go to your `text editor` and start developing. Browser will automatically refresh when files are saved. Go to your `text editor` and start developing. The browser will automatically refresh when files are saved.
## Production Build ## Production Build
To generate react production builds for remix-project. To generate react production builds for remix-project.
@ -96,14 +96,14 @@ Prerequisites:
### Run with docker ### Run with docker
If you want to run latest changes that are merged into master branch then run: If you want to run the latest changes that are merged into the master branch then run:
``` ```
docker pull remixproject/remix-ide:latest docker pull remixproject/remix-ide:latest
docker run -p 8080:80 remixproject/remix-ide:latest docker run -p 8080:80 remixproject/remix-ide:latest
``` ```
If you want to run latest remix-live release run. If you want to run the latest remix-live release run.
``` ```
docker pull remixproject/remix-ide:remix_live docker pull remixproject/remix-ide:remix_live
docker run -p 8080:80 remixproject/remix-ide:remix_live docker run -p 8080:80 remixproject/remix-ide:remix_live
@ -120,14 +120,14 @@ docker-compose up -d
Then go to http://localhost:8080 and you can use you Remix instance. Then go to http://localhost:8080 and you can use you Remix instance.
To fetch docker-compose file without cloning this repo run: To fetch the docker-compose file without cloning this repo run:
``` ```
curl https://raw.githubusercontent.com/ethereum/remix-project/master/docker-compose.yaml > docker-compose.yaml curl https://raw.githubusercontent.com/ethereum/remix-project/master/docker-compose.yaml > docker-compose.yaml
``` ```
### Troubleshooting ### Troubleshooting
If you have trouble building the project, make sure that you have the correct version of `node`, `npm` and `nvm`. Also ensure [Nx CLI](https://nx.dev/using-nx/nx-cli) is installed globally. If you have trouble building the project, make sure that you have the correct version of `node`, `npm` and `nvm`. Also, ensure [Nx CLI](https://nx.dev/using-nx/nx-cli) is installed globally.
Run: Run:
@ -137,7 +137,7 @@ npm --version
nvm --version nvm --version
``` ```
In Debian based OS such as Ubuntu 14.04LTS you may need to run `apt-get install build-essential`. After installing `build-essential`, run `npm rebuild`. In Debian-based OS such as Ubuntu 14.04LTS, you may need to run `apt-get install build-essential`. After installing `build-essential`, run `npm rebuild`.
## Unit Testing ## Unit Testing
@ -149,7 +149,7 @@ For example, to run unit tests of `remix-analyzer`, use `nx test remix-analyzer`
To run the Selenium tests via Nightwatch: To run the Selenium tests via Nightwatch:
- Install Selenium for first time: `yarn run selenium-install` - Install Selenium for the first time: `yarn run selenium-install`
- Run a selenium server: `yarn run selenium` - Run a selenium server: `yarn run selenium`
- Build & Serve Remix: `nx serve` - Build & Serve Remix: `nx serve`
- Run all the end-to-end tests: - Run all the end-to-end tests:
@ -165,11 +165,11 @@ To run the Selenium tests via Nightwatch:
**NOTE:** **NOTE:**
- **The `ballot` tests suite** requires to run `ganache-cli` locally. - **The `ballot` tests suite** requires running `ganache-cli` locally.
- **The `remixd` tests suite** requires to run `remixd` locally. - **The `remixd` tests suite** requires running `remixd` locally.
- **The `gist` tests suite** requires specifying a github access token in **.env file**. - **The `gist` tests suite** requires specifying a GitHub access token in **.env file**.
``` ```
gist_token = <token> // token should have permission to create a gist gist_token = <token> // token should have permission to create a gist
``` ```
@ -194,9 +194,9 @@ You need to have
Groups can be used to group tests in a test file together. The advantage is you can avoid running long test files when you want to focus on a specific set of tests within a test file.x Groups can be used to group tests in a test file together. The advantage is you can avoid running long test files when you want to focus on a specific set of tests within a test file.x
These groups only apply to the test file, not across all test files. So for example group1 in the ballot is not related to group1 in another test file. These groups only apply to the test file, not across all test files. So for example group1 in the ballot is not related to a group1 in another test file.
Running a group only runs the tests marked as belonging to the group + all the tests in the test file that do not have a group tag. This way you can have tests that run for all groups, for example to peform common actions. Running a group only runs the tests marked as belonging to the group + all the tests in the test file that do not have a group tag. This way you can have tests that run for all groups, for example, to perform common actions.
There is no need to number the groups in a certain order. The number of the group is arbitrary. There is no need to number the groups in a certain order. The number of the group is arbitrary.
@ -206,7 +206,7 @@ You should write your tests so they can be executed in groups and not depend on
To do this you need to: To do this you need to:
- Add a group to tag to a test, they are formatted as #group followed by a number: so it becomes #group1, #group220, #group4. Any number will do. You don't have to do it in specific order. - Add a group to tag to a test, they are formatted as #group followed by a number: so it becomes #group1, #group220, #group4. Any number will do. You don't have to do it in a specific order.
``` ```
'Should generate test file #group1': function (browser: NightwatchBrowser) { 'Should generate test file #group1': function (browser: NightwatchBrowser) {
@ -222,7 +222,7 @@ module.exports = {
init(browser, done) // , 'http://localhost:8080', false) init(browser, done) // , 'http://localhost:8080', false)
}, },
``` ```
- change package json to locally run all group tests: - change package JSON to locally run all group tests:
``` ```
"nightwatch_local_debugger": "yarn run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/debugger_*.spec.js --env=chrome", "nightwatch_local_debugger": "yarn run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/debugger_*.spec.js --env=chrome",
@ -236,14 +236,14 @@ yarn run build:e2e
### Locally testing group tests ### Locally testing group tests
You can tag any test with a groupname, for example, #group10 and easily run the test locally. You can tag any test with a group name, for example, #group10 and easily run the test locally.
- make sure you have nx installed globally - make sure you have nx installed globally
- group tests are run like any other test, just specify the correct group number - group tests are run like any other test, just specify the correct group number
#### method 1 #### method 1
This script will give you an option menu, just select the test you want This script will give you an options menu, just select the test you want
``` ```
yarn run select_test yarn run select_test
``` ```
@ -256,7 +256,7 @@ yarn run group_test --test=debugger --group=10 --env=chromeDesktop
### Run the same (flaky) test across all instances in CircleCI ### Run the same (flaky) test across all instances in CircleCI
In CircleCI all tests are divided across instances to run in paralel. In CircleCI all tests are divided across instances to run in parallel.
You can also run 1 or more tests simultaneously across all instances. You can also run 1 or more tests simultaneously across all instances.
This way the pipeline can easily be restarted to check if a test is flaky. This way the pipeline can easily be restarted to check if a test is flaky.
@ -266,7 +266,7 @@ For example:
'Static Analysis run with remixd #group3 #flaky': function (browser) { 'Static Analysis run with remixd #group3 #flaky': function (browser) {
``` ```
Now group3 of this test will be executed in firefox and chrome 80 times. Now, the group3 of this test will be executed in firefox and chrome 80 times.
If you mark more groups in other tests they will also be executed. If you mark more groups in other tests they will also be executed.
**CONFIGURATION** **CONFIGURATION**

@ -12,5 +12,5 @@
} }
], ],
"extends": ["../../.eslintrc"], "extends": ["../../.eslintrc"],
"ignorePatterns": ["!**/*"] "ignorePatterns": ["!**/*", "hardhat_compilation.ts"]
} }

@ -14,7 +14,11 @@ class addAtAddressInstance extends EventEmitter {
} }
function addInstance (browser: NightwatchBrowser, address: string, isValidFormat: boolean, isValidChecksum: boolean, isAbi: boolean, callback: VoidFunction) { function addInstance (browser: NightwatchBrowser, address: string, isValidFormat: boolean, isValidChecksum: boolean, isAbi: boolean, callback: VoidFunction) {
browser.clickLaunchIcon('udapp').clearValue('.ataddressinput').setValue('.ataddressinput', address, function () { browser
.clickLaunchIcon('udapp')
.waitForElementVisible('.ataddressinput')
.click('.ataddressinput')
.setValue('.ataddressinput', address, function () {
if (!isValidFormat || !isValidChecksum) browser.assert.elementPresent('button[id^="runAndDeployAtAdressButton"]:disabled') if (!isValidFormat || !isValidChecksum) browser.assert.elementPresent('button[id^="runAndDeployAtAdressButton"]:disabled')
else if (isAbi) { else if (isAbi) {
browser.click('button[id^="runAndDeployAtAdressButton"]') browser.click('button[id^="runAndDeployAtAdressButton"]')

@ -2,7 +2,7 @@ import { NightwatchBrowser, NightwatchContractContent } from 'nightwatch'
import EventEmitter from 'events' import EventEmitter from 'events'
class AddFile extends EventEmitter { class AddFile extends EventEmitter {
command (this: NightwatchBrowser, name: string, content: NightwatchContractContent): NightwatchBrowser { command(this: NightwatchBrowser, name: string, content: NightwatchContractContent): NightwatchBrowser {
this.api.perform((done) => { this.api.perform((done) => {
addFile(this.api, name, content, () => { addFile(this.api, name, content, () => {
done() done()
@ -13,13 +13,31 @@ class AddFile extends EventEmitter {
} }
} }
function addFile (browser: NightwatchBrowser, name: string, content: NightwatchContractContent, done: VoidFunction) { function addFile(browser: NightwatchBrowser, name: string, content: NightwatchContractContent, done: VoidFunction) {
browser.clickLaunchIcon('udapp') browser
.clickLaunchIcon('filePanel') .isVisible({
selector: "//*[@data-id='sidePanelSwapitTitle' and contains(.,'File explorer')]",
locateStrategy: 'xpath',
suppressNotFoundErrors: true,
timeout: 1000
}, (okVisible) => {
if (!okVisible.value) {
browser.clickLaunchIcon('filePanel')
}
})
.scrollInto('li[data-id="treeViewLitreeViewItemREADME.txt"]')
.waitForElementVisible('li[data-id="treeViewLitreeViewItemREADME.txt"]') .waitForElementVisible('li[data-id="treeViewLitreeViewItemREADME.txt"]')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]').pause(1000) // focus on root directory .click('li[data-id="treeViewLitreeViewItemREADME.txt"]').pause(1000) // focus on root directory
.elements('css selector', `li[data-id="treeViewLitreeViewItem${name}"]`, (res) => { .isVisible({
if (res.value && (res.value as any).length > 0) { selector: `//*[@data-id="treeViewLitreeViewItem${name}"]`,
locateStrategy: 'xpath',
abortOnFailure: false,
suppressNotFoundErrors: true,
timeout: 2000
}, (okVisible) => {
// @ts-ignore
// status === -1 means the element is not visible, 0 means it is visible.
if (okVisible.status === 0) {
browser.openFile(name) browser.openFile(name)
.perform(function () { .perform(function () {
done() done()
@ -29,10 +47,14 @@ function addFile (browser: NightwatchBrowser, name: string, content: NightwatchC
.waitForElementContainsText('*[data-id$="/blank"]', '', 60000) .waitForElementContainsText('*[data-id$="/blank"]', '', 60000)
.sendKeys('*[data-id$="/blank"] .remixui_items', name) .sendKeys('*[data-id$="/blank"] .remixui_items', name)
.sendKeys('*[data-id$="/blank"] .remixui_items', browser.Keys.ENTER) .sendKeys('*[data-id$="/blank"] .remixui_items', browser.Keys.ENTER)
.pause(2000) // isvisible is protocol action called isDisplayed https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/WebElement.html#isDisplayed--
.waitForElementVisible(`li[data-id="treeViewLitreeViewItem${name}"]`, 60000) .isVisible({
selector: `li[data-id="treeViewLitreeViewItem${name}"]`,
abortOnFailure: false,
suppressNotFoundErrors: true,
timeout: 60000
})
.setEditorValue(content.content) .setEditorValue(content.content)
.pause(1000)
.perform(function () { .perform(function () {
done() done()
}) })

@ -4,7 +4,7 @@ import EventEmitter from 'events'
const deepequal = require('deep-equal') const deepequal = require('deep-equal')
class CheckVariableDebug extends EventEmitter { class CheckVariableDebug extends EventEmitter {
command (this: NightwatchBrowser, id: string, debugValue: NightwatchCheckVariableDebugValue): NightwatchBrowser { command(this: NightwatchBrowser, id: string, debugValue: NightwatchCheckVariableDebugValue): NightwatchBrowser {
this.api.perform((done) => { this.api.perform((done) => {
checkDebug(this.api, id, debugValue, () => { checkDebug(this.api, id, debugValue, () => {
done() done()
@ -15,27 +15,36 @@ class CheckVariableDebug extends EventEmitter {
} }
} }
function checkDebug (browser: NightwatchBrowser, id: string, debugValue: NightwatchCheckVariableDebugValue, done: VoidFunction) { function checkDebug(browser: NightwatchBrowser, id: string, debugValue: NightwatchCheckVariableDebugValue, done: VoidFunction) {
// id is soliditylocals or soliditystate // id is soliditylocals or soliditystate
browser.execute(function (id: string) { let resultOfElement = null
const elem = document.querySelector('#' + id + ' .dropdownrawcontent') as HTMLElement let isEqual = false
// waitUntil will run with intervals of 1000ms for 10 seconds until the condition is met
return elem.innerText browser.waitUntil(() => {
}, [id], function (result) { browser.execute(function (id: string) {
let value const elem = document.querySelector('#' + id + ' .dropdownrawcontent') as HTMLElement
try { if (elem && elem.innerText) {
value = JSON.parse(<string>result.value) return elem.innerText
} catch (e) { }
browser.assert.fail('cant parse solidity state', e.message, '') }, [id], (result) => {
if (result.value) {
try {
resultOfElement = JSON.parse(<string>result.value)
isEqual = deepequal(debugValue, resultOfElement)
} catch (e) {
browser.assert.fail('cant parse solidity state', e.message, '')
}
}
})
if (isEqual) return true
return false
}, 10000, 1000)
.perform(() => {
if (!isEqual) {
browser.assert.fail(JSON.stringify(resultOfElement), 'info about error\n ' + JSON.stringify(debugValue) + '\n ' + JSON.stringify(resultOfElement), '')
}
done() done()
return })
}
const equal = deepequal(debugValue, value)
if (!equal) {
browser.assert.fail(JSON.stringify(value), 'info about error\n ' + JSON.stringify(debugValue) + '\n ' + JSON.stringify(value), '')
}
done()
})
} }
module.exports = CheckVariableDebug module.exports = CheckVariableDebug

@ -3,7 +3,10 @@ import EventEmitter from 'events'
class ClickLaunchIcon extends EventEmitter { class ClickLaunchIcon extends EventEmitter {
command (this: NightwatchBrowser, icon: string): NightwatchBrowser { command (this: NightwatchBrowser, icon: string): NightwatchBrowser {
this.api.waitForElementVisible('#icon-panel div[plugin="' + icon + '"]').click('#icon-panel div[plugin="' + icon + '"]').perform((done) => { this.api
.waitForElementVisible('#icon-panel div[plugin="' + icon + '"]')
.click('#icon-panel div[plugin="' + icon + '"]')
.perform((done) => {
done() done()
this.emit('complete') this.emit('complete')
}) })

@ -2,7 +2,7 @@ import { NightwatchBrowser } from 'nightwatch'
import EventEmitter from 'events' import EventEmitter from 'events'
class debugTransaction extends EventEmitter { class debugTransaction extends EventEmitter {
command (this: NightwatchBrowser, index = 0): NightwatchBrowser { command(this: NightwatchBrowser, index = 0): NightwatchBrowser {
this.api.perform((done) => { this.api.perform((done) => {
checkStyle(this.api, index, () => { checkStyle(this.api, index, () => {
done() done()
@ -13,14 +13,27 @@ class debugTransaction extends EventEmitter {
} }
} }
function checkStyle (browser: NightwatchBrowser, index: number, callback: VoidFunction) { function checkStyle(browser: NightwatchBrowser, index: number, callback: VoidFunction) {
browser.pause(5000).execute(function (index: number) { let elementsFound = 0
browser.waitUntil(() => {
browser.findElements({
selector: '*[data-shared="txLoggerDebugButton"]',
timeout: 60000,
}, (result) => {
if (Array.isArray(result.value) && result.value.length > 0) {
elementsFound = result.value.length
}
})
return elementsFound > index
}, 60000)
.execute(function (index: number) {
const debugBtn = document.querySelectorAll('*[data-shared="txLoggerDebugButton"]')[index] as HTMLInputElement const debugBtn = document.querySelectorAll('*[data-shared="txLoggerDebugButton"]')[index] as HTMLInputElement
debugBtn && debugBtn.click() debugBtn && debugBtn.click()
}, [index], function () { }, [index], function () {
browser.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]', 60000).perform(() => callback()) browser.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]', 60000).perform(() => callback())
}) })
} }
module.exports = debugTransaction module.exports = debugTransaction

@ -17,7 +17,10 @@ function goToVMtraceStep (browser: NightwatchBrowser, step: number, incr: number
.execute((step) => { .execute((step) => {
(document.querySelector('*[data-id="slider"]') as any).internal_onmouseup({ target: { value: step }}) (document.querySelector('*[data-id="slider"]') as any).internal_onmouseup({ target: { value: step }})
}, [step]) }, [step])
.pause(10000) .waitForElementVisible({
locateStrategy: 'xpath',
selector: `//*[@data-id="treeViewLivm trace step" and contains(.,"${step}")]`,
})
.perform(() => { .perform(() => {
done() done()
}) })

@ -0,0 +1,16 @@
import { NightwatchBrowser } from 'nightwatch'
import EventEmitter from 'events'
class RefreshPage extends EventEmitter {
command(this: NightwatchBrowser) {
browser.refresh()
.verifyLoad()
.perform((done) => {
done()
this.emit('complete')
})
}
}
module.exports = RefreshPage

@ -2,10 +2,22 @@ import { NightwatchBrowser } from 'nightwatch'
import EventEmitter from 'events' import EventEmitter from 'events'
class SetSolidityCompilerVersion extends EventEmitter { class SetSolidityCompilerVersion extends EventEmitter {
command (this: NightwatchBrowser, version: string): NightwatchBrowser { command(this: NightwatchBrowser, version: string): NightwatchBrowser {
this.api this.api
.waitForElementVisible({
selector: "//*[@id='versionSelector']",
locateStrategy: 'xpath'
})
.waitForElementPresent({
selector: `//option[@value='${version}']`,
locateStrategy: 'xpath'
})
.click(`#compileTabView #versionSelector [value="${version}"]`) .click(`#compileTabView #versionSelector [value="${version}"]`)
.pause(5000) .waitForElementPresent({
selector: `//span[@data-version='${version}']`,
locateStrategy: 'xpath',
timeout: 60000
})
.perform(() => { .perform(() => {
this.emit('complete') this.emit('complete')
}) })

@ -3,12 +3,12 @@ import EventEmitter from 'events'
class switchWorkspace extends EventEmitter { class switchWorkspace extends EventEmitter {
command (this: NightwatchBrowser, workspaceName: string): NightwatchBrowser { command (this: NightwatchBrowser, workspaceName: string): NightwatchBrowser {
this.api.waitForElementVisible('[data-id="workspacesSelect"]') this.api
.waitForElementVisible('[data-id="workspacesSelect"]')
.click('[data-id="workspacesSelect"]') .click('[data-id="workspacesSelect"]')
.waitForElementVisible(`[data-id="dropdown-item-${workspaceName}"]`) .waitForElementVisible(`[data-id="dropdown-item-${workspaceName}"]`)
.pause(2000)
.click(`[data-id="dropdown-item-${workspaceName}"]`) .click(`[data-id="dropdown-item-${workspaceName}"]`)
.pause(3000) .pause(7000)
.perform((done) => { .perform((done) => {
done() done()
this.emit('complete') this.emit('complete')

@ -0,0 +1,38 @@
import { NightwatchBrowser } from 'nightwatch'
import EventEmitter from 'events'
class VerifyLoad extends EventEmitter {
command(this: NightwatchBrowser) {
browser.waitForElementPresent({
selector: "//span[@data-id='typesloaded']",
locateStrategy: 'xpath',
timeout: 60000
})
.waitForElementPresent({
selector: "//span[@data-id='editorloaded']",
locateStrategy: 'xpath',
timeout: 60000
})
.waitForElementPresent({
selector: "//span[@data-id='workspaceloaded']",
locateStrategy: 'xpath',
timeout: 60000
})
.waitForElementPresent({
selector: "//span[@data-id='apploaded']",
locateStrategy: 'xpath',
timeout: 60000
})
.waitForElementPresent({
selector: "//span[@data-id='compilerloaded']",
locateStrategy: 'xpath',
timeout: 120000
})
.perform((done) => {
done()
this.emit('complete')
})
}
}
module.exports = VerifyLoad

@ -0,0 +1,587 @@
{
"abi": [
{
"inputs": [],
"name": "increment",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "number",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newNumber",
"type": "uint256"
}
],
"name": "setNumber",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
],
"bytecode": {
"object": "0x608060405234801561001057600080fd5b50610125806100206000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146052578063d09de08a14606c575b600080fd5b6050604c3660046095565b6072565b005b605a60005481565b60405190815260200160405180910390f35b60506081565b607b81607b60c3565b60005550565b600080549080608e8360d9565b9190505550565b60006020828403121560a657600080fd5b5035919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111560d35760d360ad565b92915050565b60006001820160e85760e860ad565b506001019056fea2646970667358221220981d705d73c405a1cadf6bcd0ff9f1d0fcbbc1599040e504e71517ff0d8aa53264736f6c63430008100033",
"sourceMap": "65:198:7:-:0;;;;;;;;;;;;;;;;;;;",
"linkReferences": {}
},
"deployedBytecode": {
"object": "0x6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146052578063d09de08a14606c575b600080fd5b6050604c3660046095565b6072565b005b605a60005481565b60405190815260200160405180910390f35b60506081565b607b81607b60c3565b60005550565b600080549080608e8360d9565b9190505550565b60006020828403121560a657600080fd5b5035919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111560d35760d360ad565b92915050565b60006001820160e85760e860ad565b506001019056fea2646970667358221220981d705d73c405a1cadf6bcd0ff9f1d0fcbbc1599040e504e71517ff0d8aa53264736f6c63430008100033",
"sourceMap": "65:198:7:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116:86;;;;;;:::i;:::-;;:::i;:::-;;88:21;;;;;;;;;345:25:9;;;333:2;318:18;88:21:7;;;;;;;208:53;;;:::i;116:86::-;180:15;:9;192:3;180:15;:::i;:::-;171:6;:24;-1:-1:-1;116:86:7:o;208:53::-;246:6;:8;;;:6;:8;;;:::i;:::-;;;;;;208:53::o;14:180:9:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:9;;14:180;-1:-1:-1;14:180:9:o;381:127::-;442:10;437:3;433:20;430:1;423:31;473:4;470:1;463:15;497:4;494:1;487:15;513:125;578:9;;;599:10;;;596:36;;;612:18;;:::i;:::-;513:125;;;;:::o;643:135::-;682:3;703:17;;;700:43;;723:18;;:::i;:::-;-1:-1:-1;770:1:9;759:13;;643:135::o",
"linkReferences": {}
},
"methodIdentifiers": {
"increment()": "d09de08a",
"number()": "8381f58a",
"setNumber(uint256)": "3fb5c1cb"
},
"ast": {
"absolutePath": "src/Counter.sol",
"id": 21628,
"exportedSymbols": {
"Counter": [
21605
],
"CounterYann": [
21627
]
},
"nodeType": "SourceUnit",
"src": "39:427:7",
"nodes": [
{
"id": 21583,
"nodeType": "PragmaDirective",
"src": "39:24:7",
"literals": [
"solidity",
"^",
"0.8",
".13"
]
},
{
"id": 21605,
"nodeType": "ContractDefinition",
"src": "65:198:7",
"nodes": [
{
"id": 21585,
"nodeType": "VariableDeclaration",
"src": "88:21:7",
"constant": false,
"functionSelector": "8381f58a",
"mutability": "mutable",
"name": "number",
"nameLocation": "103:6:7",
"scope": 21605,
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21584,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "88:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "public"
},
{
"id": 21597,
"nodeType": "FunctionDefinition",
"src": "116:86:7",
"body": {
"id": 21596,
"nodeType": "Block",
"src": "161:41:7",
"statements": [
{
"expression": {
"id": 21594,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"id": 21590,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21585,
"src": "171:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide": {
"commonType": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 21593,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"id": 21591,
"name": "newNumber",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21587,
"src": "180:9:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "BinaryOperation",
"operator": "+",
"rightExpression": {
"hexValue": "313233",
"id": 21592,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "192:3:7",
"typeDescriptions": {
"typeIdentifier": "t_rational_123_by_1",
"typeString": "int_const 123"
},
"value": "123"
},
"src": "180:15:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "171:24:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21595,
"nodeType": "ExpressionStatement",
"src": "171:24:7"
}
]
},
"functionSelector": "3fb5c1cb",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "setNumber",
"nameLocation": "125:9:7",
"parameters": {
"id": 21588,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 21587,
"mutability": "mutable",
"name": "newNumber",
"nameLocation": "143:9:7",
"nodeType": "VariableDeclaration",
"scope": 21597,
"src": "135:17:7",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21586,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "135:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "internal"
}
],
"src": "134:19:7"
},
"returnParameters": {
"id": 21589,
"nodeType": "ParameterList",
"parameters": [],
"src": "161:0:7"
},
"scope": 21605,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
},
{
"id": 21604,
"nodeType": "FunctionDefinition",
"src": "208:53:7",
"body": {
"id": 21603,
"nodeType": "Block",
"src": "236:25:7",
"statements": [
{
"expression": {
"id": 21601,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "UnaryOperation",
"operator": "++",
"prefix": false,
"src": "246:8:7",
"subExpression": {
"id": 21600,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21585,
"src": "246:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21602,
"nodeType": "ExpressionStatement",
"src": "246:8:7"
}
]
},
"functionSelector": "d09de08a",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "increment",
"nameLocation": "217:9:7",
"parameters": {
"id": 21598,
"nodeType": "ParameterList",
"parameters": [],
"src": "226:2:7"
},
"returnParameters": {
"id": 21599,
"nodeType": "ParameterList",
"parameters": [],
"src": "236:0:7"
},
"scope": 21605,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"abstract": false,
"baseContracts": [],
"canonicalName": "Counter",
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"linearizedBaseContracts": [
21605
],
"name": "Counter",
"nameLocation": "74:7:7",
"scope": 21628,
"usedErrors": []
},
{
"id": 21627,
"nodeType": "ContractDefinition",
"src": "265:200:7",
"nodes": [
{
"id": 21607,
"nodeType": "VariableDeclaration",
"src": "292:21:7",
"constant": false,
"functionSelector": "8381f58a",
"mutability": "mutable",
"name": "number",
"nameLocation": "307:6:7",
"scope": 21627,
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21606,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "292:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "public"
},
{
"id": 21619,
"nodeType": "FunctionDefinition",
"src": "320:84:7",
"body": {
"id": 21618,
"nodeType": "Block",
"src": "365:39:7",
"statements": [
{
"expression": {
"id": 21616,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"id": 21612,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21607,
"src": "375:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide": {
"commonType": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 21615,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"id": 21613,
"name": "newNumber",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21609,
"src": "384:9:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "BinaryOperation",
"operator": "+",
"rightExpression": {
"hexValue": "39",
"id": 21614,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "396:1:7",
"typeDescriptions": {
"typeIdentifier": "t_rational_9_by_1",
"typeString": "int_const 9"
},
"value": "9"
},
"src": "384:13:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "375:22:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21617,
"nodeType": "ExpressionStatement",
"src": "375:22:7"
}
]
},
"functionSelector": "3fb5c1cb",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "setNumber",
"nameLocation": "329:9:7",
"parameters": {
"id": 21610,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 21609,
"mutability": "mutable",
"name": "newNumber",
"nameLocation": "347:9:7",
"nodeType": "VariableDeclaration",
"scope": 21619,
"src": "339:17:7",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21608,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "339:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "internal"
}
],
"src": "338:19:7"
},
"returnParameters": {
"id": 21611,
"nodeType": "ParameterList",
"parameters": [],
"src": "365:0:7"
},
"scope": 21627,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
},
{
"id": 21626,
"nodeType": "FunctionDefinition",
"src": "410:53:7",
"body": {
"id": 21625,
"nodeType": "Block",
"src": "438:25:7",
"statements": [
{
"expression": {
"id": 21623,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "UnaryOperation",
"operator": "++",
"prefix": false,
"src": "448:8:7",
"subExpression": {
"id": 21622,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21607,
"src": "448:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21624,
"nodeType": "ExpressionStatement",
"src": "448:8:7"
}
]
},
"functionSelector": "d09de08a",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "increment",
"nameLocation": "419:9:7",
"parameters": {
"id": 21620,
"nodeType": "ParameterList",
"parameters": [],
"src": "428:2:7"
},
"returnParameters": {
"id": 21621,
"nodeType": "ParameterList",
"parameters": [],
"src": "438:0:7"
},
"scope": 21627,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"abstract": false,
"baseContracts": [],
"canonicalName": "CounterYann",
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"linearizedBaseContracts": [
21627
],
"name": "CounterYann",
"nameLocation": "274:11:7",
"scope": 21628,
"usedErrors": []
}
],
"license": "UNLICENSED"
},
"id": 7
}

File diff suppressed because one or more lines are too long

@ -10,38 +10,42 @@ type LoadPlugin = {
export default function (browser: NightwatchBrowser, callback: VoidFunction, url?: string, preloadPlugins = true, loadPlugin?: LoadPlugin): void { export default function (browser: NightwatchBrowser, callback: VoidFunction, url?: string, preloadPlugins = true, loadPlugin?: LoadPlugin): void {
browser browser
.url(url || 'http://127.0.0.1:8080') .url(url || 'http://127.0.0.1:8080')
.pause(6000) //.switchBrowserTab(0)
.switchBrowserTab(0)
.waitForElementVisible('[id="remixTourSkipbtn"]') .waitForElementVisible('[id="remixTourSkipbtn"]')
.click('[id="remixTourSkipbtn"]') .click('[id="remixTourSkipbtn"]')
.perform((done) => { .perform((done) => {
if (!loadPlugin) return done() if (!loadPlugin) return done()
browser.execute(function (loadPlugin) { // override a plugin url for testing purpose browser
localStorage.setItem('test-plugin-name', loadPlugin.name) .pause(5000)
localStorage.setItem('test-plugin-url', loadPlugin.url) .execute(function (loadPlugin) { // override a plugin url for testing purpose
}, [loadPlugin]) localStorage.setItem('test-plugin-name', loadPlugin.name)
.refresh() localStorage.setItem('test-plugin-url', loadPlugin.url)
.pause(6000) }, [loadPlugin])
.perform(done()) .refreshPage()
.perform(done())
}) })
.maximizeWindow() .verifyLoad()
.fullscreenWindow(() => { .perform(() => {
if (preloadPlugins) { if (preloadPlugins) {
initModules(browser, () => { initModules(browser, () => {
browser.pause(2000).clickLaunchIcon('solidity') browser
.clickLaunchIcon('solidity')
.waitForElementVisible('[for="autoCompile"]') .waitForElementVisible('[for="autoCompile"]')
.click('[for="autoCompile"]') .click('[for="autoCompile"]')
.verify.elementPresent('[data-id="compilerContainerAutoCompile"]:checked') .verify.elementPresent('[data-id="compilerContainerAutoCompile"]:checked')
.perform(() => { callback() })
}) })
} else {
callback()
} }
}) })
.perform(() => {
callback()
})
} }
function initModules (browser: NightwatchBrowser, callback: VoidFunction) { function initModules(browser: NightwatchBrowser, callback: VoidFunction) {
browser.pause(5000) browser
.click('[data-id="verticalIconsKindpluginManager"]') .click('[data-id="verticalIconsKindpluginManager"]')
.scrollAndClick('[data-id="pluginManagerComponentActivateButtonsolidityStaticAnalysis"]') .scrollAndClick('[data-id="pluginManagerComponentActivateButtonsolidityStaticAnalysis"]')
.scrollAndClick('[data-id="pluginManagerComponentActivateButtondebugger"]') .scrollAndClick('[data-id="pluginManagerComponentActivateButtondebugger"]')

@ -0,0 +1,878 @@
{
"contractName": "Migrations",
"abi": [
{
"constant": true,
"inputs": [],
"name": "last_completed_migration",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "uint256",
"name": "completed",
"type": "uint256"
}
],
"name": "setCompleted",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
],
"metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"last_completed_migration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"completed\",\"type\":\"uint256\"}],\"name\":\"setCompleted\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"/home/yann/truffletemp/contracts/Migrations.sol\":\"Migrations\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"/home/yann/truffletemp/contracts/Migrations.sol\":{\"keccak256\":\"0x7797e159bfd6b953422b4bd6d5de5946971d8b5ed74c4b1f6517d61fe236b851\",\"urls\":[\"bzz-raw://56bdf6130f3ced3e78baa0f3e7f34cb4c5131d90721326056bbf0dd202d8539d\",\"dweb:/ipfs/QmZqRKebKwn6YXejnnPribsyiXLmrAx32JpatFhvS76NKp\"]}},\"version\":1}",
"bytecode": "0x6080604052336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005057600080fd5b5061021e806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806101b76033913960400191505060405180910390fd5b806001819055505056fe546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572a265627a7a723158202d8ffeacea919d054933bfa385b1dba75680df6aee19f861fea56d15484b874764736f6c63430005100032",
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806101b76033913960400191505060405180910390fd5b806001819055505056fe546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572a265627a7a723158202d8ffeacea919d054933bfa385b1dba75680df6aee19f861fea56d15484b874764736f6c63430005100032",
"sourceMap": "66:352:0:-;;;113:10;90:33;;;;;;;;;;;;;;;;;;;;66:352;8:9:-1;5:2;;;30:1;27;20:12;5:2;66:352:0;;;;;;;",
"deployedSourceMap": "66:352:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66:352:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;127:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;90:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;313:103;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;313:103:0;;;;;;;;;;;;;;;;;:::i;:::-;;127:36;;;;:::o;90:33::-;;;;;;;;;;;;;:::o;313:103::-;225:5;;;;;;;;;;;211:19;;:10;:19;;;196:101;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;402:9;375:24;:36;;;;313:103;:::o",
"source": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.8.0;\n\ncontract Migrations {\n address public owner = msg.sender;\n uint public last_completed_migration;\n\n modifier restricted() {\n require(\n msg.sender == owner,\n \"This function is restricted to the contract's owner\"\n );\n _;\n }\n\n function setCompleted(uint completed) public restricted {\n last_completed_migration = completed;\n }\n}\n",
"sourcePath": "/home/yann/truffletemp/contracts/Migrations.sol",
"ast": {
"absolutePath": "/home/yann/truffletemp/contracts/Migrations.sol",
"exportedSymbols": {
"Migrations": [
32
]
},
"id": 33,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 1,
"literals": [
"solidity",
">=",
"0.4",
".22",
"<",
"0.8",
".0"
],
"nodeType": "PragmaDirective",
"src": "32:32:0"
},
{
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 32,
"linearizedBaseContracts": [
32
],
"name": "Migrations",
"nodeType": "ContractDefinition",
"nodes": [
{
"constant": false,
"id": 5,
"name": "owner",
"nodeType": "VariableDeclaration",
"scope": 32,
"src": "90:33:0",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"typeName": {
"id": 2,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "90:7:0",
"stateMutability": "nonpayable",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"value": {
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 3,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 47,
"src": "113:3:0",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 4,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "sender",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "113:10:0",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"visibility": "public"
},
{
"constant": false,
"id": 7,
"name": "last_completed_migration",
"nodeType": "VariableDeclaration",
"scope": 32,
"src": "127:36:0",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 6,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "127:4:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value": null,
"visibility": "public"
},
{
"body": {
"id": 18,
"nodeType": "Block",
"src": "190:119:0",
"statements": [
{
"expression": {
"argumentTypes": null,
"arguments": [
{
"argumentTypes": null,
"commonType": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"id": 13,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 10,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 47,
"src": "211:3:0",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 11,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "sender",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "211:10:0",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"nodeType": "BinaryOperation",
"operator": "==",
"rightExpression": {
"argumentTypes": null,
"id": 12,
"name": "owner",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 5,
"src": "225:5:0",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"src": "211:19:0",
"typeDescriptions": {
"typeIdentifier": "t_bool",
"typeString": "bool"
}
},
{
"argumentTypes": null,
"hexValue": "546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572",
"id": 14,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "string",
"lValueRequested": false,
"nodeType": "Literal",
"src": "238:53:0",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1",
"typeString": "literal_string \"This function is restricted to the contract's owner\""
},
"value": "This function is restricted to the contract's owner"
}
],
"expression": {
"argumentTypes": [
{
"typeIdentifier": "t_bool",
"typeString": "bool"
},
{
"typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1",
"typeString": "literal_string \"This function is restricted to the contract's owner\""
}
],
"id": 9,
"name": "require",
"nodeType": "Identifier",
"overloadedDeclarations": [
50,
51
],
"referencedDeclaration": 51,
"src": "196:7:0",
"typeDescriptions": {
"typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$",
"typeString": "function (bool,string memory) pure"
}
},
"id": 15,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "196:101:0",
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 16,
"nodeType": "ExpressionStatement",
"src": "196:101:0"
},
{
"id": 17,
"nodeType": "PlaceholderStatement",
"src": "303:1:0"
}
]
},
"documentation": null,
"id": 19,
"name": "restricted",
"nodeType": "ModifierDefinition",
"parameters": {
"id": 8,
"nodeType": "ParameterList",
"parameters": [],
"src": "187:2:0"
},
"src": "168:141:0",
"visibility": "internal"
},
{
"body": {
"id": 30,
"nodeType": "Block",
"src": "369:47:0",
"statements": [
{
"expression": {
"argumentTypes": null,
"id": 28,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"argumentTypes": null,
"id": 26,
"name": "last_completed_migration",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 7,
"src": "375:24:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide": {
"argumentTypes": null,
"id": 27,
"name": "completed",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21,
"src": "402:9:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "375:36:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 29,
"nodeType": "ExpressionStatement",
"src": "375:36:0"
}
]
},
"documentation": null,
"id": 31,
"implemented": true,
"kind": "function",
"modifiers": [
{
"arguments": null,
"id": 24,
"modifierName": {
"argumentTypes": null,
"id": 23,
"name": "restricted",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 19,
"src": "358:10:0",
"typeDescriptions": {
"typeIdentifier": "t_modifier$__$",
"typeString": "modifier ()"
}
},
"nodeType": "ModifierInvocation",
"src": "358:10:0"
}
],
"name": "setCompleted",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 22,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 21,
"name": "completed",
"nodeType": "VariableDeclaration",
"scope": 31,
"src": "335:14:0",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 20,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "335:4:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value": null,
"visibility": "internal"
}
],
"src": "334:16:0"
},
"returnParameters": {
"id": 25,
"nodeType": "ParameterList",
"parameters": [],
"src": "369:0:0"
},
"scope": 32,
"src": "313:103:0",
"stateMutability": "nonpayable",
"superFunction": null,
"visibility": "public"
}
],
"scope": 33,
"src": "66:352:0"
}
],
"src": "32:387:0"
},
"legacyAST": {
"absolutePath": "/home/yann/truffletemp/contracts/Migrations.sol",
"exportedSymbols": {
"Migrations": [
32
]
},
"id": 33,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 1,
"literals": [
"solidity",
">=",
"0.4",
".22",
"<",
"0.8",
".0"
],
"nodeType": "PragmaDirective",
"src": "32:32:0"
},
{
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 32,
"linearizedBaseContracts": [
32
],
"name": "Migrations",
"nodeType": "ContractDefinition",
"nodes": [
{
"constant": false,
"id": 5,
"name": "owner",
"nodeType": "VariableDeclaration",
"scope": 32,
"src": "90:33:0",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"typeName": {
"id": 2,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "90:7:0",
"stateMutability": "nonpayable",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"value": {
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 3,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 47,
"src": "113:3:0",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 4,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "sender",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "113:10:0",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"visibility": "public"
},
{
"constant": false,
"id": 7,
"name": "last_completed_migration",
"nodeType": "VariableDeclaration",
"scope": 32,
"src": "127:36:0",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 6,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "127:4:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value": null,
"visibility": "public"
},
{
"body": {
"id": 18,
"nodeType": "Block",
"src": "190:119:0",
"statements": [
{
"expression": {
"argumentTypes": null,
"arguments": [
{
"argumentTypes": null,
"commonType": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"id": 13,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 10,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 47,
"src": "211:3:0",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 11,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "sender",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "211:10:0",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"nodeType": "BinaryOperation",
"operator": "==",
"rightExpression": {
"argumentTypes": null,
"id": 12,
"name": "owner",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 5,
"src": "225:5:0",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"src": "211:19:0",
"typeDescriptions": {
"typeIdentifier": "t_bool",
"typeString": "bool"
}
},
{
"argumentTypes": null,
"hexValue": "546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572",
"id": 14,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "string",
"lValueRequested": false,
"nodeType": "Literal",
"src": "238:53:0",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1",
"typeString": "literal_string \"This function is restricted to the contract's owner\""
},
"value": "This function is restricted to the contract's owner"
}
],
"expression": {
"argumentTypes": [
{
"typeIdentifier": "t_bool",
"typeString": "bool"
},
{
"typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1",
"typeString": "literal_string \"This function is restricted to the contract's owner\""
}
],
"id": 9,
"name": "require",
"nodeType": "Identifier",
"overloadedDeclarations": [
50,
51
],
"referencedDeclaration": 51,
"src": "196:7:0",
"typeDescriptions": {
"typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$",
"typeString": "function (bool,string memory) pure"
}
},
"id": 15,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "196:101:0",
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 16,
"nodeType": "ExpressionStatement",
"src": "196:101:0"
},
{
"id": 17,
"nodeType": "PlaceholderStatement",
"src": "303:1:0"
}
]
},
"documentation": null,
"id": 19,
"name": "restricted",
"nodeType": "ModifierDefinition",
"parameters": {
"id": 8,
"nodeType": "ParameterList",
"parameters": [],
"src": "187:2:0"
},
"src": "168:141:0",
"visibility": "internal"
},
{
"body": {
"id": 30,
"nodeType": "Block",
"src": "369:47:0",
"statements": [
{
"expression": {
"argumentTypes": null,
"id": 28,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"argumentTypes": null,
"id": 26,
"name": "last_completed_migration",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 7,
"src": "375:24:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide": {
"argumentTypes": null,
"id": 27,
"name": "completed",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21,
"src": "402:9:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "375:36:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 29,
"nodeType": "ExpressionStatement",
"src": "375:36:0"
}
]
},
"documentation": null,
"id": 31,
"implemented": true,
"kind": "function",
"modifiers": [
{
"arguments": null,
"id": 24,
"modifierName": {
"argumentTypes": null,
"id": 23,
"name": "restricted",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 19,
"src": "358:10:0",
"typeDescriptions": {
"typeIdentifier": "t_modifier$__$",
"typeString": "modifier ()"
}
},
"nodeType": "ModifierInvocation",
"src": "358:10:0"
}
],
"name": "setCompleted",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 22,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 21,
"name": "completed",
"nodeType": "VariableDeclaration",
"scope": 31,
"src": "335:14:0",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 20,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "335:4:0",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value": null,
"visibility": "internal"
}
],
"src": "334:16:0"
},
"returnParameters": {
"id": 25,
"nodeType": "ParameterList",
"parameters": [],
"src": "369:0:0"
},
"scope": 32,
"src": "313:103:0",
"stateMutability": "nonpayable",
"superFunction": null,
"visibility": "public"
}
],
"scope": 33,
"src": "66:352:0"
}
],
"src": "32:387:0"
},
"compiler": {
"name": "solc",
"version": "0.5.16+commit.9c3226ce.Emscripten.clang"
},
"networks": {},
"schemaVersion": "3.3.2",
"updatedAt": "2022-09-14T10:36:42.523Z",
"devdoc": {
"methods": {}
},
"userdoc": {
"methods": {}
}
}

@ -31,7 +31,7 @@ do
done done
yarn run build:e2e yarn run build:e2e
PS3='Select a test or command: ' PS3='Select a test or command: '
TESTFILES=( $(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test\|plugin_api" | sort ) ) TESTFILES=( $(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | sort ) )
# declare -p TESTFILES # declare -p TESTFILES
TESTFILES+=("list") TESTFILES+=("list")

@ -9,13 +9,18 @@ const sources = [
] ]
module.exports = { module.exports = {
"@disabled": true,
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done) init(browser, done)
}, },
'@sources': function () { '@sources': function () {
return sources return sources
}, },
'Deploy Ballot': function (browser: NightwatchBrowser) { 'Add Ballot #group2': function (browser: NightwatchBrowser) {
browser
.addFile('Untitled.sol', sources[0]['Untitled.sol'])
},
'Deploy Ballot #group1': function (browser: NightwatchBrowser) {
browser browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
@ -34,7 +39,7 @@ module.exports = {
}) })
}, },
'Call method from Ballot to check return value': function (browser: NightwatchBrowser) { 'Call method from Ballot to check return value #group1': function (browser: NightwatchBrowser) {
browser browser
.clickFunction('winnerName - call') .clickFunction('winnerName - call')
// Test in terminal // Test in terminal
@ -47,7 +52,7 @@ module.exports = {
.assert.containsText('*[data-id="treeViewDiv0"]', 'bytes32: winnerName_ 0x48656c6c6f20576f726c64210000000000000000000000000000000000000000') .assert.containsText('*[data-id="treeViewDiv0"]', 'bytes32: winnerName_ 0x48656c6c6f20576f726c64210000000000000000000000000000000000000000')
}, },
'Debug Ballot / delegate': function (browser: NightwatchBrowser) { 'Debug Ballot / delegate #group1': function (browser: NightwatchBrowser) {
browser.pause(500) browser.pause(500)
.debugTransaction(1) .debugTransaction(1)
.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
@ -60,16 +65,24 @@ module.exports = {
.checkVariableDebug('soliditylocals', localsCheck) .checkVariableDebug('soliditylocals', localsCheck)
}, },
'Access Ballot via at address': function (browser: NightwatchBrowser) { 'Access Ballot via at address #group1': function (browser: NightwatchBrowser) {
browser.clickLaunchIcon('udapp') browser.clickLaunchIcon('udapp')
.click('*[data-id="universalDappUiUdappClose"]') .click('*[data-id="universalDappUiUdappClose"]')
.addFile('ballot.abi', { content: ballotABI }) .addFile('ballot.abi', { content: ballotABI })
.clickLaunchIcon('udapp')
.click({
selector: '*[data-id="deployAndRunClearInstances"]',
abortOnFailure: false,
suppressNotFoundErrors: true,
})
// we are not changing the visibility for not checksumed contracts // we are not changing the visibility for not checksumed contracts
// .addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3B', true, false) // .addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3B', true, false)
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3A', true, true) .addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3A', true, true)
.pause(500) .waitForElementVisible({
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]', 60000) locateStrategy: 'xpath',
selector: "//*[@id='instance0x692a70D2e424a56D2C6C27aA97D1a86395877b3A']"
})
.clickInstance(0) .clickInstance(0)
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' }) .clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('last', .testFunction('last',
@ -79,19 +92,11 @@ module.exports = {
}) })
}, },
'Deploy and use Ballot using external web3': function (browser: NightwatchBrowser) { 'Deploy and use Ballot using external web3 #group2': function (browser: NightwatchBrowser) {
browser browser
.openFile('Untitled.sol') .openFile('Untitled.sol')
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.switchEnvironment('External Http Provider') .connectToExternalHttpProvider('http://localhost:8545', 'Custom')
.waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]')
.execute(function () {
const modal = document.querySelector('[data-id="basic-http-provider-modal-footer-ok-react"]') as any
modal.click()
})
.pause(5000)
.waitForElementContainsText('#selectExEnvOptions button', 'External Http Provider')
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.pause(2000) .pause(2000)
@ -105,7 +110,7 @@ module.exports = {
.journalLastChildIncludes('data: 0x5c1...a733c') .journalLastChildIncludes('data: 0x5c1...a733c')
}, },
'Call method from Ballot to check return value using external web3': function (browser: NightwatchBrowser) { 'Call method from Ballot to check return value using external web3 #group2': function (browser: NightwatchBrowser) {
browser browser
.clickFunction('winnerName - call') .clickFunction('winnerName - call')
// Test in terminal // Test in terminal
@ -118,27 +123,113 @@ module.exports = {
.assert.containsText('*[data-id="treeViewDiv0"]', 'bytes32: winnerName_ 0x48656c6c6f20576f726c64210000000000000000000000000000000000000000') .assert.containsText('*[data-id="treeViewDiv0"]', 'bytes32: winnerName_ 0x48656c6c6f20576f726c64210000000000000000000000000000000000000000')
}, },
'Compile Ballot using config file': function (browser: NightwatchBrowser) { 'Compile Ballot using config file #group2': function (browser: NightwatchBrowser) {
browser browser
.addFile('cf.json', {content: configFile}) .addFile('cf.json', { content: configFile })
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.waitForElementVisible('*[data-id="scConfigExpander"]') .waitForElementVisible('*[data-id="scConfigExpander"]')
.click('*[data-id="scConfigExpander"]') .click('*[data-id="scConfigExpander"]')
.waitForElementVisible('*[data-id="scFileConfiguration"]', 10000) .waitForElementVisible('*[data-id="scFileConfiguration"]', 10000)
.click('*[data-id="scFileConfiguration"]') .click('*[data-id="scFileConfiguration"]')
.waitForElementVisible('*[data-id="scConfigChangeFilePath"]', 10000) // the input field behaves badly, it would often not receive the value, so retrying it a few times for now is the best thing to do
.click('*[data-id="scConfigChangeFilePath"]') .waitForElementVisible({
selector: '*[data-id="scConfigChangeFilePath"]',
abortOnFailure: false
}, 10000)
.click({
selector: '*[data-id="scConfigChangeFilePath"]',
suppressNotFoundErrors: true,
timeout: 1000
})
.click({
selector: '*[data-id="scConfigChangeFilePath"]',
suppressNotFoundErrors: true,
timeout: 1000
})
.click({
selector: '*[data-id="scConfigChangeFilePath"]',
suppressNotFoundErrors: true,
timeout: 1000
})
.waitForElementVisible('*[data-id="scConfigFilePathInput"]', 10000) .waitForElementVisible('*[data-id="scConfigFilePathInput"]', 10000)
.clearValue('*[data-id="scConfigFilePathInput"]') .sendKeys('*[data-id="scConfigFilePathInput"]', 'cf.json')
.setValue('*[data-id="scConfigFilePathInput"]', 'cf.json') .sendKeys('*[data-id="scConfigFilePathInput"]', browser.Keys.ENTER)
.sendKeys('*[data-id$="scConfigFilePathInput"]', browser.Keys.ENTER)
.isVisible({
selector:"//*[@class='py-2 remixui_compilerConfigPath' and contains(.,'cf.json')]",
suppressNotFoundErrors: true,
locateStrategy: 'xpath'
}, (okVisible) => {
// if it's not there yet, try again
if (!okVisible.value) {
browser.waitForElementVisible({
selector: '*[data-id="scConfigChangeFilePath"]',
abortOnFailure: false
}, 10000)
.click({
selector: '*[data-id="scConfigChangeFilePath"]',
suppressNotFoundErrors: true,
timeout: 1000
})
.click({
selector: '*[data-id="scConfigChangeFilePath"]',
suppressNotFoundErrors: true,
timeout: 1000
})
.click({
selector: '*[data-id="scConfigChangeFilePath"]',
suppressNotFoundErrors: true,
timeout: 1000
})
.waitForElementVisible('*[data-id="scConfigFilePathInput"]', 10000)
.sendKeys('*[data-id="scConfigFilePathInput"]', 'cf.json')
.sendKeys('*[data-id="scConfigFilePathInput"]', browser.Keys.ENTER)
}
})
.isVisible({
selector:"//*[@class='py-2 remixui_compilerConfigPath' and contains(.,'cf.json')]",
suppressNotFoundErrors: true,
locateStrategy: 'xpath'
}, (okVisible) => {
if (!okVisible.value) {
// if it's still not there, try again
browser.waitForElementVisible({
selector: '*[data-id="scConfigChangeFilePath"]',
abortOnFailure: false
}, 10000)
.click({
selector: '*[data-id="scConfigChangeFilePath"]',
suppressNotFoundErrors: true,
timeout: 1000
})
.click({
selector: '*[data-id="scConfigChangeFilePath"]',
suppressNotFoundErrors: true,
timeout: 1000
})
.click({
selector: '*[data-id="scConfigChangeFilePath"]',
suppressNotFoundErrors: true,
timeout: 1000
})
.waitForElementVisible('*[data-id="scConfigFilePathInput"]', 10000)
.sendKeys('*[data-id="scConfigFilePathInput"]', 'cf.json')
.sendKeys('*[data-id="scConfigFilePathInput"]', browser.Keys.ENTER)
}
})
.pause(5000)
.openFile('Untitled.sol') .openFile('Untitled.sol')
.verifyContracts(['Ballot'], {wait: 2000, runs: '300'}) .verifyContracts(['Ballot'], { wait: 2000, runs: '300' })
}, },
'Compile and deploy sample yul file': function (browser: NightwatchBrowser) { 'Compile and deploy sample yul file #group2': function (browser: NightwatchBrowser) {
browser browser
.addFile('sample.yul', {content: yulSample}) .addFile('sample.yul', { content: yulSample })
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.waitForElementVisible('*[data-id="scConfigExpander"]') .waitForElementVisible('*[data-id="scConfigExpander"]')
.click('*[data-id="scManualConfiguration"]') .click('*[data-id="scManualConfiguration"]')

@ -9,24 +9,33 @@ const sources = [
] ]
module.exports = { module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, null, false) init(browser, done, null, false)
}, },
'@sources': function () { '@sources': function () {
return sources return sources
}, },
'Compile Ballot with compiler version 0.4.11': function (browser: NightwatchBrowser) { 'Add Ballot': function (browser: NightwatchBrowser) {
browser
.addFile('Untitled.sol', sources[0]['Untitled.sol'])
},
'Set Ballot 0.4.14': function (browser: NightwatchBrowser) {
browser browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.setSolidityCompilerVersion('soljson-v0.4.11+commit.68ef5810.js') .setSolidityCompilerVersion('soljson-v0.4.14+commit.c2215d46.js')
.waitForElementVisible('[for="autoCompile"]') .waitForElementVisible('[for="autoCompile"]')
.click('[for="autoCompile"]') .click('[for="autoCompile"]')
.verify.elementPresent('[data-id="compilerContainerAutoCompile"]:checked') .verify.elementPresent('[data-id="compilerContainerAutoCompile"]:checked')
},
'Compile Ballot with compiler version 0.4.14': function (browser: NightwatchBrowser) {
browser
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot']) .testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot'])
}, },
'Deploy Ballot': function (browser: NightwatchBrowser) { 'Deploy Ballot #group1': function (browser: NightwatchBrowser) {
browser.pause(500) browser.pause(500)
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') .selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')
@ -42,7 +51,7 @@ module.exports = {
}) })
}, },
'Debug Ballot / delegate': function (browser: NightwatchBrowser) { 'Debug Ballot / delegate #group1': function (browser: NightwatchBrowser) {
browser.pause(500) browser.pause(500)
.debugTransaction(1) .debugTransaction(1)
.pause(2000) .pause(2000)
@ -55,16 +64,24 @@ module.exports = {
.checkVariableDebug('callstackpanel', ['0x692a70D2e424a56D2C6C27aA97D1a86395877b3A']) .checkVariableDebug('callstackpanel', ['0x692a70D2e424a56D2C6C27aA97D1a86395877b3A'])
}, },
'Access Ballot via at address': function (browser: NightwatchBrowser) { 'Access Ballot via at address #group1': function (browser: NightwatchBrowser) {
browser.clickLaunchIcon('udapp') browser.clickLaunchIcon('udapp')
.click('*[data-id="universalDappUiUdappClose"]') .click('*[data-id="universalDappUiUdappClose"]')
.addFile('ballot.abi', { content: ballotABI }) .addFile('ballot.abi', { content: ballotABI })
.clickLaunchIcon('udapp')
.click({
selector: '*[data-id="deployAndRunClearInstances"]',
abortOnFailure: false,
suppressNotFoundErrors: true,
})
// we are not changing the visibility for not checksumed contracts // we are not changing the visibility for not checksumed contracts
// .addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3B', true, false) // .addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3B', true, false)
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3A', true, true) .addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3A', true, true)
.pause(500) .waitForElementVisible({
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]', 60000) locateStrategy: 'xpath',
selector: "//*[@id='instance0x692a70D2e424a56D2C6C27aA97D1a86395877b3A']"
})
.clickInstance(0) .clickInstance(0)
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' }) .clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('last', .testFunction('last',
@ -73,18 +90,11 @@ module.exports = {
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
}) })
}, },
'Deploy and use Ballot using external web3 #group2': function (browser: NightwatchBrowser) {
'Deploy and use Ballot using external web3': function (browser: NightwatchBrowser) {
browser browser
.openFile('Untitled.sol')
.clickLaunchIcon('udapp')
.switchEnvironment('External Http Provider')
.waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]')
.execute(function () {
const modal = document.querySelector('[data-id="basic-http-provider-modal-footer-ok-react"]') as any
modal.click() .clickLaunchIcon('udapp')
}) .connectToExternalHttpProvider('http://localhost:8545', 'Custom')
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.pause(2000) .pause(2000)
@ -96,7 +106,6 @@ module.exports = {
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c' }) .clickFunction('delegate - transact (not payable)', { types: 'address to', values: '0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c' })
.journalLastChildIncludes('Ballot.delegate(address)') .journalLastChildIncludes('Ballot.delegate(address)')
.journalLastChildIncludes('data: 0x5c1...a733c') .journalLastChildIncludes('data: 0x5c1...a733c')
.end()
} }
} }

@ -14,8 +14,12 @@ module.exports = {
'Should launch debugger #group1': function (browser: NightwatchBrowser) { 'Should launch debugger #group1': function (browser: NightwatchBrowser) {
browser.addFile('blah.sol', sources[0]['blah.sol']) browser.addFile('blah.sol', sources[0]['blah.sol'])
.pause(4000)
// on autocompile sometimes the compiler returns invalid source, so we need to recompile to make sure the source is valid
.clickLaunchIcon('solidity').click('*[data-id="compilerContainerCompileBtn"]')
.pause(4000)
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.waitForElementPresent('*[title="Deploy - transact (not payable)"]', 65000) .waitForElementPresent('*[title="Deploy - transact (not payable)"]', 60000)
.click('*[title="Deploy - transact (not payable)"]') .click('*[title="Deploy - transact (not payable)"]')
.debugTransaction(0) .debugTransaction(0)
.waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000) .waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000)
@ -62,10 +66,10 @@ module.exports = {
browser.waitForElementVisible('#editorView') browser.waitForElementVisible('#editorView')
.execute(() => { .execute(() => {
(window as any).addRemixBreakpoint(11) (window as any).addRemixBreakpoint(11)
}, [], () => {}) }, [], () => { })
.execute(() => { .execute(() => {
(window as any).addRemixBreakpoint(21) (window as any).addRemixBreakpoint(21)
}, [], () => {}) }, [], () => { })
.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
.click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
.pause(2000) .pause(2000)
@ -88,15 +92,22 @@ module.exports = {
.selectContract('ERC20') .selectContract('ERC20')
.createContract('"tokenName", "symbol"') .createContract('"tokenName", "symbol"')
.debugTransaction(0) .debugTransaction(0)
.pause(2000)
.waitForElementVisible('#stepdetail') .waitForElementVisible('#stepdetail')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: '//*[@data-id="treeViewLivm trace step" and contains(.,"545")]',
})
.goToVMTraceStep(10) .goToVMTraceStep(10)
.waitForElementVisible({
locateStrategy: 'xpath',
selector: '//*[@data-id="treeViewLivm trace step" and contains(.,"10")]',
})
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`constructor (string memory name_, string memory symbol_) { browser.assert.ok(content.indexOf(`constructor (string memory name_, string memory symbol_) {
_name = name_; _name = name_;
_symbol = symbol_; _symbol = symbol_;
}`) !== -1, }`) !== -1,
'current displayed content is not from the ERC20 source code') 'current displayed content is not from the ERC20 source code')
}) })
}, },
@ -120,24 +131,25 @@ module.exports = {
.clickInstance(0) .clickInstance(0)
.clickFunction('test1 - transact (not payable)', { types: 'bytes userData', values: '0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000015b38da6a701c568545dcfcb03fcb875f56beddc4' }) .clickFunction('test1 - transact (not payable)', { types: 'bytes userData', values: '0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000015b38da6a701c568545dcfcb03fcb875f56beddc4' })
.debugTransaction(0) .debugTransaction(0)
.pause(2000)
.waitForElementVisible('#stepdetail') .waitForElementVisible('#stepdetail')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: '//*[@data-id="treeViewLivm trace step" and contains(.,"133")]',
})
.goToVMTraceStep(261) .goToVMTraceStep(261)
.pause(1000)
/*
for the test below:
source highlight should remain line `bytes32 idAsk = abi.decode(userData[:33], (bytes32));`
At this vmtrace index, the sourcemap has file = -1 because the execution is in the generated sources (ABIEncoderV2)
the atIndex of SourceLocationTracker was buggy and return an incorrect value, this is fixed
But the debugger uses now validSourcelocation, which means file is not -1.
In that case the source highlight at 261 should be the same as for step 262
*/
.waitForElementPresent('.highlightLine8') .waitForElementPresent('.highlightLine8')
/*
for the test below:
source highlight should remain line `bytes32 idAsk = abi.decode(userData[:33], (bytes32));`
At this vmtrace index, the sourcemap has file = -1 because the execution is in the generated sources (ABIEncoderV2)
the atIndex of SourceLocationTracker was buggy and return an incorrect value, this is fixed
But the debugger uses now validSourcelocation, which means file is not -1.
In that case the source highlight at 261 should be the same as for step 262
*/
.goToVMTraceStep(266) .goToVMTraceStep(266)
.pause(1000)
.checkVariableDebug('soliditylocals', localVariable_step266_ABIEncoder) // locals should not be initiated at this point, only idAsk should .checkVariableDebug('soliditylocals', localVariable_step266_ABIEncoder) // locals should not be initiated at this point, only idAsk should
.goToVMTraceStep(717) .goToVMTraceStep(717)
.pause(5000)
.checkVariableDebug('soliditylocals', localVariable_step717_ABIEncoder) // all locals should be initiaed .checkVariableDebug('soliditylocals', localVariable_step717_ABIEncoder) // all locals should be initiaed
.clearTransactions() .clearTransactions()
}, },
@ -228,7 +240,7 @@ module.exports = {
.waitForElementVisible('*[data-id="solidityLocals"]', 60000) .waitForElementVisible('*[data-id="solidityLocals"]', 60000)
.pause(10000) .pause(10000)
.checkVariableDebug('soliditylocals', { num: { value: '2', type: 'uint256' } }) .checkVariableDebug('soliditylocals', { num: { value: '2', type: 'uint256' } })
.checkVariableDebug('soliditystate', { number: { value: '0', type: 'uint256', constant: false, immutable: false } }) .checkVariableDebug('soliditystate', { number: { value: '0', type: 'uint256', constant: false, immutable: false } })
}, },
'Should debug reverted transactions #group5': function (browser: NightwatchBrowser) { 'Should debug reverted transactions #group5': function (browser: NightwatchBrowser) {

@ -26,20 +26,42 @@ module.exports = {
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/SampleERC721.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]')
.openFile('contracts/SampleERC721.sol') .openFile('contracts/MyToken.sol')
.verifyContracts(['SampleERC721']) // because the compilatiom imports are slow and sometimes stop loading (not sure why, it's bug) we need to recompile and check to see if the files are really in de FS
.clickLaunchIcon('solidity')
.pause(2000)
.click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel')
.isVisible({
selector: '*[data-id="treeViewLitreeViewItem.deps/npm/@openzeppelin/contracts/utils/introspection/IERC165.sol"]',
timeout: 120000,
suppressNotFoundErrors: true
})
.clickLaunchIcon('solidity')
.click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel')
.isVisible({
selector: '*[data-id="treeViewLitreeViewItem.deps/npm/@openzeppelin/contracts/utils/introspection/IERC165.sol"]',
timeout: 120000,
suppressNotFoundErrors: true
})
.clickLaunchIcon('solidity')
.click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel')
.waitForElementVisible({
selector: '*[data-id="treeViewLitreeViewItem.deps/npm/@openzeppelin/contracts/utils/introspection/IERC165.sol"]',
timeout: 120000,
})
.verifyContracts(['MyToken'])
// deploy contract // deploy contract
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.selectContract('SampleERC721') .selectContract('MyToken')
.createContract('E,E') .createContract('')
.testFunction('last', .testFunction('last',
{ {
status: 'true Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'decoded input': { 'decoded input': {}
'string tokenName': 'E',
'string tokenSymbol': 'E'
}
}).end() }).end()
} }
} }

@ -77,7 +77,7 @@ module.exports = {
'Should publish all explorer files to github gist': '' + function (browser: NightwatchBrowser) { 'Should publish all explorer files to github gist': '' + function (browser: NightwatchBrowser) {
const runtimeBrowser = browser.options.desiredCapabilities.browserName const runtimeBrowser = browser.options.desiredCapabilities.browserName
browser.refresh() browser.refreshPage()
.pause(10000) .pause(10000)
.waitForElementVisible('*[data-id="fileExplorerNewFilepublishToGist"]') .waitForElementVisible('*[data-id="fileExplorerNewFilepublishToGist"]')
.click('*[data-id="fileExplorerNewFilepublishToGist"]') .click('*[data-id="fileExplorerNewFilepublishToGist"]')

@ -163,7 +163,7 @@ const remixIdeThemes = {
}, },
flatly: { flatly: {
primary: '#2C3E50', primary: '#2C3E50',
secondary: '#95a5a6', secondary: '#dadfe0',
success: '#18BC9C', success: '#18BC9C',
info: '#3498DB', info: '#3498DB',
warning: '#F39C12', warning: '#F39C12',
@ -171,7 +171,7 @@ const remixIdeThemes = {
}, },
spacelab: { spacelab: {
primary: '#446E9B', primary: '#446E9B',
secondary: '#999', secondary: '#dadfe0',
success: '#3CB521', success: '#3CB521',
info: '#3399F3', info: '#3399F3',
warning: '#D47500', warning: '#D47500',
@ -179,7 +179,7 @@ const remixIdeThemes = {
}, },
cyborg: { cyborg: {
primary: '#2A9FD6', primary: '#2A9FD6',
secondary: '#555', secondary: '#3c3939',
success: '#77B300', success: '#77B300',
info: '#93C', info: '#93C',
warning: '#F80', warning: '#F80',

@ -23,7 +23,7 @@ module.exports = {
console.log('token', process.env.gist_token) console.log('token', process.env.gist_token)
const gistid = '17ac9315bc065a3d95cf8dc1b28d71f8' const gistid = '17ac9315bc065a3d95cf8dc1b28d71f8'
browser browser
.refresh() .refreshPage()
.pause(10000) .pause(10000)
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]') // focus on root directory .click('li[data-id="treeViewLitreeViewItemREADME.txt"]') // focus on root directory

@ -22,7 +22,7 @@ module.exports = {
.waitForElementVisible('*[data-id="skipbackup-btn"]', 5000) .waitForElementVisible('*[data-id="skipbackup-btn"]', 5000)
.click('*[data-id="skipbackup-btn"]') .click('*[data-id="skipbackup-btn"]')
.waitForElementVisible('[id="remixTourSkipbtn"]') .waitForElementVisible('[id="remixTourSkipbtn"]')
.click('[id="remixTourSkipbtn"]').refresh() .click('[id="remixTourSkipbtn"]').refreshPage()
}, },
'should have indexedDB storage in terminal #group1 #group7': function (browser: NightwatchBrowser) { 'should have indexedDB storage in terminal #group1 #group7': function (browser: NightwatchBrowser) {
browser.assert.containsText('*[data-id="terminalJournal"]', 'indexedDB') browser.assert.containsText('*[data-id="terminalJournal"]', 'indexedDB')

@ -112,7 +112,7 @@ module.exports = {
.waitForElementVisible('*[data-id="remixIdeSidePanel"]',3000) .waitForElementVisible('*[data-id="remixIdeSidePanel"]',3000)
.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]') .waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]')
.getInstalledPlugins((plugins) => { .getInstalledPlugins((plugins) => {
browser.refresh() browser.refreshPage()
.waitForElementVisible('*[data-id="remixIdeSidePanel"]') .waitForElementVisible('*[data-id="remixIdeSidePanel"]')
.pause(3000) .pause(3000)
.perform((done) => { .perform((done) => {

@ -5,6 +5,7 @@ import init from '../helpers/init'
let firstProxyAddress: string let firstProxyAddress: string
let lastProxyAddress: string let lastProxyAddress: string
module.exports = { module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done) init(browser, done)
}, },
@ -13,12 +14,36 @@ module.exports = {
return sources return sources
}, },
'Should show deploy proxy option for UUPS upgradeable contract': function (browser: NightwatchBrowser) {
'Should show deploy proxy option for UUPS upgradeable contract #group1': function (browser: NightwatchBrowser) {
browser browser
.addFile('myTokenV1.sol', sources[0]['myTokenV1.sol']) .addFile('myTokenV1.sol', sources[0]['myTokenV1.sol'])
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.pause(2000) .pause(2000)
// because the compilatiom imports are slow and sometimes stop loading (not sure why, it's bug) we need to recompile and check to see if the files are really in de FS
.click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel')
.isVisible({
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol"]',
timeout: 120000,
suppressNotFoundErrors: true
})
.clickLaunchIcon('solidity')
.click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel')
.isVisible({
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol"]',
timeout: 120000,
suppressNotFoundErrors: true
})
.clickLaunchIcon('solidity')
.click('[data-id="compilerContainerCompileBtn"]') .click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel')
.waitForElementVisible({
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol"]',
timeout: 120000,
})
.clickLaunchIcon('solidity')
.waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000) .waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000)
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.click('select.udapp_contractNames') .click('select.udapp_contractNames')
@ -27,7 +52,7 @@ module.exports = {
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') .waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]')
}, },
'Should show upgrade proxy option for child contract inheriting UUPS parent contract': function (browser: NightwatchBrowser) { 'Should show upgrade proxy option for child contract inheriting UUPS parent contract #group1': function (browser: NightwatchBrowser) {
browser browser
.addFile('myTokenV2.sol', sources[1]['myTokenV2.sol']) .addFile('myTokenV2.sol', sources[1]['myTokenV2.sol'])
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
@ -41,7 +66,7 @@ module.exports = {
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') .waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]')
}, },
'Should deploy proxy without initialize parameters': function (browser: NightwatchBrowser) { 'Should deploy proxy without initialize parameters #group1': function (browser: NightwatchBrowser) {
browser browser
.openFile('myTokenV1.sol') .openFile('myTokenV1.sol')
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
@ -64,7 +89,7 @@ module.exports = {
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') .waitForElementPresent('[data-id="universalDappUiTitleExpander1"]')
}, },
'Should interact with deployed contract via ERC1967 (proxy)': function (browser: NightwatchBrowser) { 'Should interact with deployed contract via ERC1967 (proxy) #group1': function (browser: NightwatchBrowser) {
browser browser
.getAddressAtPosition(1, (address) => { .getAddressAtPosition(1, (address) => {
firstProxyAddress = address firstProxyAddress = address
@ -82,7 +107,7 @@ module.exports = {
}) })
}, },
'Should deploy proxy with initialize parameters': function (browser: NightwatchBrowser) { 'Should deploy proxy with initialize parameters #group1': function (browser: NightwatchBrowser) {
browser browser
.waitForElementPresent('[data-id="deployAndRunClearInstances"]') .waitForElementPresent('[data-id="deployAndRunClearInstances"]')
.click('[data-id="deployAndRunClearInstances"]') .click('[data-id="deployAndRunClearInstances"]')
@ -111,7 +136,7 @@ module.exports = {
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') .waitForElementPresent('[data-id="universalDappUiTitleExpander1"]')
}, },
'Should interact with initialized contract to verify parameters': function (browser: NightwatchBrowser) { 'Should interact with initialized contract to verify parameters #group1': function (browser: NightwatchBrowser) {
browser browser
.getAddressAtPosition(1, (address) => { .getAddressAtPosition(1, (address) => {
lastProxyAddress = address lastProxyAddress = address
@ -129,7 +154,7 @@ module.exports = {
}) })
}, },
'Should upgrade contract using last deployed proxy address (MyTokenV1 to MyTokenV2)': function (browser: NightwatchBrowser) { 'Should upgrade contract using last deployed proxy address (MyTokenV1 to MyTokenV2) #group1': function (browser: NightwatchBrowser) {
browser browser
.waitForElementPresent('[data-id="deployAndRunClearInstances"]') .waitForElementPresent('[data-id="deployAndRunClearInstances"]')
.click('[data-id="deployAndRunClearInstances"]') .click('[data-id="deployAndRunClearInstances"]')
@ -153,12 +178,15 @@ module.exports = {
.click('[data-id="udappNotify-modal-footer-ok-react"]') .click('[data-id="udappNotify-modal-footer-ok-react"]')
.waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Update Proxy (ERC1967)') .waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Update Proxy (ERC1967)')
.waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') .waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]')
.click('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') .click(
{
selector: '[data-id="confirmProxyDeployment-modal-footer-ok-react"]',
})
.waitForElementPresent('[data-id="universalDappUiTitleExpander0"]') .waitForElementPresent('[data-id="universalDappUiTitleExpander0"]')
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') .waitForElementPresent('[data-id="universalDappUiTitleExpander1"]')
}, },
'Should interact with upgraded function in contract MyTokenV2': function (browser: NightwatchBrowser) { 'Should interact with upgraded function in contract MyTokenV2 #group1': function (browser: NightwatchBrowser) {
browser browser
.clickInstance(1) .clickInstance(1)
.perform((done) => { .perform((done) => {
@ -168,7 +196,7 @@ module.exports = {
}) })
}, },
'Should upgrade contract by providing proxy address in input field (MyTokenV1 to MyTokenV2)': function (browser: NightwatchBrowser) { 'Should upgrade contract by providing proxy address in input field (MyTokenV1 to MyTokenV2) #group1': function (browser: NightwatchBrowser) {
browser browser
.waitForElementPresent('[data-id="deployAndRunClearInstances"]') .waitForElementPresent('[data-id="deployAndRunClearInstances"]')
.click('[data-id="deployAndRunClearInstances"]') .click('[data-id="deployAndRunClearInstances"]')
@ -196,7 +224,7 @@ module.exports = {
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') .waitForElementPresent('[data-id="universalDappUiTitleExpander1"]')
}, },
'Should interact with upgraded contract through provided proxy address': function (browser: NightwatchBrowser) { 'Should interact with upgraded contract through provided proxy address #group1': function (browser: NightwatchBrowser) {
browser browser
.clickInstance(1) .clickInstance(1)
.perform((done) => { .perform((done) => {
@ -208,6 +236,7 @@ module.exports = {
} }
} }
const sources = [ const sources = [
{ {
'myTokenV1.sol': { 'myTokenV1.sol': {

@ -80,7 +80,7 @@ module.exports = {
'Should remember choice after page refresh': function (browser: NightwatchBrowser) { 'Should remember choice after page refresh': function (browser: NightwatchBrowser) {
browser browser
.refresh() .refreshPage()
.waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts"]') .waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts"]')
.click('[data-id="treeViewLitreeViewItemcontracts"]') .click('[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/1_Storage.sol') .openFile('contracts/1_Storage.sol')

@ -15,7 +15,10 @@ module.exports = {
'Run Scenario #group1': function (browser: NightwatchBrowser) { 'Run Scenario #group1': function (browser: NightwatchBrowser) {
let addressRef let addressRef
browser.addFile('scenario.json', { content: records }) browser.addFile('scenario.json', { content: records })
.pause(5000) .waitForElementVisible({
locateStrategy: 'xpath',
selector: "//*[contains(@class, 'view-lines') and contains(.,'0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')]"
})
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite .selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite
.click('[data-id="udappRecorderTitleExpander"]') .click('[data-id="udappRecorderTitleExpander"]')

@ -1,6 +1,10 @@
'use strict' 'use strict'
import { NightwatchBrowser } from 'nightwatch' import { NightwatchBrowser } from 'nightwatch'
import { writeFileSync } from 'fs'
import init from '../helpers/init' import init from '../helpers/init'
import * as hardhatCompilation from '../helpers/hardhat_compilation_8a7ab689ec618720f53ce867a3031c03.json'
import * as foundryCompilation from '../helpers/foundry_compilation.json'
import * as truffle_compilation from '../helpers/truffle_compilation.json'
const assetsTestContract = `import "./contract.sol"; const assetsTestContract = `import "./contract.sol";
contract Assets { contract Assets {
@ -112,8 +116,66 @@ module.exports = {
browser browser
.clickLaunchIcon('pluginManager') .clickLaunchIcon('pluginManager')
.scrollAndClick('#pluginManager *[data-id="pluginManagerComponentDeactivateButtonremixd"]') .scrollAndClick('#pluginManager *[data-id="pluginManagerComponentDeactivateButtonremixd"]')
.end() },
}
'Should listen on compilation result from hardhat #group5': function (browser: NightwatchBrowser) {
browser.perform((done) => {
console.log('working directory', process.cwd())
writeFileSync('./apps/remix-ide/contracts/artifacts/build-info/c7062fdd360381a85af23eeef31c98f8.json', JSON.stringify(hardhatCompilation))
done()
})
.expect.element('*[data-id="terminalJournal"]').text.to.contain('receiving compilation result from hardhat').before(60000)
browser.clickLaunchIcon('udapp')
.assert.textContains('*[data-id="udappCompiledBy"]', 'Compiled by hardhat')
.selectContract('Lock')
.createContract('1')
.expect.element('*[data-id="terminalJournal"]').text.to.contain('Unlock time should be in the future').before(60000)
},
'Should listen on compilation result from foundry #group6': function (browser: NightwatchBrowser) {
browser.perform((done) => {
console.log('working directory', process.cwd())
writeFileSync('./apps/remix-ide/contracts/out/Counter.sol/Counter.json', JSON.stringify(foundryCompilation))
done()
})
.expect.element('*[data-id="terminalJournal"]').text.to.contain('receiving compilation result from foundry').before(60000)
let contractAaddress
browser.clickLaunchIcon('udapp')
.assert.textContains('*[data-id="udappCompiledBy"]', 'Compiled by foundry')
.selectContract('Counter')
.createContract('')
.getAddressAtPosition(0, (address) => {
console.log(contractAaddress)
contractAaddress = address
})
.clickInstance(0)
.clickFunction('increment - transact (not payable)')
.perform((done) => {
browser.testConstantFunction(contractAaddress, 'number - call', null, '0:\nuint256: 1').perform(() => {
done()
})
})
},
'Should listen on compilation result from truffle #group7': function (browser: NightwatchBrowser) {
browser.perform((done) => {
console.log('working directory', process.cwd())
writeFileSync('./apps/remix-ide/contracts/build/contracts/Migrations.json', JSON.stringify(truffle_compilation))
done()
})
.expect.element('*[data-id="terminalJournal"]').text.to.contain('receiving compilation result from truffle').before(60000)
browser.clickLaunchIcon('udapp')
.assert.textContains('*[data-id="udappCompiledBy"]', 'Compiled by truffle')
.selectContract('Migrations')
.createContract('')
.testFunction('last',
{
status: 'true Transaction mined and execution succeed'
})
}
} }
function startRemixd (browser: NightwatchBrowser) { function startRemixd (browser: NightwatchBrowser) {

@ -109,7 +109,7 @@ module.exports = {
.click('.network-indicator__down-arrow') .click('.network-indicator__down-arrow')
.useXpath().click("//span[text()='Goerli Test Network']") .useXpath().click("//span[text()='Goerli Test Network']")
.useCss().switchBrowserTab(0) .useCss().switchBrowserTab(0)
.refresh() .refreshPage()
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.click('*[data-id="landingPageStartSolidity"]') .click('*[data-id="landingPageStartSolidity"]')
.pause(5000) .pause(5000)
@ -165,7 +165,7 @@ module.exports = {
.click('.network-indicator__down-arrow') .click('.network-indicator__down-arrow')
.useXpath().click("//span[text()='Main Ethereum Network']") .useXpath().click("//span[text()='Main Ethereum Network']")
.useCss().switchBrowserTab(0) .useCss().switchBrowserTab(0)
.refresh() .refreshPage()
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.click('*[data-id="landingPageStartSolidity"]') .click('*[data-id="landingPageStartSolidity"]')
.pause(5000) .pause(5000)
@ -204,7 +204,7 @@ module.exports = {
.click('.network-indicator__down-arrow') .click('.network-indicator__down-arrow')
.useXpath().click("//span[text()='Ropsten Test Network']") // switch to Ropsten .useXpath().click("//span[text()='Ropsten Test Network']") // switch to Ropsten
.useCss().switchBrowserTab(0) .useCss().switchBrowserTab(0)
.refresh() .refreshPage()
.clickLaunchIcon('pluginManager') // load debugger and source verification .clickLaunchIcon('pluginManager') // load debugger and source verification
// .scrollAndClick('#pluginManager article[id="remixPluginManagerListItem_sourcify"] button') // .scrollAndClick('#pluginManager article[id="remixPluginManagerListItem_sourcify"] button')
// debugger already activated .scrollAndClick('#pluginManager article[id="remixPluginManagerListItem_debugger"] button') // debugger already activated .scrollAndClick('#pluginManager article[id="remixPluginManagerListItem_debugger"] button')

@ -27,7 +27,27 @@ module.exports = {
'Test Failed Import #group1': function (browser: NightwatchBrowser) { 'Test Failed Import #group1': function (browser: NightwatchBrowser) {
browser.addFile('Untitled3.sol', sources[2]['Untitled3.sol']) browser.addFile('Untitled3.sol', sources[2]['Untitled3.sol'])
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.assert.containsText('#compileTabView .error pre', 'not found Untitled11.sol') .click('[data-id="compilerContainerCompileBtn"]')
.isVisible({
selector: "//span[contains(.,'not found Untitled11')]",
locateStrategy: 'xpath',
timeout: 120000,
suppressNotFoundErrors: true
})
.click('[data-id="compilerContainerCompileBtn"]')
.isVisible({
selector: "//span[contains(.,'not found Untitled11')]",
locateStrategy: 'xpath',
timeout: 120000,
suppressNotFoundErrors: true
})
.click('[data-id="compilerContainerCompileBtn"]')
.waitForElementVisible({
selector: "//span[contains(.,'not found Untitled11')]",
locateStrategy: 'xpath',
timeout: 120000,
})
}, },
'Test GitHub Import - from master branch #group1': function (browser: NightwatchBrowser) { 'Test GitHub Import - from master branch #group1': function (browser: NightwatchBrowser) {
@ -84,10 +104,27 @@ module.exports = {
'Test NPM Import (with unpkg.com) #group3': function (browser: NightwatchBrowser) { 'Test NPM Import (with unpkg.com) #group3': function (browser: NightwatchBrowser) {
browser browser
.setSolidityCompilerVersion('soljson-v0.8.7+commit.e28d00a7.js') .setSolidityCompilerVersion('soljson-v0.8.7+commit.e28d00a7.js')
.waitForElementPresent({
selector: `//*[@data-id='compilerloaded' and @data-version='soljson-v0.8.7+commit.e28d00a7.js']`,
locateStrategy: 'xpath',
timeout: 120000
})
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"') .click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled9.sol', sources[8]['Untitled9.sol']) .addFile('Untitled9.sol', sources[8]['Untitled9.sol'])
// avoid invalid source issues
.isVisible({
selector: '*[data-id="treeViewLitreeViewItem.deps/npm/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"]',
timeout: 120000,
suppressNotFoundErrors: true
})
.clickLaunchIcon('solidity')
.click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.isVisible({
selector: '*[data-id="treeViewLitreeViewItem.deps/npm/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"]',
timeout: 120000,
})
.verifyContracts(['test13', 'ERC20'], { wait: 30000 }) .verifyContracts(['test13', 'ERC20'], { wait: 30000 })
.end() .end()
} }

@ -291,9 +291,11 @@ module.exports = {
.goToVMTraceStep(316) .goToVMTraceStep(316)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalFailed()', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalFailed()', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'vote(proposal)', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'vote(proposal)', 60000)
.pause(5000) .waitForElementVisible({
locateStrategy: 'xpath',
selector: "//*[@data-id='treeViewDivtreeViewItemsender' and contains(.,'Ballot.Voter')]"
})
.checkVariableDebug('soliditylocals', locals) .checkVariableDebug('soliditylocals', locals)
.pause(5000)
.clickLaunchIcon('solidityUnitTesting').pause(2000) .clickLaunchIcon('solidityUnitTesting').pause(2000)
.scrollAndClick('#Check_winning_proposal_passed') .scrollAndClick('#Check_winning_proposal_passed')
.waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000) .waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000)
@ -303,17 +305,19 @@ module.exports = {
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalPassed()', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalPassed()', 60000)
// remix_test.sol should be opened in editor // remix_test.sol should be opened in editor
.getEditorValue((content) => browser.assert.ok(content.indexOf('library Assert {') !== -1)) .getEditorValue((content) => browser.assert.ok(content.indexOf('library Assert {') !== -1))
.pause(5000) .clickLaunchIcon('solidityUnitTesting')
.clickLaunchIcon('solidityUnitTesting').pause(2000) .waitForElementPresent('#Check_winning_proposal_again')
.scrollAndClick('#Check_winning_proposal_again') .scrollAndClick('#Check_winning_proposal_again')
.waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000) .waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalAgain()', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalAgain()', 60000)
.goToVMTraceStep(1151) .goToVMTraceStep(1151)
.waitForElementContainsText('*[data-id="functionPanel"]', 'equal(a, b, message)', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'equal(a, b, message)', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalAgain()', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalAgain()', 60000)
//.pause(5000)
.clickLaunchIcon('solidityUnitTesting')
.pause(5000)
.scrollAndClick('#Check_winnin_proposal_with_return_value')
.pause(5000) .pause(5000)
.clickLaunchIcon('solidityUnitTesting').pause(5000)
.scrollAndClick('#Check_winnin_proposal_with_return_value').pause(5000)
.waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000) .waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinninProposalWithReturnValue()', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinninProposalWithReturnValue()', 60000)
.goToVMTraceStep(321) .goToVMTraceStep(321)

@ -182,7 +182,7 @@ module.exports = {
done() done()
}) })
.pause(10000) .pause(10000)
.refresh() .refreshPage()
.perform(done => checkContent(0, done)) .perform(done => checkContent(0, done))
.perform(done => checkContent(1, done)) .perform(done => checkContent(1, done))
.perform(done => checkContent(2, done)) .perform(done => checkContent(2, done))

@ -164,6 +164,8 @@ module.exports = {
}, },
'Should print hardhat logs #group4': function (browser: NightwatchBrowser) { 'Should print hardhat logs #group4': function (browser: NightwatchBrowser) {
browser browser
.addFile('printHardhatlog.sol', { content: hardhatLog })
.clickLaunchIcon('solidity')
.click('*[data-id="terminalClearConsole"]') // clear the terminal .click('*[data-id="terminalClearConsole"]') // clear the terminal
.waitForElementVisible('[for="autoCompile"]') .waitForElementVisible('[for="autoCompile"]')
.click('[for="autoCompile"]') .click('[for="autoCompile"]')

@ -23,8 +23,6 @@ module.exports = {
status: 'true Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'decoded output': { 0: 'uint256: 8' } 'decoded output': { 0: 'uint256: 8' }
}) })
.pause(120000)
//.checkTerminalFilter('0x12332162e2e31397dc1e07ed0a1cf08f728e9b4487c6f9ed79d2f39410c92782', '')
.clickFunction('g - transact (not payable)') .clickFunction('g - transact (not payable)')
.testFunction('last', .testFunction('last',
{ {

@ -49,15 +49,17 @@ module.exports = {
'@sources': function () { '@sources': function () {
return sources return sources
}, },
'Disable auto compile': function (browser: NightwatchBrowser) {
'Should load the code from URL params (code param) #group1': function (browser: NightwatchBrowser) {
browser browser
.waitForElementVisible('[for="autoCompile"]') .waitForElementVisible('[for="autoCompile"]')
.click('[for="autoCompile"]') // we set it too false in the local storage .click('[for="autoCompile"]') // we set it too false in the local storage
.pause(5000) },
.url('http://127.0.0.1:8080/#autoCompile=true&optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0') 'Should load the code from URL params (code param) #group1': function (browser: NightwatchBrowser) {
.refresh() // we do one reload for making sure we already have the default workspace browser
.pause(5000)
.url('http://127.0.0.1:8080/#autoCompile=true&optimize=true&runs=300&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0')
.refreshPage() // we do one reload for making sure we already have the default workspace
.verify.elementPresent('[data-id="compilerContainerAutoCompile"]:checked') .verify.elementPresent('[data-id="compilerContainerAutoCompile"]:checked')
.click('[for="autoCompile"]') // we set it too false again .click('[for="autoCompile"]') // we set it too false again
.click('[for="autoCompile"]') // back to True in the local storage .click('[for="autoCompile"]') // back to True in the local storage
@ -73,10 +75,13 @@ module.exports = {
'Should load the code from URL params (url param) #group1': function (browser: NightwatchBrowser) { 'Should load the code from URL params (url param) #group1': function (browser: NightwatchBrowser) {
browser browser
.pause(5000)
.url('http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol') .url('http://127.0.0.1:8080/#optimize=true&runs=300&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol')
.refresh() // we do one reload for making sure we already have the default workspace .refreshPage() // we do one reload for making sure we already have the default workspace
.pause(5000) .waitForElementVisible({
selector: `//li[@data-id="treeViewLitreeViewItemethereum/remix-project/apps/remix-ide/contracts/app/solidity/mode.sol"]`,
locateStrategy: 'xpath'
})
.currentWorkspaceIs('code-sample') .currentWorkspaceIs('code-sample')
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content && content.indexOf( browser.assert.ok(content && content.indexOf(
@ -87,10 +92,10 @@ module.exports = {
'Should load Etherscan verified contracts from URL "address" param)': !function (browser: NightwatchBrowser) { 'Should load Etherscan verified contracts from URL "address" param)': !function (browser: NightwatchBrowser) {
browser browser
.pause(5000)
.url('http://127.0.0.1:8080/#address=0x56db08fb78bc6689a1ef66efd079083fed0e4915') .url('http://127.0.0.1:8080/#address=0x56db08fb78bc6689a1ef66efd079083fed0e4915')
.refresh() .refreshPage()
.pause(7000)
.currentWorkspaceIs('etherscan-code-sample') .currentWorkspaceIs('etherscan-code-sample')
.assert.elementPresent('*[data-id=treeViewLitreeViewItemropsten]') .assert.elementPresent('*[data-id=treeViewLitreeViewItemropsten]')
.assert.elementPresent('*[data-id=treeViewLitreeViewItemrinkeby]') .assert.elementPresent('*[data-id=treeViewLitreeViewItemrinkeby]')
@ -101,7 +106,7 @@ module.exports = {
'contract Sample {') !== -1) 'contract Sample {') !== -1)
}) })
.url('http://127.0.0.1:8080/#address=0xdac17f958d2ee523a2206206994597c13d831ec7') .url('http://127.0.0.1:8080/#address=0xdac17f958d2ee523a2206206994597c13d831ec7')
.refresh() .refreshPage()
.pause(7000) .pause(7000)
.currentWorkspaceIs('etherscan-code-sample') .currentWorkspaceIs('etherscan-code-sample')
.assert.elementPresent('*[data-id=treeViewLitreeViewItemmainnet]') .assert.elementPresent('*[data-id=treeViewLitreeViewItemmainnet]')
@ -116,37 +121,33 @@ module.exports = {
'Should load the code from URL & code params #group1': function (browser: NightwatchBrowser) { 'Should load the code from URL & code params #group1': function (browser: NightwatchBrowser) {
browser browser
.pause(5000) .url('http://127.0.0.1:8080/#optimize=true&runs=300&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0')
.url('http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0') .refreshPage() // we do one reload for making sure we already have the default workspace
.refresh() // we do one reload for making sure we already have the default workspace
.pause(5000) .waitForElementVisible('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.waitForElementVisible({
selector: `//li[@data-id="treeViewLitreeViewItemethereum/remix-project/apps/remix-ide/contracts/app/solidity/mode.sol"]`,
locateStrategy: 'xpath'
})
.currentWorkspaceIs('code-sample') .currentWorkspaceIs('code-sample')
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content && content.indexOf( browser.assert.ok(content && content.indexOf(
'proposals.length = _numProposals;') !== -1, 'proposals.length = _numProposals;') !== -1,
'code has not been loaded') 'code has been loaded')
}) })
.openFile('contract-76747f6e19.sol')
.openFile('ethereum')
.openFile('ethereum/remix-project')
.openFile('ethereum/remix-project/apps')
.openFile('ethereum/remix-project/apps/remix-ide')
.openFile('ethereum/remix-project/apps/remix-ide/contracts')
.openFile('ethereum/remix-project/apps/remix-ide/contracts/app')
.openFile('ethereum/remix-project/apps/remix-ide/contracts/app/solidity')
.openFile('ethereum/remix-project/apps/remix-ide/contracts/app/solidity/mode.sol')
}, },
'Should load the code from language & code params #group1': function (browser: NightwatchBrowser) { 'Should load the code from language & code params #group1': function (browser: NightwatchBrowser) {
browser browser
.pause(5000)
.url('http://127.0.0.1:8080/#language=yul&version=soljson-v0.8.7+commit.e28d00a7.js&code=Ly8gQSBjb250cmFjdCBjb25zaXN0cyBvZiBhIHNpbmdsZSBvYmplY3Qgd2l0aCBzdWItb2JqZWN0cyByZXByZXNlbnRpbmcKLy8gdGhlIGNvZGUgdG8gYmUgZGVwbG95ZWQgb3Igb3RoZXIgY29udHJhY3RzIGl0IGNhbiBjcmVhdGUuCi8vIFRoZSBzaW5nbGUgImNvZGUiIG5vZGUgaXMgdGhlIGV4ZWN1dGFibGUgY29kZSBvZiB0aGUgb2JqZWN0LgovLyBFdmVyeSAob3RoZXIpIG5hbWVkIG9iamVjdCBvciBkYXRhIHNlY3Rpb24gaXMgc2VyaWFsaXplZCBhbmQKLy8gbWFkZSBhY2Nlc3NpYmxlIHRvIHRoZSBzcGVjaWFsIGJ1aWx0LWluIGZ1bmN0aW9ucyBkYXRhY29weSAvIGRhdGFvZmZzZXQgLyBkYXRhc2l6ZQovLyBUaGUgY3VycmVudCBvYmplY3QsIHN1Yi1vYmplY3RzIGFuZCBkYXRhIGl0ZW1zIGluc2lkZSB0aGUgY3VycmVudCBvYmplY3QKLy8gYXJlIGluIHNjb3BlLgpvYmplY3QgIkNvbnRyYWN0MSIgewogICAgLy8gVGhpcyBpcyB0aGUgY29uc3RydWN0b3IgY29kZSBvZiB0aGUgY29udHJhY3QuCiAgICBjb2RlIHsKICAgICAgICBmdW5jdGlvbiBhbGxvY2F0ZShzaXplKSAtPiBwdHIgewogICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgaWYgaXN6ZXJvKHB0cikgeyBwdHIgOj0gMHg2MCB9CiAgICAgICAgICAgIG1zdG9yZSgweDQwLCBhZGQocHRyLCBzaXplKSkKICAgICAgICB9CgogICAgICAgIC8vIGZpcnN0IGNyZWF0ZSAiQ29udHJhY3QyIgogICAgICAgIGxldCBzaXplIDo9IGRhdGFzaXplKCJDb250cmFjdDIiKQogICAgICAgIGxldCBvZmZzZXQgOj0gYWxsb2NhdGUoc2l6ZSkKICAgICAgICAvLyBUaGlzIHdpbGwgdHVybiBpbnRvIGNvZGVjb3B5IGZvciBFVk0KICAgICAgICBkYXRhY29weShvZmZzZXQsIGRhdGFvZmZzZXQoIkNvbnRyYWN0MiIpLCBzaXplKQogICAgICAgIC8vIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBpcyBhIHNpbmdsZSBudW1iZXIgMHgxMjM0CiAgICAgICAgbXN0b3JlKGFkZChvZmZzZXQsIHNpemUpLCAweDEyMzQpCiAgICAgICAgcG9wKGNyZWF0ZShvZmZzZXQsIGFkZChzaXplLCAzMiksIDApKQoKICAgICAgICAvLyBub3cgcmV0dXJuIHRoZSBydW50aW1lIG9iamVjdCAodGhlIGN1cnJlbnRseQogICAgICAgIC8vIGV4ZWN1dGluZyBjb2RlIGlzIHRoZSBjb25zdHJ1Y3RvciBjb2RlKQogICAgICAgIHNpemUgOj0gZGF0YXNpemUoIkNvbnRyYWN0MV9kZXBsb3llZCIpCiAgICAgICAgb2Zmc2V0IDo9IGFsbG9jYXRlKHNpemUpCiAgICAgICAgLy8gVGhpcyB3aWxsIHR1cm4gaW50byBhIG1lbW9yeS0+bWVtb3J5IGNvcHkgZm9yIEV3YXNtIGFuZAogICAgICAgIC8vIGEgY29kZWNvcHkgZm9yIEVWTQogICAgICAgIGRhdGFjb3B5KG9mZnNldCwgZGF0YW9mZnNldCgiQ29udHJhY3QxX2RlcGxveWVkIiksIHNpemUpCiAgICAgICAgcmV0dXJuKG9mZnNldCwgc2l6ZSkKICAgIH0KCiAgICBkYXRhICJUYWJsZTIiIGhleCI0MTIzIgoKICAgIG9iamVjdCAiQ29udHJhY3QxX2RlcGxveWVkIiB7CiAgICAgICAgY29kZSB7CiAgICAgICAgICAgIGZ1bmN0aW9uIGFsbG9jYXRlKHNpemUpIC0+IHB0ciB7CiAgICAgICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgICAgIGlmIGlzemVybyhwdHIpIHsgcHRyIDo9IDB4NjAgfQogICAgICAgICAgICAgICAgbXN0b3JlKDB4NDAsIGFkZChwdHIsIHNpemUpKQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBydW50aW1lIGNvZGUKCiAgICAgICAgICAgIG1zdG9yZSgwLCAiSGVsbG8sIFdvcmxkISIpCiAgICAgICAgICAgIHJldHVybigwLCAweDIwKQogICAgICAgIH0KICAgIH0KCiAgICAvLyBFbWJlZGRlZCBvYmplY3QuIFVzZSBjYXNlIGlzIHRoYXQgdGhlIG91dHNpZGUgaXMgYSBmYWN0b3J5IGNvbnRyYWN0LAogICAgLy8gYW5kIENvbnRyYWN0MiBpcyB0aGUgY29kZSB0byBiZSBjcmVhdGVkIGJ5IHRoZSBmYWN0b3J5CiAgICBvYmplY3QgIkNvbnRyYWN0MiIgewogICAgICAgIGNvZGUgewogICAgICAgICAgICAvLyBjb2RlIGhlcmUgLi4uCiAgICAgICAgfQoKICAgICAgICBvYmplY3QgIkNvbnRyYWN0Ml9kZXBsb3llZCIgewogICAgICAgICAgICBjb2RlIHsKICAgICAgICAgICAgICAgIC8vIGNvZGUgaGVyZSAuLi4KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZGF0YSAiVGFibGUxIiBoZXgiNDEyMyIKICAgIH0KfQ&optimize=false&runs=200&evmVersion=null') .url('http://127.0.0.1:8080/#language=yul&code=Ly8gQSBjb250cmFjdCBjb25zaXN0cyBvZiBhIHNpbmdsZSBvYmplY3Qgd2l0aCBzdWItb2JqZWN0cyByZXByZXNlbnRpbmcKLy8gdGhlIGNvZGUgdG8gYmUgZGVwbG95ZWQgb3Igb3RoZXIgY29udHJhY3RzIGl0IGNhbiBjcmVhdGUuCi8vIFRoZSBzaW5nbGUgImNvZGUiIG5vZGUgaXMgdGhlIGV4ZWN1dGFibGUgY29kZSBvZiB0aGUgb2JqZWN0LgovLyBFdmVyeSAob3RoZXIpIG5hbWVkIG9iamVjdCBvciBkYXRhIHNlY3Rpb24gaXMgc2VyaWFsaXplZCBhbmQKLy8gbWFkZSBhY2Nlc3NpYmxlIHRvIHRoZSBzcGVjaWFsIGJ1aWx0LWluIGZ1bmN0aW9ucyBkYXRhY29weSAvIGRhdGFvZmZzZXQgLyBkYXRhc2l6ZQovLyBUaGUgY3VycmVudCBvYmplY3QsIHN1Yi1vYmplY3RzIGFuZCBkYXRhIGl0ZW1zIGluc2lkZSB0aGUgY3VycmVudCBvYmplY3QKLy8gYXJlIGluIHNjb3BlLgpvYmplY3QgIkNvbnRyYWN0MSIgewogICAgLy8gVGhpcyBpcyB0aGUgY29uc3RydWN0b3IgY29kZSBvZiB0aGUgY29udHJhY3QuCiAgICBjb2RlIHsKICAgICAgICBmdW5jdGlvbiBhbGxvY2F0ZShzaXplKSAtPiBwdHIgewogICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgaWYgaXN6ZXJvKHB0cikgeyBwdHIgOj0gMHg2MCB9CiAgICAgICAgICAgIG1zdG9yZSgweDQwLCBhZGQocHRyLCBzaXplKSkKICAgICAgICB9CgogICAgICAgIC8vIGZpcnN0IGNyZWF0ZSAiQ29udHJhY3QyIgogICAgICAgIGxldCBzaXplIDo9IGRhdGFzaXplKCJDb250cmFjdDIiKQogICAgICAgIGxldCBvZmZzZXQgOj0gYWxsb2NhdGUoc2l6ZSkKICAgICAgICAvLyBUaGlzIHdpbGwgdHVybiBpbnRvIGNvZGVjb3B5IGZvciBFVk0KICAgICAgICBkYXRhY29weShvZmZzZXQsIGRhdGFvZmZzZXQoIkNvbnRyYWN0MiIpLCBzaXplKQogICAgICAgIC8vIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBpcyBhIHNpbmdsZSBudW1iZXIgMHgxMjM0CiAgICAgICAgbXN0b3JlKGFkZChvZmZzZXQsIHNpemUpLCAweDEyMzQpCiAgICAgICAgcG9wKGNyZWF0ZShvZmZzZXQsIGFkZChzaXplLCAzMiksIDApKQoKICAgICAgICAvLyBub3cgcmV0dXJuIHRoZSBydW50aW1lIG9iamVjdCAodGhlIGN1cnJlbnRseQogICAgICAgIC8vIGV4ZWN1dGluZyBjb2RlIGlzIHRoZSBjb25zdHJ1Y3RvciBjb2RlKQogICAgICAgIHNpemUgOj0gZGF0YXNpemUoIkNvbnRyYWN0MV9kZXBsb3llZCIpCiAgICAgICAgb2Zmc2V0IDo9IGFsbG9jYXRlKHNpemUpCiAgICAgICAgLy8gVGhpcyB3aWxsIHR1cm4gaW50byBhIG1lbW9yeS0+bWVtb3J5IGNvcHkgZm9yIEV3YXNtIGFuZAogICAgICAgIC8vIGEgY29kZWNvcHkgZm9yIEVWTQogICAgICAgIGRhdGFjb3B5KG9mZnNldCwgZGF0YW9mZnNldCgiQ29udHJhY3QxX2RlcGxveWVkIiksIHNpemUpCiAgICAgICAgcmV0dXJuKG9mZnNldCwgc2l6ZSkKICAgIH0KCiAgICBkYXRhICJUYWJsZTIiIGhleCI0MTIzIgoKICAgIG9iamVjdCAiQ29udHJhY3QxX2RlcGxveWVkIiB7CiAgICAgICAgY29kZSB7CiAgICAgICAgICAgIGZ1bmN0aW9uIGFsbG9jYXRlKHNpemUpIC0+IHB0ciB7CiAgICAgICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgICAgIGlmIGlzemVybyhwdHIpIHsgcHRyIDo9IDB4NjAgfQogICAgICAgICAgICAgICAgbXN0b3JlKDB4NDAsIGFkZChwdHIsIHNpemUpKQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBydW50aW1lIGNvZGUKCiAgICAgICAgICAgIG1zdG9yZSgwLCAiSGVsbG8sIFdvcmxkISIpCiAgICAgICAgICAgIHJldHVybigwLCAweDIwKQogICAgICAgIH0KICAgIH0KCiAgICAvLyBFbWJlZGRlZCBvYmplY3QuIFVzZSBjYXNlIGlzIHRoYXQgdGhlIG91dHNpZGUgaXMgYSBmYWN0b3J5IGNvbnRyYWN0LAogICAgLy8gYW5kIENvbnRyYWN0MiBpcyB0aGUgY29kZSB0byBiZSBjcmVhdGVkIGJ5IHRoZSBmYWN0b3J5CiAgICBvYmplY3QgIkNvbnRyYWN0MiIgewogICAgICAgIGNvZGUgewogICAgICAgICAgICAvLyBjb2RlIGhlcmUgLi4uCiAgICAgICAgfQoKICAgICAgICBvYmplY3QgIkNvbnRyYWN0Ml9kZXBsb3llZCIgewogICAgICAgICAgICBjb2RlIHsKICAgICAgICAgICAgICAgIC8vIGNvZGUgaGVyZSAuLi4KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZGF0YSAiVGFibGUxIiBoZXgiNDEyMyIKICAgIH0KfQ&optimize=false&runs=200&evmVersion=null')
.refresh() .refreshPage()
.pause(5000) .waitForElementVisible('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontract-eaa022e37e.yul"]')
.currentWorkspaceIs('code-sample') .currentWorkspaceIs('code-sample')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontract-eaa022e37e.yul"]', 6000)
.openFile('contract-eaa022e37e.yul') .openFile('contract-eaa022e37e.yul')
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content && content.indexOf( browser.assert.ok(content && content.indexOf(
@ -154,16 +155,37 @@ module.exports = {
}) })
}, },
'Should select deploy with proxy option from URL params #group1': function (browser: NightwatchBrowser) { 'Should select deploy with proxy option from URL params #group2': function (browser: NightwatchBrowser) {
browser browser
.url('http://127.0.0.1:8080/#optimize=false&runs=200&deployProxy=true') .url('http://127.0.0.1:8080/#optimize=false&runs=200&deployProxy=true')
.refresh() .refreshPage()
.pause(5000)
.switchWorkspace('default_workspace') .switchWorkspace('default_workspace')
.addFile('myTokenV1.sol', sources[1]['myTokenV1.sol']) .addFile('myTokenV1.sol', sources[1]['myTokenV1.sol'])
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.pause(2000) .pause(2000)
.click('[data-id="compilerContainerCompileBtn"]') .click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel')
.isVisible({
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol"]',
timeout: 120000,
suppressNotFoundErrors: true
})
.clickLaunchIcon('solidity')
.click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel')
.isVisible({
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol"]',
timeout: 120000,
suppressNotFoundErrors: true
})
.clickLaunchIcon('solidity')
.click('[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('filePanel')
.waitForElementVisible({
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol"]',
timeout: 120000,
})
.clickLaunchIcon('solidity')
.waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000) .waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000)
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.click('select.udapp_contractNames') .click('select.udapp_contractNames')
@ -172,14 +194,18 @@ module.exports = {
.expect.element('[data-id="contractGUIDeployWithProxy"]').to.be.selected .expect.element('[data-id="contractGUIDeployWithProxy"]').to.be.selected
}, },
'Should select upgrade with proxy option from URL params #group1': function (browser: NightwatchBrowser) { 'Should select upgrade with proxy option from URL params #group2': function (browser: NightwatchBrowser) {
browser browser
.url('http://127.0.0.1:8080/#optimize=false&runs=200&upgradeProxy=true') .url('http://127.0.0.1:8080/#optimize=false&runs=200&upgradeProxy=true')
.refresh() .refreshPage()
.pause(5000) .waitForElementVisible('*[data-id="treeViewLitreeViewItemmyTokenV1.sol"]', 60000)
.openFile('myTokenV1.sol') .openFile('myTokenV1.sol')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: "//*[contains(@class, 'view-lines') and contains(.,'ERC721Upgradeable')]"
})
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.pause(2000) .waitForElementVisible('[data-id="compilerContainerCompileBtn"]')
.click('[data-id="compilerContainerCompileBtn"]') .click('[data-id="compilerContainerCompileBtn"]')
.waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000) .waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000)
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
@ -189,39 +215,42 @@ module.exports = {
.expect.element('[data-id="contractGUIUpgradeImplementation"]').to.be.selected .expect.element('[data-id="contractGUIUpgradeImplementation"]').to.be.selected
}, },
'Should load using various URL compiler params #group1': function (browser: NightwatchBrowser) { 'Should load using various URL compiler params #group2': function (browser: NightwatchBrowser) {
browser browser
.pause(5000)
.url('http://127.0.0.1:8080/#optimize=true&runs=300&autoCompile=true&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&language=Yul') .url('http://127.0.0.1:8080/#optimize=true&runs=300&autoCompile=true&evmVersion=istanbul&version=soljson-v0.8.16+commit.07a7930e.js&language=Yul')
.refresh() .refreshPage()
.pause(5000)
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.click('*[data-id="scConfigExpander"]') .click('*[data-id="scConfigExpander"]')
.assert.containsText('#versionSelector option[data-id="selected"]', '0.7.4+commit.3f05b770') .waitForElementVisible('#versionSelector option[data-id="selected"]')
.assert.containsText('#versionSelector option[data-id="selected"]', '0.8.16+commit.07a7930e')
.assert.containsText('#evmVersionSelector option[data-id="selected"]', 'istanbul') .assert.containsText('#evmVersionSelector option[data-id="selected"]', 'istanbul')
.assert.containsText('#compilierLanguageSelector option[data-id="selected"]', 'Yul') .assert.containsText('#compilierLanguageSelector option[data-id="selected"]', 'Yul')
.verify.elementPresent('#optimize:checked') .verify.elementPresent('#optimize:checked')
.verify.elementPresent('#autoCompile:checked') .verify.elementPresent('#autoCompile:checked')
.verify.attributeEquals('#runs', 'value', '300') .verify.attributeEquals('#runs', 'value', '300')
.url('http://127.0.0.1:8080/#version=0.8.7') .url('http://127.0.0.1:8080/#version=0.8.7')
.refresh() .refreshPage()
.pause(5000)
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.waitForElementVisible('#versionSelector option[data-id="selected"]')
.assert.containsText('#versionSelector option[data-id="selected"]', '0.8.7+commit.e28d00a7') .assert.containsText('#versionSelector option[data-id="selected"]', '0.8.7+commit.e28d00a7')
.url('http://127.0.0.1:8080/#version=0.8.15+commit.e14f2714') .url('http://127.0.0.1:8080/#version=0.8.15+commit.e14f2714')
.refresh() .refreshPage()
.pause(5000) .pause(3000)
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.waitForElementVisible('#versionSelector option[data-id="selected"]')
.assert.containsText('#versionSelector option[data-id="selected"]', '0.8.15+commit.e14f2714') .assert.containsText('#versionSelector option[data-id="selected"]', '0.8.15+commit.e14f2714')
}, },
'Should load using compiler from link passed in remix URL #group1': function (browser: NightwatchBrowser) { 'Should load using compiler from link passed in remix URL #group3': function (browser: NightwatchBrowser) {
browser browser
.url('http://127.0.0.1:8080/#version=https://solidity-blog.s3.eu-central-1.amazonaws.com/data/08preview/soljson.js&optimize=false') .url('http://127.0.0.1:8080/#version=https://solidity-blog.s3.eu-central-1.amazonaws.com/data/08preview/soljson.js&optimize=false')
.refresh() .refreshPage()
.pause(5000)
.clickLaunchIcon('solidity') .clickLaunchIcon('solidity')
.pause(5000)
.click('*[data-id="scConfigExpander"]') .click('*[data-id="scConfigExpander"]')
.assert.containsText('#versionSelector option[data-id="selected"]', 'custom') .assert.containsText('#versionSelector option[data-id="selected"]', 'custom')
// default values // default values
@ -233,11 +262,11 @@ module.exports = {
.verify.attributeEquals('#runs', 'value', '200') .verify.attributeEquals('#runs', 'value', '200')
}, },
'Should load json files from link passed in remix URL #group1': function (browser: NightwatchBrowser) { 'Should load json files from link passed in remix URL #group3': function (browser: NightwatchBrowser) {
browser browser
.url('http://127.0.0.1:8080/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.6.12+commit.27d51765.js&url=https://raw.githubusercontent.com/EthVM/evm-source-verification/main/contracts/1/0x011e5846975c6463a8c6337eecf3cbf64e328884/input.json') .url('http://127.0.0.1:8080/#optimize=false&runs=200&url=https://raw.githubusercontent.com/EthVM/evm-source-verification/main/contracts/1/0x011e5846975c6463a8c6337eecf3cbf64e328884/input.json')
.refresh() .refreshPage()
.pause(5000)
.switchWorkspace('code-sample') .switchWorkspace('code-sample')
.openFile('@openzeppelin') .openFile('@openzeppelin')
.openFile('@openzeppelin/contracts') .openFile('@openzeppelin/contracts')
@ -248,11 +277,11 @@ module.exports = {
.openFile('contracts/governance/UnionGovernor.sol') .openFile('contracts/governance/UnionGovernor.sol')
}, },
'Should execute function call from URL parameters #group1': function (browser: NightwatchBrowser) { 'Should execute function call from URL parameters #group3': function (browser: NightwatchBrowser) {
browser browser
.switchWorkspace('default_workspace') .switchWorkspace('default_workspace')
.url('http://127.0.0.1:8080?calls=fileManager//open//contracts/3_Ballot.sol///terminal//log//log') .url('http://127.0.0.1:8080?calls=fileManager//open//contracts/3_Ballot.sol///terminal//log//log')
.refresh() .refreshPage()
.waitForElementVisible('*[data-shared="tooltipPopup"]') .waitForElementVisible('*[data-shared="tooltipPopup"]')
.waitForElementContainsText('*[data-shared="tooltipPopup"]', 'initiating fileManager and calling "open" ...') .waitForElementContainsText('*[data-shared="tooltipPopup"]', 'initiating fileManager and calling "open" ...')
.waitForElementContainsText('*[data-shared="tooltipPopup"]', 'initiating terminal and calling "log" ...') .waitForElementContainsText('*[data-shared="tooltipPopup"]', 'initiating terminal and calling "log" ...')

@ -20,21 +20,22 @@ const sources = [
] ]
module.exports = { module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done) init(browser, done)
}, },
'@sources': function () { '@sources': function () {
return sources return sources
}, },
'Using Web Worker': function (browser: NightwatchBrowser) { 'Using Web Worker #group1': function (browser: NightwatchBrowser) {
browser browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) // using autocompile when switching compilers quickly confuses the process and results in a wrong compiler version being used or results displayed
.clickLaunchIcon('filePanel') .waitForElementVisible('[for="autoCompile"]')
.addFile('basic.sol', sources[0]['basic.sol']) .click('[for="autoCompile"]')
.clickLaunchIcon('solidity')
.waitForElementVisible('[data-id="compilerNightliesBuild"]') .waitForElementVisible('[data-id="compilerNightliesBuild"]')
.click('[data-id="compilerNightliesBuild"]') .click('[data-id="compilerNightliesBuild"]')
.noWorkerErrorFor('soljson-v0.3.4+commit.7dab8902.js') .addFile('basic.sol', sources[0]['basic.sol'])
.clickLaunchIcon('solidity')
.noWorkerErrorFor('soljson-v0.6.5+commit.f956cc89.js') .noWorkerErrorFor('soljson-v0.6.5+commit.f956cc89.js')
.noWorkerErrorFor('soljson-v0.6.8-nightly.2020.5.14+commit.a6d0067b.js') .noWorkerErrorFor('soljson-v0.6.8-nightly.2020.5.14+commit.a6d0067b.js')
.noWorkerErrorFor('soljson-v0.6.0-nightly.2019.12.17+commit.d13438ee.js') .noWorkerErrorFor('soljson-v0.6.0-nightly.2019.12.17+commit.d13438ee.js')

@ -19,7 +19,7 @@ module.exports = {
'Editor should be focused on the 3_Ballot.sol #group1': function (browser: NightwatchBrowser) { 'Editor should be focused on the 3_Ballot.sol #group1': function (browser: NightwatchBrowser) {
browser browser
.pause(5000) .pause(5000)
.refresh() .refreshPage()
.waitForElementVisible('#editorView', 30000) .waitForElementVisible('#editorView', 30000)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf('contract Ballot {') !== -1, 'content includes Ballot contract') browser.assert.ok(content.indexOf('contract Ballot {') !== -1, 'content includes Ballot contract')
@ -66,7 +66,7 @@ module.exports = {
}) })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.pause(2000) .pause(100)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1, browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1,
'Incorrect content') 'Incorrect content')
@ -124,39 +124,39 @@ module.exports = {
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/SampleERC20.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
// check js and ts files are not transformed // check js and ts files are not transformed
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.pause(5000) .pause(100)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1, browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1,
'Incorrect content') 'Incorrect content')
}) })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.pause(4000) .pause(100)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1, browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1,
'Incorrect content') 'Incorrect content')
}) })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.pause(4000) .pause(100)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1, browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1,
'Incorrect content') 'Incorrect content')
}) })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.pause(4000) .pause(100)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {`) !== -1, browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {`) !== -1,
'Incorrect content') 'Incorrect content')
}) })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]') .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) { 'Should create ERC721 workspace with files #group1': function (browser: NightwatchBrowser) {
@ -172,39 +172,145 @@ module.exports = {
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/SampleERC721.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
// check js and ts files are not transformed // check js and ts files are not transformed
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.pause(4000) .pause(100)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1, browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1,
'Incorrect content') 'Incorrect content')
}) })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.pause(4000) .pause(100)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1, browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1,
'Incorrect content') 'Incorrect content')
}) })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.pause(4000) .pause(100)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1, browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1,
'Incorrect content') 'Incorrect content')
}) })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.pause(4000) .pause(100)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {`) !== -1, browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {`) !== -1,
'Incorrect content') 'Incorrect content')
}) })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/SampleERC721_test.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/MyToken_test.sol"]')
},
'Should create ERC1155 workspace with files #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_erc1155' })
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=ozerc1155]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.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
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.pause(1000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1,
'Incorrect content')
})
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1,
'Incorrect content')
})
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1,
'Incorrect content')
})
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {`) !== -1,
'Incorrect content')
})
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/MyToken_test.sol"]')
},
'Should create ERC1155 workspace with template customizations #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=ozerc1155]')
.waitForElementPresent('*[data-id="ozCustomization"]')
.click('*[data-id="featureTypeMintable"]')
.click('*[data-id="featureTypeBurnable"]')
.click('*[data-id="featureTypePausable"]')
.click('*[data-id="upgradeTypeUups"]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]')
.click('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]')
.pause(1000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`contract MyToken is Initializable, ERC1155Upgradeable, OwnableUpgradeable, PausableUpgradeable, ERC1155BurnableUpgradeable, UUPSUpgradeable {`) !== -1,
'Incorrect content')
})
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
// check js and ts files are not transformed
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1,
'Incorrect content')
})
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1,
'Incorrect content')
})
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1,
'Incorrect content')
browser.assert.ok(content.indexOf(`gas: gas || 3600000`) !== -1,
'Incorrect gas cost')
})
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {`) !== -1,
'Incorrect content')
})
// No test file is added in upgradeable contract template
}, },
// WORKSPACE TEMPLATES E2E END // WORKSPACE TEMPLATES E2E END

@ -27,6 +27,8 @@ declare module 'nightwatch' {
debugTransaction(index: number): NightwatchBrowser, debugTransaction(index: number): NightwatchBrowser,
checkElementStyle(cssSelector: string, styleProperty: string, expectedResult: string): NightwatchBrowser, checkElementStyle(cssSelector: string, styleProperty: string, expectedResult: string): NightwatchBrowser,
openFile(name: string): NightwatchBrowser, openFile(name: string): NightwatchBrowser,
refreshPage(): NightwatchBrowser,
verifyLoad(): NightwatchBrowser,
renamePath(path: string, newFileName: string, renamedPath: string): NightwatchBrowser, renamePath(path: string, newFileName: string, renamedPath: string): NightwatchBrowser,
rightClickCustom(cssSelector: string): NightwatchBrowser, rightClickCustom(cssSelector: string): NightwatchBrowser,
scrollToLine(line: number): NightwatchBrowser, scrollToLine(line: number): NightwatchBrowser,

@ -3,7 +3,8 @@
"compilerOptions": { "compilerOptions": {
"sourceMap": false, "sourceMap": false,
"outDir": "../../dist", "outDir": "../../dist",
"allowJs": true "allowJs": true,
"resolveJsonModule": true
}, },
"include": ["**/*.ts", "**/*.js"] "include": ["**/*.ts", "**/*.js"]
} }

@ -2,7 +2,8 @@
"extends": "../../tsconfig.base.json", "extends": "../../tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"types": ["node", "nightwatch"], "types": ["node", "nightwatch"],
"esModuleInterop": true "esModuleInterop": true,
"resolveJsonModule": true
}, },
"include": ["**/*.ts", "**/*.js"] "include": ["**/*.ts", "**/*.js"]
} }

@ -12,4 +12,5 @@ remix
TODO TODO
.tern-port .tern-port
temp_publish_docker temp_publish_docker
src/assets/version.json src/assets/version.json
src/assets/js/soljson-v*

@ -2,6 +2,8 @@
set -e set -e
BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}} BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID" echo "$BUILD_ID"
TEST_EXITCODE=0 TEST_EXITCODE=0
@ -14,9 +16,12 @@ yarn run remixd &
sleep 5 sleep 5
yarn run build:e2e yarn run build:e2e
TESTFILES=$(grep -IRiL "@disabled" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test" | sort | circleci tests split ) # grep -IRiL "@disabled" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test" | xargs -I {} basename {} .test.js | grep -E "\b[${2}]"
# TESTFILES=$(grep -IRiL "@disabled" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test" | xargs -I {} basename {} .test.js | grep -E "\b[$2]" | circleci tests split --split-by=timings )
node apps/remix-ide/ci/splice_tests.js $2 $3
TESTFILES=$(node apps/remix-ide/ci/splice_tests.js $2 $3 | circleci tests split --split-by=timings)
for TESTFILE in $TESTFILES; do for TESTFILE in $TESTFILES; do
npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js $TESTFILE --env=$1 || TEST_EXITCODE=1 npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/${TESTFILE}.js --env=$1 || TEST_EXITCODE=1
done done
echo "$TEST_EXITCODE" echo "$TEST_EXITCODE"

@ -6,6 +6,7 @@ BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID" echo "$BUILD_ID"
TEST_EXITCODE=0 TEST_EXITCODE=0
yarn build etherscan
yarn run serve:production & yarn run serve:production &
npx nx serve etherscan & npx nx serve etherscan &

@ -6,6 +6,7 @@ BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID" echo "$BUILD_ID"
TEST_EXITCODE=0 TEST_EXITCODE=0
yarn build vyper
yarn run serve:production & yarn run serve:production &
npx nx serve vyper & npx nx serve vyper &

@ -0,0 +1,63 @@
const testFolder = './apps/remix-ide-e2e/src/tests/';
const fs = require('fs');
let url = 'https://binaries.soliditylang.org/wasm/list.json'
const axios = require('axios')
// use axios to download the file
axios({
url: url,
method: 'GET',
}).then((response) => {
let info = response.data;
info.builds = info.builds.filter(build => build.path.indexOf('nightly') === -1)
for (let build of info.builds) {
const buildurl = `https://solc-bin.ethereum.org/wasm/${build.path}`;
console.log(buildurl)
const path = `./dist/apps/remix-ide/assets/js/${build.path}`;
// use axios to get the file
axios({
method: 'get',
url: buildurl,
responseType: 'stream'
}).then(function (response) {
// pipe the result stream into a file on disc
response.data.pipe(fs.createWriteStream(path));
})
}
}
)
fs.readdirSync(testFolder).forEach(file => {
let c = fs.readFileSync(testFolder + file, 'utf8');
const re = /(?<=soljson).*(?=(.js))/g;
const soljson = c.match(re);
if (soljson) {
for (let i = 0; i < soljson.length; i++) {
const version = soljson[i];
if (version && version.indexOf('nightly') > -1) {
const url = `https://solc-bin.ethereum.org/bin/soljson${version}.js`;
console.log(url)
const path = `./dist/apps/remix-ide/assets/js/soljson${version}.js`;
// use axios to get the file
axios({
method: 'get',
url: url,
responseType: 'stream'
}).then(function (response) {
// pipe the result stream into a file on disc
response.data.pipe(fs.createWriteStream(path));
})
}
}
}
});

@ -0,0 +1,27 @@
const fs = require('fs')
var exec = require('child_process').exec;
let cmd = `grep -IRiL "@disabled" "dist/apps/remix-ide-e2e/src/tests"`
// get command line arguments
let args = process.argv.slice(2)
const jobsize = args[0] || 10;
const job = args[1] || 0;
exec(cmd, (error, stdout, stderr) => {
if (error) {
console.error(`error: ${error.message}`);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
return;
}
let files = stdout.split('\n').filter(f => f.includes('.test')).map(f => f.replace('dist/apps/remix-ide-e2e/src/tests/', '')).map(f => f.replace('.js', ''))
let splitIndex = Math.ceil(files.length / jobsize);
const parts = []
for (let i = 0; i < jobsize; i++) {
parts.push(files.slice(i * splitIndex, (i + 1) * splitIndex))
}
console.log(parts[job].join('\n'))
});

@ -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 { contract Ballot {
// This declares a new complex type which will
// be used for variables later.
// It will represent a single voter.
struct Voter { struct Voter {
uint weight; // weight is accumulated by delegation uint weight; // weight is accumulated by delegation
bool voted; // if true, that person already voted bool voted; // if true, that person already voted
@ -12,33 +15,31 @@ contract Ballot {
uint vote; // index of the voted proposal uint vote; // index of the voted proposal
} }
// This is a type for a single proposal.
struct 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) bytes32 name; // short name (up to 32 bytes)
uint voteCount; // number of accumulated votes uint voteCount; // number of accumulated votes
} }
address public chairperson; address public chairperson;
// This declares a state variable that
// stores a \`Voter\` struct for each possible address.
mapping(address => Voter) public voters; mapping(address => Voter) public voters;
// A dynamically-sized array of \`Proposal\` structs.
Proposal[] public proposals; 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; chairperson = msg.sender;
voters[chairperson].weight = 1; 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++) { for (uint i = 0; i < proposalNames.length; i++) {
// \`Proposal({...})\` creates a temporary // 'Proposal({...})' creates a temporary
// Proposal object and \`proposals.push(...)\` // Proposal object and 'proposals.push(...)'
// appends it to the end of \`proposals\`. // appends it to the end of 'proposals'.
proposals.push(Proposal({ proposals.push(Proposal({
name: proposalNames[i], name: proposalNames[i],
voteCount: 0 voteCount: 0
@ -46,98 +47,92 @@ contract Ballot {
} }
} }
// Give \`voter\` the right to vote on this ballot. /**
// May only be called by \`chairperson\`. * @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'.
function giveRightToVote(address voter) { * @param voter address of voter
if (msg.sender != chairperson || voters[voter].voted) { */
// \`throw\` terminates and reverts all changes to function giveRightToVote(address voter) public {
// the state and to Ether balances. It is often require(
// a good idea to use this if functions are msg.sender == chairperson,
// called incorrectly. But watch out, this "Only chairperson can give right to vote."
// will also consume all provided gas. );
throw; require(
} !voters[voter].voted,
"The voter already voted."
);
require(voters[voter].weight == 0);
voters[voter].weight = 1; voters[voter].weight = 1;
} }
/// Delegate your vote to the voter \`to\`. /**
function delegate(address to) { * @dev Delegate your vote to the voter 'to'.
// assigns reference * @param to address to which vote is delegated
Voter sender = voters[msg.sender]; */
if (sender.voted) function delegate(address to) public {
throw; Voter storage sender = voters[msg.sender];
require(!sender.voted, "You already voted.");
// Forward the delegation as long as require(to != msg.sender, "Self-delegation is disallowed.");
// \`to\` also delegated.
// In general, such loops are very dangerous, while (voters[to].delegate != address(0)) {
// 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
) {
to = voters[to].delegate; to = voters[to].delegate;
}
// We found a loop in the delegation, not allowed. // We found a loop in the delegation, not allowed.
if (to == msg.sender) { require(to != msg.sender, "Found loop in delegation.");
throw;
} }
// Since \`sender\` is a reference, this
// modifies \`voters[msg.sender].voted\`
sender.voted = true; sender.voted = true;
sender.delegate = to; sender.delegate = to;
Voter delegate = voters[to]; Voter storage delegate_ = voters[to];
if (delegate.voted) { if (delegate_.voted) {
// If the delegate already voted, // If the delegate already voted,
// directly add to the number of votes // directly add to the number of votes
proposals[delegate.vote].voteCount += sender.weight; proposals[delegate_.vote].voteCount += sender.weight;
} else { } else {
// If the delegate did not vote yet, // If the delegate did not vote yet,
// add to her weight. // 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\`. * @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'.
function vote(uint proposal) { * @param proposal index of proposal in the proposals array
Voter sender = voters[msg.sender]; */
if (sender.voted) function vote(uint proposal) public {
throw; Voter storage sender = voters[msg.sender];
require(sender.weight != 0, "Has no right to vote");
require(!sender.voted, "Already voted.");
sender.voted = true; sender.voted = true;
sender.vote = proposal; 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 // this will throw automatically and revert all
// changes. // changes.
proposals[proposal].voteCount += sender.weight; proposals[proposal].voteCount += sender.weight;
} }
/// @dev Computes the winning proposal taking all /**
/// previous votes into account. * @dev Computes the winning proposal taking all previous votes into account.
function winningProposal() constant * @return winningProposal_ index of winning proposal in the proposals array
returns (uint winningProposal) */
function winningProposal() public view
returns (uint winningProposal_)
{ {
uint winningVoteCount = 0; uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) { for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) { if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount; 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 * @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then
// returns the name of the winner * @return winnerName_ the name of the winner
function winnerName() constant */
returns (bytes32 winnerName) function winnerName() public view
returns (bytes32 winnerName_)
{ {
winnerName = proposals[winningProposal()].name; winnerName_ = proposals[winningProposal()].name;
} }
} }

@ -0,0 +1,6 @@
[profile.default]
src = 'src'
out = 'out'
libs = ['lib']
# See more config options https://github.com/foundry-rs/foundry/tree/master/config

@ -0,0 +1 @@
// simulate a hardhat project

@ -0,0 +1,266 @@
{
"abi": [
{
"inputs": [],
"name": "IS_SCRIPT",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "run",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "setUp",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "vm",
"outputs": [
{
"internalType": "contract Vm",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
],
"bytecode": {
"object": "0x60806040526000805460ff1916600117905534801561001d57600080fd5b5061014c8061002d6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80630a9254e4146100515780633a76846314610053578063c04062261461008b578063f8ccbf4714610093575b600080fd5b005b61006e737109709ecfa91a80626ff3989d68f67f5b1dd12d81565b6040516001600160a01b0390911681526020015b60405180910390f35b6100516100b0565b6000546100a09060ff1681565b6040519015158152602001610082565b604080516302bf260160e61b81529051737109709ecfa91a80626ff3989d68f67f5b1dd12d9163afc9804091600480830192600092919082900301818387803b1580156100fc57600080fd5b505af1158015610110573d6000803e3d6000fd5b5050505056fea26469706673582212203a39488c6d5e73072e1dd0c6593caff56e39d0849abc1557f1c6e25cf7dedc2e64736f6c63430008100033",
"sourceMap": "97:126:6:-:0;;;165:28:1;;;-1:-1:-1;;165:28:1;189:4;165:28;;;97:126:6;;;;;;;;;;;;;;;;",
"linkReferences": {}
},
"deployedBytecode": {
"object": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80630a9254e4146100515780633a76846314610053578063c04062261461008b578063f8ccbf4714610093575b600080fd5b005b61006e737109709ecfa91a80626ff3989d68f67f5b1dd12d81565b6040516001600160a01b0390911681526020015b60405180910390f35b6100516100b0565b6000546100a09060ff1681565b6040519015158152602001610082565b604080516302bf260160e61b81529051737109709ecfa91a80626ff3989d68f67f5b1dd12d9163afc9804091600480830192600092919082900301818387803b1580156100fc57600080fd5b505af1158015610110573d6000803e3d6000fd5b5050505056fea26469706673582212203a39488c6d5e73072e1dd0c6593caff56e39d0849abc1557f1c6e25cf7dedc2e64736f6c63430008100033",
"sourceMap": "97:126:6:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136:26;;316:38:1;;245:64;316:38;;;;;-1:-1:-1;;;;;189:32:9;;;171:51;;159:2;144:18;316:38:1;;;;;;;;168:53:6;;;:::i;165:28:1:-;;;;;;;;;;;;398:14:9;;391:22;373:41;;361:2;346:18;165:28:1;233:187:9;168:53:6;200:14;;;-1:-1:-1;;;200:14:6;;;;245:64:1;;200:12:6;;:14;;;;;269:37:1;;200:14:6;;;;;;;269:37:1;245:64;200:14:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;168:53::o",
"linkReferences": {}
},
"methodIdentifiers": {
"IS_SCRIPT()": "f8ccbf47",
"run()": "c0406226",
"setUp()": "0a9254e4",
"vm()": "3a768463"
},
"ast": {
"absolutePath": "script/Counter.s.sol",
"id": 21582,
"exportedSymbols": {
"CounterScript": [
21581
],
"Script": [
2022
],
"Vm": [
5434
],
"console": [
13498
],
"console2": [
21562
]
},
"nodeType": "SourceUnit",
"src": "39:185:6",
"nodes": [
{
"id": 21564,
"nodeType": "PragmaDirective",
"src": "39:24:6",
"literals": [
"solidity",
"^",
"0.8",
".13"
]
},
{
"id": 21565,
"nodeType": "ImportDirective",
"src": "65:30:6",
"absolutePath": "lib/forge-std/src/Script.sol",
"file": "forge-std/Script.sol",
"nameLocation": "-1:-1:-1",
"scope": 21582,
"sourceUnit": 2023,
"symbolAliases": [],
"unitAlias": ""
},
{
"id": 21581,
"nodeType": "ContractDefinition",
"src": "97:126:6",
"nodes": [
{
"id": 21571,
"nodeType": "FunctionDefinition",
"src": "136:26:6",
"body": {
"id": 21570,
"nodeType": "Block",
"src": "160:2:6",
"statements": []
},
"functionSelector": "0a9254e4",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "setUp",
"nameLocation": "145:5:6",
"parameters": {
"id": 21568,
"nodeType": "ParameterList",
"parameters": [],
"src": "150:2:6"
},
"returnParameters": {
"id": 21569,
"nodeType": "ParameterList",
"parameters": [],
"src": "160:0:6"
},
"scope": 21581,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
},
{
"id": 21580,
"nodeType": "FunctionDefinition",
"src": "168:53:6",
"body": {
"id": 21579,
"nodeType": "Block",
"src": "190:31:6",
"statements": [
{
"expression": {
"arguments": [],
"expression": {
"argumentTypes": [],
"expression": {
"id": 21574,
"name": "vm",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1817,
"src": "200:2:6",
"typeDescriptions": {
"typeIdentifier": "t_contract$_Vm_$5434",
"typeString": "contract Vm"
}
},
"id": 21576,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberLocation": "203:9:6",
"memberName": "broadcast",
"nodeType": "MemberAccess",
"referencedDeclaration": 5173,
"src": "200:12:6",
"typeDescriptions": {
"typeIdentifier": "t_function_external_nonpayable$__$returns$__$",
"typeString": "function () external"
}
},
"id": 21577,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"nameLocations": [],
"names": [],
"nodeType": "FunctionCall",
"src": "200:14:6",
"tryCall": false,
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 21578,
"nodeType": "ExpressionStatement",
"src": "200:14:6"
}
]
},
"functionSelector": "c0406226",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "run",
"nameLocation": "177:3:6",
"parameters": {
"id": 21572,
"nodeType": "ParameterList",
"parameters": [],
"src": "180:2:6"
},
"returnParameters": {
"id": 21573,
"nodeType": "ParameterList",
"parameters": [],
"src": "190:0:6"
},
"scope": 21581,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"abstract": false,
"baseContracts": [
{
"baseName": {
"id": 21566,
"name": "Script",
"nameLocations": [
"123:6:6"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2022,
"src": "123:6:6"
},
"id": 21567,
"nodeType": "InheritanceSpecifier",
"src": "123:6:6"
}
],
"canonicalName": "CounterScript",
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"linearizedBaseContracts": [
21581,
2022
],
"name": "CounterScript",
"nameLocation": "106:13:6",
"scope": 21582,
"usedErrors": []
}
],
"license": "UNLICENSED"
},
"id": 6
}

@ -0,0 +1,121 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"inputs": [],
"name": "IS_SCRIPT",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "run",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "setUp",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "vm",
"outputs": [
{
"internalType": "contract Vm",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"script/Counter.s.sol": "CounterScript"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/src/Script.sol": {
"keccak256": "0x4424dbcb8f5b741475445726f87408fcd89951fad973bec2ca442ee157f910e7",
"license": "MIT",
"urls": [
"bzz-raw://5b0b9f6dfb69245d8f888558ae82bf1d2cdeace46201444fe4b2e6a5283f944a",
"dweb:/ipfs/QmWFSKeFEZngNcwNn7A84EF7pASo5qe6r5oK24r9Kwca7Z"
]
},
"lib/forge-std/src/Vm.sol": {
"keccak256": "0xa0ede8e0d3dc3246912530aed6cacbc4703e4430c4b4acd91963ccea709755ea",
"license": "MIT",
"urls": [
"bzz-raw://a28e7d00aab57ad5159247b0f0f268eda4c6980b29eee7f903578254a2be677f",
"dweb:/ipfs/QmZrM8gY5BpW8o1QckmPNCYbBP5Q7k5DkcHdaVULKVntxp"
]
},
"lib/forge-std/src/console.sol": {
"keccak256": "0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba",
"license": "MIT",
"urls": [
"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70",
"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec"
]
},
"lib/forge-std/src/console2.sol": {
"keccak256": "0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671",
"license": "MIT",
"urls": [
"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f",
"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW"
]
},
"script/Counter.s.sol": {
"keccak256": "0x01edaa1835b1a5bd3f4f66f73451488b8441d30642d3bf1f5fa2c5bf7c005bee",
"license": "UNLICENSED",
"urls": [
"bzz-raw://3c6a0f19216ceeebf4ec16f8f2662a3bebbe18d4037d1399adf2e3e4ccbb57a2",
"dweb:/ipfs/Qmc8NknjPkSgbXLg6zZQ8uKT6kAWBvBXz5JrDvZfa88UNT"
]
}
},
"version": 1
}

@ -0,0 +1,587 @@
{
"abi": [
{
"inputs": [],
"name": "increment",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "number",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newNumber",
"type": "uint256"
}
],
"name": "setNumber",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
],
"bytecode": {
"object": "0x608060405234801561001057600080fd5b50610125806100206000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146052578063d09de08a14606c575b600080fd5b6050604c3660046095565b6072565b005b605a60005481565b60405190815260200160405180910390f35b60506081565b607b81607b60c3565b60005550565b600080549080608e8360d9565b9190505550565b60006020828403121560a657600080fd5b5035919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111560d35760d360ad565b92915050565b60006001820160e85760e860ad565b506001019056fea2646970667358221220981d705d73c405a1cadf6bcd0ff9f1d0fcbbc1599040e504e71517ff0d8aa53264736f6c63430008100033",
"sourceMap": "65:198:7:-:0;;;;;;;;;;;;;;;;;;;",
"linkReferences": {}
},
"deployedBytecode": {
"object": "0x6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146052578063d09de08a14606c575b600080fd5b6050604c3660046095565b6072565b005b605a60005481565b60405190815260200160405180910390f35b60506081565b607b81607b60c3565b60005550565b600080549080608e8360d9565b9190505550565b60006020828403121560a657600080fd5b5035919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111560d35760d360ad565b92915050565b60006001820160e85760e860ad565b506001019056fea2646970667358221220981d705d73c405a1cadf6bcd0ff9f1d0fcbbc1599040e504e71517ff0d8aa53264736f6c63430008100033",
"sourceMap": "65:198:7:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116:86;;;;;;:::i;:::-;;:::i;:::-;;88:21;;;;;;;;;345:25:9;;;333:2;318:18;88:21:7;;;;;;;208:53;;;:::i;116:86::-;180:15;:9;192:3;180:15;:::i;:::-;171:6;:24;-1:-1:-1;116:86:7:o;208:53::-;246:6;:8;;;:6;:8;;;:::i;:::-;;;;;;208:53::o;14:180:9:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:9;;14:180;-1:-1:-1;14:180:9:o;381:127::-;442:10;437:3;433:20;430:1;423:31;473:4;470:1;463:15;497:4;494:1;487:15;513:125;578:9;;;599:10;;;596:36;;;612:18;;:::i;:::-;513:125;;;;:::o;643:135::-;682:3;703:17;;;700:43;;723:18;;:::i;:::-;-1:-1:-1;770:1:9;759:13;;643:135::o",
"linkReferences": {}
},
"methodIdentifiers": {
"increment()": "d09de08a",
"number()": "8381f58a",
"setNumber(uint256)": "3fb5c1cb"
},
"ast": {
"absolutePath": "src/Counter.sol",
"id": 21628,
"exportedSymbols": {
"Counter": [
21605
],
"CounterYann": [
21627
]
},
"nodeType": "SourceUnit",
"src": "39:427:7",
"nodes": [
{
"id": 21583,
"nodeType": "PragmaDirective",
"src": "39:24:7",
"literals": [
"solidity",
"^",
"0.8",
".13"
]
},
{
"id": 21605,
"nodeType": "ContractDefinition",
"src": "65:198:7",
"nodes": [
{
"id": 21585,
"nodeType": "VariableDeclaration",
"src": "88:21:7",
"constant": false,
"functionSelector": "8381f58a",
"mutability": "mutable",
"name": "number",
"nameLocation": "103:6:7",
"scope": 21605,
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21584,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "88:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "public"
},
{
"id": 21597,
"nodeType": "FunctionDefinition",
"src": "116:86:7",
"body": {
"id": 21596,
"nodeType": "Block",
"src": "161:41:7",
"statements": [
{
"expression": {
"id": 21594,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"id": 21590,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21585,
"src": "171:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide": {
"commonType": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 21593,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"id": 21591,
"name": "newNumber",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21587,
"src": "180:9:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "BinaryOperation",
"operator": "+",
"rightExpression": {
"hexValue": "313233",
"id": 21592,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "192:3:7",
"typeDescriptions": {
"typeIdentifier": "t_rational_123_by_1",
"typeString": "int_const 123"
},
"value": "123"
},
"src": "180:15:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "171:24:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21595,
"nodeType": "ExpressionStatement",
"src": "171:24:7"
}
]
},
"functionSelector": "3fb5c1cb",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "setNumber",
"nameLocation": "125:9:7",
"parameters": {
"id": 21588,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 21587,
"mutability": "mutable",
"name": "newNumber",
"nameLocation": "143:9:7",
"nodeType": "VariableDeclaration",
"scope": 21597,
"src": "135:17:7",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21586,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "135:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "internal"
}
],
"src": "134:19:7"
},
"returnParameters": {
"id": 21589,
"nodeType": "ParameterList",
"parameters": [],
"src": "161:0:7"
},
"scope": 21605,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
},
{
"id": 21604,
"nodeType": "FunctionDefinition",
"src": "208:53:7",
"body": {
"id": 21603,
"nodeType": "Block",
"src": "236:25:7",
"statements": [
{
"expression": {
"id": 21601,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "UnaryOperation",
"operator": "++",
"prefix": false,
"src": "246:8:7",
"subExpression": {
"id": 21600,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21585,
"src": "246:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21602,
"nodeType": "ExpressionStatement",
"src": "246:8:7"
}
]
},
"functionSelector": "d09de08a",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "increment",
"nameLocation": "217:9:7",
"parameters": {
"id": 21598,
"nodeType": "ParameterList",
"parameters": [],
"src": "226:2:7"
},
"returnParameters": {
"id": 21599,
"nodeType": "ParameterList",
"parameters": [],
"src": "236:0:7"
},
"scope": 21605,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"abstract": false,
"baseContracts": [],
"canonicalName": "Counter",
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"linearizedBaseContracts": [
21605
],
"name": "Counter",
"nameLocation": "74:7:7",
"scope": 21628,
"usedErrors": []
},
{
"id": 21627,
"nodeType": "ContractDefinition",
"src": "265:200:7",
"nodes": [
{
"id": 21607,
"nodeType": "VariableDeclaration",
"src": "292:21:7",
"constant": false,
"functionSelector": "8381f58a",
"mutability": "mutable",
"name": "number",
"nameLocation": "307:6:7",
"scope": 21627,
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21606,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "292:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "public"
},
{
"id": 21619,
"nodeType": "FunctionDefinition",
"src": "320:84:7",
"body": {
"id": 21618,
"nodeType": "Block",
"src": "365:39:7",
"statements": [
{
"expression": {
"id": 21616,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"id": 21612,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21607,
"src": "375:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide": {
"commonType": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 21615,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"id": 21613,
"name": "newNumber",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21609,
"src": "384:9:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "BinaryOperation",
"operator": "+",
"rightExpression": {
"hexValue": "39",
"id": 21614,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "396:1:7",
"typeDescriptions": {
"typeIdentifier": "t_rational_9_by_1",
"typeString": "int_const 9"
},
"value": "9"
},
"src": "384:13:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "375:22:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21617,
"nodeType": "ExpressionStatement",
"src": "375:22:7"
}
]
},
"functionSelector": "3fb5c1cb",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "setNumber",
"nameLocation": "329:9:7",
"parameters": {
"id": 21610,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 21609,
"mutability": "mutable",
"name": "newNumber",
"nameLocation": "347:9:7",
"nodeType": "VariableDeclaration",
"scope": 21619,
"src": "339:17:7",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21608,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "339:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "internal"
}
],
"src": "338:19:7"
},
"returnParameters": {
"id": 21611,
"nodeType": "ParameterList",
"parameters": [],
"src": "365:0:7"
},
"scope": 21627,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
},
{
"id": 21626,
"nodeType": "FunctionDefinition",
"src": "410:53:7",
"body": {
"id": 21625,
"nodeType": "Block",
"src": "438:25:7",
"statements": [
{
"expression": {
"id": 21623,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "UnaryOperation",
"operator": "++",
"prefix": false,
"src": "448:8:7",
"subExpression": {
"id": 21622,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21607,
"src": "448:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21624,
"nodeType": "ExpressionStatement",
"src": "448:8:7"
}
]
},
"functionSelector": "d09de08a",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "increment",
"nameLocation": "419:9:7",
"parameters": {
"id": 21620,
"nodeType": "ParameterList",
"parameters": [],
"src": "428:2:7"
},
"returnParameters": {
"id": 21621,
"nodeType": "ParameterList",
"parameters": [],
"src": "438:0:7"
},
"scope": 21627,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"abstract": false,
"baseContracts": [],
"canonicalName": "CounterYann",
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"linearizedBaseContracts": [
21627
],
"name": "CounterYann",
"nameLocation": "274:11:7",
"scope": 21628,
"usedErrors": []
}
],
"license": "UNLICENSED"
},
"id": 7
}

@ -0,0 +1,82 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"inputs": [],
"name": "increment",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "number",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newNumber",
"type": "uint256"
}
],
"name": "setNumber",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"src/Counter.sol": "Counter"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"src/Counter.sol": {
"keccak256": "0x74eb20a9c3120b64f0e66b02cf476d5d1ff5e07149a4c52b8e774a6800a40b83",
"license": "UNLICENSED",
"urls": [
"bzz-raw://be4d1233bdd7aaf1846eb4c3b94c58914fa4a4b7a2fa4a5734d9d09c562975dc",
"dweb:/ipfs/QmNVGX1nn75pwmWKQjPdV8cy5u5PHuWGbL6TsztchKqmAZ"
]
}
},
"version": 1
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,561 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "",
"type": "string"
}
],
"name": "log",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "log_address",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256[]",
"name": "val",
"type": "uint256[]"
}
],
"name": "log_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "int256[]",
"name": "val",
"type": "int256[]"
}
],
"name": "log_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address[]",
"name": "val",
"type": "address[]"
}
],
"name": "log_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "log_bytes",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"name": "log_bytes32",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "int256",
"name": "",
"type": "int256"
}
],
"name": "log_int",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "address",
"name": "val",
"type": "address"
}
],
"name": "log_named_address",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "uint256[]",
"name": "val",
"type": "uint256[]"
}
],
"name": "log_named_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "int256[]",
"name": "val",
"type": "int256[]"
}
],
"name": "log_named_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "address[]",
"name": "val",
"type": "address[]"
}
],
"name": "log_named_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "bytes",
"name": "val",
"type": "bytes"
}
],
"name": "log_named_bytes",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "bytes32",
"name": "val",
"type": "bytes32"
}
],
"name": "log_named_bytes32",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "int256",
"name": "val",
"type": "int256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "decimals",
"type": "uint256"
}
],
"name": "log_named_decimal_int",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "uint256",
"name": "val",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "decimals",
"type": "uint256"
}
],
"name": "log_named_decimal_uint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "int256",
"name": "val",
"type": "int256"
}
],
"name": "log_named_int",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "string",
"name": "val",
"type": "string"
}
],
"name": "log_named_string",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "uint256",
"name": "val",
"type": "uint256"
}
],
"name": "log_named_uint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "",
"type": "string"
}
],
"name": "log_string",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "log_uint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "logs",
"type": "event"
},
{
"inputs": [],
"name": "IS_SCRIPT",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "IS_TEST",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "counter",
"outputs": [
{
"internalType": "contract Counter",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "failed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "setUp",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "testIncrement",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "x",
"type": "uint256"
}
],
"name": "testSetNumber",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "vm",
"outputs": [
{
"internalType": "contract Vm",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"test/Counter.t.sol": "CounterTest"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/lib/ds-test/src/test.sol": {
"keccak256": "0xb39cd1d5220cb474947b131e15a4538334b7e886af244b440ae5c9c6bba96a54",
"license": "GPL-3.0-or-later",
"urls": [
"bzz-raw://3101520221449ac0070bda3881311a71d9aa87e5210765e875246922cb5cb5f5",
"dweb:/ipfs/Qmbg6kAHNoG7ox9N9Xqd9Ere2H2XixMFWFqvyPwFCzB3Gr"
]
},
"lib/forge-std/src/Script.sol": {
"keccak256": "0x4424dbcb8f5b741475445726f87408fcd89951fad973bec2ca442ee157f910e7",
"license": "MIT",
"urls": [
"bzz-raw://5b0b9f6dfb69245d8f888558ae82bf1d2cdeace46201444fe4b2e6a5283f944a",
"dweb:/ipfs/QmWFSKeFEZngNcwNn7A84EF7pASo5qe6r5oK24r9Kwca7Z"
]
},
"lib/forge-std/src/Test.sol": {
"keccak256": "0x5d84dd1e27d9127431d6f9aaeb681227235f2b0285545384d1dc236cbcab1364",
"license": "MIT",
"urls": [
"bzz-raw://6fe33b19854be51975ae89d4f4d3074a8b4bbd3c0e4dc5befe84d165f7462b55",
"dweb:/ipfs/Qma45Q6fvwpmke2rdPdZapNqjXv17ReoT4xp4Tnj1JdBd7"
]
},
"lib/forge-std/src/Vm.sol": {
"keccak256": "0xa0ede8e0d3dc3246912530aed6cacbc4703e4430c4b4acd91963ccea709755ea",
"license": "MIT",
"urls": [
"bzz-raw://a28e7d00aab57ad5159247b0f0f268eda4c6980b29eee7f903578254a2be677f",
"dweb:/ipfs/QmZrM8gY5BpW8o1QckmPNCYbBP5Q7k5DkcHdaVULKVntxp"
]
},
"lib/forge-std/src/console.sol": {
"keccak256": "0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba",
"license": "MIT",
"urls": [
"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70",
"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec"
]
},
"lib/forge-std/src/console2.sol": {
"keccak256": "0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671",
"license": "MIT",
"urls": [
"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f",
"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW"
]
},
"src/Counter.sol": {
"keccak256": "0x74eb20a9c3120b64f0e66b02cf476d5d1ff5e07149a4c52b8e774a6800a40b83",
"license": "UNLICENSED",
"urls": [
"bzz-raw://be4d1233bdd7aaf1846eb4c3b94c58914fa4a4b7a2fa4a5734d9d09c562975dc",
"dweb:/ipfs/QmNVGX1nn75pwmWKQjPdV8cy5u5PHuWGbL6TsztchKqmAZ"
]
},
"test/Counter.t.sol": {
"keccak256": "0x76bdc40734abcf9acbe5d56422e22662bc218e7d410264f3de6a823036be6a6d",
"license": "UNLICENSED",
"urls": [
"bzz-raw://27118e74e69a15c903cb826430175f337a9ab5cd1bb55a767ae9439e860052bd",
"dweb:/ipfs/QmfNHmcHCDN2eDQpbaDTSRyU4uhcZjpLEdvrudZRLY5knF"
]
}
},
"version": 1
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,99 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"inputs": [],
"name": "IS_SCRIPT",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "vm",
"outputs": [
{
"internalType": "contract Vm",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"lib/forge-std/src/Script.sol": "Script"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/src/Script.sol": {
"keccak256": "0x4424dbcb8f5b741475445726f87408fcd89951fad973bec2ca442ee157f910e7",
"license": "MIT",
"urls": [
"bzz-raw://5b0b9f6dfb69245d8f888558ae82bf1d2cdeace46201444fe4b2e6a5283f944a",
"dweb:/ipfs/QmWFSKeFEZngNcwNn7A84EF7pASo5qe6r5oK24r9Kwca7Z"
]
},
"lib/forge-std/src/Vm.sol": {
"keccak256": "0xa0ede8e0d3dc3246912530aed6cacbc4703e4430c4b4acd91963ccea709755ea",
"license": "MIT",
"urls": [
"bzz-raw://a28e7d00aab57ad5159247b0f0f268eda4c6980b29eee7f903578254a2be677f",
"dweb:/ipfs/QmZrM8gY5BpW8o1QckmPNCYbBP5Q7k5DkcHdaVULKVntxp"
]
},
"lib/forge-std/src/console.sol": {
"keccak256": "0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba",
"license": "MIT",
"urls": [
"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70",
"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec"
]
},
"lib/forge-std/src/console2.sol": {
"keccak256": "0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671",
"license": "MIT",
"urls": [
"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f",
"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW"
]
}
},
"version": 1
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,505 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "",
"type": "string"
}
],
"name": "log",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "log_address",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256[]",
"name": "val",
"type": "uint256[]"
}
],
"name": "log_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "int256[]",
"name": "val",
"type": "int256[]"
}
],
"name": "log_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address[]",
"name": "val",
"type": "address[]"
}
],
"name": "log_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "log_bytes",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"name": "log_bytes32",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "int256",
"name": "",
"type": "int256"
}
],
"name": "log_int",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "address",
"name": "val",
"type": "address"
}
],
"name": "log_named_address",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "uint256[]",
"name": "val",
"type": "uint256[]"
}
],
"name": "log_named_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "int256[]",
"name": "val",
"type": "int256[]"
}
],
"name": "log_named_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "address[]",
"name": "val",
"type": "address[]"
}
],
"name": "log_named_array",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "bytes",
"name": "val",
"type": "bytes"
}
],
"name": "log_named_bytes",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "bytes32",
"name": "val",
"type": "bytes32"
}
],
"name": "log_named_bytes32",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "int256",
"name": "val",
"type": "int256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "decimals",
"type": "uint256"
}
],
"name": "log_named_decimal_int",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "uint256",
"name": "val",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "decimals",
"type": "uint256"
}
],
"name": "log_named_decimal_uint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "int256",
"name": "val",
"type": "int256"
}
],
"name": "log_named_int",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "string",
"name": "val",
"type": "string"
}
],
"name": "log_named_string",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "uint256",
"name": "val",
"type": "uint256"
}
],
"name": "log_named_uint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "",
"type": "string"
}
],
"name": "log_string",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "log_uint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "logs",
"type": "event"
},
{
"inputs": [],
"name": "IS_SCRIPT",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "IS_TEST",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "failed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "vm",
"outputs": [
{
"internalType": "contract Vm",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"lib/forge-std/src/Test.sol": "Test"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/lib/ds-test/src/test.sol": {
"keccak256": "0xb39cd1d5220cb474947b131e15a4538334b7e886af244b440ae5c9c6bba96a54",
"license": "GPL-3.0-or-later",
"urls": [
"bzz-raw://3101520221449ac0070bda3881311a71d9aa87e5210765e875246922cb5cb5f5",
"dweb:/ipfs/Qmbg6kAHNoG7ox9N9Xqd9Ere2H2XixMFWFqvyPwFCzB3Gr"
]
},
"lib/forge-std/src/Script.sol": {
"keccak256": "0x4424dbcb8f5b741475445726f87408fcd89951fad973bec2ca442ee157f910e7",
"license": "MIT",
"urls": [
"bzz-raw://5b0b9f6dfb69245d8f888558ae82bf1d2cdeace46201444fe4b2e6a5283f944a",
"dweb:/ipfs/QmWFSKeFEZngNcwNn7A84EF7pASo5qe6r5oK24r9Kwca7Z"
]
},
"lib/forge-std/src/Test.sol": {
"keccak256": "0x5d84dd1e27d9127431d6f9aaeb681227235f2b0285545384d1dc236cbcab1364",
"license": "MIT",
"urls": [
"bzz-raw://6fe33b19854be51975ae89d4f4d3074a8b4bbd3c0e4dc5befe84d165f7462b55",
"dweb:/ipfs/Qma45Q6fvwpmke2rdPdZapNqjXv17ReoT4xp4Tnj1JdBd7"
]
},
"lib/forge-std/src/Vm.sol": {
"keccak256": "0xa0ede8e0d3dc3246912530aed6cacbc4703e4430c4b4acd91963ccea709755ea",
"license": "MIT",
"urls": [
"bzz-raw://a28e7d00aab57ad5159247b0f0f268eda4c6980b29eee7f903578254a2be677f",
"dweb:/ipfs/QmZrM8gY5BpW8o1QckmPNCYbBP5Q7k5DkcHdaVULKVntxp"
]
},
"lib/forge-std/src/console.sol": {
"keccak256": "0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba",
"license": "MIT",
"urls": [
"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70",
"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec"
]
},
"lib/forge-std/src/console2.sol": {
"keccak256": "0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671",
"license": "MIT",
"urls": [
"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f",
"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW"
]
}
},
"version": 1
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,219 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"inputs": [],
"name": "arithmeticError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "assertionError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "divisionError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "encodeStorageError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "enumConversionError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "indexOOBError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "lowLevelError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "memOverflowError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "popError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "zeroVarError",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"lib/forge-std/src/Test.sol": "stdError"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/lib/ds-test/src/test.sol": {
"keccak256": "0xb39cd1d5220cb474947b131e15a4538334b7e886af244b440ae5c9c6bba96a54",
"license": "GPL-3.0-or-later",
"urls": [
"bzz-raw://3101520221449ac0070bda3881311a71d9aa87e5210765e875246922cb5cb5f5",
"dweb:/ipfs/Qmbg6kAHNoG7ox9N9Xqd9Ere2H2XixMFWFqvyPwFCzB3Gr"
]
},
"lib/forge-std/src/Script.sol": {
"keccak256": "0x4424dbcb8f5b741475445726f87408fcd89951fad973bec2ca442ee157f910e7",
"license": "MIT",
"urls": [
"bzz-raw://5b0b9f6dfb69245d8f888558ae82bf1d2cdeace46201444fe4b2e6a5283f944a",
"dweb:/ipfs/QmWFSKeFEZngNcwNn7A84EF7pASo5qe6r5oK24r9Kwca7Z"
]
},
"lib/forge-std/src/Test.sol": {
"keccak256": "0x5d84dd1e27d9127431d6f9aaeb681227235f2b0285545384d1dc236cbcab1364",
"license": "MIT",
"urls": [
"bzz-raw://6fe33b19854be51975ae89d4f4d3074a8b4bbd3c0e4dc5befe84d165f7462b55",
"dweb:/ipfs/Qma45Q6fvwpmke2rdPdZapNqjXv17ReoT4xp4Tnj1JdBd7"
]
},
"lib/forge-std/src/Vm.sol": {
"keccak256": "0xa0ede8e0d3dc3246912530aed6cacbc4703e4430c4b4acd91963ccea709755ea",
"license": "MIT",
"urls": [
"bzz-raw://a28e7d00aab57ad5159247b0f0f268eda4c6980b29eee7f903578254a2be677f",
"dweb:/ipfs/QmZrM8gY5BpW8o1QckmPNCYbBP5Q7k5DkcHdaVULKVntxp"
]
},
"lib/forge-std/src/console.sol": {
"keccak256": "0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba",
"license": "MIT",
"urls": [
"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70",
"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec"
]
},
"lib/forge-std/src/console2.sol": {
"keccak256": "0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671",
"license": "MIT",
"urls": [
"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f",
"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW"
]
}
},
"version": 1
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,88 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"lib/forge-std/src/Test.sol": "stdMath"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/lib/ds-test/src/test.sol": {
"keccak256": "0xb39cd1d5220cb474947b131e15a4538334b7e886af244b440ae5c9c6bba96a54",
"license": "GPL-3.0-or-later",
"urls": [
"bzz-raw://3101520221449ac0070bda3881311a71d9aa87e5210765e875246922cb5cb5f5",
"dweb:/ipfs/Qmbg6kAHNoG7ox9N9Xqd9Ere2H2XixMFWFqvyPwFCzB3Gr"
]
},
"lib/forge-std/src/Script.sol": {
"keccak256": "0x4424dbcb8f5b741475445726f87408fcd89951fad973bec2ca442ee157f910e7",
"license": "MIT",
"urls": [
"bzz-raw://5b0b9f6dfb69245d8f888558ae82bf1d2cdeace46201444fe4b2e6a5283f944a",
"dweb:/ipfs/QmWFSKeFEZngNcwNn7A84EF7pASo5qe6r5oK24r9Kwca7Z"
]
},
"lib/forge-std/src/Test.sol": {
"keccak256": "0x5d84dd1e27d9127431d6f9aaeb681227235f2b0285545384d1dc236cbcab1364",
"license": "MIT",
"urls": [
"bzz-raw://6fe33b19854be51975ae89d4f4d3074a8b4bbd3c0e4dc5befe84d165f7462b55",
"dweb:/ipfs/Qma45Q6fvwpmke2rdPdZapNqjXv17ReoT4xp4Tnj1JdBd7"
]
},
"lib/forge-std/src/Vm.sol": {
"keccak256": "0xa0ede8e0d3dc3246912530aed6cacbc4703e4430c4b4acd91963ccea709755ea",
"license": "MIT",
"urls": [
"bzz-raw://a28e7d00aab57ad5159247b0f0f268eda4c6980b29eee7f903578254a2be677f",
"dweb:/ipfs/QmZrM8gY5BpW8o1QckmPNCYbBP5Q7k5DkcHdaVULKVntxp"
]
},
"lib/forge-std/src/console.sol": {
"keccak256": "0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba",
"license": "MIT",
"urls": [
"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70",
"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec"
]
},
"lib/forge-std/src/console2.sol": {
"keccak256": "0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671",
"license": "MIT",
"urls": [
"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f",
"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW"
]
}
},
"version": 1
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,163 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "who",
"type": "address"
},
{
"indexed": false,
"internalType": "bytes4",
"name": "fsig",
"type": "bytes4"
},
{
"indexed": false,
"internalType": "bytes32",
"name": "keysHash",
"type": "bytes32"
},
{
"indexed": false,
"internalType": "uint256",
"name": "slot",
"type": "uint256"
}
],
"name": "SlotFound",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "who",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "slot",
"type": "uint256"
}
],
"name": "WARNING_UninitedSlot",
"type": "event"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "b",
"type": "bytes"
},
{
"internalType": "uint256",
"name": "offset",
"type": "uint256"
}
],
"name": "bytesToBytes32",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"lib/forge-std/src/Test.sol": "stdStorage"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/lib/ds-test/src/test.sol": {
"keccak256": "0xb39cd1d5220cb474947b131e15a4538334b7e886af244b440ae5c9c6bba96a54",
"license": "GPL-3.0-or-later",
"urls": [
"bzz-raw://3101520221449ac0070bda3881311a71d9aa87e5210765e875246922cb5cb5f5",
"dweb:/ipfs/Qmbg6kAHNoG7ox9N9Xqd9Ere2H2XixMFWFqvyPwFCzB3Gr"
]
},
"lib/forge-std/src/Script.sol": {
"keccak256": "0x4424dbcb8f5b741475445726f87408fcd89951fad973bec2ca442ee157f910e7",
"license": "MIT",
"urls": [
"bzz-raw://5b0b9f6dfb69245d8f888558ae82bf1d2cdeace46201444fe4b2e6a5283f944a",
"dweb:/ipfs/QmWFSKeFEZngNcwNn7A84EF7pASo5qe6r5oK24r9Kwca7Z"
]
},
"lib/forge-std/src/Test.sol": {
"keccak256": "0x5d84dd1e27d9127431d6f9aaeb681227235f2b0285545384d1dc236cbcab1364",
"license": "MIT",
"urls": [
"bzz-raw://6fe33b19854be51975ae89d4f4d3074a8b4bbd3c0e4dc5befe84d165f7462b55",
"dweb:/ipfs/Qma45Q6fvwpmke2rdPdZapNqjXv17ReoT4xp4Tnj1JdBd7"
]
},
"lib/forge-std/src/Vm.sol": {
"keccak256": "0xa0ede8e0d3dc3246912530aed6cacbc4703e4430c4b4acd91963ccea709755ea",
"license": "MIT",
"urls": [
"bzz-raw://a28e7d00aab57ad5159247b0f0f268eda4c6980b29eee7f903578254a2be677f",
"dweb:/ipfs/QmZrM8gY5BpW8o1QckmPNCYbBP5Q7k5DkcHdaVULKVntxp"
]
},
"lib/forge-std/src/console.sol": {
"keccak256": "0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba",
"license": "MIT",
"urls": [
"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70",
"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec"
]
},
"lib/forge-std/src/console2.sol": {
"keccak256": "0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671",
"license": "MIT",
"urls": [
"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f",
"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW"
]
}
},
"version": 1
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,48 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"lib/forge-std/src/console.sol": "console"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/src/console.sol": {
"keccak256": "0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba",
"license": "MIT",
"urls": [
"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70",
"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec"
]
}
},
"version": 1
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,48 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"lib/forge-std/src/console2.sol": "console2"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/src/console2.sol": {
"keccak256": "0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671",
"license": "MIT",
"urls": [
"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f",
"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW"
]
}
},
"version": 1
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,343 @@
{
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "",
"type": "string"
}
],
"name": "log",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "log_address",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "log_bytes",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"name": "log_bytes32",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "int256",
"name": "",
"type": "int256"
}
],
"name": "log_int",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "address",
"name": "val",
"type": "address"
}
],
"name": "log_named_address",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "bytes",
"name": "val",
"type": "bytes"
}
],
"name": "log_named_bytes",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "bytes32",
"name": "val",
"type": "bytes32"
}
],
"name": "log_named_bytes32",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "int256",
"name": "val",
"type": "int256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "decimals",
"type": "uint256"
}
],
"name": "log_named_decimal_int",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "uint256",
"name": "val",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "decimals",
"type": "uint256"
}
],
"name": "log_named_decimal_uint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "int256",
"name": "val",
"type": "int256"
}
],
"name": "log_named_int",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "string",
"name": "val",
"type": "string"
}
],
"name": "log_named_string",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "key",
"type": "string"
},
{
"indexed": false,
"internalType": "uint256",
"name": "val",
"type": "uint256"
}
],
"name": "log_named_uint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "",
"type": "string"
}
],
"name": "log_string",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "log_uint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "logs",
"type": "event"
},
{
"inputs": [],
"name": "IS_TEST",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "failed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"compilationTarget": {
"lib/forge-std/lib/ds-test/src/test.sol": "DSTest"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
]
},
"sources": {
"lib/forge-std/lib/ds-test/src/test.sol": {
"keccak256": "0xb39cd1d5220cb474947b131e15a4538334b7e886af244b440ae5c9c6bba96a54",
"license": "GPL-3.0-or-later",
"urls": [
"bzz-raw://3101520221449ac0070bda3881311a71d9aa87e5210765e875246922cb5cb5f5",
"dweb:/ipfs/Qmbg6kAHNoG7ox9N9Xqd9Ere2H2XixMFWFqvyPwFCzB3Gr"
]
}
},
"version": 1
}

@ -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;
}
}

@ -0,0 +1 @@
// simulate a hardhat project

@ -34,6 +34,7 @@ import { ExternalHttpProvider } from './app/tabs/external-http-provider'
import { Injected0ptimismProvider } from './app/tabs/injected-optimism-provider' import { Injected0ptimismProvider } from './app/tabs/injected-optimism-provider'
import { InjectedArbitrumOneProvider } from './app/tabs/injected-arbitrum-one-provider' import { InjectedArbitrumOneProvider } from './app/tabs/injected-arbitrum-one-provider'
import { FileDecorator } from './app/plugins/file-decorator' import { FileDecorator } from './app/plugins/file-decorator'
import { CodeFormat } from './app/plugins/code-format'
const isElectron = require('is-electron') const isElectron = require('is-electron')
@ -64,7 +65,7 @@ const Terminal = require('./app/panels/terminal')
const { TabProxy } = require('./app/panels/tab-proxy.js') const { TabProxy } = require('./app/panels/tab-proxy.js')
class AppComponent { class AppComponent {
constructor () { constructor() {
this.appManager = new RemixAppManager({}) this.appManager = new RemixAppManager({})
this.queryParams = new QueryParams() this.queryParams = new QueryParams()
this._components = {} this._components = {}
@ -101,7 +102,7 @@ class AppComponent {
}) })
} }
async run () { async run() {
// APP_MANAGER // APP_MANAGER
const appManager = this.appManager const appManager = this.appManager
const pluginLoader = this.appManager.pluginLoader const pluginLoader = this.appManager.pluginLoader
@ -165,6 +166,9 @@ class AppComponent {
// ------- FILE DECORATOR PLUGIN ------------------ // ------- FILE DECORATOR PLUGIN ------------------
const fileDecorator = new FileDecorator() const fileDecorator = new FileDecorator()
// ------- CODE FORMAT PLUGIN ------------------
const codeFormat = new CodeFormat()
//----- search //----- search
const search = new SearchPlugin() const search = new SearchPlugin()
@ -246,6 +250,7 @@ class AppComponent {
offsetToLineColumnConverter, offsetToLineColumnConverter,
codeParser, codeParser,
fileDecorator, fileDecorator,
codeFormat,
terminal, terminal,
web3Provider, web3Provider,
compileAndRun, compileAndRun,
@ -339,6 +344,7 @@ class AppComponent {
filePanel.remixdHandle, filePanel.remixdHandle,
filePanel.gitHandle, filePanel.gitHandle,
filePanel.hardhatHandle, filePanel.hardhatHandle,
filePanel.foundryHandle,
filePanel.truffleHandle, filePanel.truffleHandle,
filePanel.slitherHandle, filePanel.slitherHandle,
linkLibraries, linkLibraries,
@ -355,7 +361,7 @@ class AppComponent {
} }
} }
async activate () { async activate() {
const queryParams = new QueryParams() const queryParams = new QueryParams()
const params = queryParams.get() const params = queryParams.get()
@ -372,14 +378,18 @@ class AppComponent {
await this.appManager.activatePlugin(['sidePanel']) // activating host plugin separately await this.appManager.activatePlugin(['sidePanel']) // activating host plugin separately
await this.appManager.activatePlugin(['home']) await this.appManager.activatePlugin(['home'])
await this.appManager.activatePlugin(['settings', 'config']) await this.appManager.activatePlugin(['settings', 'config'])
await this.appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'codeParser', 'fileDecorator', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport', 'gistHandler']) await this.appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'codeParser', 'codeFormatter', 'fileDecorator', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport', 'gistHandler'])
await this.appManager.activatePlugin(['settings']) await this.appManager.activatePlugin(['settings'])
await this.appManager.activatePlugin(['walkthrough','storage', 'search','compileAndRun', 'recorder']) await this.appManager.activatePlugin(['walkthrough', 'storage', 'search', 'compileAndRun', 'recorder'])
this.appManager.on( this.appManager.on(
'filePanel', 'filePanel',
'workspaceInitializationCompleted', 'workspaceInitializationCompleted',
async () => { async () => {
// for e2e tests
const loadedElement = document.createElement('span')
loadedElement.setAttribute('data-id', 'workspaceloaded')
document.body.appendChild(loadedElement)
await this.appManager.registerContextMenuItems() await this.appManager.registerContextMenuItems()
} }
) )
@ -416,7 +426,7 @@ class AppComponent {
if (callDetails.length > 1) { if (callDetails.length > 1) {
this.appManager.call('notification', 'toast', `initiating ${callDetails[0]} and calling "${callDetails[1]}" ...`) this.appManager.call('notification', 'toast', `initiating ${callDetails[0]} and calling "${callDetails[1]}" ...`)
// @todo(remove the timeout when activatePlugin is on 0.3.0) // @todo(remove the timeout when activatePlugin is on 0.3.0)
this.appManager.call(...callDetails).catch(console.error) await this.appManager.call(...callDetails).catch(console.error)
} }
} }
@ -442,9 +452,15 @@ class AppComponent {
} }
} }
} }
}) })
.catch(console.error) .catch(console.error)
} }
const loadedElement = document.createElement('span')
loadedElement.setAttribute('data-id', 'apploaded')
document.body.appendChild(loadedElement)
}) })
// activate solidity plugin // activate solidity plugin
this.appManager.activatePlugin(['solidity', 'udapp', 'deploy-libraries', 'link-libraries', 'openzeppelin-proxy']) this.appManager.activatePlugin(['solidity', 'udapp', 'deploy-libraries', 'link-libraries', 'openzeppelin-proxy'])

@ -5,6 +5,7 @@ import { EditorUI } from '@remix-ui/editor' // eslint-disable-line
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
import { PluginViewWrapper } from '@remix-ui/helper' import { PluginViewWrapper } from '@remix-ui/helper'
import { exists } from 'fs'
const EventManager = require('../../lib/events') const EventManager = require('../../lib/events')
@ -74,30 +75,15 @@ class Editor extends Plugin {
updateComponent(state) { updateComponent(state) {
return <EditorUI return <EditorUI
editorAPI={state.api} editorAPI={state.api}
themeType={state.currentThemeType} themeType={state.currentThemeType}
currentFile={state.currentFile} currentFile={state.currentFile}
events={state.events} events={state.events}
plugin={state.plugin} plugin={state.plugin}
/> />
} }
render () { render () {
/* if (this.el) return this.el
this.el = document.createElement('div')
this.el.setAttribute('id', 'editorView')
this.el.currentContent = () => this.currentContent() // used by e2e test
this.el.setCurrentContent = (value) => {
if (this.sessions[this.currentFile]) {
this.sessions[this.currentFile].setValue(value)
this._onChange(this.currentFile)
}
}
this.el.gotoLine = (line, column) => this.gotoLine(line, column || 0)
this.el.getCursorPosition = () => this.getCursorPosition() */
return <div ref={(element)=>{ return <div ref={(element)=>{
this.ref = element this.ref = element
this.ref.currentContent = () => this.currentContent() // used by e2e test this.ref.currentContent = () => this.currentContent() // used by e2e test
@ -113,7 +99,7 @@ class Editor extends Plugin {
this.ref.clearDecorationsByPlugin = (filePath, plugin, typeOfDecoration) => this.clearDecorationsByPlugin(filePath, plugin, typeOfDecoration) this.ref.clearDecorationsByPlugin = (filePath, plugin, typeOfDecoration) => this.clearDecorationsByPlugin(filePath, plugin, typeOfDecoration)
this.ref.keepDecorationsFor = (name, typeOfDecoration) => this.keepDecorationsFor(name, typeOfDecoration) this.ref.keepDecorationsFor = (name, typeOfDecoration) => this.keepDecorationsFor(name, typeOfDecoration)
}} id='editorView'> }} id='editorView'>
<PluginViewWrapper plugin={this} /> <PluginViewWrapper plugin={this} />
</div> </div>
} }
@ -229,15 +215,20 @@ class Editor extends Plugin {
try { try {
// we can't use the fileManager plugin call directly // we can't use the fileManager plugin call directly
// because it's itself called in a plugin context, and that causes a timeout in the plugin stack // because it's itself called in a plugin context, and that causes a timeout in the plugin stack
const contentDep = await readFile(pathDep) const pathExists = await exists(pathDep)
if (contentDep !== null) { let contentDep = ''
this.emit('addModel', contentDep, 'typescript', pathDep, false) if (pathExists) {
contentDep = await readFile(pathDep)
if (contentDep !== '') {
this.emit('addModel', contentDep, 'typescript', pathDep, false)
}
} else {
console.log("The file ", pathDep, " can't be found.")
} }
} catch (e) { } catch (e) {
console.log(e) console.log(e)
} }
} }
} }
} }
@ -367,8 +358,8 @@ class Editor extends Plugin {
/** /**
* The position of the cursor * The position of the cursor
*/ */
getCursorPosition () { getCursorPosition (offset = true) {
return this.api.getCursorPosition() return this.api.getCursorPosition(offset)
} }
/** /**

@ -0,0 +1,18 @@
import { WebsocketPlugin } from '@remixproject/engine-web'
import * as packageJson from '../../../../../package.json'
const profile = {
name: 'foundry',
displayName: 'Foundry',
url: 'ws://127.0.0.1:65525',
methods: [],
description: 'Using Remixd daemon, allow to access foundry API',
kind: 'other',
version: packageJson.version
}
export class FoundryHandle extends WebsocketPlugin {
constructor () {
super(profile)
}
}

@ -7,6 +7,7 @@ import Registry from '../state/registry'
import { RemixdHandle } from '../plugins/remixd-handle' import { RemixdHandle } from '../plugins/remixd-handle'
const { GitHandle } = require('../files/git-handle.js') const { GitHandle } = require('../files/git-handle.js')
const { HardhatHandle } = require('../files/hardhat-handle.js') const { HardhatHandle } = require('../files/hardhat-handle.js')
const { FoundryHandle } = require('../files/foundry-handle.js')
const { TruffleHandle } = require('../files/truffle-handle.js') const { TruffleHandle } = require('../files/truffle-handle.js')
const { SlitherHandle } = require('../files/slither-handle.js') const { SlitherHandle } = require('../files/slither-handle.js')
@ -54,6 +55,7 @@ module.exports = class Filepanel extends ViewPlugin {
this.remixdHandle = new RemixdHandle(this.fileProviders.localhost, appManager) this.remixdHandle = new RemixdHandle(this.fileProviders.localhost, appManager)
this.gitHandle = new GitHandle() this.gitHandle = new GitHandle()
this.hardhatHandle = new HardhatHandle() this.hardhatHandle = new HardhatHandle()
this.foundryHandle = new FoundryHandle()
this.truffleHandle = new TruffleHandle() this.truffleHandle = new TruffleHandle()
this.slitherHandle = new SlitherHandle() this.slitherHandle = new SlitherHandle()
this.workspaces = [] this.workspaces = []

@ -0,0 +1,82 @@
'use strict'
import { Plugin } from '@remixproject/engine'
import prettier from 'prettier/standalone'
import { Options } from 'prettier';
import sol from './code-format/index'
import * as ts from 'prettier/parser-typescript'
import * as babel from 'prettier/parser-babel'
import * as espree from 'prettier/parser-espree'
import path from 'path'
const profile = {
name: 'codeFormatter',
desciption: 'prettier plugin for Remix',
methods: ['format'],
events: [''],
version: '0.0.1'
}
export class CodeFormat extends Plugin {
constructor() {
super(profile)
}
async format(file: string) {
try {
const content = await this.call('fileManager', 'readFile', file)
if (!content) return
let parserName = ''
let options: Options = {
}
switch (path.extname(file)) {
case '.sol':
parserName = 'solidity-parse'
break
case '.ts':
parserName = 'typescript'
options = {
...options,
trailingComma: 'all',
semi: false,
singleQuote: true,
quoteProps: 'as-needed',
bracketSpacing: true,
arrowParens: 'always',
}
break
case '.js':
parserName = "espree"
options = {
...options,
semi: false,
singleQuote: true,
}
break
case '.json':
parserName = 'json'
break
}
const result = prettier.format(content, {
plugins: [sol as any, ts, babel, espree],
parser: parserName,
...options
})
await this.call('fileManager', 'writeFile', file, result)
} catch (e) {
// do nothing
}
}
}
function getRange(index, node) {
if (node.range) {
return node.range[index];
}
if (node.expression && node.expression.range) {
return node.expression.range[index];
}
return null;
}

@ -0,0 +1,61 @@
import { handleComments, printComment } from 'prettier-plugin-solidity/src/comments';
import massageAstNode from 'prettier-plugin-solidity/src/clean.js';
import options from 'prettier-plugin-solidity/src/options.js';
import print from 'prettier-plugin-solidity/src/printer.js';
import loc from 'prettier-plugin-solidity/src/loc.js';
import { parse } from './parser'
// https://prettier.io/docs/en/plugins.html#languages
// https://github.com/ikatyang/linguist-languages/blob/master/data/Solidity.json
const languages = [
{
linguistLanguageId: 237469032,
name: 'Solidity',
type: 'programming',
color: '#AA6746',
aceMode: 'text',
tmScope: 'source.solidity',
extensions: ['.sol'],
parsers: ['solidity-parse'],
vscodeLanguageIds: ['solidity']
}
];
// https://prettier.io/docs/en/plugins.html#parsers
const parser = { astFormat: 'solidity-ast', parse, ...loc };
const parsers = {
'solidity-parse': parser
};
const canAttachComment = (node) =>
node.type && node.type !== 'BlockComment' && node.type !== 'LineComment';
// https://prettier.io/docs/en/plugins.html#printers
const printers = {
'solidity-ast': {
canAttachComment,
handleComments: {
ownLine: handleComments.handleOwnLineComment,
endOfLine: handleComments.handleEndOfLineComment,
remaining: handleComments.handleRemainingComment
},
isBlockComment: handleComments.isBlockComment,
massageAstNode,
print,
printComment
}
};
// https://prettier.io/docs/en/plugins.html#defaultoptions
const defaultOptions = {
bracketSpacing: false,
tabWidth: 4
};
export default {
languages,
parsers,
printers,
options,
defaultOptions
};

@ -0,0 +1,197 @@
// https://prettier.io/docs/en/plugins.html#parsers
import extractComments from 'solidity-comments-extractor';
// use the parser already included in the app
const parser = (window as any).SolidityParser
import semver from 'semver';
const tryHug = (node, operators) => {
if (node.type === 'BinaryOperation' && operators.includes(node.operator))
return {
type: 'TupleExpression',
components: [node],
isArray: false
};
return node;
};
export function parse(text, _parsers, options) {
const compiler = semver.coerce(options.compiler);
const parsed = parser.parse(text, { loc: true, range: true });
parsed.comments = extractComments(text)
parser.visit(parsed, {
PragmaDirective(ctx) {
// if the pragma is not for solidity we leave.
if (ctx.name !== 'solidity') return;
// if the compiler option has not been provided we leave.
if (!compiler) return;
// we make a check against each pragma directive in the document.
if (!semver.satisfies(compiler, ctx.value)) {
// @TODO: investigate the best way to warn that would apply to
// different editors.
// eslint-disable-next-line no-console
console.warn(
`[prettier-solidity] The compiler option is set to '${options.compiler}', which does not satisfy 'pragma solidity ${ctx.value}'.`
);
}
},
ModifierDefinition(ctx) {
if (!ctx.parameters) {
ctx.parameters = [];
}
},
FunctionDefinition(ctx) {
if (!ctx.isConstructor) {
ctx.modifiers.forEach((modifier) => {
if (modifier.arguments && modifier.arguments.length === 0) {
// eslint-disable-next-line no-param-reassign
modifier.arguments = null;
}
});
}
},
ForStatement(ctx) {
if (ctx.initExpression) {
ctx.initExpression.omitSemicolon = true;
}
ctx.loopExpression.omitSemicolon = true;
},
HexLiteral(ctx) {
ctx.value = options.singleQuote
? `hex'${ctx.value.slice(4, -1)}'`
: `hex"${ctx.value.slice(4, -1)}"`;
},
ElementaryTypeName(ctx) {
// if the compiler is below 0.8.0 we will recognize the type 'byte' as an
// alias of 'bytes1'. Otherwise we will ignore this and enforce always
// 'bytes1'.
const pre080 = compiler && semver.satisfies(compiler, '<0.8.0');
if (!pre080 && ctx.name === 'byte') ctx.name = 'bytes1';
if (options.explicitTypes === 'always') {
if (ctx.name === 'uint') ctx.name = 'uint256';
if (ctx.name === 'int') ctx.name = 'int256';
if (pre080 && ctx.name === 'byte') ctx.name = 'bytes1';
} else if (options.explicitTypes === 'never') {
if (ctx.name === 'uint256') ctx.name = 'uint';
if (ctx.name === 'int256') ctx.name = 'int';
if (pre080 && ctx.name === 'bytes1') ctx.name = 'byte';
}
},
BinaryOperation(ctx) {
switch (ctx.operator) {
case '+':
case '-':
ctx.left = tryHug(ctx.left, ['%']);
ctx.right = tryHug(ctx.right, ['%']);
break;
case '*':
ctx.left = tryHug(ctx.left, ['/', '%']);
break;
case '/':
ctx.left = tryHug(ctx.left, ['*', '%']);
break;
case '%':
ctx.left = tryHug(ctx.left, ['*', '/', '%']);
break;
case '**':
// If the compiler has not been given as an option using we leave a**b**c.
if (!compiler) break;
if (semver.satisfies(compiler, '<0.8.0')) {
// If the compiler is less than 0.8.0 then a**b**c is formatted as
// (a**b)**c.
ctx.left = tryHug(ctx.left, ['**']);
break;
}
if (
ctx.left.type === 'BinaryOperation' &&
ctx.left.operator === '**'
) {
// the parser still organizes the a**b**c as (a**b)**c so we need
// to restructure it.
ctx.right = {
type: 'TupleExpression',
components: [
{
type: 'BinaryOperation',
operator: '**',
left: ctx.left.right,
right: ctx.right
}
],
isArray: false
};
ctx.left = ctx.left.left;
}
break;
case '<<':
case '>>':
ctx.left = tryHug(ctx.left, ['+', '-', '*', '/', '**', '<<', '>>']);
ctx.right = tryHug(ctx.right, ['+', '-', '*', '/', '**']);
break;
case '&':
ctx.left = tryHug(ctx.left, ['+', '-', '*', '/', '**', '<<', '>>']);
ctx.right = tryHug(ctx.right, ['+', '-', '*', '/', '**', '<<', '>>']);
break;
case '|':
ctx.left = tryHug(ctx.left, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&',
'^'
]);
ctx.right = tryHug(ctx.right, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&',
'^'
]);
break;
case '^':
ctx.left = tryHug(ctx.left, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&'
]);
ctx.right = tryHug(ctx.right, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&'
]);
break;
case '||':
ctx.left = tryHug(ctx.left, ['&&']);
ctx.right = tryHug(ctx.right, ['&&']);
break;
case '&&':
default:
break;
}
}
});
return parsed;
}

@ -6,6 +6,7 @@ import { CompilationResult } from '@remix-project/remix-solidity'
import CodeParserGasService from './services/code-parser-gas-service' import CodeParserGasService from './services/code-parser-gas-service'
import CodeParserCompiler from './services/code-parser-compiler' import CodeParserCompiler from './services/code-parser-compiler'
import CodeParserAntlrService from './services/code-parser-antlr-service' import CodeParserAntlrService from './services/code-parser-antlr-service'
import CodeParserImports, { CodeParserImportsData } from './services/code-parser-imports'
import React from 'react' import React from 'react'
import { Profile } from '@remixproject/plugin-utils' import { Profile } from '@remixproject/plugin-utils'
import { ContractDefinitionAstNode, EventDefinitionAstNode, FunctionCallAstNode, FunctionDefinitionAstNode, IdentifierAstNode, ImportDirectiveAstNode, ModifierDefinitionAstNode, SourceUnitAstNode, StructDefinitionAstNode, VariableDeclarationAstNode } from 'dist/libs/remix-analyzer/src/types' import { ContractDefinitionAstNode, EventDefinitionAstNode, FunctionCallAstNode, FunctionDefinitionAstNode, IdentifierAstNode, ImportDirectiveAstNode, ModifierDefinitionAstNode, SourceUnitAstNode, StructDefinitionAstNode, VariableDeclarationAstNode } from 'dist/libs/remix-analyzer/src/types'
@ -15,7 +16,7 @@ import { ParseResult } from './types/antlr-types'
const profile: Profile = { const profile: Profile = {
name: 'codeParser', name: 'codeParser',
methods: ['nodesAtPosition', 'getContractNodes', 'getCurrentFileNodes', 'getLineColumnOfNode', 'getLineColumnOfPosition', 'getFunctionParamaters', 'getDeclaration', 'getFunctionReturnParameters', 'getVariableDeclaration', 'getNodeDocumentation', 'getNodeLink', 'listAstNodes', 'getANTLRBlockAtPosition', 'getLastNodeInLine', 'resolveImports', 'parseSolidity', 'getNodesWithScope', 'getNodesWithName', 'getNodes', 'compile', 'getNodeById', 'getLastCompilationResult', 'positionOfDefinition', 'definitionAtPosition', 'jumpToDefinition', 'referrencesAtPosition', 'referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf', 'getGasEstimates'], methods: ['nodesAtPosition', 'getContractNodes', 'getCurrentFileNodes', 'getLineColumnOfNode', 'getLineColumnOfPosition', 'getFunctionParamaters', 'getDeclaration', 'getFunctionReturnParameters', 'getVariableDeclaration', 'getNodeDocumentation', 'getNodeLink', 'listAstNodes', 'getANTLRBlockAtPosition', 'getLastNodeInLine', 'resolveImports', 'parseSolidity', 'getNodesWithScope', 'getNodesWithName', 'getNodes', 'compile', 'getNodeById', 'getLastCompilationResult', 'positionOfDefinition', 'definitionAtPosition', 'jumpToDefinition', 'referrencesAtPosition', 'referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf', 'getGasEstimates', 'getImports'],
events: [], events: [],
version: '0.0.1' version: '0.0.1'
} }
@ -57,8 +58,6 @@ interface codeParserIndex {
export class CodeParser extends Plugin { export class CodeParser extends Plugin {
antlrParserResult: antlr.ParseResult // contains the simple parsed AST for the current file
compilerAbstract: CompilerAbstract compilerAbstract: CompilerAbstract
currentFile: string currentFile: string
nodeIndex: codeParserIndex nodeIndex: codeParserIndex
@ -70,12 +69,15 @@ export class CodeParser extends Plugin {
gasService: CodeParserGasService gasService: CodeParserGasService
compilerService: CodeParserCompiler compilerService: CodeParserCompiler
antlrService: CodeParserAntlrService antlrService: CodeParserAntlrService
importService: CodeParserImports
parseSolidity: (text: string) => Promise<antlr.ParseResult> parseSolidity: (text: string) => Promise<antlr.ParseResult>
getLastNodeInLine: (ast: string) => Promise<any> getLastNodeInLine: (ast: string) => Promise<any>
listAstNodes: () => Promise<any> listAstNodes: () => Promise<any>
getANTLRBlockAtPosition: (position: any, text?: string) => Promise<any> getANTLRBlockAtPosition: (position: any, text?: string) => Promise<any>
getCurrentFileAST: (text?: string) => Promise<ParseResult> setCurrentFileAST: (text?: string) => Promise<ParseResult>
getImports: () => Promise<CodeParserImportsData[]>
constructor(astWalker: any) { constructor(astWalker: any) {
super(profile) super(profile)
@ -90,11 +92,13 @@ export class CodeParser extends Plugin {
async handleChangeEvents() { async handleChangeEvents() {
const completionSettings = await this.call('config', 'getAppParameter', 'auto-completion') const completionSettings = await this.call('config', 'getAppParameter', 'auto-completion')
if (completionSettings) { if (completionSettings) {
await this.antlrService.getCurrentFileAST() this.antlrService.enableWorker()
} else {
this.antlrService.disableWorker()
} }
const showGasSettings = await this.call('config', 'getAppParameter', 'show-gas') const showGasSettings = await this.call('config', 'getAppParameter', 'show-gas')
const showErrorSettings = await this.call('config', 'getAppParameter', 'display-errors') const showErrorSettings = await this.call('config', 'getAppParameter', 'display-errors')
if(showGasSettings || showErrorSettings || completionSettings) { if (showGasSettings || showErrorSettings || completionSettings) {
await this.compilerService.compile() await this.compilerService.compile()
} }
} }
@ -104,13 +108,14 @@ export class CodeParser extends Plugin {
this.gasService = new CodeParserGasService(this) this.gasService = new CodeParserGasService(this)
this.compilerService = new CodeParserCompiler(this) this.compilerService = new CodeParserCompiler(this)
this.antlrService = new CodeParserAntlrService(this) this.antlrService = new CodeParserAntlrService(this)
this.importService = new CodeParserImports(this)
this.parseSolidity = this.antlrService.parseSolidity.bind(this.antlrService) this.parseSolidity = this.antlrService.parseSolidity.bind(this.antlrService)
this.getLastNodeInLine = this.antlrService.getLastNodeInLine.bind(this.antlrService) this.getLastNodeInLine = this.antlrService.getLastNodeInLine.bind(this.antlrService)
this.listAstNodes = this.antlrService.listAstNodes.bind(this.antlrService) this.listAstNodes = this.antlrService.listAstNodes.bind(this.antlrService)
this.getANTLRBlockAtPosition = this.antlrService.getANTLRBlockAtPosition.bind(this.antlrService) this.getANTLRBlockAtPosition = this.antlrService.getANTLRBlockAtPosition.bind(this.antlrService)
this.getCurrentFileAST = this.antlrService.getCurrentFileAST.bind(this.antlrService) this.setCurrentFileAST = this.antlrService.setCurrentFileAST.bind(this.antlrService)
this.getImports = this.importService.getImports.bind(this.importService)
this.on('editor', 'didChangeFile', async (file) => { this.on('editor', 'didChangeFile', async (file) => {
await this.call('editor', 'discardLineTexts') await this.call('editor', 'discardLineTexts')
@ -119,11 +124,22 @@ export class CodeParser extends Plugin {
this.on('filePanel', 'setWorkspace', async () => { this.on('filePanel', 'setWorkspace', async () => {
await this.call('fileDecorator', 'clearFileDecorators') await this.call('fileDecorator', 'clearFileDecorators')
await this.importService.setFileTree()
}) })
this.on('fileManager', 'fileAdded', async () => {
await this.importService.setFileTree()
})
this.on('fileManager', 'fileRemoved', async () => {
await this.importService.setFileTree()
})
this.on('fileManager', 'currentFileChanged', async () => { this.on('fileManager', 'currentFileChanged', async () => {
await this.call('editor', 'discardLineTexts') await this.call('editor', 'discardLineTexts')
const completionSettings = await this.call('config', 'getAppParameter', 'auto-completion')
if (completionSettings) {
this.antlrService.setCurrentFileAST()
}
await this.handleChangeEvents() await this.handleChangeEvents()
}) })
@ -135,8 +151,6 @@ export class CodeParser extends Plugin {
} }
/** /**
* *
* @returns * @returns
@ -145,10 +159,6 @@ export class CodeParser extends Plugin {
return this.compilerAbstract return this.compilerAbstract
} }
getSubNodes<T extends genericASTNode>(node: T): number[] { getSubNodes<T extends genericASTNode>(node: T): number[] {
return node.nodeType == "ContractDefinition" && node.contractDependencies; return node.nodeType == "ContractDefinition" && node.contractDependencies;
} }
@ -405,19 +415,21 @@ export class CodeParser extends Plugin {
return nodeDefinition return nodeDefinition
} else { } else {
const astNodes = await this.antlrService.listAstNodes() const astNodes = await this.antlrService.listAstNodes()
for (const node of astNodes) { if (astNodes && astNodes.length) {
if (node.range[0] <= position && node.range[1] >= position) { for (const node of astNodes) {
if (nodeDefinition && nodeDefinition.range[0] < node.range[0]) { if (node.range[0] <= position && node.range[1] >= position) {
nodeDefinition = node if (nodeDefinition && nodeDefinition.range[0] < node.range[0]) {
nodeDefinition = node
}
if (!nodeDefinition) nodeDefinition = node
} }
if (!nodeDefinition) nodeDefinition = node
} }
if (nodeDefinition && nodeDefinition.type && nodeDefinition.type === 'Identifier') {
const nodeForIdentifier = await this.findIdentifier(nodeDefinition)
if (nodeForIdentifier) nodeDefinition = nodeForIdentifier
}
return nodeDefinition
} }
if (nodeDefinition && nodeDefinition.type && nodeDefinition.type === 'Identifier') {
const nodeForIdentifier = await this.findIdentifier(nodeDefinition)
if (nodeForIdentifier) nodeDefinition = nodeForIdentifier
}
return nodeDefinition
} }
} }
@ -551,7 +563,7 @@ export class CodeParser extends Plugin {
async getNodeLink(node: genericASTNode) { async getNodeLink(node: genericASTNode) {
const lineColumn = await this.getLineColumnOfNode(node) const lineColumn = await this.getLineColumnOfNode(node)
const position = await this.positionOfDefinition(node) const position = await this.positionOfDefinition(node)
if (this.compilerAbstract && this.compilerAbstract.source) { if (this.compilerAbstract && this.compilerAbstract.source && position) {
const fileName = this.compilerAbstract.getSourceName(position.file) const fileName = this.compilerAbstract.getSourceName(position.file)
return lineColumn ? `${fileName} ${lineColumn.start.line}:${lineColumn.start.column}` : null return lineColumn ? `${fileName} ${lineColumn.start.line}:${lineColumn.start.column}` : null
} }
@ -650,4 +662,4 @@ export class CodeParser extends Plugin {
} }

@ -0,0 +1,54 @@
let parser: any
// 'DedicatedWorkerGlobalScope' object (the Worker global scope) is accessible through the self keyword
// 'dom' and 'webworker' library files can't be included together https://github.com/microsoft/TypeScript/issues/20595
export default function (self) { // eslint-disable-line @typescript-eslint/explicit-module-boundary-types
self.addEventListener('message', (e) => {
const data: any = e.data
switch (data.cmd) {
case 'load':
{
delete self.Module
// NOTE: workaround some browsers?
self.Module = undefined
// importScripts() method of synchronously imports one or more scripts into the worker's scope
self.importScripts(e.data.url)
// @ts-ignore
parser = SolidityParser as any;
self.postMessage({
cmd: 'loaded',
})
break
}
case 'parse':
if (data.text && parser) {
try {
let startTime = performance.now()
const blocks = parser.parseBlock(data.text, { loc: true, range: true, tolerant: true })
const blockDuration = performance.now() - startTime
startTime = performance.now()
const ast = parser.parse(data.text, { loc: true, range: true, tolerant: true })
const endTime = performance.now()
self.postMessage({
cmd: 'parsed',
timestamp: data.timestamp,
ast,
text: data.text,
file: data.file,
duration: endTime - startTime,
blockDuration,
blocks
})
} catch (e) {
// do nothing
}
}
break
}
}, false)
}

@ -3,18 +3,112 @@
import { AstNode } from "@remix-project/remix-solidity-ts" import { AstNode } from "@remix-project/remix-solidity-ts"
import { CodeParser } from "../code-parser" import { CodeParser } from "../code-parser"
import { antlr } from '../types' import { antlr } from '../types'
import work from 'webworkify-webpack'
const SolidityParser = (window as any).SolidityParser = (window as any).SolidityParser || [] const SolidityParser = (window as any).SolidityParser = (window as any).SolidityParser || []
interface BlockDefinition {
end: number
endColumn: number
endLine: number
name: string
parent: string
start: number
startColumn: number
startLine: number
type: string
}
export default class CodeParserAntlrService { export default class CodeParserAntlrService {
plugin: CodeParser plugin: CodeParser
worker: Worker
parserStartTime: number = 0
workerTimer: NodeJS.Timer
parserTreshHold: number = 10
cache: {
[name: string]: {
text: string,
ast: antlr.ParseResult | null,
duration?: number,
parsingEnabled?: boolean,
blocks?: BlockDefinition[],
blockDurations?: number[]
}
} = {};
constructor(plugin: CodeParser) { constructor(plugin: CodeParser) {
this.plugin = plugin this.plugin = plugin
this.createWorker()
} }
/* createWorker() {
* simple parsing is used to quickly parse the current file or a text source without using the compiler or having to resolve imports this.worker = work(require.resolve('./antlr-worker'));
*/ this.worker.postMessage({
cmd: 'load',
url: document.location.protocol + '//' + document.location.host + '/assets/js/parser/antlr.js',
});
const self = this
this.worker.addEventListener('message', function (ev) {
switch (ev.data.cmd) {
case 'parsed':
if (ev.data.ast && self.parserStartTime === ev.data.timestamp) {
self.cache[ev.data.file] = {
...self.cache[ev.data.file],
text: ev.data.text,
ast: ev.data.ast,
duration: ev.data.duration,
blocks: ev.data.blocks,
blockDurations: self.cache[ev.data.file].blockDurations? [...self.cache[ev.data.file].blockDurations.slice(-3), ev.data.blockDuration]: [ev.data.blockDuration]
}
self.setFileParsingState(ev.data.file)
}
break;
}
});
}
setFileParsingState(file: string) {
if (this.cache[file]) {
if (this.cache[file].blockDurations && this.cache[file].blockDurations.length > 3) {
// calculate average of durations to determine if the parsing should be disabled
const values = [...this.cache[file].blockDurations]
const average = values.reduce((a, b) => a + b, 0) / values.length
if (average > this.parserTreshHold) {
this.cache[file].parsingEnabled = false
this.plugin.call('notification', 'toast','Some autocomplete features will be temporarily disabled because the file takes too long to process.')
} else {
this.cache[file].parsingEnabled = true
}
}
}
}
enableWorker() {
if (!this.workerTimer) {
this.workerTimer = setInterval(() => {
this.setCurrentFileAST()
}, 5000)
}
}
disableWorker() {
clearInterval(this.workerTimer)
}
async parseWithWorker(text: string, file: string) {
this.parserStartTime = Date.now()
this.worker.postMessage({
cmd: 'parse',
text,
timestamp: this.parserStartTime,
file,
parsingEnabled: (this.cache[file] && this.cache[file].parsingEnabled) || true
});
}
async parseSolidity(text: string) { async parseSolidity(text: string) {
const ast: antlr.ParseResult = (SolidityParser as any).parse(text, { loc: true, range: true, tolerant: true }) const ast: antlr.ParseResult = (SolidityParser as any).parse(text, { loc: true, range: true, tolerant: true })
@ -27,18 +121,29 @@ export default class CodeParserAntlrService {
* @param text * @param text
* @returns * @returns
*/ */
async getCurrentFileAST(text: string | null = null) { async setCurrentFileAST(text: string | null = null) {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file') try {
if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) { this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (!this.plugin.currentFile) return if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) {
const fileContent = text || await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile) const fileContent = text || await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile)
try { if (!this.cache[this.plugin.currentFile]) {
const ast = await this.parseSolidity(fileContent) this.cache[this.plugin.currentFile] = {
this.plugin.antlrParserResult = ast text: '',
} catch (e) { ast: null,
// do nothing parsingEnabled: true,
blockDurations: []
}
}
if (this.cache[this.plugin.currentFile] && this.cache[this.plugin.currentFile].text !== fileContent) {
try {
await this.parseWithWorker(fileContent, this.plugin.currentFile)
} catch (e) {
// do nothing
}
}
} }
return this.plugin.antlrParserResult } catch (e) {
// do nothing
} }
} }
@ -48,9 +153,10 @@ export default class CodeParserAntlrService {
* @returns * @returns
*/ */
async listAstNodes() { async listAstNodes() {
await this.getCurrentFileAST(); this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (!this.cache[this.plugin.currentFile]) return
const nodes: AstNode[] = []; const nodes: AstNode[] = [];
(SolidityParser as any).visit(this.plugin.antlrParserResult, { (SolidityParser as any).visit(this.cache[this.plugin.currentFile].ast, {
StateVariableDeclaration: (node: antlr.StateVariableDeclaration) => { StateVariableDeclaration: (node: antlr.StateVariableDeclaration) => {
if (node.variables) { if (node.variables) {
for (const variable of node.variables) { for (const variable of node.variables) {
@ -127,6 +233,32 @@ export default class CodeParserAntlrService {
} }
return lastNode return lastNode
} }
/*
* get the code blocks of the current file
*/
async getCurrentFileBlocks(text: string | null = null) {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (this.cache[this.plugin.currentFile]) {
if (!this.cache[this.plugin.currentFile].parsingEnabled) {
return
}
}
if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) {
const fileContent = text || await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile)
try {
const startTime = Date.now()
const blocks = (SolidityParser as any).parseBlock(fileContent, { loc: true, range: true, tolerant: true })
if(this.cache[this.plugin.currentFile] && this.cache[this.plugin.currentFile].blockDurations){
this.cache[this.plugin.currentFile].blockDurations = [...this.cache[this.plugin.currentFile].blockDurations.slice(-3), Date.now() - startTime]
this.setFileParsingState(this.plugin.currentFile)
}
if (blocks) this.cache[this.plugin.currentFile].blocks = blocks
return blocks
} catch (e) {
// do nothing
}
}
}
/** /**
* Returns the block surrounding the given position * Returns the block surrounding the given position
@ -136,23 +268,22 @@ export default class CodeParserAntlrService {
* @return {any} * @return {any}
* */ * */
async getANTLRBlockAtPosition(position: any, text: string = null) { async getANTLRBlockAtPosition(position: any, text: string = null) {
await this.getCurrentFileAST(text) const blocks: any[] = await this.getCurrentFileBlocks(text)
const allowedTypes = ['SourceUnit', 'ContractDefinition', 'FunctionDefinition']
const walkAst = (node: any) => { const walkAst = (blocks) => {
if (node.loc.start.line <= position.lineNumber && node.loc.end.line >= position.lineNumber) { let nodeFound = null
const children = node.children || node.subNodes for (const object of blocks) {
if (children && allowedTypes.indexOf(node.type) !== -1) { if (object.start <= position) {
for (const child of children) { nodeFound = object
const result = walkAst(child) break
if (result) return result
}
} }
return node
} }
return null return nodeFound
} }
if (!this.plugin.antlrParserResult) return if (!blocks) return
return walkAst(this.plugin.antlrParserResult) blocks.reverse()
const block = walkAst(blocks)
return block
} }
} }

@ -8,22 +8,23 @@ import { fileDecoration, fileDecorationType } from '@remix-ui/file-decorators'
import { sourceMappingDecoder } from '@remix-project/remix-debug' import { sourceMappingDecoder } from '@remix-project/remix-debug'
import { CompilerRetriggerMode } from '@remix-project/remix-solidity-ts'; import { CompilerRetriggerMode } from '@remix-project/remix-solidity-ts';
import { MarkerSeverity } from 'monaco-editor'; import { MarkerSeverity } from 'monaco-editor';
import { findLinesInStringWithMatch, SearchResultLine } from '@remix-ui/search'
type errorMarker = { type errorMarker = {
message: string message: string
severity: MarkerSeverity severity: MarkerSeverity
position: { position: {
start: { start: {
line: number line: number
column: number column: number
}, },
end: { end: {
line: number line: number
column: number column: number
} }
}, },
file: string file: string
} }
export default class CodeParserCompiler { export default class CodeParserCompiler {
plugin: CodeParser plugin: CodeParser
compiler: any // used to compile the current file seperately from the main compiler compiler: any // used to compile the current file seperately from the main compiler
@ -43,36 +44,47 @@ export default class CodeParserCompiler {
this.errorState = true this.errorState = true
const result = new CompilerAbstract('soljson', data, source, input) const result = new CompilerAbstract('soljson', data, source, input)
let allErrors: errorMarker[] = [] let allErrors: errorMarker[] = []
if (data.errors) { if (data.errors || data.error) {
const sources = result.getSourceCode().sources const file = await this.plugin.call('fileManager', 'getCurrentFile')
for (const error of data.errors) { const currentFileContent = await this.plugin.call('fileManager', 'readFile', file)
const sources = result.getSourceCode().sources || []
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(sources[error.sourceLocation.file].content) if (data.error) {
const lineColumn = sourceMappingDecoder.convertOffsetToLineColumn({ if (data.error.formattedMessage) {
start: error.sourceLocation.start, // mark this file as error
length: error.sourceLocation.end - error.sourceLocation.start const errorMarker = await this.createErrorMarker(data.error, file, { start: { line: 0, column: 0 }, end: { line: 0, column: 100 } })
}, lineBreaks) allErrors = [...allErrors, errorMarker]
}
const filePath = error.sourceLocation.file } else {
for (const error of data.errors) {
allErrors = [...allErrors, { if (!error.sourceLocation) {
message: error.formattedMessage, // mark this file as error
severity: error.severity === 'error' ? MarkerSeverity.Error : MarkerSeverity.Warning, const errorMarker = await this.createErrorMarker(error, file, { start: { line: 0, column: 0 }, end: { line: 0, column: 100 } })
position: { allErrors = [...allErrors, errorMarker]
start: { } else {
line: ((lineColumn.start && lineColumn.start.line) || 0) + 1, const lineBreaks = sourceMappingDecoder.getLinebreakPositions(sources[error.sourceLocation.file].content)
column: ((lineColumn.start && lineColumn.start.column) || 0) + 1 const lineColumn = sourceMappingDecoder.convertOffsetToLineColumn({
}, start: error.sourceLocation.start,
end: { length: error.sourceLocation.end - error.sourceLocation.start
line: ((lineColumn.end && lineColumn.end.line) || 0) + 1, }, lineBreaks)
column: ((lineColumn.end && lineColumn.end.column) || 0) + 1
const filePath = error.sourceLocation.file
const fileTarget = await this.plugin.call('fileManager', 'getUrlFromPath', filePath)
const importFilePositions = await this.getPositionForImportErrors(fileTarget.file, currentFileContent)
for (const importFilePosition of importFilePositions) {
for (const line of importFilePosition.lines) {
allErrors = [...allErrors, await this.createErrorMarker(error, file, line.position)]
}
} }
allErrors = [...allErrors, await this.createErrorMarker(error, filePath, lineColumn)]
} }
, file: filePath }
}]
} }
const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors') const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors')
if(displayErrors) await this.plugin.call('editor', 'addErrorMarker', allErrors) if (displayErrors) await this.plugin.call('editor', 'addErrorMarker', allErrors)
this.addDecorators(allErrors, sources) this.addDecorators(allErrors, sources)
} else { } else {
await this.plugin.call('editor', 'clearErrorMarkers', result.getSourceCode().sources) await this.plugin.call('editor', 'clearErrorMarkers', result.getSourceCode().sources)
@ -122,8 +134,8 @@ export default class CodeParserCompiler {
"language": "Solidity", "language": "Solidity",
"settings": { "settings": {
"optimizer": { "optimizer": {
"enabled": false, "enabled": state.optimize,
"runs": 200 "runs": state.runs
}, },
"outputSelection": { "outputSelection": {
"*": { "*": {
@ -131,7 +143,7 @@ export default class CodeParserCompiler {
"*": ["evm.gasEstimates"] "*": ["evm.gasEstimates"]
} }
}, },
"evmVersion": state.evmVersion && state.evmVersion.toString() || "byzantium", "evmVersion": state.evmVersion && state.evmVersion.toString() || "berlin",
} }
} }
@ -143,14 +155,14 @@ export default class CodeParserCompiler {
this.compiler.compile(sources, this.plugin.currentFile) this.compiler.compile(sources, this.plugin.currentFile)
} }
} catch (e) { } catch (e) {
// do nothing // do nothing
} }
} }
async addDecorators(allErrors: errorMarker[], sources: any) { async addDecorators(allErrors: errorMarker[], sources: any) {
const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors') const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors')
if(!displayErrors) return if (!displayErrors) return
const errorsPerFiles: {[fileName: string]: errorMarker[]} = {} const errorsPerFiles: { [fileName: string]: errorMarker[] } = {}
for (const error of allErrors) { for (const error of allErrors) {
if (!errorsPerFiles[error.file]) { if (!errorsPerFiles[error.file]) {
errorsPerFiles[error.file] = [] errorsPerFiles[error.file] = []
@ -164,7 +176,7 @@ export default class CodeParserCompiler {
} }
// sort errorPerFiles by error priority // sort errorPerFiles by error priority
const sortedErrorsPerFiles: {[fileName: string]: errorMarker[]} = {} const sortedErrorsPerFiles: { [fileName: string]: errorMarker[] } = {}
for (const fileName in errorsPerFiles) { for (const fileName in errorsPerFiles) {
const errors = errorsPerFiles[fileName] const errors = errorsPerFiles[fileName]
errors.sort((a, b) => { errors.sort((a, b) => {
@ -178,10 +190,11 @@ export default class CodeParserCompiler {
const decorators: fileDecoration[] = [] const decorators: fileDecoration[] = []
for (const fileName in sortedErrorsPerFiles) { for (const fileName in sortedErrorsPerFiles) {
const errors = sortedErrorsPerFiles[fileName] const errors = sortedErrorsPerFiles[fileName]
const fileTarget = await this.plugin.call('fileManager', 'getPathFromUrl', fileName)
const decorator: fileDecoration = { const decorator: fileDecoration = {
path: fileName, path: fileTarget.file,
isDirectory: false, isDirectory: false,
fileStateType: errors[0].severity == MarkerSeverity.Error? fileDecorationType.Error : fileDecorationType.Warning, fileStateType: errors[0].severity == MarkerSeverity.Error ? fileDecorationType.Error : fileDecorationType.Warning,
fileStateLabelClass: errors[0].severity == MarkerSeverity.Error ? 'text-danger' : 'text-warning', fileStateLabelClass: errors[0].severity == MarkerSeverity.Error ? 'text-danger' : 'text-warning',
fileStateIconClass: '', fileStateIconClass: '',
fileStateIcon: '', fileStateIcon: '',
@ -193,8 +206,9 @@ export default class CodeParserCompiler {
decorators.push(decorator) decorators.push(decorator)
} }
for (const fileName of filesWithOutErrors) { for (const fileName of filesWithOutErrors) {
const fileTarget = await this.plugin.call('fileManager', 'getPathFromUrl', fileName)
const decorator: fileDecoration = { const decorator: fileDecoration = {
path: fileName, path: fileTarget.file,
isDirectory: false, isDirectory: false,
fileStateType: fileDecorationType.None, fileStateType: fileDecorationType.None,
fileStateLabelClass: '', fileStateLabelClass: '',
@ -211,8 +225,27 @@ export default class CodeParserCompiler {
} }
async createErrorMarker(error: any, filePath: string, lineColumn): Promise<errorMarker> {
return {
message: error.formattedMessage,
severity: error.severity === 'error' ? MarkerSeverity.Error : MarkerSeverity.Warning,
position: {
start: {
line: ((lineColumn.start && lineColumn.start.line) || 0) + 1,
column: ((lineColumn.start && lineColumn.start.column) || 0) + 1
},
end: {
line: ((lineColumn.end && lineColumn.end.line) || 0) + 1,
column: ((lineColumn.end && lineColumn.end.column) || 0) + 1
}
}
, file: filePath
}
}
async clearDecorators(sources: any) { async clearDecorators(sources: any) {
const decorators: fileDecoration[] = [] const decorators: fileDecoration[] = []
if (!sources) return
for (const fileName of Object.keys(sources)) { for (const fileName of Object.keys(sources)) {
const decorator: fileDecoration = { const decorator: fileDecoration = {
path: fileName, path: fileName,
@ -232,4 +265,13 @@ export default class CodeParserCompiler {
await this.plugin.call('fileDecorator', 'setFileDecorators', decorators) await this.plugin.call('fileDecorator', 'setFileDecorators', decorators)
} }
async getPositionForImportErrors(importedFileName: string, text: string) {
const re = new RegExp(importedFileName, 'gi')
const result: SearchResultLine[] = findLinesInStringWithMatch(
text,
re
)
return result
}
} }

@ -0,0 +1,82 @@
'use strict'
import { CodeParser } from "../code-parser";
export type CodeParserImportsData= {
files?: string[],
modules?: string[],
packages?: string[],
}
export default class CodeParserImports {
plugin: CodeParser
data: CodeParserImportsData = {}
constructor(plugin: CodeParser) {
this.plugin = plugin
this.init()
}
async getImports(){
return this.data
}
async init() {
// @ts-ignore
const txt = await import('raw-loader!libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt')
this.data.modules = txt.default.split('\n')
.filter(x => x !== '')
.map(x => x.replace('./node_modules/', ''))
.filter(x => {
if(x.includes('@openzeppelin')) {
return !x.includes('mock')
}else{
return true
}
})
// get unique first words of the values in the array
this.data.packages = [...new Set(this.data.modules.map(x => x.split('/')[0]))]
}
setFileTree = async () => {
this.data.files = await this.getDirectory('/')
this.data.files = this.data.files.filter(x => x.endsWith('.sol') && !x.startsWith('.deps') && !x.startsWith('.git'))
}
getDirectory = async (dir: string) => {
let result = []
const files = await this.plugin.call('fileManager', 'readdir', dir)
const fileArray = this.normalize(files)
for (const fi of fileArray) {
if (fi) {
const type = fi.data.isDirectory
if (type === true) {
result = [...result, ...(await this.getDirectory(`${fi.filename}`))]
} else {
result = [...result, fi.filename]
}
}
}
return result
}
normalize = filesList => {
const folders = []
const files = []
Object.keys(filesList || {}).forEach(key => {
if (filesList[key].isDirectory) {
folders.push({
filename: key,
data: filesList[key]
})
} else {
files.push({
filename: key,
data: filesList[key]
})
}
})
return [...folders, ...files]
}
}

@ -46,6 +46,7 @@ export class RemixdHandle extends WebsocketPlugin {
if (this.appManager.isActive('hardhat')) this.appManager.deactivatePlugin('hardhat') if (this.appManager.isActive('hardhat')) this.appManager.deactivatePlugin('hardhat')
if (this.appManager.isActive('truffle')) this.appManager.deactivatePlugin('truffle') if (this.appManager.isActive('truffle')) this.appManager.deactivatePlugin('truffle')
if (this.appManager.isActive('slither')) this.appManager.deactivatePlugin('slither') if (this.appManager.isActive('slither')) this.appManager.deactivatePlugin('slither')
if (this.appManager.isActive('foundry')) this.appManager.deactivatePlugin('foundry')
this.localhostProvider.close((error) => { this.localhostProvider.close((error) => {
if (error) console.log(error) if (error) console.log(error)
}) })
@ -94,6 +95,7 @@ export class RemixdHandle extends WebsocketPlugin {
this.call('manager', 'activatePlugin', 'hardhat') this.call('manager', 'activatePlugin', 'hardhat')
this.call('manager', 'activatePlugin', 'truffle') this.call('manager', 'activatePlugin', 'truffle')
this.call('manager', 'activatePlugin', 'slither') this.call('manager', 'activatePlugin', 'slither')
this.call('manager', 'activatePlugin', 'foundry')
} }
} }
if (this.localhostProvider.isConnected()) { if (this.localhostProvider.isConnected()) {

@ -8,6 +8,7 @@ import { QueryParams } from '@remix-project/remix-lib'
// import { ICompilerApi } from '@remix-project/remix-lib-ts' // import { ICompilerApi } from '@remix-project/remix-lib-ts'
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
import { compilerConfigChangedToastMsg, compileToastMsg } from '@remix-ui/helper' import { compilerConfigChangedToastMsg, compileToastMsg } from '@remix-ui/helper'
import { isNative } from '../../remixAppManager'
const profile = { const profile = {
name: 'solidity', name: 'solidity',
@ -105,7 +106,7 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
} }
compile (fileName) { compile (fileName) {
this.call('notification', 'toast', compileToastMsg(this.currentRequest.from, fileName)) if (!isNative(this.currentRequest.from)) this.call('notification', 'toast', compileToastMsg(this.currentRequest.from, fileName))
super.compile(fileName) super.compile(fileName)
} }

@ -30,7 +30,7 @@ export class Web3ProviderModule extends Plugin {
// see https://github.com/ethereum/web3.js/pull/1018/files#diff-d25786686c1053b786cc2626dc6e048675050593c0ebaafbf0814e1996f22022R129 // see https://github.com/ethereum/web3.js/pull/1018/files#diff-d25786686c1053b786cc2626dc6e048675050593c0ebaafbf0814e1996f22022R129
provider[provider.sendAsync ? 'sendAsync' : 'send'](payload, async (error, message) => { provider[provider.sendAsync ? 'sendAsync' : 'send'](payload, async (error, message) => {
if (error) { if (error) {
const errorData = error.data ? error.data : error.message const errorData = error.data ? error.data : error.message ? error.message : error
// See: https://github.com/ethers-io/ethers.js/issues/901 // See: https://github.com/ethers-io/ethers.js/issues/901
if (!(typeof errorData === 'string' && errorData.includes("unknown method eth_chainId"))) this.call('terminal', 'log', error.data ? error.data : error.message) if (!(typeof errorData === 'string' && errorData.includes("unknown method eth_chainId"))) this.call('terminal', 'log', error.data ? error.data : error.message)
return reject(errorData) return reject(errorData)

@ -25,7 +25,7 @@
--gray:#555; --gray:#555;
--gray-dark:#222; --gray-dark:#222;
--primary:#2a9fd6; --primary:#2a9fd6;
--secondary:#555; --secondary:#3c3939;
--success:#77b300; --success:#77b300;
--info:#93c; --info:#93c;
--warning:#f80; --warning:#f80;
@ -5595,7 +5595,7 @@ a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:
background-color:#2180ac!important background-color:#2180ac!important
} }
.bg-secondary { .bg-secondary {
background-color:#555!important background-color:#3c3939!important
} }
a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover { a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover {
background-color:#3c3c3c!important background-color:#3c3c3c!important
@ -8358,7 +8358,7 @@ a.text-warning:focus,a.text-warning:hover {
color:#b35f00!important color:#b35f00!important
} }
.text-danger { .text-danger {
color:#c00!important color:#ff4242!important
} }
a.text-danger:focus,a.text-danger:hover { a.text-danger:focus,a.text-danger:hover {
color:maroon!important color:maroon!important
@ -8594,7 +8594,7 @@ legend {
color:#555 color:#555
} }
.nav-pills .nav-link.active,.nav-tabs .nav-link.active { .nav-pills .nav-link.active,.nav-tabs .nav-link.active {
background-color:#2a9fd6 background-color:#034767
} }
.breadcrumb a { .breadcrumb a {
color:#fff color:#fff

@ -24,7 +24,7 @@
--gray:#95a5a6; --gray:#95a5a6;
--gray-dark:#343a40; --gray-dark:#343a40;
--primary:#2c3e50; --primary:#2c3e50;
--secondary:#95a5a6; --secondary:#dadfe0;
--success:#18bc9c; --success:#18bc9c;
--info:#3498db; --info:#3498db;
--warning:#f39c12; --warning:#f39c12;
@ -4460,7 +4460,7 @@ a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:
background-color:#1a252f!important background-color:#1a252f!important
} }
.bg-secondary { .bg-secondary {
background-color:#95a5a6!important background-color:#dadfe0!important
} }
a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover { a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover {
background-color:#798d8f!important background-color:#798d8f!important

@ -25,7 +25,7 @@
--gray:#777; --gray:#777;
--gray-dark:#333; --gray-dark:#333;
--primary:#446e9b; --primary:#446e9b;
--secondary:#999; --secondary:#dadfe0;
--success:#3cb521; --success:#3cb521;
--info:#3399f3; --info:#3399f3;
--warning:#d47500; --warning:#d47500;
@ -5596,7 +5596,7 @@ a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:
background-color:#345578!important background-color:#345578!important
} }
.bg-secondary { .bg-secondary {
background-color:#999!important background-color:#dadfe0!important
} }
a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover { a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover {
background-color:gray!important background-color:gray!important

@ -3641,7 +3641,7 @@ input[type="submit"].btn-block {
.nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-item.show .nav-link,
.nav-tabs .nav-link.active { .nav-tabs .nav-link.active {
color: #fff; color: #fff;
background-color: var(--body-bg); background-color: #2a2c3f;
border-color: #3f4455; border-color: #3f4455;
} }
.nav-tabs .dropdown-menu { .nav-tabs .dropdown-menu {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save