├── .circleci └── config.yml ├── .gitignore ├── .gitmodules ├── .npmignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs ├── Makefile ├── conf.py ├── index.rst └── make.bat ├── docs_old ├── Makefile ├── analysis_tab.rst ├── compile_tab.rst ├── conf.py ├── debugger_tab.rst ├── file_explorer.rst ├── images │ ├── remix_analysistab.png │ ├── remix_compiletab.png │ ├── remix_debuggertab.png │ ├── remix_editor.png │ ├── remix_file_explorer_browser.png │ ├── remix_file_explorer_menu.png │ ├── remix_quickstart_javascriptvm_callinginstance.png │ ├── remix_quickstart_javascriptvm_creation.png │ ├── remix_quickstart_javascriptvm_creationTransaction.png │ ├── remix_recorder.png │ ├── remix_runtab.png │ ├── remix_runtab_example.png │ ├── remix_settingstab.png │ ├── remix_supporttab.png │ └── remix_terminal.png ├── index.rst ├── make.bat ├── mist1.png ├── quickstart_javascriptvm.rst ├── remix1.png ├── remix2.png ├── remix3.png ├── remix4.png ├── remix5.png ├── remix_breakpoint.png ├── remix_debuginstructions.png ├── remix_debugtransactioninfo.png ├── remix_enterdebugsession.png ├── remix_executionexception.png ├── remix_navigation.png ├── remix_soliditylocals.png ├── remix_soliditystate.png ├── remix_startdebugging.png ├── remix_stepdetail.png ├── remix_valueinput.png ├── remixd_alert.png ├── remixd_connectionok.png ├── remixd_noconnection.png ├── run_tab.rst ├── settings_tab.rst ├── solidity_editor.rst ├── support_tab.rst ├── tabs_panel.rst ├── terminal.rst ├── tuto_basicimport.png ├── tuto_importgit.png ├── tuto_importswarm.png ├── tutorial_debug.rst ├── tutorial_import.rst ├── tutorial_mist.rst └── tutorial_remixd_filesystem.rst ├── gulpfile.js ├── lerna.json ├── package-lock.json ├── package.json ├── release-process.md ├── remix-analyzer ├── .npmignore ├── README.md ├── index.ts ├── package-lock.json ├── package.json ├── src │ ├── solidity-analyzer │ │ ├── index.ts │ │ └── modules │ │ │ ├── abstractAstView.ts │ │ │ ├── algorithmCategories.ts │ │ │ ├── assignAndCompare.ts │ │ │ ├── blockBlockhash.ts │ │ │ ├── blockTimestamp.ts │ │ │ ├── categories.ts │ │ │ ├── checksEffectsInteraction.ts │ │ │ ├── constantFunctions.ts │ │ │ ├── deleteDynamicArrays.ts │ │ │ ├── deleteFromDynamicArray.ts │ │ │ ├── erc20Decimals.ts │ │ │ ├── etherTransferInLoop.ts │ │ │ ├── forLoopIteratesOverDynamicArray.ts │ │ │ ├── functionCallGraph.ts │ │ │ ├── gasCosts.ts │ │ │ ├── guardConditions.ts │ │ │ ├── index.ts │ │ │ ├── inlineAssembly.ts │ │ │ ├── intDivisionTruncate.ts │ │ │ ├── list.ts │ │ │ ├── lowLevelCalls.ts │ │ │ ├── noReturn.ts │ │ │ ├── selfdestruct.ts │ │ │ ├── similarVariableNames.ts │ │ │ ├── staticAnalysisCommon.ts │ │ │ ├── stringBytesLength.ts │ │ │ ├── thisLocal.ts │ │ │ └── txOrigin.ts │ └── types.ts ├── test │ ├── analysis │ │ ├── astBlocks │ │ │ ├── abiNamespaceCallNodes.json │ │ │ ├── assignment.json │ │ │ ├── blockHashAccess.json │ │ │ ├── blockTimestamp.json │ │ │ ├── contractDefinition.json │ │ │ ├── doWhileLoopNode.json │ │ │ ├── dynamicDeleteUnaryOp.json │ │ │ ├── externalDirect.json │ │ │ ├── forLoopNode.json │ │ │ ├── fullyQualifiedFunctionDefinition.json │ │ │ ├── funcDefForComplexParams.json │ │ │ ├── functionDefinition.json │ │ │ ├── index.js │ │ │ ├── inheritance.json │ │ │ ├── inlineAssembly.json │ │ │ ├── libCall.json │ │ │ ├── localCall.json │ │ │ ├── lowlevelCall.json │ │ │ ├── nowAst.json │ │ │ ├── parameterFunction.json │ │ │ ├── parameterFunctionCall.json │ │ │ ├── requireCall.json │ │ │ ├── selfdestruct.json │ │ │ ├── stateVariableContractNode.json │ │ │ ├── storageVariableNodes.json │ │ │ ├── superLocal.json │ │ │ ├── thisLocalCall.json │ │ │ ├── unaryOperation.json │ │ │ └── whileLoopNode.json │ │ ├── compilationDetails │ │ │ └── CompiledContractObj.json │ │ ├── staticAnalysisCommon-test.ts │ │ ├── staticAnalysisIntegration-test-0.4.24.ts │ │ ├── staticAnalysisIntegration-test-0.5.0.ts │ │ ├── staticAnalysisIssues-test-0.4.24.ts │ │ ├── staticAnalysisIssues-test-0.5.0.ts │ │ └── test-contracts │ │ │ ├── solidity-v0.4.24 │ │ │ ├── ERC20.sol │ │ │ ├── KingOfTheEtherThrone.sol │ │ │ ├── assembly.sol │ │ │ ├── ballot.sol │ │ │ ├── ballot_reentrant.sol │ │ │ ├── ballot_withoutWarnings.sol │ │ │ ├── blockLevelCompare.sol │ │ │ ├── cross_contract.sol │ │ │ ├── ctor.sol │ │ │ ├── deleteDynamicArray.sol │ │ │ ├── deleteFromDynamicArray.sol │ │ │ ├── etherTransferInLoop.sol │ │ │ ├── forLoopIteratesOverDynamicArray.sol │ │ │ ├── forgottenReturn.sol │ │ │ ├── functionParameters.sol │ │ │ ├── globals.sol │ │ │ ├── inheritance.sol │ │ │ ├── intDivisionTruncate.sol │ │ │ ├── library.sol │ │ │ ├── loops.sol │ │ │ ├── modifier1.sol │ │ │ ├── modifier2.sol │ │ │ ├── notReentrant.sol │ │ │ ├── reentrant.sol │ │ │ ├── selfdestruct.sol │ │ │ ├── stringBytesLength.sol │ │ │ ├── structReentrant.sol │ │ │ ├── thisLocal.sol │ │ │ └── transfer.sol │ │ │ └── solidity-v0.5 │ │ │ ├── ERC20.sol │ │ │ ├── KingOfTheEtherThrone.sol │ │ │ ├── assembly.sol │ │ │ ├── ballot.sol │ │ │ ├── ballot_reentrant.sol │ │ │ ├── ballot_withoutWarnings.sol │ │ │ ├── blockLevelCompare.sol │ │ │ ├── cross_contract.sol │ │ │ ├── ctor.sol │ │ │ ├── deleteDynamicArray.sol │ │ │ ├── deleteFromDynamicArray.sol │ │ │ ├── etherTransferInLoop.sol │ │ │ ├── forLoopIteratesOverDynamicArray.sol │ │ │ ├── forgottenReturn.sol │ │ │ ├── functionParameters.sol │ │ │ ├── globals.sol │ │ │ ├── inheritance.sol │ │ │ ├── intDivisionTruncate.sol │ │ │ ├── library.sol │ │ │ ├── loops.sol │ │ │ ├── modifier1.sol │ │ │ ├── modifier2.sol │ │ │ ├── notReentrant.sol │ │ │ ├── reentrant.sol │ │ │ ├── selfdestruct.sol │ │ │ ├── stringBytesLength.sol │ │ │ ├── structReentrant.sol │ │ │ ├── thisLocal.sol │ │ │ └── transfer.sol │ └── tests.ts └── tsconfig.json ├── remix-astwalker ├── .gitignore ├── .npmignore ├── README.md ├── package-lock.json ├── package.json ├── src │ ├── @types │ │ └── remix-lib │ │ │ └── index.d.ts │ ├── astWalker.ts │ ├── index.ts │ ├── sourceMappings.ts │ └── types.ts ├── tests │ ├── LegacyTest.ts │ ├── newTests.ts │ ├── resources │ │ ├── ast.ts │ │ ├── legacyAST.ts │ │ ├── newAST.ts │ │ └── test.sol │ └── sourceMappings.ts └── tsconfig.json ├── remix-debug ├── .npmignore ├── README.md ├── bin │ └── rdb ├── compilation.json ├── index.js ├── package-lock.json ├── package.json ├── src │ ├── Ethdebugger.js │ ├── cmdline │ │ ├── contextManager.js │ │ └── index.js │ ├── debugger │ │ ├── VmDebugger.js │ │ ├── debugger.js │ │ ├── solidityLocals.js │ │ ├── solidityState.js │ │ └── stepManager.js │ ├── solidity-decoder │ │ ├── astHelper.js │ │ ├── decodeInfo.js │ │ ├── index.js │ │ ├── internalCallTree.js │ │ ├── localDecoder.js │ │ ├── solidityProxy.js │ │ ├── stateDecoder.js │ │ └── types │ │ │ ├── Address.js │ │ │ ├── ArrayType.js │ │ │ ├── Bool.js │ │ │ ├── DynamicByteArray.js │ │ │ ├── Enum.js │ │ │ ├── FixedByteArray.js │ │ │ ├── Int.js │ │ │ ├── Mapping.js │ │ │ ├── RefType.js │ │ │ ├── StringType.js │ │ │ ├── Struct.js │ │ │ ├── Uint.js │ │ │ ├── ValueType.js │ │ │ └── util.js │ └── storage │ │ ├── mappingPreimages.js │ │ ├── storageResolver.js │ │ └── storageViewer.js ├── test.js └── test │ ├── debugger.js │ ├── decoder │ ├── contracts │ │ ├── byteStorage.js │ │ ├── intLocal.js │ │ ├── intStorage.js │ │ ├── mappingStorage.js │ │ ├── miscContracts.js │ │ ├── miscLocal.js │ │ ├── simpleContract.js │ │ ├── structArrayLocal.js │ │ └── structArrayStorage.js │ ├── decodeInfo.js │ ├── localDecoder.js │ ├── localsTests │ │ ├── helper.js │ │ ├── int.js │ │ ├── misc.js │ │ ├── misc2.js │ │ └── structArray.js │ ├── mockStorageResolver.js │ ├── stateTests │ │ └── mapping.js │ ├── storageDecoder.js │ ├── storageLocation.js │ └── vmCall.js │ ├── init.js │ ├── resources │ ├── testWeb3.js │ └── testWeb3.json │ ├── sol │ ├── ballot.sol │ └── simple_storage.sol │ ├── tests.js │ └── vmCall.js ├── remix-debugger ├── README.md ├── assets │ ├── css │ │ └── font-awesome.min.css │ └── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 ├── ci │ ├── browser_tests.sh │ ├── deploy_from_travis.sh │ ├── deploy_key.enc │ └── sauceDisconnect.js ├── findClient.js ├── index.html ├── index.js ├── nightwatch.js ├── package-lock.json ├── package.json ├── runNode.sh ├── src │ └── ui │ │ ├── BasicPanel.js │ │ ├── ButtonNavigator.js │ │ ├── CalldataPanel.js │ │ ├── CallstackPanel.js │ │ ├── CodeListView.js │ │ ├── DropdownPanel.js │ │ ├── Ethdebugger.js │ │ ├── FullStoragesChanges.js │ │ ├── MemoryPanel.js │ │ ├── Slider.js │ │ ├── SolidityLocals.js │ │ ├── SolidityState.js │ │ ├── SolidityTypeFormatter.js │ │ ├── StackPanel.js │ │ ├── StepDetail.js │ │ ├── StepManager.js │ │ ├── StoragePanel.js │ │ ├── TreeView.js │ │ ├── TxBrowser.js │ │ ├── VmDebugger.js │ │ └── styles │ │ ├── basicStyles.js │ │ ├── dropdownPanel.js │ │ ├── sliderStyles.js │ │ └── treeView.js └── test-browser │ ├── resources │ ├── insertTestWeb3.js │ └── testWeb3.json │ └── test │ ├── init.js │ ├── sauce.js │ └── vmdebugger.js ├── remix-lib ├── .npmignore ├── README.md ├── index.js ├── package-lock.json ├── package.json ├── src │ ├── astWalker.js │ ├── code │ │ ├── breakpointManager.js │ │ ├── codeManager.js │ │ ├── codeResolver.js │ │ ├── codeUtils.js │ │ ├── disassembler.js │ │ └── opcodes.js │ ├── eventManager.js │ ├── execution │ │ ├── eventsDecoder.js │ │ ├── execution-context.js │ │ ├── logsManager.js │ │ ├── txExecution.js │ │ ├── txFormat.js │ │ ├── txHelper.js │ │ ├── txListener.js │ │ ├── txRunner.js │ │ └── typeConversion.js │ ├── helpers │ │ ├── compilerHelper.js │ │ ├── traceHelper.js │ │ ├── txResultHelper.js │ │ └── uiHelper.js │ ├── init.js │ ├── offsetToLineColumnConverter.js │ ├── sourceLocationTracker.js │ ├── sourceMappingDecoder.js │ ├── storage.js │ ├── trace │ │ ├── traceAnalyser.js │ │ ├── traceCache.js │ │ ├── traceManager.js │ │ ├── traceRetriever.js │ │ └── traceStepManager.js │ ├── universalDapp.js │ ├── util.js │ └── web3Provider │ │ ├── dummyProvider.js │ │ ├── web3Providers.js │ │ └── web3VmProvider.js └── test │ ├── astwalker.js │ ├── codeManager.js │ ├── disassembler.js │ ├── eventManager.js │ ├── init.js │ ├── resources │ ├── ast.js │ ├── sourceMapping.js │ ├── testWeb3.js │ └── testWeb3.json │ ├── sourceMappingDecoder.js │ ├── tests.js │ ├── traceManager.js │ ├── txFormat.js │ ├── txHelper.js │ ├── txResultHelper.js │ └── util.js ├── remix-simulator ├── .npmignore ├── README.md ├── bin │ └── ethsim ├── index.js ├── package-lock.json ├── package.json ├── src │ ├── genesis.js │ ├── methods │ │ ├── accounts.js │ │ ├── blocks.js │ │ ├── filters.js │ │ ├── misc.js │ │ ├── net.js │ │ ├── transactions.js │ │ └── txProcess.js │ ├── provider.js │ ├── server.js │ └── utils │ │ └── logs.js └── test │ ├── accounts.js │ ├── blocks.js │ └── misc.js ├── remix-solidity ├── .npmignore ├── README.md ├── index.ts ├── package-lock.json ├── package.json ├── src │ └── compiler │ │ ├── compiler-input.ts │ │ ├── compiler-worker.ts │ │ ├── compiler.ts │ │ ├── txHelper.ts │ │ └── types.ts └── tsconfig.json ├── remix-tests ├── .npmignore ├── LICENSE.md ├── README.md ├── bin │ └── remix-tests ├── examples │ ├── simple_storage.sol │ ├── simple_storage2_test.sol │ └── simple_storage_test.sol ├── package-lock.json ├── package.json ├── sol │ ├── tests.sol.js │ └── tests_accounts.sol.js ├── src │ ├── compiler.ts │ ├── deployer.ts │ ├── fileSystem.ts │ ├── index.ts │ ├── logger.ts │ ├── run.ts │ ├── runTestFiles.ts │ ├── runTestSources.ts │ ├── testRunner.ts │ └── types.ts ├── tests │ ├── examples_1 │ │ ├── simple_storage.sol │ │ └── simple_storage_test.sol │ ├── examples_2 │ │ ├── simple_storage.sol │ │ └── simple_storage_test.sol │ ├── examples_3 │ │ ├── simple_string.sol │ │ └── simple_string_test.sol │ ├── examples_4 │ │ ├── SafeMath.sol │ │ ├── SafeMathProxy.sol │ │ └── SafeMath_test.sol │ ├── examples_5 │ │ ├── contract │ │ │ └── simple_storage.sol │ │ ├── lib │ │ │ └── EvenOdd.sol │ │ └── test │ │ │ └── simple_storage_test.sol │ ├── number │ │ └── number_test.sol │ ├── testRunner.ts │ └── various_sender │ │ └── sender_and_value_test.sol └── tsconfig.json ├── remix-url-resolver ├── .gitignore ├── .npmignore ├── README.md ├── package-lock.json ├── package.json ├── src │ ├── index.ts │ └── resolve.ts ├── tests │ ├── example_1 │ │ ├── greeter.sol │ │ └── mortal.sol │ └── test.ts ├── tsconfig.json └── tslint.json └── tasks.todo /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | node_modules 4 | npm-debug.log 5 | lint.xml 6 | .idea 7 | .vscode 8 | test-browser/reports/* 9 | babelify-src 10 | docs/_build 11 | .DS_Store 12 | .tern-port 13 | TODO 14 | soljson.js 15 | lerna-debug.log 16 | *~ 17 | /tmp 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "remixd"] 2 | path = remixd 3 | url = https://github.com/ethereum/remixd 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .travis.yml 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Everyone is very welcome to contribute on the codebase of Remix. Please reach us in [Gitter](https://gitter.im/ethereum/remix) in case of any queries. 4 | 5 | ## Development 6 | Remix libraries work closely with [Remix IDE](https://remix.ethereum.org). Each library has a readme to explain its application. 7 | 8 | When you add a code in any library, please ensure you add related tests. You can visit [here](https://github.com/ethereum/remix-ide#installation) to test your changes by linking the remix libraries with Remix IDE. 9 | 10 | ## Coding style 11 | 12 | Please conform to [standard](https://standardjs.com/) for code styles. 13 | 14 | ## Submitting Pull Request 15 | Please follow Github's standard model of making changes & submitting pull request which is very well explained [here](https://guides.github.com/activities/forking/). Make sure your code works fine locally before submitting a pull request. 16 | 17 | 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2018 Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Remix documentation has moved! 2 | =============================== 3 | 4 | Please go to `remix-ide.readthedocs.io `__ 5 | -------------------------------------------------------------------------------- /docs_old/analysis_tab.rst: -------------------------------------------------------------------------------- 1 | Analysis 2 | ======== 3 | 4 | This section gives information about the last compilation. 5 | By default, a new analysis is run at each compilation. 6 | 7 | The analysis tab gives detailed information about the contract code. It can help you avoid code mistakes and to enforce best practices. 8 | 9 | .. image:: images/remix_analysistab.png 10 | 11 | Here is the list of analyzers: 12 | 13 | - Security: 14 | - Transaction origin: Warns if tx.origin is used 15 | - Check effects: Avoid potential reentrancy bugs 16 | - Inline assembly: Use of Inline Assembly 17 | - Block timestamp: Semantics maybe unclear 18 | - Low level calls: Semantics maybe unclear 19 | - Block.blockhash usage: Semantics maybe unclear 20 | 21 | - Gas & Economy: 22 | - Gas costs: Warns if the gas requirements of the functions are too high 23 | - This on local calls: Invocation of local functions via this 24 | 25 | - Miscellaneous: 26 | - Constant functions: Checks for potentially constant functions 27 | - Similar variable names: Checks if variable names are too similar 28 | -------------------------------------------------------------------------------- /docs_old/compile_tab.rst: -------------------------------------------------------------------------------- 1 | Compiling contracts 2 | =================== 3 | 4 | By default Remix triggers a compilation each time the current file is changed or another file is selected. 5 | If the contract has a lot of dependencies and takes a long time to compile, it is possible to disable the `autocompilation`. 6 | 7 | .. image:: images/remix_compiletab.png 8 | 9 | After each compilation, a list is updated with all the newly compiled contracts. 10 | 11 | `Details` modal dialog displays detailed information about the current selected contract. 12 | 13 | From this tab, you can also publish your contract to Swarm (only non abstract contracts can be published). 14 | 15 | Published data notably contains the ``abi`` and solidity source code. 16 | 17 | After a contract is published, you can find its metadata information using the `bzz` URL located in the details modal dialog ``SWARM LOCATION``. 18 | 19 | Compilation Errors and Warning are displayed below the contract section. At each compilation, the static analysis tab builds a report. It is very valuable when addressing reported issues even if the compiler doesn't complain. 20 | (see :doc:`../analysis_tab`) 21 | -------------------------------------------------------------------------------- /docs_old/debugger_tab.rst: -------------------------------------------------------------------------------- 1 | Debugging 2 | ========= 3 | 4 | This module allows you to debug the transaction. 5 | It can be used to deploy transactions created from Remix and already mined transactions. 6 | (debugging works only if the current environment provides the necessary features). 7 | 8 | .. image:: images/remix_debuggertab.png 9 | 10 | For more information about debugging, click on the following link: 11 | :doc:`../tutorial_debug` 12 | -------------------------------------------------------------------------------- /docs_old/file_explorer.rst: -------------------------------------------------------------------------------- 1 | File Explorer 2 | ============= 3 | 4 | The file explorer lists by default all the files stored in your browser. You can see them in the `browser` folder. You can always rename, remove or add new files to the file explorer. 5 | 6 | .. image:: images/remix_file_explorer_browser.png 7 | 8 | Note that clearing the browser storage will permanently delete all the solidity files you wrote. To avoid this, you can use Remixd, which enables you to store and sync files in the browser with your local computer (for more information see :doc:`../tutorial_remixd_filesystem`) 9 | 10 | .. image:: images/remix_file_explorer_menu.png 11 | 12 | We will start by reviewing at the icons at the top left - from left to the right: 13 | 14 | Create new File 15 | --------------- 16 | 17 | Creates a new file in the `browser` explorer. 18 | 19 | Add Local File 20 | -------------- 21 | 22 | Allows you to select files from the local file system and import them to the Remix browser storage. 23 | 24 | Publish to Gist 25 | --------------- 26 | 27 | Publishes files from the browser storage to an anonymous public gist. 28 | 29 | Copy to another instance 30 | ------------------------ 31 | 32 | Enables you to copy files from the browser storage to another instance (URL) of Remix. 33 | 34 | Connect to Localhost 35 | -------------------- 36 | 37 | Allows to use file located in your file system (see :doc:`../tutorial_remixd_filesystem`). 38 | -------------------------------------------------------------------------------- /docs_old/images/remix_analysistab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_analysistab.png -------------------------------------------------------------------------------- /docs_old/images/remix_compiletab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_compiletab.png -------------------------------------------------------------------------------- /docs_old/images/remix_debuggertab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_debuggertab.png -------------------------------------------------------------------------------- /docs_old/images/remix_editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_editor.png -------------------------------------------------------------------------------- /docs_old/images/remix_file_explorer_browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_file_explorer_browser.png -------------------------------------------------------------------------------- /docs_old/images/remix_file_explorer_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_file_explorer_menu.png -------------------------------------------------------------------------------- /docs_old/images/remix_quickstart_javascriptvm_callinginstance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_quickstart_javascriptvm_callinginstance.png -------------------------------------------------------------------------------- /docs_old/images/remix_quickstart_javascriptvm_creation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_quickstart_javascriptvm_creation.png -------------------------------------------------------------------------------- /docs_old/images/remix_quickstart_javascriptvm_creationTransaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_quickstart_javascriptvm_creationTransaction.png -------------------------------------------------------------------------------- /docs_old/images/remix_recorder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_recorder.png -------------------------------------------------------------------------------- /docs_old/images/remix_runtab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_runtab.png -------------------------------------------------------------------------------- /docs_old/images/remix_runtab_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_runtab_example.png -------------------------------------------------------------------------------- /docs_old/images/remix_settingstab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_settingstab.png -------------------------------------------------------------------------------- /docs_old/images/remix_supporttab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_supporttab.png -------------------------------------------------------------------------------- /docs_old/images/remix_terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/images/remix_terminal.png -------------------------------------------------------------------------------- /docs_old/mist1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/mist1.png -------------------------------------------------------------------------------- /docs_old/remix1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix1.png -------------------------------------------------------------------------------- /docs_old/remix2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix2.png -------------------------------------------------------------------------------- /docs_old/remix3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix3.png -------------------------------------------------------------------------------- /docs_old/remix4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix4.png -------------------------------------------------------------------------------- /docs_old/remix5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix5.png -------------------------------------------------------------------------------- /docs_old/remix_breakpoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_breakpoint.png -------------------------------------------------------------------------------- /docs_old/remix_debuginstructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_debuginstructions.png -------------------------------------------------------------------------------- /docs_old/remix_debugtransactioninfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_debugtransactioninfo.png -------------------------------------------------------------------------------- /docs_old/remix_enterdebugsession.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_enterdebugsession.png -------------------------------------------------------------------------------- /docs_old/remix_executionexception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_executionexception.png -------------------------------------------------------------------------------- /docs_old/remix_navigation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_navigation.png -------------------------------------------------------------------------------- /docs_old/remix_soliditylocals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_soliditylocals.png -------------------------------------------------------------------------------- /docs_old/remix_soliditystate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_soliditystate.png -------------------------------------------------------------------------------- /docs_old/remix_startdebugging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_startdebugging.png -------------------------------------------------------------------------------- /docs_old/remix_stepdetail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_stepdetail.png -------------------------------------------------------------------------------- /docs_old/remix_valueinput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remix_valueinput.png -------------------------------------------------------------------------------- /docs_old/remixd_alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remixd_alert.png -------------------------------------------------------------------------------- /docs_old/remixd_connectionok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remixd_connectionok.png -------------------------------------------------------------------------------- /docs_old/remixd_noconnection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/remixd_noconnection.png -------------------------------------------------------------------------------- /docs_old/settings_tab.rst: -------------------------------------------------------------------------------- 1 | Settings 2 | ======== 3 | 4 | This section displays the current compiler version and allows one to change to another version. 5 | 6 | .. image:: images/remix_settingstab.png 7 | 8 | Settings, available here: 9 | 10 | - Text wrap: controls if the text in the editor should be wrapped. 11 | - Enable optimization: defines if the compiler should enable optimization during compilation. Enabling this option saves execution gas. 12 | It is useful to enable optimization for contracts ready to be deployed in production 13 | but could lead to some inconsistencies when debugging such a contract. 14 | -------------------------------------------------------------------------------- /docs_old/solidity_editor.rst: -------------------------------------------------------------------------------- 1 | Solidity Editor 2 | =============== 3 | 4 | The Remix editor recompiles the code each time the current file is changed or another file is selected. It also provides syntax highlighting mapped to solidity keywords. 5 | 6 | .. image:: images/remix_editor.png 7 | 8 | Here's the list of some important features: 9 | 10 | - It display opened files as tabs. 11 | - Compilation Warning and Error are displayed in the gutter 12 | - Remix saves the current file continuously (5s after the last changes) 13 | - +/- on the top left corner enable you to increase/decrease the font size of the editor 14 | -------------------------------------------------------------------------------- /docs_old/support_tab.rst: -------------------------------------------------------------------------------- 1 | Support 2 | ======= 3 | 4 | This section provides a link to Remix Issues where users can report a bug or suggest a feature, as well as providing other useful links. It also displays a `Remix developers' channel `_ 5 | 6 | .. image:: images/remix_supporttab.png 7 | -------------------------------------------------------------------------------- /docs_old/tabs_panel.rst: -------------------------------------------------------------------------------- 1 | Tabs Panel 2 | ========== 3 | 4 | - :doc:`../compile_tab` 5 | - :doc:`../run_tab` 6 | - :doc:`../settings_tab` 7 | - :doc:`../debugger_tab` 8 | - :doc:`../analysis_tab` 9 | - :doc:`../support_tab` 10 | -------------------------------------------------------------------------------- /docs_old/terminal.rst: -------------------------------------------------------------------------------- 1 | Terminal 2 | ======== 3 | 4 | .. image:: images/remix_terminal.png 5 | 6 | Features, available in the terminal: 7 | 8 | - It integrates a JavaScript interpreter and the ``web3`` object. It enables the execution of the JavaScript script which interacts with the current context. (note that ``web3`` is only available if the ``web provider`` or ``injected provider`` mode is selected). 9 | 10 | - It displays important actions made while interacting with the Remix IDE (i.e. sending a new transaction). 11 | 12 | - It displays transactions that are mined in the current context. You can choose to display all transactions or only transactions that refers to the contracts Remix knows (e.g transaction created from the Remix IDE). 13 | 14 | - It allows searching for the data and clearing the logs from the terminal. 15 | -------------------------------------------------------------------------------- /docs_old/tuto_basicimport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/tuto_basicimport.png -------------------------------------------------------------------------------- /docs_old/tuto_importgit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/tuto_importgit.png -------------------------------------------------------------------------------- /docs_old/tuto_importswarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/docs_old/tuto_importswarm.png -------------------------------------------------------------------------------- /docs_old/tutorial_import.rst: -------------------------------------------------------------------------------- 1 | Importing Source Files in Solidity 2 | ================================== 3 | 4 | .. _tutorial-import: 5 | 6 | This tutorial will show you how to import local and external files. 7 | 8 | The compilation result will also contain contracts implemented in the imported files. 9 | 10 | For a detailed explanation of the ``import`` keyword see the ``Solidity`` 11 | `documentation `_ 12 | 13 | Importing a local file 14 | ---------------------- 15 | 16 | Other files in Remix can be imported just by specifying their path. 17 | Please use `./` for relative paths to increase portability. 18 | 19 | .. image:: tuto_basicimport.png 20 | 21 | Importing from Github 22 | ---------------------- 23 | 24 | It is possible to import files directly from github with URLs like 25 | ``https://github.com///``. 26 | 27 | .. image:: tuto_importgit.png 28 | 29 | Importing from Swarm 30 | -------------------- 31 | 32 | Files can be imported using all URLs supported by swarm. If you do not have a swarm 33 | node, swarm-gateways.net will be used instead. 34 | 35 | .. image:: tuto_importswarm.png 36 | -------------------------------------------------------------------------------- /docs_old/tutorial_remixd_filesystem.rst: -------------------------------------------------------------------------------- 1 | Accessing a shared folder in Remix IDE using Remixd 2 | =================================================== 3 | 4 | .. _tutorial-remixd-filesystem: 5 | 6 | Remixd is an npm module. Its purpose is to give the remix web application access to a folder from your local computer. 7 | 8 | The code of Remixd can be checked out `here `_ . 9 | 10 | Remixd can be globally installed using the following command: ``npm install -g remixd``. 11 | 12 | Then ``remixd -s `` will start Remixd and share the given folder. 13 | 14 | The folder is shared using a websocket connection between ``Remix IDE`` and ``Remixd``. 15 | 16 | Be sure the user executing Remix has read/write permission on the folder. 17 | 18 | .. warning:: 19 | Remixd provides full read and write access to the given folder for any application that can access the TCP port 65520 on your local host. 20 | 21 | From ``Remix IDE``, you will need to activate the connection. 22 | 23 | Click on the ``localhost connection`` icon: 24 | 25 | .. image:: remixd_noconnection.png 26 | 27 | A modal dialog will ask confirmation 28 | 29 | .. image:: remixd_alert.png 30 | 31 | Accepting this dialog will start a session. Once the connection is made, the status will update and the connection icon should shows up in green. 32 | 33 | Hovering the icon will give more connection status information. 34 | 35 | At this point if the connection is successful, the shared folder will be available in the file explorer. 36 | 37 | .. image:: remixd_connectionok.png 38 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict'; 4 | const { task } = require('gulp'); 5 | const fs = require('fs'); 6 | const util = require('util'); 7 | const promisifyExec = util.promisify(require('child_process').exec); 8 | 9 | var packageJSON = require('./package.json'); 10 | 11 | /** 12 | * @dev Task to create git tag using version from package.json and pushing this specific tag 13 | */ 14 | task('publishTag', async function () { 15 | const tag = "v" + packageJSON.version 16 | await promisifyExec(`git tag ${tag}; git push origin ${tag}`); 17 | }); 18 | 19 | /** 20 | * @dev Task to update changelog for latest release 21 | */ 22 | task('updateChangelog', async function () { 23 | const previous_version = process.argv[4]; 24 | const next_version = "v" + packageJSON.version; 25 | 26 | // Create changes.md with latest release changelog temporarily 27 | await promisifyExec(`github-changes -o ethereum -r remix -a --file changes.md --only-pulls --use-commit-body --only-merges --between-tags ${previous_version} ... ${next_version}`); 28 | const latestChangelog = fs.readFileSync(__dirname + '/changes.md', 'utf8') 29 | const oldChangelog = fs.readFileSync(__dirname + '/CHANGELOG.md', 'utf8') 30 | // Concatenate latest changelog content to the top of old changelog file content 31 | const data = latestChangelog + '\n\n' + oldChangelog 32 | // Delete current changelog file CHANGELOG.md 33 | fs.unlinkSync(__dirname + '/CHANGELOG.md'); 34 | // Delete changes.md 35 | fs.unlinkSync(__dirname + '/changes.md'); 36 | // Write the concatenated content to CHANGELOG.md (We delete and create file to place the new data on top) 37 | fs.writeFileSync(__dirname + '/CHANGELOG.md', data); 38 | await Promise.resolve(); 39 | }); -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "2.10.2", 3 | "packages": [ 4 | "remix-debug", 5 | "remix-lib", 6 | "remix-solidity", 7 | "remix-analyzer", 8 | "remix-tests", 9 | "remix-simulator", 10 | "remix-url-resolver", 11 | "remix-astwalker" 12 | ], 13 | "command": { 14 | "init": { 15 | "exact": true 16 | }, 17 | "publish": { 18 | "exact": true, 19 | "skipGit": true 20 | } 21 | }, 22 | "version": "independent" 23 | } 24 | -------------------------------------------------------------------------------- /release-process.md: -------------------------------------------------------------------------------- 1 | # Release process 2 | This document details steps for publishing packages and tag the code base accordingly: 3 | 4 | 5 | 1) Publish (using lerna) all the modules that depends on one of the newly published module 6 | 7 | - checkout a new branch from master 8 | - npm run publish (that command use lerna) 9 | - commit 10 | 11 | 2) Increment the root (repository scoped) package.json 12 | 13 | - increment root package.json version 14 | - commit 15 | - merge the branch 16 | 17 | 3) Create a tag (using the package.json version) 18 | 19 | - checkout latest origin/master 20 | - npm run tag 21 | - previousVersion=[previous_version] npm run updateChangelog 22 | - create a new release out of the changes of CHANGELOG.md 23 | 24 | 4) Commit new updated CHANGELOG.md 25 | 26 | 27 | -------------------------------------------------------------------------------- /remix-analyzer/.npmignore: -------------------------------------------------------------------------------- 1 | test/ -------------------------------------------------------------------------------- /remix-analyzer/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CodeAnalysis} from './src/solidity-analyzer' 2 | -------------------------------------------------------------------------------- /remix-analyzer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "remix-analyzer", 3 | "version": "0.5.3", 4 | "description": "Tool to perform static analysis on Solidity smart contracts", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "contributors": [ 8 | { 9 | "name": "Alex Beregszaszi", 10 | "email": "alex@rtfs.hu" 11 | }, 12 | { 13 | "name": "Iuri Matias", 14 | "email": "iuri@ethereum.org" 15 | }, 16 | { 17 | "name": "Yann Levreau", 18 | "email": "yann@ethdev.com" 19 | } 20 | ], 21 | "dependencies": { 22 | "remix-astwalker": "0.0.25", 23 | "remix-lib": "0.4.30" 24 | }, 25 | "scripts": { 26 | "build": "tsc", 27 | "lint": "standard", 28 | "test": "tsc && npm run lint && ts-node node_modules/tape/bin/tape ./test/tests.ts" 29 | }, 30 | "standard": { 31 | "ignore": [ 32 | "node_modules/*", 33 | "dist/" 34 | ], 35 | "parser": "babel-eslint" 36 | }, 37 | "author": "Remix Team", 38 | "license": "MIT", 39 | "homepage": "https://github.com/ethereum/remix/tree/master/remix-analyzer#readme", 40 | "devDependencies": { 41 | "@types/node": "^13.7.0", 42 | "babel-eslint": "^7.1.1", 43 | "babel-plugin-transform-object-assign": "^6.22.0", 44 | "babel-preset-es2015": "^6.24.0", 45 | "npm-install-version": "^6.0.2", 46 | "standard": "^7.0.1", 47 | "tape": "^4.6.0", 48 | "ts-node": "^8.6.2", 49 | "typescript": "^3.7.5" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/algorithmCategories.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Should be used to categorize different modules, main reason is to give users feedback if the modules 3 | * Produce exact results or have false positives and negatives in them 4 | * A further category could be approximate if some form of approximation is used 5 | */ 6 | export default { 7 | EXACT: { hasFalsePositives: false, hasFalseNegatives: false, id: 'EXACT' }, 8 | HEURISTIC: { hasFalsePositives: true, hasFalseNegatives: true, id: 'HEURI' } 9 | } 10 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/assignAndCompare.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { isSubScopeWithTopLevelUnAssignedBinOp, getUnAssignedTopLevelBinOps } from './staticAnalysisCommon' 3 | import { default as algorithm } from './algorithmCategories' 4 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, BlockAstNode, IfStatementAstNode, 5 | WhileStatementAstNode, ForStatementAstNode, CompilationResult, ExpressionStatementAstNode, SupportedVersion} from './../../types' 6 | 7 | export default class assignAndCompare implements AnalyzerModule { 8 | warningNodes: ExpressionStatementAstNode[] = [] 9 | name: string = `Result not used: ` 10 | description: string = `The result of an operation not used` 11 | category: ModuleCategory = category.MISC 12 | algorithm: ModuleAlgorithm = algorithm.EXACT 13 | version: SupportedVersion = { 14 | start: '0.4.12' 15 | } 16 | 17 | visit (node: BlockAstNode | IfStatementAstNode | WhileStatementAstNode | ForStatementAstNode): void { 18 | if (node?.nodeType && isSubScopeWithTopLevelUnAssignedBinOp(node)) getUnAssignedTopLevelBinOps(node).forEach((n) => this.warningNodes.push(n)) 19 | } 20 | 21 | report (compilationResults: CompilationResult): ReportObj[] { 22 | return this.warningNodes.map((item, i) => { 23 | return { 24 | warning: 'A binary operation yields a value that is not used further. This is often caused by confusing assignment (=) and comparison (==).', 25 | location: item.src 26 | } 27 | }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/blockBlockhash.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { isBlockBlockHashAccess } from './staticAnalysisCommon' 3 | import { default as algorithm } from './algorithmCategories' 4 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, FunctionCallAstNode, SupportedVersion} from './../../types' 5 | 6 | export default class blockBlockhash implements AnalyzerModule { 7 | warningNodes: FunctionCallAstNode[] = [] 8 | name: string = `Block hash: ` 9 | description: string = `Can be influenced by miners` 10 | category: ModuleCategory = category.SECURITY 11 | algorithm: ModuleAlgorithm = algorithm.EXACT 12 | version: SupportedVersion = { 13 | start: '0.4.12' 14 | } 15 | 16 | visit (node: FunctionCallAstNode): void { 17 | if (node.nodeType === 'FunctionCall' && isBlockBlockHashAccess(node)) this.warningNodes.push(node) 18 | } 19 | 20 | report (compilationResults: CompilationResult): ReportObj[] { 21 | return this.warningNodes.map((item, i) => { 22 | return { 23 | warning: `Use of "blockhash": "blockhash(uint blockNumber)" is used to access the last 256 block hashes. 24 | A miner computes the block hash by "summing up" the information in the current block mined. 25 | By "summing up" the information cleverly, a miner can try to influence the outcome of a transaction in the current block. 26 | This is especially easy if there are only a small number of equally likely outcomes.`, 27 | location: item.src 28 | } 29 | }) 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/categories.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | SECURITY: {displayName: 'Security', id: 'SEC'}, 3 | GAS: {displayName: 'Gas & Economy', id: 'GAS'}, 4 | MISC: {displayName: 'Miscellaneous', id: 'MISC'}, 5 | ERC: {displayName: 'ERC', id: 'ERC'} 6 | } 7 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/deleteDynamicArrays.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { isDeleteOfDynamicArray, getCompilerVersion } from './staticAnalysisCommon' 3 | import { default as algorithm } from './algorithmCategories' 4 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, UnaryOperationAstNode, SupportedVersion} from './../../types' 5 | 6 | export default class deleteDynamicArrays implements AnalyzerModule { 7 | rel: UnaryOperationAstNode[] = [] 8 | name: string = `Delete dynamic array: ` 9 | description: string = `Use require/assert to ensure complete deletion` 10 | category: ModuleCategory = category.GAS 11 | algorithm: ModuleAlgorithm = algorithm.EXACT 12 | version: SupportedVersion = { 13 | start: '0.4.12' 14 | } 15 | 16 | visit (node: UnaryOperationAstNode): void { 17 | if (isDeleteOfDynamicArray(node)) this.rel.push(node) 18 | } 19 | 20 | report (compilationResults: CompilationResult): ReportObj[] { 21 | const version = getCompilerVersion(compilationResults.contracts) 22 | return this.rel.map((node) => { 23 | return { 24 | warning: `The "delete" operation when applied to a dynamically sized array in Solidity generates code to delete each of the elements contained. If the array is large, this operation can surpass the block gas limit and raise an OOG exception. Also nested dynamically sized objects can produce the same results.`, 25 | location: node.src, 26 | more: `https://solidity.readthedocs.io/en/${version}/types.html#delete` 27 | } 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/deleteFromDynamicArray.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { default as algorithm } from './algorithmCategories' 3 | import { isDeleteFromDynamicArray, isMappingIndexAccess } from './staticAnalysisCommon' 4 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, UnaryOperationAstNode, SupportedVersion} from './../../types' 5 | 6 | export default class deleteFromDynamicArray implements AnalyzerModule { 7 | relevantNodes: UnaryOperationAstNode[] = [] 8 | name: string = `Delete from dynamic array: ` 9 | description: string = `'delete' leaves a gap in array` 10 | category: ModuleCategory = category.MISC 11 | algorithm: ModuleAlgorithm = algorithm.EXACT 12 | version: SupportedVersion = { 13 | start: '0.4.12' 14 | } 15 | 16 | visit (node: UnaryOperationAstNode): void { 17 | if (isDeleteFromDynamicArray(node) && !isMappingIndexAccess(node.subExpression)) this.relevantNodes.push(node) 18 | } 19 | 20 | report (compilationResults: CompilationResult): ReportObj[] { 21 | return this.relevantNodes.map((node) => { 22 | return { 23 | warning: `Using "delete" on an array leaves a gap. The length of the array remains the same. If you want to remove the empty position you need to shift items manually and update the "length" property.`, 24 | location: node.src, 25 | more: 'https://github.com/miguelmota/solidity-idiosyncrasies#examples' 26 | } 27 | }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/guardConditions.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { isRequireCall, isAssertCall, getCompilerVersion } from './staticAnalysisCommon' 3 | import { default as algorithm } from './algorithmCategories' 4 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, FunctionCallAstNode, SupportedVersion} from './../../types' 5 | 6 | export default class guardConditions implements AnalyzerModule { 7 | guards: FunctionCallAstNode[] = [] 8 | name: string = `Guard conditions: ` 9 | description: string = `Ensure appropriate use of require/assert` 10 | category: ModuleCategory = category.MISC 11 | algorithm: ModuleAlgorithm = algorithm.EXACT 12 | version: SupportedVersion = { 13 | start: '0.4.12' 14 | } 15 | 16 | visit (node: FunctionCallAstNode): void { 17 | if (isRequireCall(node) || isAssertCall(node)) this.guards.push(node) 18 | } 19 | 20 | report (compilationResults: CompilationResult): ReportObj[] { 21 | const version = getCompilerVersion(compilationResults.contracts) 22 | return this.guards.map((node) => { 23 | return { 24 | warning: `Use "assert(x)" if you never ever want x to be false, not in any circumstance (apart from a bug in your code). Use "require(x)" if x can be false, due to e.g. invalid input or a failing external component.`, 25 | location: node.src, 26 | more: `https://solidity.readthedocs.io/en/${version}/control-structures.html#error-handling-assert-require-revert-and-exceptions` 27 | } 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/index.ts: -------------------------------------------------------------------------------- 1 | export { default as txOrigin } from './txOrigin' 2 | export { default as gasCosts } from './gasCosts' 3 | export { default as thisLocal } from './thisLocal' 4 | export { default as checksEffectsInteraction } from './checksEffectsInteraction' 5 | export { default as constantFunctions } from './constantFunctions' 6 | export { default as similarVariableNames } from './similarVariableNames' 7 | export { default as inlineAssembly } from './inlineAssembly' 8 | export { default as blockTimestamp } from './blockTimestamp' 9 | export { default as lowLevelCalls } from './lowLevelCalls' 10 | export { default as blockBlockhash } from './blockBlockhash' 11 | export { default as noReturn } from './noReturn' 12 | export { default as selfdestruct } from './selfdestruct' 13 | export { default as guardConditions } from './guardConditions' 14 | export { default as deleteDynamicArrays } from './deleteDynamicArrays' 15 | export { default as assignAndCompare } from './assignAndCompare' 16 | export { default as erc20Decimals } from './erc20Decimals' 17 | export { default as stringBytesLength } from './stringBytesLength' 18 | export { default as intDivisionTruncate } from './intDivisionTruncate' 19 | export { default as etherTransferInLoop } from './etherTransferInLoop' 20 | export { default as deleteFromDynamicArray } from './deleteFromDynamicArray' 21 | export { default as forLoopIteratesOverDynamicArray } from './forLoopIteratesOverDynamicArray' -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { default as algorithm } from './algorithmCategories' 3 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, InlineAssemblyAstNode, SupportedVersion} from './../../types' 4 | import { getCompilerVersion } from './staticAnalysisCommon' 5 | 6 | export default class inlineAssembly implements AnalyzerModule { 7 | inlineAssNodes: InlineAssemblyAstNode[] = [] 8 | name: string = `Inline assembly: ` 9 | description: string = `Inline assembly used` 10 | category: ModuleCategory = category.SECURITY 11 | algorithm: ModuleAlgorithm = algorithm.EXACT 12 | version: SupportedVersion = { 13 | start: '0.4.12' 14 | } 15 | 16 | visit (node: InlineAssemblyAstNode): void { 17 | if(node.nodeType === 'InlineAssembly') this.inlineAssNodes.push(node) 18 | } 19 | 20 | report (compilationResults: CompilationResult): ReportObj[] { 21 | const version = getCompilerVersion(compilationResults.contracts) 22 | return this.inlineAssNodes.map((node) => { 23 | return { 24 | warning: `The Contract uses inline assembly, this is only advised in rare cases. 25 | Additionally static analysis modules do not parse inline Assembly, this can lead to wrong analysis results.`, 26 | location: node.src, 27 | more: `https://solidity.readthedocs.io/en/${version}/assembly.html` 28 | } 29 | }) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/intDivisionTruncate.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { isIntDivision } from './staticAnalysisCommon' 3 | import { default as algorithm } from './algorithmCategories' 4 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, BinaryOperationAstNode, SupportedVersion} from './../../types' 5 | 6 | export default class intDivisionTruncate implements AnalyzerModule { 7 | warningNodes: BinaryOperationAstNode[] = [] 8 | name: string = `Data truncated: ` 9 | description: string = `Division on int/uint values truncates the result` 10 | category: ModuleCategory = category.MISC 11 | algorithm: ModuleAlgorithm = algorithm.EXACT 12 | version: SupportedVersion = { 13 | start: '0.4.12' 14 | } 15 | 16 | visit (node: BinaryOperationAstNode): void { 17 | if (isIntDivision(node)) this.warningNodes.push(node) 18 | } 19 | 20 | report (compilationResults: CompilationResult): ReportObj[] { 21 | return this.warningNodes.map((item, i) => { 22 | return { 23 | warning: 'Division of integer values yields an integer value again. That means e.g. 10 / 100 = 0 instead of 0.1 since the result is an integer again. This does not hold for division of (only) literal values since those yield rational constants.', 24 | location: item.src 25 | } 26 | }) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/list.ts: -------------------------------------------------------------------------------- 1 | import txOrigin from './txOrigin' 2 | import gasCosts from './gasCosts' 3 | import thisLocal from './thisLocal' 4 | import checksEffectsInteraction from './checksEffectsInteraction' 5 | import constantFunctions from './constantFunctions' 6 | import similarVariableNames from './similarVariableNames' 7 | import inlineAssembly from './inlineAssembly' 8 | import blockTimestamp from './blockTimestamp' 9 | import lowLevelCalls from './lowLevelCalls' 10 | import blockBlockhash from './blockBlockhash' 11 | import noReturn from './noReturn' 12 | import selfdestruct from './selfdestruct' 13 | import guardConditions from './guardConditions' 14 | import deleteDynamicArrays from './deleteDynamicArrays' 15 | import assignAndCompare from './assignAndCompare' 16 | import erc20Decimals from './erc20Decimals' 17 | import stringBytesLength from './stringBytesLength' 18 | import deleteFromDynamicArray from './deleteFromDynamicArray' 19 | import forLoopIteratesOverDynamicArray from './forLoopIteratesOverDynamicArray' 20 | import etherTransferInLoop from './etherTransferInLoop' 21 | import intDivisionTruncate from './intDivisionTruncate' 22 | 23 | export default [ 24 | txOrigin, 25 | gasCosts, 26 | thisLocal, 27 | checksEffectsInteraction, 28 | erc20Decimals, 29 | constantFunctions, 30 | similarVariableNames, 31 | inlineAssembly, 32 | blockTimestamp, 33 | lowLevelCalls, 34 | blockBlockhash, 35 | noReturn, 36 | selfdestruct, 37 | guardConditions, 38 | deleteDynamicArrays, 39 | assignAndCompare, 40 | stringBytesLength, 41 | deleteFromDynamicArray, 42 | forLoopIteratesOverDynamicArray, 43 | etherTransferInLoop, 44 | intDivisionTruncate 45 | ] 46 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/stringBytesLength.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { default as algorithm } from './algorithmCategories' 3 | import { isStringToBytesConversion, isBytesLengthCheck, getCompilerVersion } from './staticAnalysisCommon' 4 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, FunctionCallAstNode, SupportedVersion} from './../../types' 5 | 6 | export default class stringBytesLength implements AnalyzerModule { 7 | name: string = `String length: ` 8 | description: string = `Bytes length != String length` 9 | category: ModuleCategory = category.MISC 10 | algorithm: ModuleAlgorithm = algorithm.EXACT 11 | version: SupportedVersion = { 12 | start: '0.4.12' 13 | } 14 | 15 | stringToBytesConversions: FunctionCallAstNode[] = [] 16 | bytesLengthChecks: MemberAccessAstNode[] = [] 17 | 18 | visit (node: FunctionCallAstNode | MemberAccessAstNode): void { 19 | if (node.nodeType === "FunctionCall" && isStringToBytesConversion(node)) this.stringToBytesConversions.push(node) 20 | else if (node.nodeType === "MemberAccess" && isBytesLengthCheck(node)) this.bytesLengthChecks.push(node) 21 | } 22 | 23 | report (compilationResults: CompilationResult): ReportObj[] { 24 | const version = getCompilerVersion(compilationResults.contracts) 25 | if (this.stringToBytesConversions.length > 0 && this.bytesLengthChecks.length > 0) { 26 | return [{ 27 | warning: `"bytes" and "string" lengths are not the same since strings are assumed to be UTF-8 encoded (according to the ABI defintion) therefore one character is not nessesarily encoded in one byte of data.`, 28 | location: this.bytesLengthChecks[0].src, 29 | more: `https://solidity.readthedocs.io/en/${version}/abi-spec.html#argument-encoding` 30 | }] 31 | } else { 32 | return [] 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/thisLocal.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { isThisLocalCall, getCompilerVersion } from './staticAnalysisCommon' 3 | import { default as algorithm } from './algorithmCategories' 4 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, SupportedVersion} from './../../types' 5 | 6 | export default class thisLocal implements AnalyzerModule { 7 | warningNodes: MemberAccessAstNode[] = [] 8 | name: string = `This on local calls: ` 9 | description: string = `Invocation of local functions via 'this'` 10 | category: ModuleCategory = category.GAS 11 | algorithm: ModuleAlgorithm = algorithm.EXACT 12 | version: SupportedVersion = { 13 | start: '0.4.12' 14 | } 15 | 16 | visit (node: MemberAccessAstNode): void { 17 | if (node.nodeType === 'MemberAccess' && isThisLocalCall(node)) this.warningNodes.push(node) 18 | } 19 | 20 | report (compilationResults: CompilationResult): ReportObj[] { 21 | const version = getCompilerVersion(compilationResults.contracts) 22 | return this.warningNodes.map(function (item, i) { 23 | return { 24 | warning: `Use of "this" for local functions: Never use "this" to call functions in the same contract, it only consumes more gas than normal local calls.`, 25 | location: item.src, 26 | more: `https://solidity.readthedocs.io/en/${version}/control-structures.html#external-function-calls` 27 | } 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /remix-analyzer/src/solidity-analyzer/modules/txOrigin.ts: -------------------------------------------------------------------------------- 1 | import { default as category } from './categories' 2 | import { default as algorithm } from './algorithmCategories' 3 | import { isTxOriginAccess, getCompilerVersion } from './staticAnalysisCommon' 4 | import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, SupportedVersion} from './../../types' 5 | 6 | export default class txOrigin implements AnalyzerModule { 7 | txOriginNodes: MemberAccessAstNode[] = [] 8 | name: string = `Transaction origin: ` 9 | description: string = `'tx.origin' used` 10 | category: ModuleCategory = category.SECURITY 11 | algorithm: ModuleAlgorithm = algorithm.EXACT 12 | version: SupportedVersion = { 13 | start: '0.4.12' 14 | } 15 | 16 | visit (node: MemberAccessAstNode): void { 17 | if (isTxOriginAccess(node)) this.txOriginNodes.push(node) 18 | 19 | } 20 | 21 | report (compilationResults: CompilationResult): ReportObj[] { 22 | const version = getCompilerVersion(compilationResults.contracts) 23 | return this.txOriginNodes.map((item, i) => { 24 | return { 25 | warning: `Use of tx.origin: "tx.origin" is useful only in very exceptional cases. 26 | If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.`, 27 | location: item.src, 28 | more: `https://solidity.readthedocs.io/en/${version}/security-considerations.html#tx-origin` 29 | } 30 | }) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/assignment.json: -------------------------------------------------------------------------------- 1 | { 2 | "argumentTypes": null, 3 | "id": 5, 4 | "isConstant": false, 5 | "isLValue": false, 6 | "isPure": false, 7 | "lValueRequested": false, 8 | "leftHandSide": 9 | { 10 | "argumentTypes": null, 11 | "id": 3, 12 | "name": "a", 13 | "nodeType": "Identifier", 14 | "overloadedDeclarations": [], 15 | "referencedDeclaration": 22, 16 | "src": "52:1:0", 17 | "typeDescriptions": 18 | { 19 | "typeIdentifier": "t_uint256", 20 | "typeString": "uint256" 21 | } 22 | }, 23 | "nodeType": "Assignment", 24 | "operator": "=", 25 | "rightHandSide": 26 | { 27 | "argumentTypes": null, 28 | "hexValue": "31", 29 | "id": 4, 30 | "isConstant": false, 31 | "isLValue": false, 32 | "isPure": true, 33 | "kind": "number", 34 | "lValueRequested": false, 35 | "nodeType": "Literal", 36 | "src": "56:5:0", 37 | "subdenomination": "wei", 38 | "typeDescriptions": 39 | { 40 | "typeIdentifier": "t_rational_1_by_1", 41 | "typeString": "int_const 1" 42 | }, 43 | "value": "1" 44 | }, 45 | "src": "52:9:0", 46 | "typeDescriptions": 47 | { 48 | "typeIdentifier": "t_uint256", 49 | "typeString": "uint256" 50 | } 51 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/blockHashAccess.json: -------------------------------------------------------------------------------- 1 | { 2 | "argumentTypes": null, 3 | "arguments": 4 | [ 5 | { 6 | "argumentTypes": null, 7 | "hexValue": "33", 8 | "id": 6, 9 | "isConstant": false, 10 | "isLValue": false, 11 | "isPure": true, 12 | "kind": "number", 13 | "lValueRequested": false, 14 | "nodeType": "Literal", 15 | "src": "79:1:0", 16 | "subdenomination": null, 17 | "typeDescriptions": 18 | { 19 | "typeIdentifier": "t_rational_3_by_1", 20 | "typeString": "int_const 3" 21 | }, 22 | "value": "3" 23 | } 24 | ], 25 | "expression": 26 | { 27 | "argumentTypes": 28 | [ 29 | { 30 | "typeIdentifier": "t_rational_3_by_1", 31 | "typeString": "int_const 3" 32 | } 33 | ], 34 | "id": 5, 35 | "name": "blockhash", 36 | "nodeType": "Identifier", 37 | "overloadedDeclarations": [], 38 | "referencedDeclaration": -5, 39 | "src": "69:9:0", 40 | "typeDescriptions": 41 | { 42 | "typeIdentifier": "t_function_blockhash_view$_t_uint256_$returns$_t_bytes32_$", 43 | "typeString": "function (uint256) view returns (bytes32)" 44 | } 45 | }, 46 | "id": 7, 47 | "isConstant": false, 48 | "isLValue": false, 49 | "isPure": false, 50 | "kind": "functionCall", 51 | "lValueRequested": false, 52 | "names": [], 53 | "nodeType": "FunctionCall", 54 | "src": "69:12:0", 55 | "tryCall": false, 56 | "typeDescriptions": 57 | { 58 | "typeIdentifier": "t_bytes32", 59 | "typeString": "bytes32" 60 | } 61 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/blockTimestamp.json: -------------------------------------------------------------------------------- 1 | { "argumentTypes": null, 2 | "expression": 3 | { "argumentTypes": null, 4 | "id": 109, 5 | "name": "block", 6 | "nodeType": "Identifier", 7 | "overloadedDeclarations": [], 8 | "referencedDeclaration": -4, 9 | "src": "1507:5:0", 10 | "typeDescriptions": { "typeIdentifier": "t_magic_block", "typeString": "block" } }, 11 | "id": 110, 12 | "isConstant": false, 13 | "isLValue": false, 14 | "isPure": false, 15 | "lValueRequested": false, 16 | "memberName": "timestamp", 17 | "nodeType": "MemberAccess", 18 | "referencedDeclaration": null, 19 | "src": "1507:15:0", 20 | "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/dynamicDeleteUnaryOp.json: -------------------------------------------------------------------------------- 1 | { "argumentTypes": null, 2 | "id": 74, 3 | "isConstant": false, 4 | "isLValue": false, 5 | "isPure": false, 6 | "lValueRequested": false, 7 | "nodeType": "UnaryOperation", 8 | "operator": "delete", 9 | "prefix": true, 10 | "src": "627:12:0", 11 | "subExpression": 12 | { "argumentTypes": null, 13 | "id": 73, 14 | "name": "users", 15 | "nodeType": "Identifier", 16 | "overloadedDeclarations": [], 17 | "referencedDeclaration": 4, 18 | "src": "634:5:0", 19 | "typeDescriptions": { 20 | "typeIdentifier": "t_array$_t_uint256_$dyn_storage", 21 | "typeString": "uint256[] storage ref" 22 | } 23 | }, 24 | "typeDescriptions": { 25 | "typeIdentifier": "t_tuple$__$", 26 | "typeString": "tuple()" 27 | } 28 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | localCall: require('./localCall.json'), 3 | contractDefinition: require('./contractDefinition.json'), 4 | unaryOperation: require('./unaryOperation.json'), 5 | blockTimestamp: require('./blockTimestamp.json'), 6 | dynamicDeleteUnaryOp: require('./dynamicDeleteUnaryOp.json'), 7 | nowAst: require('./nowAst.json'), 8 | requireCall: require('./requireCall.json'), 9 | thisLocalCall: require('./thisLocalCall.json'), 10 | libCall: require('./libCall.json'), 11 | externalDirect: require('./externalDirect.json'), 12 | superLocal: require('./superLocal.json'), 13 | assignment: require('./assignment.json'), 14 | inlineAssembly: require('./inlineAssembly.json'), 15 | forLoopNode: require('./forLoopNode.json'), 16 | whileLoopNode: require('./whileLoopNode.json'), 17 | doWhileLoopNode: require('./doWhileLoopNode.json'), 18 | stateVariableContractNode: require('./stateVariableContractNode.json'), 19 | functionDefinition: require('./functionDefinition.json'), 20 | fullyQualifiedFunctionDefinition: require('./fullyQualifiedFunctionDefinition.json'), 21 | selfdestruct: require('./selfdestruct.json'), 22 | storageVariableNodes: require('./storageVariableNodes.json'), 23 | abiNamespaceCallNodes: require('./abiNamespaceCallNodes.json'), 24 | lowlevelCall: require('./lowlevelCall.json'), 25 | parameterFunction: require('./parameterFunction.json'), 26 | parameterFunctionCall: require('./parameterFunctionCall.json'), 27 | inheritance: require('./inheritance.json'), 28 | blockHashAccess: require('./blockHashAccess.json'), 29 | funcDefForComplexParams: require('./funcDefForComplexParams.json') 30 | } 31 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/inheritance.json: -------------------------------------------------------------------------------- 1 | { 2 | "arguments": null, 3 | "baseName": 4 | { 5 | "contractScope": null, 6 | "id": 19, 7 | "name": "A", 8 | "nodeType": "UserDefinedTypeName", 9 | "referencedDeclaration": 9, 10 | "src": "176:1:0", 11 | "typeDescriptions": 12 | { 13 | "typeIdentifier": "t_contract$_A_$9", 14 | "typeString": "contract A" 15 | } 16 | }, 17 | "id": 20, 18 | "nodeType": "InheritanceSpecifier", 19 | "src": "176:1:0" 20 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/nowAst.json: -------------------------------------------------------------------------------- 1 | { 2 | "argumentTypes": null, 3 | "id": 11, 4 | "name": "now", 5 | "nodeType": "Identifier", 6 | "overloadedDeclarations": [], 7 | "referencedDeclaration": -17, 8 | "src": "110:3:0", 9 | "typeDescriptions": 10 | { 11 | "typeIdentifier": "t_uint256", 12 | "typeString": "uint256" 13 | } 14 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/parameterFunctionCall.json: -------------------------------------------------------------------------------- 1 | { 2 | "argumentTypes": null, 3 | "arguments": 4 | [ 5 | { 6 | "argumentTypes": null, 7 | "id": 216, 8 | "name": "internalPureFunc", 9 | "nodeType": "Identifier", 10 | "overloadedDeclarations": [], 11 | "referencedDeclaration": 12, 12 | "src": "1636:16:0", 13 | "typeDescriptions": 14 | { 15 | "typeIdentifier": "t_function_internal_pure$_t_uint256_$returns$_t_uint256_$", 16 | "typeString": "function (uint256) pure returns (uint256)" 17 | } 18 | } 19 | ], 20 | "expression": 21 | { 22 | "argumentTypes": 23 | [ 24 | { 25 | "typeIdentifier": "t_function_internal_pure$_t_uint256_$returns$_t_uint256_$", 26 | "typeString": "function (uint256) pure returns (uint256)" 27 | } 28 | ], 29 | "id": 215, 30 | "name": "funcTakesInternalPure", 31 | "nodeType": "Identifier", 32 | "overloadedDeclarations": [], 33 | "referencedDeclaration": 104, 34 | "src": "1614:21:0", 35 | "typeDescriptions": 36 | { 37 | "typeIdentifier": "t_function_internal_pure$_t_function_internal_pure$_t_uint256_$returns$_t_uint256_$_$returns$_t_uint256_$", 38 | "typeString": "function (function (uint256) pure returns (uint256)) pure returns (uint256)" 39 | } 40 | }, 41 | "id": 217, 42 | "isConstant": false, 43 | "isLValue": false, 44 | "isPure": false, 45 | "kind": "functionCall", 46 | "lValueRequested": false, 47 | "names": [], 48 | "nodeType": "FunctionCall", 49 | "src": "1614:39:0", 50 | "tryCall": false, 51 | "typeDescriptions": 52 | { 53 | "typeIdentifier": "t_uint256", 54 | "typeString": "uint256" 55 | } 56 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/selfdestruct.json: -------------------------------------------------------------------------------- 1 | { 2 | "argumentTypes": null, 3 | "arguments": 4 | [ 5 | { 6 | "argumentTypes": null, 7 | "id": 6, 8 | "name": "a", 9 | "nodeType": "Identifier", 10 | "overloadedDeclarations": [], 11 | "referencedDeclaration": 2, 12 | "src": "77:1:0", 13 | "typeDescriptions": 14 | { 15 | "typeIdentifier": "t_address_payable", 16 | "typeString": "address payable" 17 | } 18 | } 19 | ], 20 | "expression": 21 | { 22 | "argumentTypes": 23 | [ 24 | { 25 | "typeIdentifier": "t_address_payable", 26 | "typeString": "address payable" 27 | } 28 | ], 29 | "id": 5, 30 | "name": "selfdestruct", 31 | "nodeType": "Identifier", 32 | "overloadedDeclarations": [], 33 | "referencedDeclaration": -21, 34 | "src": "64:12:0", 35 | "typeDescriptions": 36 | { 37 | "typeIdentifier": "t_function_selfdestruct_nonpayable$_t_address_payable_$returns$__$", 38 | "typeString": "function (address payable)" 39 | } 40 | }, 41 | "id": 7, 42 | "isConstant": false, 43 | "isLValue": false, 44 | "isPure": false, 45 | "kind": "functionCall", 46 | "lValueRequested": false, 47 | "names": [], 48 | "nodeType": "FunctionCall", 49 | "src": "64:15:0", 50 | "tryCall": false, 51 | "typeDescriptions": 52 | { 53 | "typeIdentifier": "t_tuple$__$", 54 | "typeString": "tuple()" 55 | } 56 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/superLocal.json: -------------------------------------------------------------------------------- 1 | { 2 | "argumentTypes": null, 3 | "arguments": [], 4 | "expression": 5 | { 6 | "argumentTypes": [], 7 | "expression": 8 | { 9 | "argumentTypes": null, 10 | "id": 10, 11 | "name": "super", 12 | "nodeType": "Identifier", 13 | "overloadedDeclarations": [], 14 | "referencedDeclaration": -25, 15 | "src": "162:5:0", 16 | "typeDescriptions": 17 | { 18 | "typeIdentifier": "t_super$_B_$17", 19 | "typeString": "contract super B" 20 | } 21 | }, 22 | "id": 12, 23 | "isConstant": false, 24 | "isLValue": false, 25 | "isPure": false, 26 | "lValueRequested": false, 27 | "memberName": "x", 28 | "nodeType": "MemberAccess", 29 | "referencedDeclaration": 4, 30 | "src": "162:7:0", 31 | "typeDescriptions": 32 | { 33 | "typeIdentifier": "t_function_internal_pure$__$returns$__$", 34 | "typeString": "function () pure" 35 | } 36 | }, 37 | "id": 13, 38 | "isConstant": false, 39 | "isLValue": false, 40 | "isPure": false, 41 | "kind": "functionCall", 42 | "lValueRequested": false, 43 | "names": [], 44 | "nodeType": "FunctionCall", 45 | "src": "162:9:0", 46 | "tryCall": false, 47 | "typeDescriptions": 48 | { 49 | "typeIdentifier": "t_tuple$__$", 50 | "typeString": "tuple()" 51 | } 52 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/thisLocalCall.json: -------------------------------------------------------------------------------- 1 | { 2 | "argumentTypes": null, 3 | "arguments": [], 4 | "expression": 5 | { 6 | "argumentTypes": [], 7 | "expression": 8 | { 9 | "argumentTypes": null, 10 | "id": 10, 11 | "name": "this", 12 | "nodeType": "Identifier", 13 | "overloadedDeclarations": [], 14 | "referencedDeclaration": -28, 15 | "src": "99:4:0", 16 | "typeDescriptions": 17 | { 18 | "typeIdentifier": "t_contract$_C_$26", 19 | "typeString": "contract C" 20 | } 21 | }, 22 | "id": 11, 23 | "isConstant": false, 24 | "isLValue": false, 25 | "isPure": false, 26 | "lValueRequested": false, 27 | "memberName": "f", 28 | "nodeType": "MemberAccess", 29 | "referencedDeclaration": 25, 30 | "src": "99:6:0", 31 | "typeDescriptions": 32 | { 33 | "typeIdentifier": "t_function_external_nonpayable$__$returns$_t_uint256_$_t_uint256_$", 34 | "typeString": "function () external returns (uint256,uint256)" 35 | } 36 | }, 37 | "id": 12, 38 | "isConstant": false, 39 | "isLValue": false, 40 | "isPure": false, 41 | "kind": "functionCall", 42 | "lValueRequested": false, 43 | "names": [], 44 | "nodeType": "FunctionCall", 45 | "src": "99:8:0", 46 | "tryCall": true, 47 | "typeDescriptions": 48 | { 49 | "typeIdentifier": "t_tuple$_t_uint256_$_t_uint256_$", 50 | "typeString": "tuple(uint256,uint256)" 51 | } 52 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/astBlocks/unaryOperation.json: -------------------------------------------------------------------------------- 1 | { 2 | "argumentTypes": null, 3 | "id": 13, 4 | "isConstant": false, 5 | "isLValue": false, 6 | "isPure": false, 7 | "lValueRequested": false, 8 | "nodeType": "UnaryOperation", 9 | "operator": "++", 10 | "prefix": false, 11 | "src": "95:3:0", 12 | "subExpression": 13 | { 14 | "argumentTypes": null, 15 | "id": 12, 16 | "name": "x", 17 | "nodeType": "Identifier", 18 | "overloadedDeclarations": [], 19 | "referencedDeclaration": 4, 20 | "src": "95:1:0", 21 | "typeDescriptions": 22 | { 23 | "typeIdentifier": "t_uint256", 24 | "typeString": "uint256" 25 | } 26 | }, 27 | "typeDescriptions": 28 | { 29 | "typeIdentifier": "t_uint256", 30 | "typeString": "uint256" 31 | } 32 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/staticAnalysisIssues-test-0.4.24.ts: -------------------------------------------------------------------------------- 1 | import { default as test} from "tape" 2 | import { helpers } from 'remix-lib' 3 | import { readFileSync } from 'fs' 4 | import { join } from 'path' 5 | import { default as StatRunner } from '../../dist/src/solidity-analyzer' 6 | import { CompilationResult, AnalysisReportObj, AnalysisReport, AnalyzerModule } from '../../src/types' 7 | import { checksEffectsInteraction } from '../../src/solidity-analyzer/modules/' 8 | import { install, require as requireNPMmodule } from 'npm-install-version' 9 | install('solc@0.4.24') 10 | const compiler = requireNPMmodule('solc@0.4.24') 11 | const { compilerInput } = helpers.compiler 12 | const folder: string = 'solidity-v0.4.24' 13 | 14 | function compile (fileName: string): CompilationResult { 15 | const content: string = readFileSync(join(__dirname, 'test-contracts/' + folder, fileName), 'utf8') 16 | return JSON.parse(compiler.compileStandardWrapper(compilerInput(content))) 17 | } 18 | 19 | test('staticAnalysisIssues.functionParameterPassingError', function (t) { 20 | // https://github.com/ethereum/remix-ide/issues/889#issuecomment-351746474 21 | t.plan(2) 22 | const res: CompilationResult = compile('functionParameters.sol') 23 | const Module: any = checksEffectsInteraction 24 | const statRunner: StatRunner = new StatRunner() 25 | 26 | t.doesNotThrow(() => { 27 | statRunner.runWithModuleList(res, [{ name: new Module().name, mod: new Module() }], (reports: AnalysisReport[]) => {}) 28 | }, 'Analysis should not throw') 29 | 30 | statRunner.runWithModuleList(res, [{ name: new Module().name, mod: new Module() }], (reports: AnalysisReport[]) => { 31 | t.ok(!reports.some((mod: AnalysisReport) => mod.report.some((rep: AnalysisReportObj) => rep.warning.includes('INTERNAL ERROR')), 'Should not have internal errors')) 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/staticAnalysisIssues-test-0.5.0.ts: -------------------------------------------------------------------------------- 1 | import { default as test} from "tape" 2 | import { helpers } from 'remix-lib' 3 | import { readFileSync } from 'fs' 4 | import { join } from 'path' 5 | import { default as StatRunner } from '../../dist/src/solidity-analyzer' 6 | import { CompilationResult, AnalysisReportObj, AnalysisReport } from '../../src/types' 7 | import { checksEffectsInteraction } from '../../src/solidity-analyzer/modules/' 8 | import { install, require as requireNPMmodule } from 'npm-install-version' 9 | install('solc@0.5.0') 10 | const compiler = requireNPMmodule('solc@0.5.0') 11 | const {compilerInput } = helpers.compiler 12 | const folder: string = 'solidity-v0.5' 13 | 14 | function compile (fileName): CompilationResult { 15 | const content: string = readFileSync(join(__dirname, 'test-contracts/' + folder, fileName), 'utf8') 16 | return JSON.parse(compiler.compile(compilerInput(content))) 17 | } 18 | 19 | test('staticAnalysisIssues.functionParameterPassingError', function (t) { 20 | // https://github.com/ethereum/remix-ide/issues/889#issuecomment-351746474 21 | t.plan(2) 22 | const res: CompilationResult = compile('functionParameters.sol') 23 | const Module: any = checksEffectsInteraction 24 | const statRunner: StatRunner = new StatRunner() 25 | 26 | t.doesNotThrow(() => { 27 | statRunner.runWithModuleList(res, [{ name: new Module().name, mod: new Module() }], (reports: AnalysisReport[]) => {}) 28 | }, 'Analysis should not throw') 29 | 30 | statRunner.runWithModuleList(res, [{ name: new Module().name, mod: new Module() }], (reports: AnalysisReport[]) => { 31 | t.ok(!reports.some((mod: AnalysisReport) => mod.report.some((rep: AnalysisReportObj) => rep.warning.includes('INTERNAL ERROR')), 'Should not have internal errors')) 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/ERC20.sol: -------------------------------------------------------------------------------- 1 | 2 | pragma solidity ^0.4.17; 3 | contract EIP20 { 4 | 5 | uint public decimals = 12; 6 | 7 | // optional 8 | function name() public pure returns (string) { 9 | return "MYTOKEN"; 10 | } 11 | 12 | // optional 13 | function symbol() public pure returns (string) { 14 | return "MT"; 15 | } 16 | 17 | // optional 18 | //function decimals() internal pure returns (uint8) { 19 | // return 12; 20 | //} 21 | 22 | function totalSupply() public pure returns (uint256) { 23 | return 12000; 24 | } 25 | 26 | function balanceOf(address _owner) public pure returns (uint256) { 27 | return 0; 28 | } 29 | 30 | function transfer(address _to, uint256 _value) public pure returns (bool success) { 31 | return true; 32 | } 33 | 34 | function transferFrom(address _from, address _to, uint256 _value) public pure returns (bool) { 35 | return true; 36 | } 37 | 38 | function approve(address _spender, uint256 _value) public pure returns (bool) { 39 | return true; 40 | } 41 | 42 | function allowance(address _owner, address _spender) public pure returns (uint256) { 43 | return 0; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/KingOfTheEtherThrone.sol: -------------------------------------------------------------------------------- 1 | // return value send 2 | contract KingOfTheEtherThrone{ 3 | struct Monarch { 4 | // address of the king . 5 | address ethAddr ; 6 | string name ; 7 | // how much he pays to previous king 8 | uint claimPrice ; 9 | uint coronationTimestamp; 10 | } 11 | Monarch public currentMonarch ; 12 | 13 | function claimThrone ( string name ) { 14 | address wizardAddress; 15 | uint compensation = 100; 16 | uint valuePaid = 10; 17 | 18 | if ( currentMonarch.ethAddr != wizardAddress ) 19 | if (currentMonarch.ethAddr.send( compensation )) throw; 20 | 21 | currentMonarch = Monarch(msg.sender,name,valuePaid,block.timestamp); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/assembly.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.9; 2 | contract test { 3 | 4 | address owner; 5 | 6 | function at(address _addr) returns (bytes o_code) { 7 | assert(_addr != 0x0); 8 | assembly { 9 | // retrieve the size of the code, this needs assembly 10 | let size := extcodesize(_addr) 11 | // allocate output byte array - this could also be done without assembly 12 | // by using o_code = new bytes(size) 13 | o_code := mload(0x40) 14 | // new "memory end" including padding 15 | mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) 16 | // store length in memory 17 | mstore(o_code, size) 18 | // actually retrieve the code, this needs assembly 19 | extcodecopy(_addr, add(o_code, 0x20), 0, size) 20 | } 21 | } 22 | 23 | function bla() { 24 | require(tx.origin == owner); 25 | msg.sender.send(19); 26 | assembly { 27 | 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/ballot_withoutWarnings.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | /// @title Voting with delegation. 4 | contract Ballot { 5 | 6 | struct Proposal 7 | { 8 | bytes32 name; // short name (up to 32 bytes) 9 | uint voteCount; // number of accumulated votes 10 | } 11 | 12 | // A dynamically-sized array of `Proposal` structs. 13 | Proposal[] public proposals; 14 | 15 | /// @dev Computes the winning proposal taking all 16 | /// previous votes into account. 17 | function winningProposal() constant 18 | returns (uint winningProposal) 19 | { 20 | winningProposal = 0; 21 | } 22 | 23 | // Calls winningProposal() function to get the index 24 | // of the winner contained in the proposals array and then 25 | // returns the name of the winner 26 | function winnerName() constant 27 | returns (bytes32 winnerName) 28 | { 29 | winnerName = proposals[winningProposal()].name; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/blockLevelCompare.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.22; 2 | contract grr { 3 | bool breaker; 4 | 5 | function() public { 6 | uint a = 1; 7 | string memory sig = "withdraw()"; 8 | uint b = 3; 9 | 10 | bytes4 selector = bytes4(keccak256(sig)); 11 | 12 | abi.encode(a,b); 13 | 14 | abi.encodePacked(a,b); 15 | 16 | a = -b; 17 | 18 | a == b; 19 | 20 | if(a == b) { 21 | abi.encodeWithSelector(selector, a, b); 22 | abi.encodeWithSignature(sig, a, b); 23 | } 24 | 25 | if(b < 4) { a == b; } 26 | 27 | if(b > 4) b == a; 28 | 29 | while(true) a == b; 30 | 31 | for(int i = 0; i < 3; i++) b == a; 32 | 33 | while(false) { 34 | int c = 3; 35 | uint(c) + a; 36 | 37 | c == 5; 38 | 39 | } 40 | 41 | a + b; 42 | breaker = false; 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/cross_contract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | contract a { 4 | 5 | uint x; 6 | 7 | function foo() { 8 | x++; 9 | } 10 | } 11 | 12 | contract b { 13 | a x; 14 | function bar() constant { 15 | address a; 16 | a.send(100 wei); 17 | x.foo(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/ctor.sol: -------------------------------------------------------------------------------- 1 | contract c { 2 | uint x; 3 | uint x_abc; 4 | function c(uint _x, uint _abc) { 5 | x=_x; 6 | x_abc=_abc; 7 | } 8 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/deleteDynamicArray.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.22; 2 | contract arr { 3 | uint[] users; 4 | 5 | bytes access_rights_per_user; 6 | 7 | uint user_index; 8 | 9 | address owner; 10 | 11 | string grr = "message"; 12 | 13 | uint[100] last_100_users; 14 | 15 | constructor(address owner1) public { 16 | owner = owner1; 17 | user_index = 0; 18 | } 19 | 20 | function addUser(uint id, byte rights) public{ 21 | users[user_index] = id; 22 | last_100_users[user_index % 100] = id; 23 | access_rights_per_user[user_index] = rights; 24 | user_index++; 25 | } 26 | 27 | function resetState() public{ 28 | require(msg.sender == owner, grr); 29 | delete users; 30 | delete access_rights_per_user; 31 | delete last_100_users; 32 | } 33 | 34 | function bla(string bal) public { 35 | grr = bal; 36 | } 37 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/deleteFromDynamicArray.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.22; 2 | contract arr { 3 | uint[] array = [1,2,3]; 4 | function removeAtIndex() public returns (uint[]) { 5 | delete array[1]; 6 | return array; 7 | } 8 | 9 | // TODO: deleteFromDynamicArray should not generate warnings if array item is shifted and removed 10 | /* function safeRemoveAtIndex(uint index) returns (uint[]) { 11 | if (index >= array.length) return; 12 | 13 | for (uint i = index; i < array.length-1; i++) { 14 | array[i] = array[i+1]; 15 | } 16 | 17 | delete array[array.length-1]; 18 | array.length--; 19 | 20 | return array; 21 | } */ 22 | } 23 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/etherTransferInLoop.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | contract etherTransferInLoop { 4 | address owner; 5 | 6 | constructor() public { 7 | owner = msg.sender; 8 | } 9 | 10 | function transferInForLoop(uint index) public { 11 | for (uint i = index; i < 10; i++) { 12 | owner.transfer(i); 13 | } 14 | } 15 | 16 | function transferInWhileLoop(uint index) public { 17 | uint i = index; 18 | while (i < 10) { 19 | owner.transfer(i); 20 | i++; 21 | } 22 | } 23 | 24 | function transferInDoWhileLoop(uint index) public { 25 | uint i = index; 26 | do { 27 | owner.transfer(i); 28 | i++; 29 | } while (i < 10); 30 | } 31 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/forLoopIteratesOverDynamicArray.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.22; 2 | contract forLoopArr { 3 | uint[] array; 4 | constructor(uint[] _array) { 5 | array = _array; 6 | } 7 | 8 | function shiftArrItem(uint index) returns(uint[]) { 9 | for (uint i = index; i < array.length; i++) { 10 | array[i] = array[i+1]; 11 | } 12 | return array; 13 | } 14 | 15 | function shiftArrItem2(uint index) returns(uint[]) { 16 | for (uint i = index; i < array.length - 1; i++) { 17 | array[i] = array[i+1]; 18 | } 19 | return array; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/forgottenReturn.sol: -------------------------------------------------------------------------------- 1 | contract Sheep { 2 | string public name; 3 | string public dna; 4 | bool g = true; 5 | function Sheep(string _name, string _dna) { 6 | name = _name; 7 | dna = _dna; 8 | } 9 | 10 | function geneticallyEngineer(string _dna) returns (bool) { 11 | dna = _dna; 12 | } 13 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/functionParameters.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | contract B { 4 | function plus(uint a, uint b) pure internal returns (uint) { 5 | return a + b; 6 | } 7 | 8 | function eval(function (uint, uint) pure internal returns (uint) f, uint x, uint y) pure internal returns (uint) { 9 | return f(x, y); 10 | } 11 | 12 | function calc(uint x, uint y) pure public returns (uint) { 13 | return eval(plus, x, y); 14 | // return plus(x, y); 15 | } 16 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/globals.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.9; 2 | contract bla { 3 | uint brr; 4 | function duper() { 5 | brr++; 6 | } 7 | } 8 | 9 | contract a is bla { 10 | 11 | function blub() { 12 | brr++; 13 | } 14 | 15 | function r () { 16 | address a; 17 | bytes32 hash; 18 | uint8 v; 19 | bytes32 r; 20 | bytes32 s; 21 | 22 | block.blockhash(1); 23 | block.coinbase; 24 | block.difficulty; 25 | block.gaslimit; 26 | block.number; 27 | block.timestamp; 28 | msg.data; 29 | msg.gas; 30 | msg.sender; 31 | msg.value; 32 | now; 33 | tx.gasprice; 34 | tx.origin; 35 | // assert(1 == 2); 36 | // require(1 == 1); 37 | keccak256(a); 38 | sha3(a); 39 | sha256(a); 40 | ripemd160(a); 41 | ecrecover(hash, v, r, s); 42 | addmod(1, 2, 2); 43 | mulmod(4,4,12); 44 | 45 | a.balance; 46 | blub(); 47 | a.send(a.balance); 48 | 49 | 50 | 51 | super.duper(); 52 | //a.transfer(a.balance); 53 | selfdestruct(a); 54 | //revert(); 55 | assert(a.balance == 0); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/inheritance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.9; 2 | 3 | contract r { 4 | function s() constant {} 5 | } 6 | 7 | contract a is r { 8 | uint x = 1; 9 | 10 | function getX() constant returns (uint) { 11 | return x; 12 | } 13 | } 14 | 15 | contract b is a { 16 | uint y = 2; 17 | uint x = 3; 18 | 19 | 20 | function getY(uint z, bool r) returns (uint) { 21 | return y++; 22 | } 23 | 24 | function getY(string storage n) internal constant returns (uint) { return 10; } 25 | 26 | } 27 | 28 | contract c is b { 29 | string x; 30 | 31 | function d() returns (uint a, uint b) { 32 | //d(); 33 | //sha3("bla"); 34 | msg.sender.call.gas(200000).value(this.balance)(bytes4(sha3("pay()"))); 35 | //x++; 36 | getY(x); 37 | a = getX() + getY(1, false); 38 | b = getX() + getY(x); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/intDivisionTruncate.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.19; 2 | 3 | contract CharityCampaign { 4 | mapping (address => uint) contributions; 5 | int128 feePercentage; 6 | uint p2; 7 | address processor; 8 | address beneficiary; 9 | 10 | function CharityCampaign(address _beneficiary, int128 _feePercentage) public { 11 | processor = msg.sender; 12 | beneficiary = _beneficiary; 13 | feePercentage = _feePercentage; 14 | } 15 | 16 | function contribute() payable public returns (uint feeCollected) { 17 | uint fee = msg.value * uint256(feePercentage / 100); 18 | fee = msg.value * (p2 / 100); 19 | contributions[msg.sender] = msg.value - fee; 20 | processor.transfer(fee); 21 | return fee; 22 | } 23 | 24 | function endCampaign() public returns (bool) { 25 | require(msg.sender == processor || msg.sender == beneficiary); 26 | selfdestruct(beneficiary); 27 | return true; 28 | } 29 | 30 | // FALSE POSITIVE FOR SELFDESTRUCT TERMINAL 31 | function endAmbiguous() public { 32 | if(msg.sender == 0x0) { 33 | selfdestruct(beneficiary); 34 | } else { 35 | selfdestruct(processor); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/library.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | library Set { 4 | // We define a new struct datatype that will be used to 5 | // hold its data in the calling contract. 6 | struct Data { mapping(uint => bool) flags; } 7 | 8 | // Note that the first parameter is of type "storage 9 | // reference" and thus only its storage address and not 10 | // its contents is passed as part of the call. This is a 11 | // special feature of library functions. It is idiomatic 12 | // to call the first parameter 'self', if the function can 13 | // be seen as a method of that object. 14 | function insert(Data storage self, uint value) 15 | returns (bool) 16 | { 17 | if (self.flags[value]) 18 | return false; // already there 19 | self.flags[value] = true; 20 | 21 | return true; 22 | } 23 | 24 | function remove(Data storage self, uint value) 25 | returns (bool) 26 | { 27 | if (!self.flags[value]) 28 | return false; // not there 29 | self.flags[value] = false; 30 | return true; 31 | } 32 | 33 | function contains(Data storage self, uint value) 34 | returns (bool) 35 | { 36 | return self.flags[value]; 37 | } 38 | } 39 | 40 | 41 | contract C { 42 | Set.Data knownValues; 43 | 44 | function register(uint value) { 45 | // The library functions can be called without a 46 | // specific instance of the library, since the 47 | // "instance" will be the current contract. 48 | address a; 49 | a.send(10 wei); 50 | if (!Set.insert(knownValues, value)) 51 | throw; 52 | } 53 | // In this contract, we can also directly access knownValues.flags, if we want. 54 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/loops.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.9; 2 | 3 | contract loops { 4 | uint[] array; 5 | constructor(uint[] memory _array) public { 6 | array = _array; 7 | } 8 | 9 | function fnWithForLoop(uint index) public { 10 | for (uint i = index; i < 10; i++) { 11 | array.push(i); 12 | } 13 | } 14 | 15 | function fnWithWhileLoop(uint index) public { 16 | uint i = index; 17 | while (i < 10) { 18 | array.push(i); 19 | i++; 20 | } 21 | } 22 | 23 | function fnWithDoWhileLoop(uint index) public { 24 | uint i = index; 25 | do{ 26 | array.push(i); 27 | i++; 28 | }while (i < 10); 29 | } 30 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/modifier1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | contract test { 4 | 5 | address owner; 6 | 7 | modifier onlyOwner { 8 | var a = 0; 9 | if (msg.sender != owner) 10 | throw; 11 | _; 12 | } 13 | 14 | function b(address a) onlyOwner returns (bool) { 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/modifier2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | contract owned { 4 | 5 | uint r=0; 6 | 7 | modifier ntimes(uint n) { 8 | for(uint i=0;i uint) shares; 6 | /// Withdraw your share. 7 | function withdraw() { 8 | var share = shares[msg.sender]; 9 | shares[msg.sender] = 0; 10 | if (!msg.sender.send(share)) 11 | throw; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/reentrant.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | contract InfoFeed { 4 | uint c; 5 | function info() constant returns (uint ret) {return c;} 6 | function call1(uint a) constant returns (bool) {return true;} 7 | } 8 | 9 | // THIS CONTRACT CONTAINS A BUG - DO NOT USE 10 | contract Fund { 11 | /// Mapping of ether shares of the contract. 12 | //mapping(address => uint) shares; 13 | /// Withdraw your share. 14 | 15 | uint c = 0; 16 | function withdraw() constant { 17 | InfoFeed f; 18 | 19 | 20 | //shares[msg.sender] /= 1; 21 | 22 | f.info(); 23 | 24 | //if (msg.sender.send(shares[msg.sender])) throw; 25 | // shares[msg.sender] = 0; 26 | 27 | 28 | b(true, false); 29 | //shares[msg.sender]++; 30 | //c++; 31 | 32 | } 33 | mapping(address => uint) shares; 34 | 35 | function b(bool a, bool b) returns (bool) { 36 | mapping(address => uint) c = shares; 37 | c[msg.sender] = 0; 38 | //f(); 39 | //withdraw(); 40 | //shares[msg.sender]++; 41 | //c++; 42 | return true; 43 | } 44 | 45 | function f() { 46 | c++; 47 | withdraw(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/selfdestruct.sol: -------------------------------------------------------------------------------- 1 | contract sd { 2 | 3 | uint x = 0; 4 | function() public payable { } 5 | 6 | function c () public constant { 7 | selfdestruct(address(0xdeadbeef)); 8 | } 9 | 10 | function b () public payable { 11 | selfdestruct(address(0xdeadbeef)); 12 | x = 1; 13 | } 14 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/stringBytesLength.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | contract bytesString { 3 | 4 | function length(string a) public pure returns(uint) { 5 | bytes memory x = bytes(a); 6 | 7 | return x.length; 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/structReentrant.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.9; 2 | 3 | contract Ballot { 4 | 5 | struct Voter { 6 | uint weight; 7 | bool voted; 8 | uint8 vote; 9 | address delegate; 10 | baz foo; 11 | } 12 | 13 | struct baz{ 14 | uint bar; 15 | } 16 | 17 | mapping(address => Voter) voters; 18 | 19 | /// Create a new ballot with $(_numProposals) different proposals. 20 | function bla(address a) { 21 | Voter x = voters[a]; 22 | 23 | if (!a.send(10)) 24 | throw; 25 | 26 | //voters[a] = Voter(10,true,1,a); 27 | //x.foo.bar *= 100; 28 | bli(x); 29 | } 30 | 31 | //function bla(){} 32 | 33 | function bli(Voter storage x) private { 34 | x.foo.bar++; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/thisLocal.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | contract test { 4 | 5 | function (){ 6 | address x; 7 | this.b(x); 8 | x.call('something'); 9 | x.send(1 wei); 10 | 11 | } 12 | 13 | function b(address a) returns (bool) { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.4.24/transfer.sol: -------------------------------------------------------------------------------- 1 | contract c { 2 | uint x; 3 | function f(address r) { 4 | r.transfer(1); 5 | x = 2; 6 | } 7 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/ERC20.sol: -------------------------------------------------------------------------------- 1 | 2 | pragma solidity >=0.4.9 <0.6.0; 3 | contract EIP20 { 4 | 5 | uint public decimals = 12; 6 | 7 | // optional 8 | function name() public pure returns (string memory) { 9 | return "MYTOKEN"; 10 | } 11 | 12 | // optional 13 | function symbol() public pure returns (string memory) { 14 | return "MT"; 15 | } 16 | 17 | // optional 18 | //function decimals() internal pure returns (uint8) { 19 | // return 12; 20 | //} 21 | 22 | function totalSupply() public pure returns (uint256) { 23 | return 12000; 24 | } 25 | 26 | function balanceOf(address _owner) public pure returns (uint256) { 27 | return 0; 28 | } 29 | 30 | function transfer(address _to, uint256 _value) public pure returns (bool success) { 31 | return true; 32 | } 33 | 34 | function transferFrom(address _from, address _to, uint256 _value) public pure returns (bool) { 35 | return true; 36 | } 37 | 38 | function approve(address _spender, uint256 _value) public pure returns (bool) { 39 | return true; 40 | } 41 | 42 | function allowance(address _owner, address _spender) public pure returns (uint256) { 43 | return 0; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/KingOfTheEtherThrone.sol: -------------------------------------------------------------------------------- 1 | // return value send 2 | contract KingOfTheEtherThrone{ 3 | struct Monarch { 4 | // address of the king . 5 | address payable ethAddr ; 6 | string name ; 7 | // how much he pays to previous king 8 | uint claimPrice ; 9 | uint coronationTimestamp; 10 | } 11 | Monarch public currentMonarch ; 12 | 13 | function claimThrone ( string memory name ) public { 14 | address wizardAddress; 15 | uint compensation = 100; 16 | uint valuePaid = 10; 17 | 18 | if ( currentMonarch.ethAddr != wizardAddress ) 19 | if (currentMonarch.ethAddr.send( compensation )) revert(); 20 | 21 | currentMonarch = Monarch(msg.sender,name,valuePaid,block.timestamp); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/assembly.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | contract test { 3 | 4 | address owner; 5 | 6 | function at(address _addr) public returns (bytes memory o_code) { 7 | assert(_addr != address(0x0)); 8 | assembly { 9 | // retrieve the size of the code, this needs assembly 10 | let size := extcodesize(_addr) 11 | // allocate output byte array - this could also be done without assembly 12 | // by using o_code = new bytes(size) 13 | o_code := mload(0x40) 14 | // new "memory end" including padding 15 | mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) 16 | // store length in memory 17 | mstore(o_code, size) 18 | // actually retrieve the code, this needs assembly 19 | extcodecopy(_addr, add(o_code, 0x20), 0, size) 20 | } 21 | } 22 | 23 | function bla() public { 24 | require(tx.origin == owner); 25 | msg.sender.send(19); 26 | assembly { 27 | 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/ballot_withoutWarnings.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | /// @title Voting with delegation. 4 | contract Ballot { 5 | 6 | struct Proposal 7 | { 8 | bytes32 name; // short name (up to 32 bytes) 9 | uint voteCount; // number of accumulated votes 10 | } 11 | 12 | // A dynamically-sized array of `Proposal` structs. 13 | Proposal[] public proposals; 14 | 15 | /// @dev Computes the winning proposal taking all 16 | /// previous votes into account. 17 | function winningProposal() public view 18 | returns (uint winningProposal) 19 | { 20 | winningProposal = 0; 21 | } 22 | 23 | // Calls winningProposal() function to get the index 24 | // of the winner contained in the proposals array and then 25 | // returns the name of the winner 26 | function winnerName() public view 27 | returns (bytes32 winnerName) 28 | { 29 | winnerName = proposals[winningProposal()].name; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/blockLevelCompare.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | contract grr { 3 | bool breaker; 4 | 5 | function() external { 6 | uint a = 1; 7 | string memory sig = "withdraw()"; 8 | uint b = 3; 9 | 10 | bytes4 selector = bytes4(keccak256(abi.encodePacked(sig))); 11 | 12 | abi.encode(a,b); 13 | 14 | abi.encodePacked(a,b); 15 | 16 | a = -b; 17 | 18 | a == b; 19 | 20 | if(a == b) { 21 | abi.encodeWithSelector(selector, a, b); 22 | abi.encodeWithSignature(sig, a, b); 23 | } 24 | 25 | if(b < 4) { a == b; } 26 | 27 | if(b > 4) b == a; 28 | 29 | while(true) a == b; 30 | 31 | for(int i = 0; i < 3; i++) b == a; 32 | 33 | while(false) { 34 | int c = 3; 35 | uint(c) + a; 36 | 37 | c == 5; 38 | 39 | } 40 | 41 | a + b; 42 | breaker = false; 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/cross_contract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract a { 4 | 5 | uint x; 6 | 7 | function foo() public { 8 | x++; 9 | } 10 | } 11 | 12 | contract b { 13 | a x; 14 | function bar() public { 15 | address payable a; 16 | a.send(100 wei); 17 | x.foo(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/ctor.sol: -------------------------------------------------------------------------------- 1 | contract c { 2 | uint x; 3 | uint x_abc; 4 | constructor(uint _x, uint _abc) public { 5 | x=_x; 6 | x_abc=_abc; 7 | } 8 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/deleteDynamicArray.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.7.0; 2 | contract arr { 3 | uint[] users; 4 | 5 | bytes access_rights_per_user; 6 | 7 | uint user_index; 8 | 9 | address owner; 10 | 11 | string grr = "message"; 12 | 13 | uint[100] last_100_users; 14 | 15 | constructor(address owner1) public { 16 | owner = owner1; 17 | user_index = 0; 18 | } 19 | 20 | function addUser(uint id, byte rights) public{ 21 | users[user_index] = id; 22 | last_100_users[user_index % 100] = id; 23 | access_rights_per_user[user_index] = rights; 24 | user_index++; 25 | } 26 | 27 | function resetState() public{ 28 | require(msg.sender == owner, grr); 29 | delete users; 30 | delete access_rights_per_user; 31 | delete last_100_users; 32 | } 33 | 34 | function bla(string memory bal) public { 35 | grr = bal; 36 | } 37 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/deleteFromDynamicArray.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | contract arr { 3 | uint[] array = [1,2,3]; 4 | function removeAtIndex() public returns (uint[] memory) { 5 | delete array[1]; 6 | return array; 7 | } 8 | 9 | // TODO: deleteFromDynamicArray should not generate warnings if array item is shifted and removed 10 | /* function safeRemoveAtIndex(uint index) returns (uint[] memory) { 11 | if (index >= array.length) return; 12 | 13 | for (uint i = index; i < array.length-1; i++) { 14 | array[i] = array[i+1]; 15 | } 16 | 17 | delete array[array.length-1]; 18 | array.length--; 19 | 20 | return array; 21 | } */ 22 | } 23 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/etherTransferInLoop.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract etherTransferInLoop { 4 | address payable owner; 5 | 6 | constructor() public { 7 | owner = msg.sender; 8 | } 9 | 10 | function transferInForLoop(uint index) public { 11 | for (uint i = index; i < 10; i++) { 12 | owner.transfer(i); 13 | } 14 | } 15 | 16 | function transferInWhileLoop(uint index) public { 17 | uint i = index; 18 | while (i < 10) { 19 | owner.transfer(i); 20 | i++; 21 | } 22 | } 23 | 24 | function transferInDoWhileLoop(uint index) public { 25 | uint i = index; 26 | do { 27 | owner.transfer(i); 28 | i++; 29 | } while (i < 10); 30 | } 31 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/forLoopIteratesOverDynamicArray.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | contract forLoopArr { 3 | uint[] array; 4 | constructor(uint[] memory _array) public { 5 | array = _array; 6 | } 7 | 8 | function shiftArrItem(uint index) public returns(uint[] memory) { 9 | for (uint i = index; i < array.length; i++) { 10 | array[i] = array[i+1]; 11 | } 12 | return array; 13 | } 14 | 15 | function shiftArrItem2(uint index) public returns(uint[] memory) { 16 | for (uint i = index; i < array.length - 1; i++) { 17 | array[i] = array[i+1]; 18 | } 19 | return array; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/forgottenReturn.sol: -------------------------------------------------------------------------------- 1 | contract Sheep { 2 | string public name; 3 | string public dna; 4 | bool g = true; 5 | constructor(string memory _name, string memory _dna) public { 6 | name = _name; 7 | dna = _dna; 8 | } 9 | 10 | function geneticallyEngineer(string memory _dna) public returns (bool) { 11 | dna = _dna; 12 | } 13 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/functionParameters.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract B { 4 | function plus(uint a, uint b) pure internal returns (uint) { 5 | return a + b; 6 | } 7 | 8 | function eval(function (uint, uint) pure internal returns (uint) f, uint x, uint y) pure internal returns (uint) { 9 | return f(x, y); 10 | } 11 | 12 | function calc(uint x, uint y) pure public returns (uint) { 13 | return eval(plus, x, y); 14 | // return plus(x, y); 15 | } 16 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/globals.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | contract bla { 3 | uint brr; 4 | function duper() public { 5 | brr++; 6 | } 7 | } 8 | 9 | contract a is bla { 10 | 11 | function blub() public { 12 | brr++; 13 | } 14 | 15 | function r () public payable { 16 | address payable a; 17 | bytes32 hash; 18 | uint8 v; 19 | bytes32 r; 20 | bytes32 s; 21 | 22 | blockhash(1); 23 | block.coinbase; 24 | block.difficulty; 25 | block.gaslimit; 26 | block.number; 27 | block.timestamp; 28 | msg.data; 29 | gasleft(); 30 | msg.sender; 31 | msg.value; 32 | now; 33 | tx.gasprice; 34 | tx.origin; 35 | // assert(1 == 2); 36 | // require(1 == 1); 37 | keccak256(abi.encodePacked(a)); 38 | sha256(abi.encodePacked(a)); 39 | ripemd160(abi.encodePacked(a)); 40 | ecrecover(hash, v, r, s); 41 | addmod(1, 2, 2); 42 | mulmod(4,4,12); 43 | 44 | a.balance; 45 | blub(); 46 | a.send(a.balance); 47 | 48 | 49 | 50 | super.duper(); 51 | //a.transfer(a.balance); 52 | selfdestruct(a); 53 | //revert(); 54 | assert(a.balance == 0); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/inheritance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract r { 4 | function s() public view {} 5 | } 6 | 7 | contract a is r { 8 | uint x = 1; 9 | 10 | function getX() public view returns (uint) { 11 | return x; 12 | } 13 | } 14 | 15 | contract b is a { 16 | uint y = 2; 17 | uint x = 3; 18 | 19 | 20 | function getY(uint z, bool r) public returns (uint) { 21 | return y++; 22 | } 23 | 24 | function getY(string storage n) internal view returns (uint) { return 10; } 25 | 26 | } 27 | 28 | contract c is b { 29 | string x; 30 | 31 | function d() public returns (uint a, uint b) { 32 | //d(); 33 | //sha3("bla"); 34 | address payable o = msg.sender; 35 | o.call.gas(200000).value(address(this).balance)(abi.encode("pay()")); 36 | //x++; 37 | getY(x); 38 | a = getX() + getY(1, false); 39 | b = getX() + getY(x); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/intDivisionTruncate.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract CharityCampaign { 4 | mapping (address => uint) contributions; 5 | int128 feePercentage; 6 | uint p2; 7 | address payable processor; 8 | address payable beneficiary; 9 | 10 | constructor(address payable _beneficiary, int128 _feePercentage) public { 11 | processor = msg.sender; 12 | beneficiary = _beneficiary; 13 | feePercentage = _feePercentage; 14 | } 15 | 16 | function contribute() payable public returns (uint feeCollected) { 17 | uint fee = msg.value * uint256(feePercentage / 100); 18 | fee = msg.value * (p2 / 100); 19 | contributions[msg.sender] = msg.value - fee; 20 | processor.transfer(fee); 21 | return fee; 22 | } 23 | 24 | function endCampaign() public returns (bool) { 25 | require(msg.sender == processor || msg.sender == beneficiary); 26 | selfdestruct(beneficiary); 27 | return true; 28 | } 29 | 30 | // FALSE POSITIVE FOR SELFDESTRUCT TERMINAL 31 | function endAmbiguous() public { 32 | if(msg.sender == address(0x0)) { 33 | selfdestruct(beneficiary); 34 | } else { 35 | selfdestruct(processor); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/library.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | library Set { 4 | // We define a new struct datatype that will be used to 5 | // hold its data in the calling contract. 6 | struct Data { mapping(uint => bool) flags; } 7 | 8 | // Note that the first parameter is of type "storage 9 | // reference" and thus only its storage address and not 10 | // its contents is passed as part of the call. This is a 11 | // special feature of library functions. It is idiomatic 12 | // to call the first parameter 'self', if the function can 13 | // be seen as a method of that object. 14 | function insert(Data storage self, uint value) public 15 | returns (bool) 16 | { 17 | if (self.flags[value]) 18 | return false; // already there 19 | self.flags[value] = true; 20 | 21 | return true; 22 | } 23 | 24 | function remove(Data storage self, uint value) public 25 | returns (bool) 26 | { 27 | if (!self.flags[value]) 28 | return false; // not there 29 | self.flags[value] = false; 30 | return true; 31 | } 32 | 33 | function contains(Data storage self, uint value) public 34 | returns (bool) 35 | { 36 | return self.flags[value]; 37 | } 38 | } 39 | 40 | 41 | contract C { 42 | Set.Data knownValues; 43 | 44 | function register(uint value) public { 45 | // The library functions can be called without a 46 | // specific instance of the library, since the 47 | // "instance" will be the current contract. 48 | address payable a; 49 | a.send(10 wei); 50 | if (!Set.insert(knownValues, value)) 51 | revert(); 52 | } 53 | 54 | // In this contract, we can also directly access knownValues.flags, if we want. 55 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/loops.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract loops { 4 | uint[] array; 5 | constructor(uint[] memory _array) public { 6 | array = _array; 7 | } 8 | 9 | function fnWithForLoop(uint index) public { 10 | for (uint i = index; i < 10; i++) { 11 | array.push(i); 12 | } 13 | } 14 | 15 | function fnWithWhileLoop(uint index) public { 16 | uint i = index; 17 | while (i < 10) { 18 | array.push(i); 19 | i++; 20 | } 21 | } 22 | 23 | function fnWithDoWhileLoop(uint index) public { 24 | uint i = index; 25 | do{ 26 | array.push(i); 27 | i++; 28 | }while (i < 10); 29 | } 30 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/modifier1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract test { 4 | 5 | address owner; 6 | 7 | modifier onlyOwner { 8 | uint a = 0; 9 | if (msg.sender != owner) 10 | revert(); 11 | _; 12 | } 13 | 14 | function b(address a) public onlyOwner returns (bool) { 15 | return true; 16 | } 17 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/modifier2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract owned { 4 | 5 | uint r=0; 6 | 7 | modifier ntimes(uint n) { 8 | for(uint i=0;i=0.4.9 <0.6.0; 2 | 3 | contract Fund { 4 | /// Mapping of ether shares of the contract. 5 | mapping(address => uint) shares; 6 | /// Withdraw your share. 7 | function withdraw() public { 8 | uint share = shares[msg.sender]; 9 | shares[msg.sender] = 0; 10 | if (!msg.sender.send(share)) 11 | revert(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/reentrant.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract InfoFeed { 4 | uint c; 5 | function info() constant returns (uint ret) {return c;} 6 | function call1(uint a) constant returns (bool) {return true;} 7 | } 8 | 9 | // THIS CONTRACT CONTAINS A BUG - DO NOT USE 10 | contract Fund { 11 | /// Mapping of ether shares of the contract. 12 | //mapping(address => uint) shares; 13 | /// Withdraw your share. 14 | 15 | uint c = 0; 16 | function withdraw() constant { 17 | InfoFeed f; 18 | 19 | 20 | //shares[msg.sender] /= 1; 21 | 22 | f.info(); 23 | 24 | //if (msg.sender.send(shares[msg.sender])) throw; 25 | // shares[msg.sender] = 0; 26 | 27 | 28 | b(true, false); 29 | //shares[msg.sender]++; 30 | //c++; 31 | 32 | } 33 | mapping(address => uint) shares; 34 | 35 | function b(bool a, bool b) returns (bool) { 36 | mapping(address => uint) c = shares; 37 | c[msg.sender] = 0; 38 | //f(); 39 | //withdraw(); 40 | //shares[msg.sender]++; 41 | //c++; 42 | return true; 43 | } 44 | 45 | function f() { 46 | c++; 47 | withdraw(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/selfdestruct.sol: -------------------------------------------------------------------------------- 1 | contract sd { 2 | 3 | uint x = 0; 4 | function() external payable { } 5 | 6 | function c () public { 7 | selfdestruct(address(0xdeadbeef)); 8 | } 9 | 10 | function b () public { 11 | selfdestruct(address(0xdeadbeef)); 12 | x = 1; 13 | } 14 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/stringBytesLength.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | contract bytesString { 3 | 4 | function length(string memory a) public pure returns(uint) { 5 | bytes memory x = bytes(a); 6 | 7 | return x.length; 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/structReentrant.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract Ballot { 4 | 5 | struct Voter { 6 | uint weight; 7 | bool voted; 8 | uint8 vote; 9 | address delegate; 10 | baz foo; 11 | } 12 | 13 | struct baz{ 14 | uint bar; 15 | } 16 | 17 | mapping(address => Voter) voters; 18 | 19 | /// Create a new ballot with $(_numProposals) different proposals. 20 | function bla(address payable a) public { 21 | Voter storage x = voters[a]; 22 | 23 | if (!a.send(10)) 24 | revert(); 25 | 26 | //voters[a] = Voter(10,true,1,a); 27 | //x.foo.bar *= 100; 28 | bli(x); 29 | } 30 | 31 | //function bla(){} 32 | 33 | function bli(Voter storage x) private { 34 | x.foo.bar++; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/thisLocal.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.9 <0.6.0; 2 | 3 | contract test { 4 | 5 | function () external { 6 | address payable x; 7 | this.b(x); 8 | x.call('something'); 9 | x.send(1 wei); 10 | 11 | } 12 | 13 | function b(address a) public returns (bool) { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /remix-analyzer/test/analysis/test-contracts/solidity-v0.5/transfer.sol: -------------------------------------------------------------------------------- 1 | contract c { 2 | uint x; 3 | function f(address payable r) public payable { 4 | r.transfer(1); 5 | x = 2; 6 | } 7 | } -------------------------------------------------------------------------------- /remix-analyzer/test/tests.ts: -------------------------------------------------------------------------------- 1 | require('./analysis/staticAnalysisCommon-test') 2 | 3 | require('./analysis/staticAnalysisIntegration-test-0.4.24') 4 | require('./analysis/staticAnalysisIssues-test-0.4.24') 5 | 6 | require('./analysis/staticAnalysisIntegration-test-0.5.0') 7 | require('./analysis/staticAnalysisIssues-test-0.5.0') 8 | -------------------------------------------------------------------------------- /remix-analyzer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src", "index.ts"], 3 | "compilerOptions": { 4 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": ["dom", "es2018"], /* Specify library files to be included in the compilation. */ 7 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 8 | "sourceMap": true, /* Generates corresponding '.map' file. */ 9 | "outDir": "./dist", /* Redirect output structure to the directory. */ 10 | /* Strict Type-Checking Options */ 11 | "strict": true, /* Enable all strict type-checking options. */ 12 | "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ 13 | /* Module Resolution Options */ 14 | "baseUrl": "./src", /* Base directory to resolve non-absolute module names. */ 15 | "paths": { "remix-analyzer": ["./"] }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 16 | "typeRoots": [ 17 | "./@types", 18 | "./node_modules/@types" 19 | ], 20 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 21 | /* Experimental Options */ 22 | "experimentalDecorators": false, /* Enables experimental support for ES7 decorators. */ 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /remix-astwalker/.gitignore: -------------------------------------------------------------------------------- 1 | .nyc_output 2 | coverage 3 | build 4 | -------------------------------------------------------------------------------- /remix-astwalker/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | tests/ -------------------------------------------------------------------------------- /remix-astwalker/README.md: -------------------------------------------------------------------------------- 1 | **The project has been moved to https://github.com/ethereum/remix-project/tree/master/libs/remix-astwalker** 2 | 3 | ## Remix ASTwalker 4 | `remix-astwalker` module walks through solidity AST and spits out AST nodes. 5 | 6 | #### Example 7 | ```ts 8 | import { AstWalker } from "remix-astwalker"; 9 | 10 | const astWalker = new AstWalker(); 11 | astWalker.on("node", node => { 12 | if (node.nodeType === "ContractDefinition") { 13 | checkContract(st, node); 14 | } 15 | 16 | if (node.nodeType === "PragmaDirective") { 17 | checkProgramDirective(st, node); 18 | } 19 | }); 20 | ``` 21 | For more examples see `tests`. 22 | -------------------------------------------------------------------------------- /remix-astwalker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "remix-astwalker", 3 | "version": "0.0.25", 4 | "description": "Remix sub-module for walking through AST", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "build": "tsc", 8 | "test": "nyc --reporter=lcov --require ts-node/register tape ./tests/*.ts | tap-spec; nyc report ---reporter=text", 9 | "prepublish": "npm run build" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/ethereum/remix.git" 14 | }, 15 | "keywords": [ 16 | "Solidity", 17 | "AST", 18 | "remix" 19 | ], 20 | "author": "0mkara", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/ethereum/remix/issues" 24 | }, 25 | "homepage": "https://github.com/ethereum/remix#readme", 26 | "nyc": { 27 | "include": [ 28 | "src/**/*.ts" 29 | ], 30 | "extension": [ 31 | ".ts" 32 | ] 33 | }, 34 | "dependencies": { 35 | "@types/tape": "^4.2.33", 36 | "nyc": "^13.3.0", 37 | "remix-lib": "0.4.30", 38 | "tape": "^4.10.1", 39 | "ts-node": "^8.0.3", 40 | "typescript": "^3.4.3" 41 | }, 42 | "devDependencies": { 43 | "tap-spec": "^5.0.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /remix-astwalker/src/@types/remix-lib/index.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitiosn for the things we need from remix-lib 2 | 3 | declare module "remix-lib" { 4 | export module util { 5 | export function findLowerBound(target: number, array: Array): number; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /remix-astwalker/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types' 2 | export * from './astWalker' 3 | export * from './sourceMappings' 4 | -------------------------------------------------------------------------------- /remix-astwalker/tests/resources/test.sol: -------------------------------------------------------------------------------- 1 | contract test { 2 | int x; 3 | 4 | int y; 5 | 6 | function set(int _x) returns (int _r) 7 | { 8 | x = _x; 9 | y = 10; 10 | _r = x; 11 | } 12 | 13 | function get() returns (uint x, uint y) 14 | { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /remix-debug/.npmignore: -------------------------------------------------------------------------------- 1 | test/ -------------------------------------------------------------------------------- /remix-debug/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const EthDebugger = require('./src/Ethdebugger') 3 | const TransactionDebugger = require('./src/debugger/debugger') 4 | const CmdLine = require('./src/cmdline') 5 | 6 | const StorageViewer = require('./src/storage/storageViewer') 7 | const StorageResolver = require('./src/storage/storageResolver') 8 | 9 | const SolidityDecoder = require('./src/solidity-decoder') 10 | 11 | const remixLib = require('remix-lib') 12 | const BreakpointManager = remixLib.code.BreakpointManager 13 | 14 | /* 15 | Use of breakPointManager : 16 | 17 | var breakPointManager = new BreakpointManager(this.debugger, (sourceLocation) => { 18 | return line/column from offset (sourceLocation) 19 | }) 20 | this.debugger.setBreakpointManager(breakPointManager) 21 | */ 22 | module.exports = { 23 | EthDebugger: EthDebugger, 24 | TransactionDebugger: TransactionDebugger, 25 | /** 26 | * constructor 27 | * 28 | * @param {Object} _debugger - type of EthDebugger 29 | * @return {Function} _locationToRowConverter - function implemented by editor which return a column/line position for a char source location 30 | */ 31 | BreakpointManager: BreakpointManager, 32 | SolidityDecoder: SolidityDecoder, 33 | storage: { 34 | StorageViewer: StorageViewer, 35 | StorageResolver: StorageResolver 36 | }, 37 | CmdLine: CmdLine 38 | } 39 | 40 | -------------------------------------------------------------------------------- /remix-debug/src/cmdline/contextManager.js: -------------------------------------------------------------------------------- 1 | const remixLib = require('remix-lib') 2 | 3 | const EventManager = remixLib.EventManager 4 | const Web3Providers = remixLib.vm.Web3Providers 5 | const DummyProvider = remixLib.vm.DummyProvider 6 | const init = remixLib.init 7 | 8 | class ContextManager { 9 | constructor (executionContext) { 10 | this.executionContext = executionContext 11 | this.web3 = this.executionContext.web3() 12 | this.event = new EventManager() 13 | } 14 | 15 | initProviders () { 16 | this.web3Providers = new Web3Providers() 17 | this.addProvider('DUMMYWEB3', new DummyProvider()) 18 | this.switchProvider('DUMMYWEB3') 19 | 20 | this.addProvider('vm', this.executionContext.vm()) 21 | this.addProvider('injected', this.executionContext.internalWeb3()) 22 | this.addProvider('web3', this.executionContext.internalWeb3()) 23 | this.switchProvider(this.executionContext.getProvider()) 24 | } 25 | 26 | getWeb3 () { 27 | return this.web3 28 | } 29 | 30 | addProvider (type, obj) { 31 | this.web3Providers.addProvider(type, obj) 32 | this.event.trigger('providerAdded', [type]) 33 | } 34 | 35 | switchProvider (type, cb) { 36 | this.web3Providers.get(type, (error, obj) => { 37 | if (error) { 38 | // console.log('provider ' + type + ' not defined') 39 | } else { 40 | this.web3 = obj 41 | this.executionContext.detectNetwork((error, network) => { 42 | if (error || !network) { 43 | this.web3 = obj 44 | } else { 45 | var webDebugNode = init.web3DebugNode(network.name) 46 | this.web3 = (!webDebugNode ? obj : webDebugNode) 47 | } 48 | this.event.trigger('providerChanged', [type, this.web3]) 49 | if (cb) return cb() 50 | }) 51 | this.event.trigger('providerChanged', [type, this.web3]) 52 | } 53 | }) 54 | } 55 | 56 | } 57 | 58 | module.exports = ContextManager 59 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/index.js: -------------------------------------------------------------------------------- 1 | const SolidityProxy = require('./solidityProxy') 2 | const stateDecoder = require('./stateDecoder') 3 | const localDecoder = require('./localDecoder') 4 | const InternalCallTree = require('./internalCallTree') 5 | 6 | module.exports = { 7 | SolidityProxy: SolidityProxy, 8 | stateDecoder: stateDecoder, 9 | localDecoder: localDecoder, 10 | InternalCallTree: InternalCallTree 11 | } 12 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/localDecoder.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | async function solidityLocals (vmtraceIndex, internalTreeCall, stack, memory, storageResolver, currentSourceLocation) { 4 | const scope = internalTreeCall.findScope(vmtraceIndex) 5 | if (!scope) { 6 | const error = { 'message': 'Can\'t display locals. reason: compilation result might not have been provided' } 7 | throw error 8 | } 9 | const locals = {} 10 | memory = formatMemory(memory) 11 | let anonymousIncr = 1 12 | for (let local in scope.locals) { 13 | var variable = scope.locals[local] 14 | if (variable.stackDepth < stack.length && variable.sourceLocation.start <= currentSourceLocation.start) { 15 | let name = variable.name 16 | if (name.indexOf('$') !== -1) { 17 | name = '<' + anonymousIncr + '>' 18 | anonymousIncr++ 19 | } 20 | try { 21 | locals[name] = await variable.type.decodeFromStack(variable.stackDepth, stack, memory, storageResolver) 22 | } catch (e) { 23 | console.log(e) 24 | locals[name] = '' 25 | } 26 | } 27 | } 28 | return locals 29 | } 30 | 31 | function formatMemory (memory) { 32 | if (memory instanceof Array) { 33 | memory = memory.join('').replace(/0x/g, '') 34 | } 35 | return memory 36 | } 37 | 38 | module.exports = { 39 | solidityLocals: solidityLocals 40 | } 41 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/types/Address.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const util = require('./util') 3 | const ValueType = require('./ValueType') 4 | 5 | class Address extends ValueType { 6 | constructor () { 7 | super(1, 20, 'address') 8 | } 9 | 10 | decodeValue (value) { 11 | if (!value) { 12 | return '0x0000000000000000000000000000000000000000' 13 | } else { 14 | return '0x' + util.extractHexByteSlice(value, this.storageBytes, 0).toUpperCase() 15 | } 16 | } 17 | } 18 | 19 | module.exports = Address 20 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/types/Bool.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const ValueType = require('./ValueType') 3 | const util = require('./util') 4 | 5 | class Bool extends ValueType { 6 | constructor () { 7 | super(1, 1, 'bool') 8 | } 9 | 10 | decodeValue (value) { 11 | if (!value) { 12 | return false 13 | } else { 14 | value = util.extractHexByteSlice(value, this.storageBytes, 0) 15 | return value !== '00' 16 | } 17 | } 18 | } 19 | 20 | module.exports = Bool 21 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/types/Enum.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const ValueType = require('./ValueType') 3 | 4 | class Enum extends ValueType { 5 | constructor (enumDef) { 6 | let storageBytes = 0 7 | let length = enumDef.children.length 8 | while (length > 1) { 9 | length = length / 256 10 | storageBytes++ 11 | } 12 | super(1, storageBytes, 'enum') 13 | this.enumDef = enumDef 14 | } 15 | 16 | decodeValue (value) { 17 | if (!value) { 18 | return this.enumDef.children[0].attributes.name 19 | } else { 20 | value = parseInt(value, 16) 21 | if (this.enumDef.children.length > value) { 22 | return this.enumDef.children[value].attributes.name 23 | } else { 24 | return 'INVALID_ENUM<' + value + '>' 25 | } 26 | } 27 | } 28 | } 29 | 30 | module.exports = Enum 31 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/types/FixedByteArray.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const ValueType = require('./ValueType') 3 | 4 | class FixedByteArray extends ValueType { 5 | constructor (storageBytes) { 6 | super(1, storageBytes, 'bytes' + storageBytes) 7 | } 8 | 9 | decodeValue (value) { 10 | return '0x' + value.substr(0, 2 * this.storageBytes).toUpperCase() 11 | } 12 | } 13 | 14 | module.exports = FixedByteArray 15 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/types/Int.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const util = require('./util') 3 | const ValueType = require('./ValueType') 4 | 5 | class Int extends ValueType { 6 | constructor (storageBytes) { 7 | super(1, storageBytes, 'int' + storageBytes * 8) 8 | } 9 | 10 | decodeValue (value) { 11 | value = util.extractHexByteSlice(value, this.storageBytes, 0) 12 | return util.decodeIntFromHex(value, this.storageBytes, true) 13 | } 14 | } 15 | 16 | module.exports = Int 17 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/types/StringType.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const DynamicBytes = require('./DynamicByteArray') 3 | 4 | class StringType extends DynamicBytes { 5 | constructor (location) { 6 | super(location) 7 | this.typeName = 'string' 8 | } 9 | 10 | async decodeFromStorage (location, storageResolver) { 11 | let decoded = '0x' 12 | try { 13 | decoded = await super.decodeFromStorage(location, storageResolver) 14 | } catch (e) { 15 | console.log(e) 16 | return '' 17 | } 18 | return format(decoded) 19 | } 20 | 21 | async decodeFromStack (stackDepth, stack, memory) { 22 | try { 23 | return await super.decodeFromStack(stackDepth, stack, memory) 24 | } catch (e) { 25 | console.log(e) 26 | return '' 27 | } 28 | } 29 | 30 | decodeFromMemoryInternal (offset, memory) { 31 | const decoded = super.decodeFromMemoryInternal(offset, memory) 32 | return format(decoded) 33 | } 34 | } 35 | 36 | function format (decoded) { 37 | if (decoded.error) { 38 | return decoded 39 | } 40 | let value = decoded.value 41 | value = value.replace('0x', '').replace(/(..)/g, '%$1') 42 | const ret = { 43 | length: decoded.length, 44 | raw: decoded.value, 45 | type: 'string' 46 | } 47 | try { 48 | ret.value = decodeURIComponent(value) 49 | } catch (e) { 50 | ret.error = 'Invalid UTF8 encoding' 51 | ret.raw = decoded.value 52 | } 53 | return ret 54 | } 55 | 56 | module.exports = StringType 57 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/types/Struct.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const util = require('./util') 3 | const RefType = require('./RefType') 4 | 5 | class Struct extends RefType { 6 | constructor (memberDetails, location, fullType) { 7 | super(memberDetails.storageSlots, 32, 'struct ' + fullType, location) 8 | this.members = memberDetails.members 9 | } 10 | 11 | async decodeFromStorage (location, storageResolver) { 12 | const ret = {} 13 | for (var item of this.members) { 14 | const globalLocation = { 15 | offset: location.offset + item.storagelocation.offset, 16 | slot: util.add(location.slot, item.storagelocation.slot) 17 | } 18 | try { 19 | ret[item.name] = await item.type.decodeFromStorage(globalLocation, storageResolver) 20 | } catch (e) { 21 | console.log(e) 22 | ret[item.name] = '' 23 | } 24 | } 25 | return { 26 | value: ret, 27 | type: this.typeName 28 | } 29 | } 30 | 31 | decodeFromMemoryInternal (offset, memory) { 32 | const ret = {} 33 | this.members.map((item, i) => { 34 | var contentOffset = offset 35 | var member = item.type.decodeFromMemory(contentOffset, memory) 36 | ret[item.name] = member 37 | offset += 32 38 | }) 39 | return { 40 | value: ret, 41 | type: this.typeName 42 | } 43 | } 44 | } 45 | 46 | module.exports = Struct 47 | -------------------------------------------------------------------------------- /remix-debug/src/solidity-decoder/types/Uint.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const util = require('./util') 3 | const ValueType = require('./ValueType') 4 | 5 | class Uint extends ValueType { 6 | constructor (storageBytes) { 7 | super(1, storageBytes, 'uint' + storageBytes * 8) 8 | } 9 | 10 | decodeValue (value) { 11 | value = util.extractHexByteSlice(value, this.storageBytes, 0) 12 | return util.decodeIntFromHex(value, this.storageBytes, false) 13 | } 14 | } 15 | 16 | module.exports = Uint 17 | -------------------------------------------------------------------------------- /remix-debug/test/decoder/contracts/intLocal.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | contract: ` 5 | contract proxy { 6 | struct testStruct { 7 | int one; 8 | uint two; 9 | } 10 | } 11 | contract intLocal { 12 | constructor () public { 13 | proxy.testStruct memory p; 14 | uint8 ui8 = 130; 15 | uint16 ui16 = 456; 16 | uint32 ui32 = 4356; 17 | uint64 ui64 = 3543543543; 18 | uint128 ui128 = 234567; 19 | uint256 ui256 = 115792089237316195423570985008687907853269984665640564039457584007880697216513; 20 | uint ui = 123545666; 21 | int8 i8 = -45; 22 | int16 i16 = -1234; 23 | int32 i32 = 3455; 24 | int64 i64 = -35566; 25 | int128 i128 = -444444; 26 | int256 i256 = 3434343; 27 | int i = -32432423423; 28 | int32 ishrink = 2; 29 | level11(123); 30 | level12(12); 31 | level11(123); 32 | } 33 | 34 | function level11(uint8 foo) public { 35 | uint8 ui8 = foo; 36 | level12(12); 37 | } 38 | function level12(uint8 asd) public { 39 | uint8 ui81 = asd; 40 | } 41 | } 42 | `} 43 | -------------------------------------------------------------------------------- /remix-debug/test/decoder/contracts/intStorage.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | contract: ` 5 | contract intStorage { 6 | uint8 ui8 = 130; 7 | uint16 ui16 = 456; 8 | uint32 ui32 = 4356; 9 | uint64 ui64 = 3543543543; 10 | uint128 ui128 = 234567; 11 | uint256 public ui256 = 115792089237316195423570985008687907853269984665640564039457584007880697216513; 12 | uint ui = 123545666; 13 | int8 i8 = -45; 14 | int16 i16 = -1234; 15 | int32 i32 = 3455; 16 | int64 i64 = -35566; 17 | int128 i128 = -444444; 18 | int256 i256 = 3434343; 19 | int i = -32432423423; 20 | int32 ishrink = 2; 21 | } 22 | `, 23 | fullStorage: { 24 | '0x0000000000000000000000000000000000000000000000000000000000000000': '0x000000000000000000000000000003944700000000d3362ef70000110401c882', 25 | '0x0000000000000000000000000000000000000000000000000000000000000001': '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffff872e07e01', 26 | '0x0000000000000000000000000000000000000000000000000000000000000002': '0x00000000000000000000000000000000000000000000000000000000075d2842', 27 | '0x0000000000000000000000000000000000000000000000000000000000000003': '0x00fffffffffffffffffffffffffff937e4ffffffffffff751200000d7ffb2ed3', 28 | '0x0000000000000000000000000000000000000000000000000000000000000004': '0x0000000000000000000000000000000000000000000000000000000000346767', 29 | '0x0000000000000000000000000000000000000000000000000000000000000005': '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffff872e07e01', 30 | '0x0000000000000000000000000000000000000000000000000000000000000006': '0x0000000000000000000000000000000000000000000000000000000000000002' 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /remix-debug/test/decoder/contracts/mappingStorage.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | contract: ` 3 | contract SimpleMappingState { 4 | uint _num; 5 | mapping(string => uint) _iBreakSolidityState; 6 | mapping(uint => uint) _iBreakSolidityStateInt; 7 | function updateNum(uint num, string memory str) public { 8 | _num = num; 9 | _iBreakSolidityState[str] = num; 10 | _iBreakSolidityStateInt[num] = num; 11 | } 12 | } 13 | ` 14 | } 15 | -------------------------------------------------------------------------------- /remix-debug/test/decoder/contracts/miscLocal.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | contract: ` 5 | contract miscLocal { 6 | enum enumDef { 7 | one, 8 | two, 9 | three, 10 | four 11 | } 12 | constructor () public { 13 | bool boolFalse = false; 14 | bool boolTrue = true; 15 | enumDef testEnum; 16 | testEnum = enumDef.three; 17 | address sender = msg.sender; 18 | byte _bytes1 = hex"99"; 19 | bytes1 __bytes1 = hex"99"; 20 | bytes2 __bytes2 = hex"99AB"; 21 | bytes4 __bytes4 = hex"99FA"; 22 | bytes6 __bytes6 = hex"99"; 23 | bytes7 __bytes7 = hex"993567"; 24 | bytes8 __bytes8 = hex"99ABD417"; 25 | bytes9 __bytes9 = hex"99156744AF"; 26 | bytes13 __bytes13 = hex"991234234253"; 27 | bytes16 __bytes16 = hex"99AFAD234324"; 28 | bytes24 __bytes24 = hex"99AFAD234324"; 29 | bytes32 __bytes32 = hex"9999ABD41799ABD417"; 30 | } 31 | } 32 | 33 | contract miscLocal2 { 34 | constructor () public { 35 | bytes memory dynbytes = "dynamicbytes"; 36 | string memory smallstring = "test_test_test"; 37 | } 38 | } 39 | `} 40 | -------------------------------------------------------------------------------- /remix-debug/test/decoder/contracts/simpleContract.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = ` 3 | contract simpleContract { 4 | struct structDef { 5 | uint8 ui; 6 | string str; 7 | } 8 | enum enumDef { 9 | first, 10 | second, 11 | third 12 | } 13 | structDef structDec; 14 | structDef[3] array; 15 | enumDef enumDec; 16 | } 17 | 18 | contract test1 { 19 | struct str { 20 | uint8 ui; 21 | } 22 | } 23 | 24 | contract test2 { 25 | test1.str a; 26 | } 27 | ` 28 | -------------------------------------------------------------------------------- /remix-debug/test/decoder/localsTests/helper.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var localDecoder = require('../../../src/solidity-decoder/localDecoder') 3 | 4 | /* 5 | Decode local variable 6 | */ 7 | function decodeLocal (st, index, traceManager, callTree, verifier) { 8 | try { 9 | traceManager.waterfall([ 10 | traceManager.getStackAt, 11 | traceManager.getMemoryAt], 12 | index, 13 | function (error, result) { 14 | if (!error) { 15 | localDecoder.solidityLocals(index, callTree, result[0].value, result[1].value, {}, {start: 5000}).then((locals) => { 16 | verifier(locals) 17 | }) 18 | } else { 19 | st.fail(error) 20 | } 21 | }) 22 | } catch (e) { 23 | st.fail(e.message) 24 | } 25 | } 26 | 27 | module.exports = { 28 | decodeLocals: decodeLocal 29 | } 30 | -------------------------------------------------------------------------------- /remix-debug/test/decoder/mockStorageResolver.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var remixLib = require('remix-lib') 3 | var util = remixLib.util 4 | 5 | class MockStorageResolver { 6 | constructor (_storage) { 7 | this.storage = {} 8 | for (var k in _storage) { 9 | var hashed = util.sha3_256(k) 10 | this.storage[hashed] = { 11 | hashed: hashed, 12 | key: k, 13 | value: _storage[k] 14 | } 15 | } 16 | } 17 | 18 | storageRange (callback) { 19 | callback(null, this.storage) 20 | } 21 | 22 | storageSlot (slot, callback) { 23 | var hashed = util.sha3_256(slot) 24 | callback(null, this.storage[hashed]) 25 | } 26 | 27 | isComplete (address) { 28 | return true 29 | } 30 | 31 | fromCache (address, slotKey) { 32 | return this.storage[slotKey] 33 | } 34 | 35 | toCache (address, storage, complete) { 36 | } 37 | } 38 | 39 | module.exports = MockStorageResolver 40 | -------------------------------------------------------------------------------- /remix-debug/test/init.js: -------------------------------------------------------------------------------- 1 | var init = { 2 | overrideWeb3: function (web3, web3Override) { 3 | web3.eth.getCode = web3Override.getCode 4 | web3.debug.traceTransaction = web3Override.traceTransaction 5 | web3.debug.storageRangeAt = web3Override.storageRangeAt 6 | web3.eth.getTransaction = web3Override.getTransaction 7 | web3.eth.getTransactionFromBlock = web3Override.getTransactionFromBlock 8 | web3.eth.getBlockNumber = web3Override.getBlockNumber 9 | }, 10 | 11 | readFile: function (filename, callback) { 12 | var fs = require('fs') 13 | try { 14 | console.log('reading ' + filename) 15 | if (callback) { 16 | fs.readFile(filename, 'utf8', callback) 17 | } else { 18 | return fs.readFileSync(filename, 'utf8') 19 | } 20 | } catch (e) { 21 | console.log(e) 22 | if (callback) { 23 | callback(e) 24 | } else { 25 | return e 26 | } 27 | } 28 | } 29 | } 30 | 31 | module.exports = init 32 | -------------------------------------------------------------------------------- /remix-debug/test/resources/testWeb3.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var init = require('../init') 3 | var web3Override = {} 4 | web3Override.eth = {} 5 | web3Override.debug = {} 6 | var data = init.readFile(require('path').resolve(__dirname, 'testWeb3.json')) 7 | data = JSON.parse(data) 8 | 9 | web3Override.eth.getCode = function (address, callback) { 10 | if (callback) { 11 | callback(null, data.testCodes[address]) 12 | } else { 13 | return data.testCodes[address] 14 | } 15 | } 16 | 17 | web3Override.debug.traceTransaction = function (txHash, options, callback) { 18 | callback(null, data.testTraces[txHash]) 19 | } 20 | 21 | web3Override.debug.storageRangeAt = function (blockNumber, txIndex, address, start, maxSize, callback) { 22 | callback(null, { storage: {}, complete: true }) 23 | } 24 | 25 | web3Override.eth.getTransaction = function (txHash, callback) { 26 | if (callback) { 27 | callback(null, data.testTxs[txHash]) 28 | } else { 29 | return data.testTxs[txHash] 30 | } 31 | } 32 | 33 | web3Override.eth.getTransactionFromBlock = function (blockNumber, txIndex, callback) { 34 | if (callback) { 35 | callback(null, data.testTxsByBlock[blockNumber + '-' + txIndex]) 36 | } else { 37 | return data.testTxsByBlock[blockNumber + '-' + txIndex] 38 | } 39 | } 40 | 41 | web3Override.eth.getBlockNumber = function (callback) { callback('web3 modified testing purposes :)') } 42 | 43 | web3Override.eth.setProvider = function (provider) {} 44 | 45 | web3Override.eth.providers = { 'HttpProvider': function (url) {} } 46 | 47 | web3Override.eth.currentProvider = {'host': 'test provider'} 48 | 49 | if (typeof (module) !== 'undefined' && typeof (module.exports) !== 'undefined') { 50 | module.exports = web3Override 51 | } 52 | -------------------------------------------------------------------------------- /remix-debug/test/sol/simple_storage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | 3 | contract SimpleStorage { 4 | uint public storedData; 5 | address owner; 6 | 7 | constructor(uint initialValue) public { 8 | storedData = initialValue; 9 | owner = msg.sender; 10 | } 11 | 12 | function set(uint x) public { 13 | storedData = x; 14 | require(msg.sender != owner); 15 | storedData = x + 2; 16 | } 17 | 18 | function get() public view returns (uint retVal) { 19 | return storedData; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /remix-debug/test/tests.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | require('./decoder/decodeInfo.js') 4 | require('./decoder/storageLocation.js') 5 | require('./decoder/storageDecoder.js') 6 | require('./decoder/localDecoder.js') 7 | require('./debugger.js') 8 | -------------------------------------------------------------------------------- /remix-debugger/assets/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/remix-debugger/assets/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /remix-debugger/assets/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/remix-debugger/assets/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /remix-debugger/assets/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/remix-debugger/assets/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /remix-debugger/assets/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/remix-debugger/assets/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /remix-debugger/assets/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/remix-debugger/assets/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /remix-debugger/ci/browser_tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if test $(uname -s) = "Darwin" 6 | then 7 | OS="osx" 8 | FILEFORMAT="zip" 9 | else 10 | OS="linux" 11 | FILEFORMAT="tar.gz" 12 | fi 13 | SC_VERSION="4.4.11" 14 | SAUCECONNECT_URL="https://saucelabs.com/downloads/sc-$SC_VERSION-$OS.$FILEFORMAT" 15 | SAUCECONNECT_USERNAME="yanneth" 16 | SAUCECONNECT_ACCESSKEY="1f5a4560-b02b-41aa-b52b-f033aad30870" 17 | BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}} 18 | SAUCECONNECT_JOBIDENTIFIER="remix_tests_${BUILD_ID}" 19 | SAUCECONNECT_READYFILE="sc.ready" 20 | TEST_EXITCODE=0 21 | 22 | npm run build 23 | npm run serve & 24 | 25 | wget $SAUCECONNECT_URL 26 | tar -zxvf sc-"$SC_VERSION"-"$OS"."$FILEFORMAT" 27 | ./sc-"$SC_VERSION"-$OS/bin/sc -u $SAUCECONNECT_USERNAME -k $SAUCECONNECT_ACCESSKEY -i $SAUCECONNECT_JOBIDENTIFIER --readyfile $SAUCECONNECT_READYFILE & 28 | while [ ! -f $SAUCECONNECT_READYFILE ]; do 29 | sleep .5 30 | done 31 | 32 | npm run nightwatch_remote_parallel || TEST_EXITCODE=1 33 | 34 | node ci/sauceDisconnect.js $SAUCECONNECT_USERNAME $SAUCECONNECT_ACCESSKEY $SAUCECONNECT_JOBIDENTIFIER 35 | 36 | echo $TEST_EXITCODE 37 | if [ $TEST_EXITCODE -eq 1 ] 38 | then 39 | exit 1 40 | fi 41 | -------------------------------------------------------------------------------- /remix-debugger/ci/deploy_from_travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | SHA=`git rev-parse --verify HEAD` 6 | 7 | git config user.name "Travis CI" 8 | git config user.email "builds@ethereum.org" 9 | git checkout --orphan gh-pages 10 | git rm --cached -r . 11 | echo "# Automatic build" > README.md 12 | echo "Built website from {$SHA}. See https://github.com/ethereum/remix/ for details." >> README.md 13 | # -f is needed because "build" is part of .gitignore 14 | 15 | # copying file to the root folder 16 | cp remix-debugger/index.html index.html 17 | mkdir build 18 | cp remix-debugger/build/app.js build/app.js 19 | mkdir assets 20 | cp -R remix-debugger/assets/. assets/ 21 | 22 | git add -f README.md index.html build/app.js assets 23 | git commit -m "Built website from {$SHA}." 24 | 25 | ENCRYPTION_LABEL=fade88419824 26 | ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key" 27 | ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv" 28 | ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR} 29 | ENCRYPTED_IV=${!ENCRYPTED_IV_VAR} 30 | openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ci/deploy_key.enc -out deploy_key -d 31 | chmod 600 deploy_key 32 | eval `ssh-agent -s` 33 | ssh-add deploy_key 34 | 35 | git push -f git@github.com:ethereum/remix.git gh-pages 36 | -------------------------------------------------------------------------------- /remix-debugger/ci/deploy_key.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/remix/2973bb621031f604a918b9435eb7d168b0c8b5e8/remix-debugger/ci/deploy_key.enc -------------------------------------------------------------------------------- /remix-debugger/findClient.js: -------------------------------------------------------------------------------- 1 | var which = require('which') 2 | 3 | var geth = null 4 | var eth = null 5 | 6 | try { 7 | geth = which.sync('geth') 8 | } catch (e) { 9 | } 10 | 11 | try { 12 | eth = which.sync('eth') 13 | } catch (e) { 14 | } 15 | if (process.argv.length > 2) { 16 | if (geth && process.argv[2] === 'geth') { 17 | runGeth() 18 | } else if (eth && process.argv[2] === 'eth') { 19 | runEth() 20 | } 21 | } else if (geth && eth) { 22 | console.log('both eth and geth has been found in your system') 23 | console.log('restart the command with the desired client:') 24 | console.log('npm run start_eth') 25 | console.log('or') 26 | console.log('npm run start_geth') 27 | } else if (geth) { 28 | runGeth() 29 | } else if (eth) { 30 | runEth() 31 | } else { 32 | console.log('neither eth or geth has been found in your system') 33 | } 34 | 35 | function runEth () { 36 | console.log('starting eth...') 37 | process.exit(20) 38 | } 39 | 40 | function runGeth () { 41 | console.log('starting geth...') 42 | process.exit(21) 43 | } 44 | -------------------------------------------------------------------------------- /remix-debugger/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /remix-debugger/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var VMDebugger = require('./src/ui/VmDebugger') 3 | var Debugger = require('./src/ui/Ethdebugger') 4 | var BasicPanel = require('./src/ui/BasicPanel') 5 | var TreeView = require('./src/ui/TreeView') 6 | 7 | if (typeof (module) !== 'undefined' && typeof (module.exports) !== 'undefined') { 8 | module.exports = modules() 9 | } 10 | 11 | if (typeof (window) !== 'undefined') { 12 | window.remix = modules() 13 | } 14 | 15 | function modules () { 16 | return { 17 | ui: { 18 | Debugger: Debugger, 19 | VMdebugger: VMDebugger, 20 | BasicPanel: BasicPanel, 21 | TreeView: TreeView 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /remix-debugger/runNode.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | node findClient.js $1 4 | RUNCLIENT=$? 5 | if [ $RUNCLIENT -eq '20' ] 6 | then 7 | npm run start_eth 8 | fi 9 | 10 | if [ $RUNCLIENT -eq '21' ] 11 | then 12 | echo $? 13 | npm run start_geth 14 | fi -------------------------------------------------------------------------------- /remix-debugger/src/ui/BasicPanel.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var style = require('./styles/basicStyles') 3 | var yo = require('yo-yo') 4 | var remixLib = require('remix-lib') 5 | var ui = remixLib.helpers.ui 6 | 7 | var csjs = require('csjs-inject') 8 | 9 | var css = csjs` 10 | .container { 11 | width: 70%; 12 | } 13 | ` 14 | 15 | function BasicPanel (_name, _width, _height) { 16 | this.data 17 | this.name = _name 18 | this.width = _width 19 | this.height = _height 20 | this.view 21 | } 22 | 23 | BasicPanel.prototype.update = function () { 24 | yo.update(this.view, this.render()) 25 | } 26 | 27 | BasicPanel.prototype.hide = function () { 28 | this.view.style.display = 'none' 29 | } 30 | 31 | BasicPanel.prototype.show = function () { 32 | this.view.style.display = 'block' 33 | } 34 | 35 | BasicPanel.prototype.render = function () { 36 | var view = yo` 37 |
38 |
39 | ${this.name} 40 |
41 |
42 |
${this.data}
43 |
44 |
` 45 | if (!this.view) { 46 | this.view = view 47 | } 48 | return view 49 | } 50 | 51 | module.exports = BasicPanel 52 | -------------------------------------------------------------------------------- /remix-debugger/src/ui/CalldataPanel.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var DropdownPanel = require('./DropdownPanel') 3 | var yo = require('yo-yo') 4 | 5 | function CalldataPanel (_parent, _traceManager) { 6 | this.parent = _parent 7 | this.traceManager = _traceManager 8 | this.basicPanel = new DropdownPanel('Call Data', {json: true}) 9 | this.init() 10 | } 11 | 12 | CalldataPanel.prototype.render = function () { 13 | return yo`
${this.basicPanel.render()}
` 14 | } 15 | 16 | CalldataPanel.prototype.init = function () { 17 | var self = this 18 | this.parent.event.register('indexChanged', this, function (index) { 19 | if (index < 0) return 20 | if (self.parent.currentStepIndex !== index) return 21 | 22 | self.traceManager.getCallDataAt(index, function (error, calldata) { 23 | if (error) { 24 | self.basicPanel.update({}) 25 | console.log(error) 26 | } else if (self.parent.currentStepIndex === index) { 27 | self.basicPanel.update(calldata) 28 | } 29 | }) 30 | }) 31 | } 32 | 33 | module.exports = CalldataPanel 34 | -------------------------------------------------------------------------------- /remix-debugger/src/ui/CallstackPanel.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var DropdownPanel = require('./DropdownPanel') 3 | var yo = require('yo-yo') 4 | 5 | function CallstackPanel (_parent, _traceManager) { 6 | this.parent = _parent 7 | this.traceManager = _traceManager 8 | this.basicPanel = new DropdownPanel('Call Stack', {json: true}) 9 | this.init() 10 | } 11 | 12 | CallstackPanel.prototype.render = function () { 13 | return yo`
${this.basicPanel.render()}
` 14 | } 15 | 16 | CallstackPanel.prototype.init = function () { 17 | var self = this 18 | this.parent.event.register('indexChanged', this, function (index) { 19 | if (index < 0) return 20 | if (self.parent.currentStepIndex !== index) return 21 | 22 | self.traceManager.getCallStackAt(index, function (error, callstack) { 23 | if (error) { 24 | console.log(error) 25 | self.basicPanel.update({}) 26 | } else if (self.parent.currentStepIndex === index) { 27 | self.basicPanel.update(callstack) 28 | } 29 | }) 30 | }) 31 | } 32 | 33 | module.exports = CallstackPanel 34 | -------------------------------------------------------------------------------- /remix-debugger/src/ui/MemoryPanel.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var DropdownPanel = require('./DropdownPanel') 3 | var remixLib = require('remix-lib') 4 | var ui = remixLib.helpers.ui 5 | var yo = require('yo-yo') 6 | 7 | function MemoryPanel (_parent, _traceManager) { 8 | this.parent = _parent 9 | this.traceManager = _traceManager 10 | this.basicPanel = new DropdownPanel('Memory', { 11 | json: true, 12 | css: { 13 | 'font-family': 'monospace' 14 | }}) 15 | this.init() 16 | } 17 | 18 | MemoryPanel.prototype.render = function () { 19 | return yo`
${this.basicPanel.render()}
` 20 | } 21 | 22 | MemoryPanel.prototype.init = function () { 23 | var self = this 24 | this.parent.event.register('indexChanged', this, function (index) { 25 | if (index < 0) return 26 | if (self.parent.currentStepIndex !== index) return 27 | 28 | self.traceManager.getMemoryAt(index, function (error, memory) { 29 | if (error) { 30 | console.log(error) 31 | self.basicPanel.update({}) 32 | } else if (self.parent.currentStepIndex === index) { 33 | self.basicPanel.update(ui.formatMemory(memory, 16)) 34 | } 35 | }) 36 | }) 37 | } 38 | 39 | module.exports = MemoryPanel 40 | -------------------------------------------------------------------------------- /remix-debugger/src/ui/StackPanel.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var DropdownPanel = require('./DropdownPanel') 3 | var yo = require('yo-yo') 4 | 5 | function StackPanel (_parent, _traceManager) { 6 | this.parent = _parent 7 | this.traceManager = _traceManager 8 | this.basicPanel = new DropdownPanel('Stack', {json: true}) 9 | this.init() 10 | } 11 | 12 | StackPanel.prototype.render = function () { 13 | return yo`
${this.basicPanel.render()}
` 14 | } 15 | 16 | StackPanel.prototype.init = function () { 17 | var self = this 18 | this.parent.event.register('indexChanged', this, function (index) { 19 | if (index < 0) return 20 | if (self.parent.currentStepIndex !== index) return 21 | 22 | self.traceManager.getStackAt(index, function (error, stack) { 23 | if (error) { 24 | self.basicPanel.update({}) 25 | console.log(error) 26 | } else if (self.parent.currentStepIndex === index) { 27 | self.basicPanel.update(stack) 28 | } 29 | }) 30 | }) 31 | } 32 | 33 | module.exports = StackPanel 34 | -------------------------------------------------------------------------------- /remix-debugger/src/ui/StoragePanel.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var DropdownPanel = require('./DropdownPanel') 3 | var remixCore = require('remix-core') 4 | var StorageViewer = remixCore.storage.StorageViewer 5 | var yo = require('yo-yo') 6 | 7 | function StoragePanel (_parent, _traceManager) { 8 | this.parent = _parent 9 | this.storageResolver = null 10 | this.traceManager = _traceManager 11 | this.basicPanel = new DropdownPanel('Storage', {json: true}) 12 | this.init() 13 | this.disabled = false 14 | } 15 | 16 | StoragePanel.prototype.render = function () { 17 | return yo`
${this.basicPanel.render()}
` 18 | } 19 | 20 | StoragePanel.prototype.init = function () { 21 | var self = this 22 | this.parent.event.register('indexChanged', this, function (index) { 23 | if (self.disabled) return 24 | if (index < 0) return 25 | if (self.parent.currentStepIndex !== index) return 26 | if (!self.storageResolver) return 27 | 28 | this.traceManager.getCurrentCalledAddressAt(index, (error, address) => { 29 | if (!error) { 30 | var storageViewer = new StorageViewer({ 31 | stepIndex: self.parent.currentStepIndex, 32 | tx: self.parent.tx, 33 | address: address 34 | }, self.storageResolver, self.traceManager) 35 | 36 | storageViewer.storageRange((error, storage) => { 37 | if (error) { 38 | console.log(error) 39 | self.basicPanel.update({}) 40 | } else if (self.parent.currentStepIndex === index) { 41 | var header = storageViewer.isComplete(address) ? 'completely loaded' : 'partially loaded...' 42 | self.basicPanel.update(storage, header) 43 | } 44 | }) 45 | } 46 | }) 47 | }) 48 | } 49 | 50 | module.exports = StoragePanel 51 | -------------------------------------------------------------------------------- /remix-debugger/src/ui/styles/dropdownPanel.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | title: { 4 | 'border': '1px solid #dadada', 5 | 'background-color': 'white', 6 | 'width': '100%', 7 | 'color': '#363f47', 8 | 'margin-top': '5px', 9 | 'cursor': 'pointer' 10 | }, 11 | titleInner: { 12 | 'display': 'inline-block' 13 | }, 14 | content: { 15 | 'color': '#111111', 16 | 'width': '100%', 17 | 'min-height': '20px' 18 | }, 19 | inner: { 20 | 'padding': '2px', 21 | 'word-break': 'break-all' 22 | }, 23 | copyBtn: { 24 | 'float': 'right', 25 | 'margin-top': '3px' 26 | }, 27 | caret: { 28 | 'margin-left': '10px', 29 | 'margin-right': '10px' 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /remix-debugger/src/ui/styles/sliderStyles.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | rule: { 4 | 'width': '100%' 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /remix-debugger/src/ui/styles/treeView.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | cssUl: { 4 | 'list-style-type': 'none', 5 | '-webkit-margin-before': '0px', 6 | '-webkit-margin-after': '0px', 7 | '-webkit-margin-start': '0px', 8 | '-webkit-margin-end': '0px', 9 | '-webkit-padding-start': '0px' 10 | }, 11 | cssLi: { 12 | 'list-style-type': 'none', 13 | '-webkit-margin-before': '0px', 14 | '-webkit-margin-after': '0px', 15 | '-webkit-margin-start': '0px', 16 | '-webkit-margin-end': '0px', 17 | '-webkit-padding-start': '0px', 18 | 'margin-left': '10px' 19 | }, 20 | label: { 21 | 'vertical-align': 'top', 22 | 'font-family': 'arial,sans-serif' 23 | }, 24 | caret: { 25 | 'margin-top': '3px', 26 | 'width': '10px' 27 | }, 28 | data: { 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /remix-debugger/test-browser/test/sauce.js: -------------------------------------------------------------------------------- 1 | const https = require('https') 2 | 3 | module.exports = function sauce (callback) { 4 | const currentTest = this.client.currentTest 5 | const username = this.client.options.username 6 | const sessionId = this.client.capabilities['webdriver.remote.sessionid'] 7 | const accessKey = this.client.options.accessKey 8 | 9 | if (!this.client.launch_url.match(/saucelabs/)) { 10 | console.log('Not saucelabs ...') 11 | return callback() 12 | } 13 | 14 | if (!username || !accessKey || !sessionId) { 15 | console.log(this.client) 16 | console.log('No username, accessKey or sessionId') 17 | return callback() 18 | } 19 | 20 | const passed = currentTest.results.passed === currentTest.results.tests 21 | 22 | const data = JSON.stringify({passed}) 23 | 24 | const requestPath = `/rest/v1/${username}/jobs/${sessionId}` 25 | 26 | function responseCallback (res) { 27 | res.setEncoding('utf8') 28 | console.log('Response: ', res.statusCode, JSON.stringify(res.headers)) 29 | res.on('data', function onData (chunk) { 30 | console.log('BODY: ' + chunk) 31 | }) 32 | res.on('end', function onEnd () { 33 | console.info('Finished updating saucelabs') 34 | callback() 35 | }) 36 | } 37 | 38 | try { 39 | console.log('Updating saucelabs', requestPath) 40 | 41 | const req = https.request({ 42 | hostname: 'saucelabs.com', 43 | path: requestPath, 44 | method: 'PUT', 45 | auth: `${username}:${accessKey}`, 46 | headers: { 47 | 'Content-Type': 'application/json', 48 | 'Content-Length': data.length 49 | } 50 | }, responseCallback) 51 | 52 | req.on('error', function onError (e) { 53 | console.log('problem with request: ' + e.message) 54 | }) 55 | req.write(data) 56 | req.end() 57 | } catch (error) { 58 | console.log('Error', error) 59 | callback() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /remix-lib/.npmignore: -------------------------------------------------------------------------------- 1 | test/ -------------------------------------------------------------------------------- /remix-lib/README.md: -------------------------------------------------------------------------------- 1 | **The project has been moved to https://github.com/ethereum/remix-project/tree/master/libs/remix-lib** 2 | 3 | # `remix-lib` 4 | 5 | Provides: 6 | 7 | { 8 | EventManager: EventManager, 9 | helpers: { 10 | trace: traceHelper, 11 | ui: uiHelper 12 | }, 13 | vm: { 14 | Web3Providers: Web3Providers, 15 | DummyProvider: DummyProvider, 16 | Web3VMProvider: Web3VMProvider 17 | }, 18 | SourceMappingDecoder: SourceMappingDecoder, 19 | SourceLocationTracker: SourceLocationTracker, 20 | init: init, 21 | util: util, 22 | AstWalker: AstWalker, 23 | ui: { 24 | styleGuide: styleGuide 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /remix-lib/src/astWalker.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | /** 3 | * Crawl the given AST through the function walk(ast, callback) 4 | */ 5 | function AstWalker () { 6 | } 7 | 8 | /** 9 | * visit all the AST nodes 10 | * 11 | * @param {Object} ast - AST node 12 | * @param {Object or Function} callback - if (Function) the function will be called for every node. 13 | * - if (Object) callback[] will be called for 14 | * every node of type . callback["*"] will be called for all other nodes. 15 | * in each case, if the callback returns false it does not descend into children. 16 | * If no callback for the current type, children are visited. 17 | */ 18 | AstWalker.prototype.walk = function (ast, callback) { 19 | if (callback instanceof Function) { 20 | callback = {'*': callback} 21 | } 22 | if (!('*' in callback)) { 23 | callback['*'] = function () { return true } 24 | } 25 | if (manageCallBack(ast, callback) && ast.children && ast.children.length > 0) { 26 | for (let k in ast.children) { 27 | const child = ast.children[k] 28 | this.walk(child, callback) 29 | } 30 | } 31 | } 32 | 33 | /** 34 | * walk the given @astList 35 | * 36 | * @param {Object} sourcesList - sources list (containing root AST node) 37 | * @param {Function} - callback used by AstWalker to compute response 38 | */ 39 | AstWalker.prototype.walkAstList = function (sourcesList, callback) { 40 | const walker = new AstWalker() 41 | for (let k in sourcesList) { 42 | walker.walk(sourcesList[k].legacyAST, callback) 43 | } 44 | } 45 | 46 | function manageCallBack (node, callback) { 47 | if (node.name in callback) { 48 | return callback[node.name](node) 49 | } else { 50 | return callback['*'](node) 51 | } 52 | } 53 | 54 | module.exports = AstWalker 55 | -------------------------------------------------------------------------------- /remix-lib/src/code/disassembler.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const parseCode = require('./codeUtils').parseCode 4 | const util = require('../util') 5 | 6 | const createExpressions = function (instructions) { 7 | const expressions = [] 8 | let labels = 0 9 | for (let i = 0; i < instructions.length; i++) { 10 | const expr = instructions[i] 11 | expr.functional = false 12 | if (expr.name === 'JUMPDEST') { 13 | expr.label = 'label' + (++labels) 14 | } else if (expr.name.slice(0, 3) === 'DUP') { 15 | } else if (expr.name.slice(0, 4) === 'SWAP') { 16 | } else if (expr.out <= 1 && expr.in <= expressions.length) { 17 | let error = false 18 | for (let j = 0; j < expr.in && !error; j++) { 19 | const arg = expressions[expressions.length - j - 1] 20 | if (!arg.functional || arg.out !== 1) { 21 | error = true 22 | break 23 | } 24 | } 25 | if (!error) { 26 | expr.args = expressions.splice(expressions.length - expr.in) 27 | expr.functional = true 28 | } 29 | } 30 | expressions.push(expr) 31 | } 32 | return expressions 33 | } 34 | 35 | const toString = function (expr) { 36 | if (expr.name.slice(0, 4) === 'PUSH') { 37 | return util.hexConvert(expr.pushData) 38 | } else if (expr.name === 'JUMPDEST') { 39 | return expr.label + ':' 40 | } else if (expr.args) { 41 | return expr.name.toLowerCase() + '(' + expr.args.reverse().map(toString).join(', ') + ')' 42 | } else { 43 | return expr.name.toLowerCase() 44 | } 45 | } 46 | 47 | const disassemble = function (input) { 48 | const code = parseCode(util.hexToIntArray(input)) 49 | return createExpressions(code).map(toString).join('\n') 50 | } 51 | 52 | module.exports = { 53 | /** 54 | * Disassembler that turns bytecode (as a hex string) into Solidity inline assembly. 55 | */ 56 | disassemble: disassemble 57 | } 58 | -------------------------------------------------------------------------------- /remix-lib/src/execution/typeConversion.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const ethJSUtil = require('ethereumjs-util') 3 | const BN = ethJSUtil.BN 4 | 5 | module.exports = { 6 | toInt: (h) => { 7 | if (h.indexOf && h.indexOf('0x') === 0) { 8 | return (new BN(h.replace('0x', ''), 16)).toString(10) 9 | } else if (h.constructor && h.constructor.name === 'BigNumber' || BN.isBN(h)) { 10 | return h.toString(10) 11 | } 12 | return h 13 | }, 14 | stringify: stringify 15 | } 16 | 17 | function stringify (v) { 18 | try { 19 | if (v instanceof Array) { 20 | const ret = [] 21 | for (var k in v) { 22 | ret.push(stringify(v[k])) 23 | } 24 | return ret 25 | } else if (BN.isBN(v) || (v.constructor && v.constructor.name === 'BigNumber')) { 26 | return v.toString(10) 27 | } else if (v._isBuffer) { 28 | return ethJSUtil.bufferToHex(v) 29 | } else if (typeof v === 'object') { 30 | const retObject = {} 31 | for (let i in v) { 32 | retObject[i] = stringify(v[i]) 33 | } 34 | return retObject 35 | } else { 36 | return v 37 | } 38 | } catch (e) { 39 | console.log(e) 40 | return v 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /remix-lib/src/helpers/compilerHelper.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | compilerInput: compilerInput 3 | } 4 | 5 | function compilerInput (contracts) { 6 | return JSON.stringify({ 7 | language: 'Solidity', 8 | sources: { 9 | 'test.sol': { 10 | content: contracts 11 | } 12 | }, 13 | settings: { 14 | optimizer: { 15 | enabled: false, 16 | runs: 200 17 | }, 18 | outputSelection: { 19 | '*': { 20 | '': [ 'legacyAST', 'ast' ], 21 | '*': [ 'abi', 'metadata', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ] 22 | } 23 | } 24 | } 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /remix-lib/src/helpers/txResultHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const { bufferToHex, isHexString } = require('ethereumjs-util') 3 | 4 | function convertToPrefixedHex (input) { 5 | if (input === undefined || input === null || isHexString(input)) { 6 | return input 7 | } else if (Buffer.isBuffer(input)) { 8 | return bufferToHex(input) 9 | } 10 | return '0x' + input.toString(16) 11 | } 12 | 13 | /* 14 | txResult.result can be 3 different things: 15 | - VM call or tx: ethereumjs-vm result object 16 | - Node transaction: object returned from eth.getTransactionReceipt() 17 | - Node call: return value from function call (not an object) 18 | 19 | Also, VM results use BN and Buffers, Node results use hex strings/ints, 20 | So we need to normalize the values to prefixed hex strings 21 | */ 22 | function resultToRemixTx (txResult) { 23 | const { result, transactionHash } = txResult 24 | const { status, execResult, gasUsed, createdAddress, contractAddress } = result 25 | let returnValue, errorMessage 26 | 27 | if (isHexString(result)) { 28 | returnValue = result 29 | } else if (execResult !== undefined) { 30 | returnValue = execResult.returnValue 31 | errorMessage = execResult.exceptionError 32 | } 33 | 34 | return { 35 | transactionHash, 36 | status, 37 | gasUsed: convertToPrefixedHex(gasUsed), 38 | error: errorMessage, 39 | return: convertToPrefixedHex(returnValue), 40 | createdAddress: convertToPrefixedHex(createdAddress || contractAddress) 41 | } 42 | } 43 | 44 | module.exports = { 45 | resultToRemixTx 46 | } 47 | -------------------------------------------------------------------------------- /remix-lib/src/offsetToLineColumnConverter.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const SourceMappingDecoder = require('./sourceMappingDecoder') 3 | 4 | function offsetToColumnConverter (compilerEvent) { 5 | this.lineBreakPositionsByContent = {} 6 | this.sourceMappingDecoder = new SourceMappingDecoder() 7 | var self = this 8 | if (compilerEvent) { 9 | compilerEvent.register('compilationFinished', (success, data, source) => { 10 | self.clear() 11 | }) 12 | } 13 | } 14 | 15 | offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, sources, asts) { 16 | if (!this.lineBreakPositionsByContent[file]) { 17 | for (let filename in asts) { 18 | const source = asts[filename] 19 | // source id was string before. in newer versions it has been changed to an integer so we need to check the type here 20 | if (typeof source.id === 'string') source.id = parseInt(source.id, 10) 21 | if (source.id === file) { 22 | this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[filename].content) 23 | break 24 | } 25 | } 26 | } 27 | return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file]) 28 | } 29 | 30 | offsetToColumnConverter.prototype.clear = function () { 31 | this.lineBreakPositionsByContent = {} 32 | } 33 | 34 | module.exports = offsetToColumnConverter 35 | -------------------------------------------------------------------------------- /remix-lib/src/trace/traceRetriever.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | function TraceRetriever (options) { 4 | this.web3 = options.web3 5 | } 6 | 7 | TraceRetriever.prototype.getTrace = function (txHash, callback) { 8 | const options = { 9 | disableStorage: true, 10 | disableMemory: false, 11 | disableStack: false, 12 | fullStorage: false 13 | } 14 | this.web3.debug.traceTransaction(txHash, options, function (error, result) { 15 | callback(error, result) 16 | }) 17 | } 18 | 19 | module.exports = TraceRetriever 20 | -------------------------------------------------------------------------------- /remix-lib/src/web3Provider/dummyProvider.js: -------------------------------------------------------------------------------- 1 | function dummyProvider () { 2 | this.eth = {} 3 | this.debug = {} 4 | this.eth.getCode = (address, cb) => { return this.getCode(address, cb) } 5 | this.eth.getTransaction = (hash, cb) => { return this.getTransaction(hash, cb) } 6 | this.eth.getTransactionFromBlock = (blockNumber, txIndex, cb) => { return this.getTransactionFromBlock(blockNumber, txIndex, cb) } 7 | this.eth.getBlockNumber = (cb) => { return this.getBlockNumber(cb) } 8 | this.debug.traceTransaction = (hash, options, cb) => { return this.traceTransaction(hash, options, cb) } 9 | this.debug.storageRangeAt = (blockNumber, txIndex, address, start, end, maxLength, cb) => { return this.storageRangeAt(blockNumber, txIndex, address, start, end, maxLength, cb) } 10 | this.providers = { 'HttpProvider': function (url) {} } 11 | this.currentProvider = {'host': ''} 12 | } 13 | 14 | dummyProvider.prototype.getCode = function (address, cb) { 15 | cb(null, '') 16 | } 17 | 18 | dummyProvider.prototype.setProvider = function (provider) {} 19 | 20 | dummyProvider.prototype.traceTransaction = function (txHash, options, cb) { 21 | if (cb) { 22 | cb(null, {}) 23 | } 24 | return {} 25 | } 26 | 27 | dummyProvider.prototype.storageRangeAt = function (blockNumber, txIndex, address, start, end, maxLength, cb) { 28 | if (cb) { 29 | cb(null, {}) 30 | } 31 | return {} 32 | } 33 | 34 | dummyProvider.prototype.getBlockNumber = function (cb) { cb(null, '') } 35 | 36 | dummyProvider.prototype.getTransaction = function (txHash, cb) { 37 | if (cb) { 38 | cb(null, {}) 39 | } 40 | return {} 41 | } 42 | 43 | dummyProvider.prototype.getTransactionFromBlock = function (blockNumber, txIndex, cb) { 44 | if (cb) { 45 | cb(null, {}) 46 | } 47 | return {} 48 | } 49 | 50 | module.exports = dummyProvider 51 | -------------------------------------------------------------------------------- /remix-lib/src/web3Provider/web3Providers.js: -------------------------------------------------------------------------------- 1 | const Web3VMProvider = require('./web3VmProvider') 2 | const init = require('../init') 3 | 4 | function Web3Providers () { 5 | this.modes = {} 6 | } 7 | 8 | Web3Providers.prototype.addProvider = function (type, obj) { 9 | if (type === 'INTERNAL') { 10 | const web3 = init.loadWeb3() 11 | this.addWeb3(type, web3) 12 | } else if (type === 'vm') { 13 | this.addVM(type, obj) 14 | } else { 15 | init.extendWeb3(obj) 16 | this.addWeb3(type, obj) 17 | } 18 | } 19 | 20 | Web3Providers.prototype.get = function (type, cb) { 21 | if (this.modes[type]) { 22 | cb(null, this.modes[type]) 23 | } else { 24 | cb('error: this provider has not been setup (' + type + ')', null) 25 | } 26 | } 27 | 28 | Web3Providers.prototype.addWeb3 = function (type, web3) { 29 | this.modes[type] = web3 30 | } 31 | 32 | Web3Providers.prototype.addVM = function (type, vm) { 33 | const vmProvider = new Web3VMProvider() 34 | vmProvider.setVM(vm) 35 | this.modes[type] = vmProvider 36 | } 37 | 38 | module.exports = Web3Providers 39 | -------------------------------------------------------------------------------- /remix-lib/test/eventManager.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const tape = require('tape') 3 | const EventManager = require('../src/eventManager') 4 | tape('eventManager', function (t) { 5 | t.test('eventManager', function (st) { 6 | const events = new EventManager() 7 | const listenner = {} 8 | 9 | let trace = '' 10 | listenner.listen = function (data1) { 11 | trace += data1 12 | } 13 | const registeredFunction = function (data) { 14 | trace += data 15 | } 16 | events.register('event1', listenner, listenner.listen) 17 | events.register('event2', registeredFunction) 18 | events.trigger('event1', ['event1']) 19 | events.trigger('event2', ['event2']) 20 | st.equal(trace, 'event1event2') 21 | 22 | events.unregister('event1', listenner.listen) 23 | st.equal(events.registered['event1'].length, 1) 24 | st.equal(events.registered['event2'].length, 1) 25 | 26 | events.unregister('event1', listenner, listenner.listen) 27 | st.equal(events.registered['event1'].length, 0) 28 | st.equal(events.registered['event2'].length, 1) 29 | 30 | events.unregister('event2', registeredFunction) 31 | st.equal(events.registered['event1'].length, 0) 32 | st.equal(events.registered['event2'].length, 0) 33 | st.end() 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /remix-lib/test/init.js: -------------------------------------------------------------------------------- 1 | var init = { 2 | overrideWeb3: function (web3, web3Override) { 3 | web3.eth.getCode = web3Override.getCode 4 | web3.debug.traceTransaction = web3Override.traceTransaction 5 | web3.debug.storageRangeAt = web3Override.storageRangeAt 6 | web3.eth.getTransaction = web3Override.getTransaction 7 | web3.eth.getTransactionFromBlock = web3Override.getTransactionFromBlock 8 | web3.eth.getBlockNumber = web3Override.getBlockNumber 9 | }, 10 | 11 | readFile: function (filename, callback) { 12 | const fs = require('fs') 13 | try { 14 | console.log('reading ' + filename) 15 | if (callback) { 16 | fs.readFile(filename, 'utf8', callback) 17 | } else { 18 | return fs.readFileSync(filename, 'utf8') 19 | } 20 | } catch (e) { 21 | console.log(e) 22 | if (callback) { 23 | callback(e) 24 | } else { 25 | return e 26 | } 27 | } 28 | } 29 | } 30 | 31 | module.exports = init 32 | -------------------------------------------------------------------------------- /remix-lib/test/resources/testWeb3.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const init = require('../init') 3 | const web3Override = {} 4 | web3Override.eth = {} 5 | web3Override.debug = {} 6 | let data = init.readFile(require('path').resolve(__dirname, 'testWeb3.json')) 7 | data = JSON.parse(data) 8 | 9 | web3Override.eth.getCode = function (address, callback) { 10 | if (callback) { 11 | callback(null, data.testCodes[address]) 12 | } else { 13 | return data.testCodes[address] 14 | } 15 | } 16 | 17 | web3Override.debug.traceTransaction = function (txHash, options, callback) { 18 | callback(null, data.testTraces[txHash]) 19 | } 20 | 21 | web3Override.debug.storageRangeAt = function (blockNumber, txIndex, address, start, maxSize, callback) { 22 | callback(null, { storage: {}, complete: true }) 23 | } 24 | 25 | web3Override.eth.getTransaction = function (txHash, callback) { 26 | if (callback) { 27 | callback(null, data.testTxs[txHash]) 28 | } else { 29 | return data.testTxs[txHash] 30 | } 31 | } 32 | 33 | web3Override.eth.getTransactionFromBlock = function (blockNumber, txIndex, callback) { 34 | if (callback) { 35 | callback(null, data.testTxsByBlock[blockNumber + '-' + txIndex]) 36 | } else { 37 | return data.testTxsByBlock[blockNumber + '-' + txIndex] 38 | } 39 | } 40 | 41 | web3Override.eth.getBlockNumber = function (callback) { callback('web3 modified testing purposes :)') } 42 | 43 | web3Override.eth.setProvider = function (provider) {} 44 | 45 | web3Override.eth.providers = { 'HttpProvider': function (url) {} } 46 | 47 | web3Override.eth.currentProvider = {'host': 'test provider'} 48 | 49 | if (typeof (module) !== 'undefined' && typeof (module.exports) !== 'undefined') { 50 | module.exports = web3Override 51 | } 52 | -------------------------------------------------------------------------------- /remix-lib/test/tests.js: -------------------------------------------------------------------------------- 1 | require('./astwalker.js') 2 | require('./eventManager.js') 3 | require('./sourceMappingDecoder.js') 4 | require('./util.js') 5 | require('./txFormat.js') 6 | require('./txHelper.js') 7 | 8 | require('./traceManager.js') 9 | require('./codeManager.js') 10 | require('./disassembler.js') 11 | require('./txResultHelper.js') 12 | -------------------------------------------------------------------------------- /remix-simulator/.npmignore: -------------------------------------------------------------------------------- 1 | test/ -------------------------------------------------------------------------------- /remix-simulator/bin/ethsim: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const program = require('commander') 4 | const version = require('../package.json').version 5 | 6 | program 7 | .command('version') 8 | .description("outputs version number") 9 | .action(() => { 10 | console.log(version) 11 | process.exit(0) 12 | }) 13 | 14 | program 15 | .command('help') 16 | .description("outputs usage information") 17 | .action(() => { 18 | program.help() 19 | process.exit(0) 20 | }) 21 | 22 | program 23 | .option('-p, --port [port]', 'specify port') 24 | .option('-b, --ip [host]', 'specify host') 25 | .option('-c, --coinbase [coinbase]', 'specify host') 26 | .option('--rpc', 'run rpc server only') 27 | .option('--details', 'display payloads for every requests and their responses') 28 | .parse(process.argv) 29 | 30 | const Server = require('../src/server') 31 | const server = new Server({ 32 | coinbase: program.coinbase || "0x0000000000000000000000000000000000000000", 33 | rpc: program.rpc, 34 | logDetails: program.details 35 | }) 36 | server.start(program.host || '127.0.0.1', program.port || 8545) 37 | 38 | -------------------------------------------------------------------------------- /remix-simulator/index.js: -------------------------------------------------------------------------------- 1 | const Provider = require('./src/provider') 2 | 3 | module.exports = { 4 | Provider: Provider 5 | } 6 | -------------------------------------------------------------------------------- /remix-simulator/src/genesis.js: -------------------------------------------------------------------------------- 1 | const EthJSBlock = require('ethereumjs-block') 2 | const ethJSUtil = require('ethereumjs-util') 3 | const BN = ethJSUtil.BN 4 | 5 | function generateBlock (executionContext) { 6 | const block = new EthJSBlock({ 7 | header: { 8 | timestamp: (new Date().getTime() / 1000 | 0), 9 | number: 0, 10 | coinbase: '0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a', 11 | difficulty: (new BN('69762765929000', 10)), 12 | gasLimit: new BN('8000000').imuln(1) 13 | }, 14 | transactions: [], 15 | uncleHeaders: [] 16 | }) 17 | 18 | executionContext.vm().runBlock({ block: block, generate: true, skipBlockValidation: true, skipBalance: false }).then(() => { 19 | executionContext.addBlock(block) 20 | }) 21 | } 22 | 23 | module.exports = generateBlock 24 | -------------------------------------------------------------------------------- /remix-simulator/src/methods/misc.js: -------------------------------------------------------------------------------- 1 | const version = require('../../package.json').version 2 | const web3 = require('web3') 3 | 4 | const Misc = function () { 5 | } 6 | 7 | Misc.prototype.methods = function () { 8 | return { 9 | web3_clientVersion: this.web3_clientVersion.bind(this), 10 | eth_protocolVersion: this.eth_protocolVersion.bind(this), 11 | eth_syncing: this.eth_syncing.bind(this), 12 | eth_mining: this.eth_mining.bind(this), 13 | eth_hashrate: this.eth_hashrate.bind(this), 14 | web3_sha3: this.web3_sha3.bind(this), 15 | eth_getCompilers: this.eth_getCompilers.bind(this), 16 | eth_compileSolidity: this.eth_compileSolidity.bind(this), 17 | eth_compileLLL: this.eth_compileLLL.bind(this), 18 | eth_compileSerpent: this.eth_compileSerpent.bind(this) 19 | } 20 | } 21 | 22 | Misc.prototype.web3_clientVersion = function (payload, cb) { 23 | cb(null, 'Remix Simulator/' + version) 24 | } 25 | 26 | Misc.prototype.eth_protocolVersion = function (payload, cb) { 27 | cb(null, '0x3f') 28 | } 29 | 30 | Misc.prototype.eth_syncing = function (payload, cb) { 31 | cb(null, false) 32 | } 33 | 34 | Misc.prototype.eth_mining = function (payload, cb) { 35 | // TODO: should depend on the state 36 | cb(null, false) 37 | } 38 | 39 | Misc.prototype.eth_hashrate = function (payload, cb) { 40 | cb(null, '0x0') 41 | } 42 | 43 | Misc.prototype.web3_sha3 = function (payload, cb) { 44 | const str = payload.params[0] 45 | cb(null, web3.utils.sha3(str)) 46 | } 47 | 48 | Misc.prototype.eth_getCompilers = function (payload, cb) { 49 | cb(null, []) 50 | } 51 | 52 | Misc.prototype.eth_compileSolidity = function (payload, cb) { 53 | cb(null, 'unsupported') 54 | } 55 | 56 | Misc.prototype.eth_compileLLL = function (payload, cb) { 57 | cb(null, 'unsupported') 58 | } 59 | 60 | Misc.prototype.eth_compileSerpent = function (payload, cb) { 61 | cb(null, 'unsupported') 62 | } 63 | 64 | module.exports = Misc 65 | -------------------------------------------------------------------------------- /remix-simulator/src/methods/net.js: -------------------------------------------------------------------------------- 1 | 2 | const Net = function () { 3 | } 4 | 5 | Net.prototype.methods = function () { 6 | return { 7 | net_version: this.net_version, 8 | net_listening: this.net_listening, 9 | net_peerCount: this.net_peerCount 10 | } 11 | } 12 | 13 | Net.prototype.net_version = function (payload, cb) { 14 | // should be configured networkId 15 | cb(null, 1337) 16 | } 17 | 18 | Net.prototype.net_listening = function (payload, cb) { 19 | cb(null, true) 20 | } 21 | 22 | Net.prototype.net_peerCount = function (payload, cb) { 23 | cb(null, 0) 24 | } 25 | 26 | module.exports = Net 27 | -------------------------------------------------------------------------------- /remix-simulator/src/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const cors = require('cors') 3 | const bodyParser = require('body-parser') 4 | const app = express() 5 | const expressWs = require('express-ws') 6 | const Provider = require('./provider') 7 | const log = require('./utils/logs.js') 8 | 9 | class Server { 10 | constructor (options) { 11 | this.provider = new Provider(options) 12 | this.provider.init().then(() => { 13 | log('Provider initiated') 14 | }).catch((error) => { 15 | log(error) 16 | }) 17 | this.rpcOnly = options.rpc 18 | } 19 | 20 | start (host, port) { 21 | expressWs(app) 22 | 23 | app.use(cors()) 24 | app.use(bodyParser.urlencoded({extended: true})) 25 | app.use(bodyParser.json()) 26 | 27 | app.get('/', (req, res) => { 28 | res.send('Welcome to remix-simulator') 29 | }) 30 | 31 | if (this.rpcOnly) { 32 | app.use((req, res) => { 33 | this.provider.sendAsync(req.body, (err, jsonResponse) => { 34 | if (err) { 35 | return res.send(JSON.stringify({ error: err })) 36 | } 37 | res.send(jsonResponse) 38 | }) 39 | }) 40 | } else { 41 | app.ws('/', (ws, req) => { 42 | ws.on('message', (msg) => { 43 | this.provider.sendAsync(JSON.parse(msg), (err, jsonResponse) => { 44 | if (err) { 45 | return ws.send(JSON.stringify({ error: err })) 46 | } 47 | ws.send(JSON.stringify(jsonResponse)) 48 | }) 49 | }) 50 | 51 | this.provider.on('data', (result) => { 52 | ws.send(JSON.stringify(result)) 53 | }) 54 | }) 55 | } 56 | 57 | app.listen(port, host, () => { 58 | log('Remix Simulator listening on ws://' + host + ':' + port) 59 | if (!this.rpcOnly) { 60 | log('http json-rpc is deprecated and disabled by default. To enable it use --rpc') 61 | } 62 | }) 63 | } 64 | } 65 | 66 | module.exports = Server 67 | -------------------------------------------------------------------------------- /remix-simulator/test/accounts.js: -------------------------------------------------------------------------------- 1 | /* global describe, before, it */ 2 | const Web3 = require('web3') 3 | const RemixSim = require('../index.js') 4 | const web3 = new Web3() 5 | const assert = require('assert') 6 | 7 | describe('Accounts', () => { 8 | before(function () { 9 | const provider = new RemixSim.Provider() 10 | web3.setProvider(provider) 11 | }) 12 | 13 | describe('eth_getAccounts', () => { 14 | it('should get a list of accounts', async function () { 15 | const accounts = await web3.eth.getAccounts() 16 | assert.notEqual(accounts.length, 0) 17 | }) 18 | }) 19 | 20 | describe('eth_getBalance', () => { 21 | it('should get a account balance', async () => { 22 | const accounts = await web3.eth.getAccounts() 23 | const balance0 = await web3.eth.getBalance(accounts[0]) 24 | const balance1 = await web3.eth.getBalance(accounts[1]) 25 | const balance2 = await web3.eth.getBalance(accounts[2]) 26 | 27 | assert.deepEqual(balance0, '100000000000000000000') 28 | assert.deepEqual(balance1, '100000000000000000000') 29 | assert.deepEqual(balance2, '100000000000000000000') 30 | }) 31 | }) 32 | 33 | describe('eth_sign', () => { 34 | it('should sign payloads', async () => { 35 | const accounts = await web3.eth.getAccounts() 36 | const signature = await web3.eth.sign('Hello world', accounts[0]) 37 | 38 | assert.deepEqual(signature.length, 132) 39 | }) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /remix-solidity/.npmignore: -------------------------------------------------------------------------------- 1 | src/ -------------------------------------------------------------------------------- /remix-solidity/index.ts: -------------------------------------------------------------------------------- 1 | export { Compiler } from './src/compiler/compiler' 2 | export { default as CompilerInput} from './src/compiler/compiler-input' 3 | -------------------------------------------------------------------------------- /remix-solidity/src/compiler/compiler-input.ts: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import { CompilerInput, Source, CompilerInputOptions } from './types' 4 | 5 | export default (sources: Source, opts: CompilerInputOptions) => { 6 | const o: CompilerInput = { 7 | language: 'Solidity', 8 | sources: sources, 9 | settings: { 10 | optimizer: { 11 | enabled: opts.optimize === true || opts.optimize === 1, 12 | runs: 200 13 | }, 14 | libraries: opts.libraries, 15 | outputSelection: { 16 | '*': { 17 | '': [ 'legacyAST', 'ast' ], 18 | '*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ] 19 | } 20 | } 21 | } 22 | } 23 | if (opts.evmVersion) { 24 | o.settings.evmVersion = opts.evmVersion 25 | } 26 | if (opts.language) { 27 | o.language = opts.language 28 | } 29 | if (opts.language === 'Yul' && o.settings.optimizer.enabled) { 30 | if (!o.settings.optimizer.details) 31 | o.settings.optimizer.details = {} 32 | o.settings.optimizer.details.yul = true 33 | } 34 | return JSON.stringify(o) 35 | } 36 | -------------------------------------------------------------------------------- /remix-solidity/src/compiler/txHelper.ts: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import { CompilationResult, visitContractsCallbackParam, visitContractsCallbackInterface } from './types' 4 | export default { 5 | 6 | /** 7 | * @dev Get contract obj of given contract name from last compilation result. 8 | * @param name contract name 9 | * @param contracts 'contracts' object from last compilation result 10 | */ 11 | 12 | getContract: (contractName: string, contracts: CompilationResult["contracts"]) : Record | null => { 13 | for (const file in contracts) { 14 | if (contracts[file][contractName]) { 15 | return { object: contracts[file][contractName], file: file } 16 | } 17 | } 18 | return null 19 | }, 20 | 21 | /** 22 | * @dev call the given callback for all contracts from last compilation result, stop visiting when cb return true 23 | * @param contracts - 'contracts' object from last compilation result 24 | * @param cb - callback 25 | */ 26 | 27 | visitContracts: (contracts: CompilationResult["contracts"], cb: visitContractsCallbackInterface) : void => { 28 | for (const file in contracts) { 29 | for (const name in contracts[file]) { 30 | const param: visitContractsCallbackParam = { 31 | name: name, 32 | object: contracts[file][name], 33 | file: file 34 | } 35 | if (cb(param)) return 36 | } 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /remix-solidity/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src", "index.ts"], 3 | "compilerOptions": { 4 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": ["dom", "es2018"], /* Specify library files to be included in the compilation. */ 7 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 8 | "sourceMap": true, /* Generates corresponding '.map' file. */ 9 | "outDir": "./dist", /* Redirect output structure to the directory. */ 10 | /* Strict Type-Checking Options */ 11 | "strict": true, /* Enable all strict type-checking options. */ 12 | "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ 13 | /* Module Resolution Options */ 14 | "baseUrl": "./src", /* Base directory to resolve non-absolute module names. */ 15 | "paths": { "remix-solidity": ["./"] }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 16 | "typeRoots": [ 17 | "./@types", 18 | "./node_modules/@types" 19 | ], 20 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 21 | /* Experimental Options */ 22 | "experimentalDecorators": false, /* Enables experimental support for ES7 decorators. */ 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /remix-tests/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | tests/ 3 | examples/ -------------------------------------------------------------------------------- /remix-tests/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Remix Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /remix-tests/bin/remix-tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../dist/run.js'); 4 | 5 | -------------------------------------------------------------------------------- /remix-tests/examples/simple_storage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | contract SimpleStorage { 3 | uint public storedData; 4 | 5 | constructor() public { 6 | storedData = 100; 7 | } 8 | 9 | function set(uint x) public { 10 | storedData = x; 11 | } 12 | 13 | function get() public view returns (uint retVal) { 14 | return storedData; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /remix-tests/examples/simple_storage2_test.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | import "remix_tests.sol"; 3 | import "./simple_storage.sol"; 4 | 5 | contract MyTest2 { 6 | SimpleStorage storage foo; 7 | uint storage i = 0; 8 | 9 | function beforeAll() public { 10 | foo = new SimpleStorage(); 11 | } 12 | 13 | function beforeEach() public { 14 | if (i == 1) { 15 | foo.set(200); 16 | } 17 | i += 1; 18 | } 19 | 20 | function initialValueShouldBe100() public view returns (bool) { 21 | return Assert.equal(foo.get(), 100, "initial value is not correct"); 22 | } 23 | 24 | function initialValueShouldBe200() public view returns (bool) { 25 | return Assert.equal(foo.get(), 200, "initial value is not correct"); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /remix-tests/examples/simple_storage_test.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | import "./simple_storage.sol"; 3 | 4 | contract MyTest { 5 | SimpleStorage storage foo; 6 | uint storage i = 0; 7 | 8 | function beforeAll() public { 9 | foo = new SimpleStorage(); 10 | } 11 | 12 | function beforeEach() public { 13 | if (i == 1) { 14 | foo.set(200); 15 | } 16 | i += 1; 17 | } 18 | 19 | function initialValueShouldBe100() public { 20 | Assert.equal(foo.get(), 100, "initial value is not correct"); 21 | } 22 | 23 | function initialValueShouldBe200() public { 24 | Assert.equal(foo.get(), 200, "initial value is not correct"); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /remix-tests/sol/tests_accounts.sol.js: -------------------------------------------------------------------------------- 1 | module.exports = ` 2 | library TestsAccounts { 3 | function getAccount(uint index) public returns (address) { 4 | >accounts< 5 | return accounts[index]; 6 | } 7 | } 8 | ` 9 | -------------------------------------------------------------------------------- /remix-tests/src/fileSystem.ts: -------------------------------------------------------------------------------- 1 | // Extend fs 2 | let fs: any = require('fs') 3 | import path from 'path' 4 | 5 | // https://github.com/mikeal/node-utils/blob/master/file/lib/main.js 6 | fs.walkSync = function (start: string, callback: Function) { 7 | fs.readdirSync(start).forEach((name: string) => { 8 | if (name === 'node_modules') { 9 | return // hack 10 | } 11 | const abspath = path.join(start, name) 12 | if (fs.statSync(abspath).isDirectory()) { 13 | fs.walkSync(abspath, callback) 14 | } else { 15 | callback(abspath) 16 | } 17 | }) 18 | } 19 | 20 | export = fs 21 | -------------------------------------------------------------------------------- /remix-tests/src/index.ts: -------------------------------------------------------------------------------- 1 | export { runTestFiles } from './runTestFiles' 2 | export { runTestSources } from './runTestSources' 3 | export { runTest } from './testRunner' 4 | export * from './types' 5 | export const assertLibCode = require('../sol/tests.sol.js') 6 | -------------------------------------------------------------------------------- /remix-tests/src/logger.ts: -------------------------------------------------------------------------------- 1 | import colors from 'colors' 2 | import winston, { Logger, LoggerOptions } from 'winston' 3 | import timestamp from 'time-stamp'; 4 | import supportsColor from 'color-support' 5 | 6 | function hasFlag (flag: string) { 7 | return ((typeof (process) !== 'undefined') && (process.argv.indexOf('--' + flag) !== -1)) 8 | } 9 | 10 | function addColor (str: string) { 11 | if (hasFlag('no-color')) { 12 | return str 13 | } 14 | 15 | if (hasFlag('color')) { 16 | return colors.gray(str) 17 | } 18 | 19 | if (supportsColor()) { 20 | return colors.gray(str) 21 | } 22 | 23 | return str 24 | } 25 | function getTimestamp () { 26 | return '[' + addColor(timestamp('HH:mm:ss')) + ']' 27 | } 28 | // create winston logger format 29 | const logFmt = winston.format.printf((info) => { 30 | return `${getTimestamp()} ${info.level}: ${info.message}` 31 | }) 32 | 33 | class Log { 34 | logger: Logger; 35 | constructor () { 36 | this.logger = winston.createLogger({ 37 | level: 'error', 38 | transports: [new winston.transports.Console()], 39 | format: winston.format.combine( 40 | winston.format.colorize({ all: true }), 41 | logFmt 42 | ) 43 | }) 44 | } 45 | setVerbosity (v: LoggerOptions["level"]) { 46 | this.logger.configure({ 47 | level: v, 48 | transports: [new winston.transports.Console()], 49 | format: winston.format.combine( 50 | winston.format.colorize({ all: true }), 51 | logFmt 52 | ) 53 | }) 54 | } 55 | } 56 | 57 | export = Log 58 | -------------------------------------------------------------------------------- /remix-tests/tests/examples_1/simple_storage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | contract SimpleStorage { 3 | uint public storedData; 4 | 5 | constructor() public { 6 | storedData = 100; 7 | } 8 | 9 | function set(uint x) public { 10 | storedData = x; 11 | } 12 | 13 | function get() public view returns (uint retVal) { 14 | return storedData; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /remix-tests/tests/examples_1/simple_storage_test.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | import "./simple_storage.sol"; 3 | 4 | contract MyTest { 5 | SimpleStorage foo; 6 | 7 | function beforeAll() public { 8 | foo = new SimpleStorage(); 9 | } 10 | 11 | function initialValueShouldBe100() public returns (bool) { 12 | return Assert.equal(foo.get(), 100, "initial value is not correct"); 13 | } 14 | 15 | function initialValueShouldNotBe200() public returns (bool) { 16 | return Assert.notEqual(foo.get(), 200, "initial value is not correct"); 17 | } 18 | 19 | function shouldTriggerOneFail() public { 20 | Assert.equal(uint(1), uint(2), "uint test 1 fails"); 21 | Assert.notEqual(uint(1), uint(2), "uint test 2 passes"); 22 | } 23 | 24 | function shouldTriggerOnePass() public { 25 | Assert.equal(uint(1), uint(1), "uint test 3 passes"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /remix-tests/tests/examples_2/simple_storage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | contract SimpleStorage { 3 | uint public storedData; 4 | 5 | constructor() public { 6 | storedData = 100; 7 | } 8 | 9 | function set(uint x) public { 10 | storedData = x; 11 | } 12 | 13 | function get() public view returns (uint retVal) { 14 | return storedData; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /remix-tests/tests/examples_2/simple_storage_test.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | import "./simple_storage.sol"; 3 | 4 | contract MyTest { 5 | SimpleStorage foo; 6 | uint i = 0; 7 | 8 | function beforeEach() public { 9 | foo = new SimpleStorage(); 10 | if (i == 1) { 11 | foo.set(200); 12 | } 13 | i += 1; 14 | } 15 | 16 | function initialValueShouldBe100() public returns (bool) { 17 | return Assert.equal(foo.get(), 100, "initial value is not correct"); 18 | } 19 | 20 | function valueIsSet200() public returns (bool) { 21 | return Assert.equal(foo.get(), 200, "value is not correct after first execution"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /remix-tests/tests/examples_3/simple_string.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | contract SimpleString { 3 | string public storedData; 4 | 5 | constructor() public { 6 | storedData = "Hello world!"; 7 | } 8 | 9 | function get() public view returns (string memory retVal) { 10 | return storedData; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /remix-tests/tests/examples_3/simple_string_test.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | import "./simple_string.sol"; 3 | 4 | contract StringTest { 5 | SimpleString foo; 6 | 7 | function beforeAll() public { 8 | foo = new SimpleString(); 9 | } 10 | 11 | function initialValueShouldBeHelloWorld() public returns (bool) { 12 | return Assert.equal(foo.get(), "Hello world!", "initial value is not correct"); 13 | } 14 | 15 | function valueShouldNotBeHelloWordl() public returns (bool) { 16 | return Assert.notEqual(foo.get(), "Hello wordl!", "value should not be hello wordl"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /remix-tests/tests/examples_4/SafeMathProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.22 <0.7.0; 2 | import "./SafeMath.sol"; 3 | 4 | /* 5 | Using a proxy contract here allows revert-causing functions that contain 6 | require() to return false rather than halt execution 7 | https://truffleframework.com/tutorials/testing-for-throws-in-solidity-tests 8 | */ 9 | contract SafeMathProxy { 10 | using SafeMath for uint; 11 | 12 | function divProxy(uint256 a, uint256 b) public pure returns (uint256) { 13 | return a.div(b); 14 | } 15 | 16 | function mulProxy(uint256 a, uint256 b) public pure returns (uint256) { 17 | return a.mul(b); 18 | } 19 | 20 | function subProxy(uint256 a, uint256 b) public pure returns (uint256) { 21 | return a.sub(b); 22 | } 23 | 24 | function addProxy(uint256 a, uint256 b) public pure returns (uint256) { 25 | return a.add(b); 26 | } 27 | 28 | function modProxy(uint256 a, uint256 b) public pure returns (uint256) { 29 | return a.mod(b); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /remix-tests/tests/examples_5/contract/simple_storage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | 3 | import "../../examples_4/SafeMath.sol"; 4 | import "../lib/EvenOdd.sol"; 5 | 6 | contract SimpleStorage is EvenOdd{ 7 | using SafeMath for uint256; 8 | uint public storedData; 9 | 10 | constructor() public { 11 | storedData = 100; 12 | } 13 | 14 | function set(uint x) public { 15 | storedData = x; 16 | } 17 | 18 | function get() public view returns (uint retVal) { 19 | return storedData; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /remix-tests/tests/examples_5/lib/EvenOdd.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | 3 | contract EvenOdd { 4 | 5 | /** 6 | * @dev Tells whether a number is even or odd 7 | * @param num Number to check 8 | */ 9 | 10 | function check(int num) public pure returns (string memory){ 11 | if(num % 2 == 0) 12 | return "EVEN"; 13 | return "ODD"; 14 | } 15 | } -------------------------------------------------------------------------------- /remix-tests/tests/examples_5/test/simple_storage_test.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | import "./../contract/simple_storage.sol"; 3 | 4 | contract StorageResolveTest { 5 | SimpleStorage foo; 6 | 7 | function beforeAll() public { 8 | foo = new SimpleStorage(); 9 | } 10 | 11 | function initialValueShouldBe100() public returns (bool) { 12 | return Assert.equal(foo.get(), 100, "initial value is not correct"); 13 | } 14 | 15 | //Test imported contract functions 16 | function checkIfEven() public returns (bool) { 17 | return Assert.equal(foo.check(10), 'EVEN', "value is odd"); 18 | } 19 | 20 | function checkIfOdd() public returns (bool) { 21 | return Assert.equal(foo.check(11), 'ODD', "value is even"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /remix-tests/tests/number/number_test.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.5.0 < 0.7.0; 2 | 3 | contract IntegerTest { 4 | 5 | // GREATER THAN [>] tests 6 | function _2_shouldBeGreaterThan_1() public returns (bool) { 7 | return Assert.greaterThan(uint(2), uint(1), "2 is greater than 1"); 8 | } 9 | 10 | function _0_shouldBeGreaterThan_neg_1() public returns (bool) { 11 | return Assert.greaterThan(uint(0), int(-1), "0 is greater than -1"); 12 | } 13 | 14 | function _neg_1_shouldNotBeGreaterThan_1() public returns (bool) { 15 | return Assert.greaterThan(int(-1), uint(1), "-1 is not greater than 1"); 16 | } 17 | 18 | function _1_shouldBeGreaterThan_neg_1() public returns (bool) { 19 | return Assert.greaterThan(uint(1), int(-1), "1 is greater than -1"); 20 | } 21 | 22 | // LESSER THAN [<] tests 23 | function _1_shouldBeLesserThan_2() public returns (bool) { 24 | return Assert.lesserThan(uint(1), uint(2), "1 is lesser than 2"); 25 | } 26 | 27 | function _neg_1_shouldBeLesserThan_0() public returns (bool) { 28 | return Assert.lesserThan(int(-1), uint(0), "-1 is lesser than 0"); 29 | } 30 | 31 | function _neg_2_shouldBeLesserThan_neg_1() public returns (bool) { 32 | return Assert.lesserThan(int(-2), int(-1), "-2 is lesser than -1"); 33 | } 34 | 35 | function _0_shouldNotBeLesserThan_neg_1() public returns (bool) { 36 | return Assert.lesserThan(uint(0), int(-1), "0 is not lesser than -1"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /remix-tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": ["dom", "es2018"], /* Specify library files to be included in the compilation. */ 7 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 8 | "sourceMap": true, /* Generates corresponding '.map' file. */ 9 | "outDir": "./dist", /* Redirect output structure to the directory. */ 10 | /* Strict Type-Checking Options */ 11 | "strict": true, /* Enable all strict type-checking options. */ 12 | "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ 13 | /* Module Resolution Options */ 14 | "baseUrl": "./src", /* Base directory to resolve non-absolute module names. */ 15 | "paths": { "remix-tests": ["./"] }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 16 | "typeRoots": [ 17 | "./@types", 18 | "./node_modules/@types" 19 | ], 20 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 21 | /* Experimental Options */ 22 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /remix-url-resolver/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /remix-url-resolver/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | tests/ -------------------------------------------------------------------------------- /remix-url-resolver/README.md: -------------------------------------------------------------------------------- 1 | **The project has been moved to https://github.com/ethereum/remix-project/tree/master/libs/remix-url-resolver** 2 | 3 | ## Remix URL resolver engine 4 | 5 | `resolve(url, urlHandler)` 6 | 7 | Returns `json` object with exact same path as `import` statement. 8 | 9 | **Output** 10 | ```json 11 | { 12 | content: 'pragma solidity ^0.5.0;\nimport "./mortal.sol";\n\ncontract Greeter is Mortal {\n /* Define variable greeting of the type string */\n string greeting;\n\n /* This runs when the contract is executed */\n constructor(string memory _greeting) public {\n greeting = _greeting;\n }\n\n /* Main function */\n function greet() public view returns (string memory) {\n return greeting;\n }\n}\n', 13 | cleanURL: '../greeter.sol', 14 | type: 'local' 15 | } 16 | ``` 17 | 18 | #### Usage 19 | 20 | `resolve(url, urlHandler)` function should be called from within `handleImportCb` function of `solc.compile(input, handleImportCb)`. 21 | 22 | ```ts 23 | import { RemixURLResolver } from 'remix-url-resolver' 24 | 25 | const urlResolver = new RemixURLResolver() 26 | const fileName: string = '../greeter.sol' 27 | urlResolver.resolve(fileName, urlHandler) 28 | .then((sources: object) => { 29 | console.log(sources) 30 | }) 31 | .catch((e: Error) => { 32 | throw e 33 | }) 34 | ``` 35 | 36 | #### References 37 | 38 | * [TypeScript Publishing](http://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) 39 | * [DefinitelyTyped 'Create a new package' guide](https://github.com/DefinitelyTyped/DefinitelyTyped#create-a-new-package) 40 | -------------------------------------------------------------------------------- /remix-url-resolver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "remix-url-resolver", 3 | "version": "0.0.16", 4 | "description": "Solidity import url resolver engine", 5 | "main": "dist", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsc", 9 | "lint": "standard", 10 | "test": "standard && mocha --require ts-node/register tests/*.ts -t 300000", 11 | "prepublish": "npm run build" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/ethereum/remix.git" 16 | }, 17 | "keywords": [ 18 | "solidity", 19 | "remix", 20 | "resolve", 21 | "import" 22 | ], 23 | "author": "Remix Team", 24 | "license": "MIT", 25 | "standard": { 26 | "ignore": [ 27 | "tests/" 28 | ] 29 | }, 30 | "dependencies": { 31 | "axios": "^0.18.0", 32 | "solc": "^0.6.0", 33 | "url": "^0.11.0", 34 | "valid-url": "^1.0.9" 35 | }, 36 | "devDependencies": { 37 | "@types/chai": "^4.1.7", 38 | "@types/mocha": "^5.2.5", 39 | "@types/node": "^10.12.18", 40 | "chai": "^4.2.0", 41 | "mocha": "^5.1.0", 42 | "remix-plugin": "0.0.1-alpha.2", 43 | "standard": "^12.0.1", 44 | "ts-node": "^7.0.1", 45 | "tslint": "^5.11.0", 46 | "typescript": "^3.1.6" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /remix-url-resolver/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './resolve' 2 | -------------------------------------------------------------------------------- /remix-url-resolver/tests/example_1/greeter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | import "./mortal.sol"; 3 | 4 | contract Greeter is Mortal { 5 | /* Define variable greeting of the type string */ 6 | string greeting; 7 | 8 | /* This runs when the contract is executed */ 9 | constructor(string memory _greeting) public { 10 | greeting = _greeting; 11 | } 12 | 13 | /* Main function */ 14 | function greet() public view returns (string memory) { 15 | return greeting; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /remix-url-resolver/tests/example_1/mortal.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | contract Mortal { 4 | /* Define variable owner of the type address */ 5 | address payable owner; 6 | 7 | /* This function is executed at initialization and sets the owner of the contract */ 8 | function mortal() public { owner = msg.sender; } 9 | 10 | /* Function to recover the funds on the contract */ 11 | function kill() public { if (msg.sender == owner) selfdestruct(owner); } 12 | } 13 | -------------------------------------------------------------------------------- /remix-url-resolver/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "baseUrl": "./src", 6 | "outDir": "./dist", 7 | "sourceMap": true, 8 | "declaration": true, 9 | "module": "commonjs", 10 | "strict": true, 11 | "noImplicitAny": false, 12 | "strictPropertyInitialization": false, 13 | "experimentalDecorators": true, 14 | "target": "es5", 15 | "typeRoots": ["node_modules/@types"], 16 | "lib": ["dom", "es2018"], 17 | "paths": { 18 | "remix-url-resolver": ["./"] 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tasks.todo: -------------------------------------------------------------------------------- 1 | - [] remix-debug: Add tests for debugger (stepOverForward) --------------------------------------------------------------------------------