Unverified Commit 43fd1f97 authored by yann300's avatar yann300 Committed by GitHub

Merge branch 'master' into include_remix_test_sol

parents f74d765a 0afe8e3e
...@@ -11,3 +11,4 @@ package-lock.json ...@@ -11,3 +11,4 @@ package-lock.json
.tern-port .tern-port
TODO TODO
soljson.js soljson.js
lerna-debug.log
[submodule "remixd"]
path = remixd
url = https://github.com/ethereum/remixd
language: node_js
node_js:
- stable
env:
- TEST_DIR=remix-lib
- TEST_DIR=remix-solidity
- TEST_DIR=remix-debug
- TEST_DIR=remix-tests
- TEST_DIR=remix-simulator
script:
- cd $TEST_DIR && npm install && npm test
deploy:
provider: script
script: remix-debugger/ci/deploy_from_travis.sh
skip_cleanup: true
on:
branch: master
condition: $TEST_DIR = remix-debugger
cache: false
# Remix # Remix
[![Join the chat at https://gitter.im/ethereum/remix](https://badges.gitter.im/ethereum/remix.svg)](https://gitter.im/ethereum/remix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/ethereum/remix](https://badges.gitter.im/ethereum/remix.svg)](https://gitter.im/ethereum/remix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![CircleCI](https://circleci.com/gh/ethereum/remix.svg?style=svg)](https://circleci.com/gh/ethereum/remix) [![CircleCI](https://circleci.com/gh/ethereum/remix/tree/master.svg?style=svg)](https://circleci.com/gh/ethereum/remix/tree/master)
[![Documentation Status](https://readthedocs.org/projects/docs/badge/?version=latest)](https://remix.readthedocs.io/en/latest/) [![Documentation Status](https://readthedocs.org/projects/docs/badge/?version=latest)](https://remix.readthedocs.io/en/latest/)
Ethereum tools for the web. Ethereum tools for the web.
...@@ -50,6 +50,7 @@ Remix is built out of several different modules: ...@@ -50,6 +50,7 @@ Remix is built out of several different modules:
+ [`remix-lib`](remix-lib/README.md) + [`remix-lib`](remix-lib/README.md)
+ [`remix-debug`](remix-debugger/README.md) is now *deprecated*. It contains the debugger. + [`remix-debug`](remix-debugger/README.md) is now *deprecated*. It contains the debugger.
+ [`remix-tests`](remix-tests/README.md) contains our tests. + [`remix-tests`](remix-tests/README.md) contains our tests.
+ [`remixd`](https://github.com/ethereum/remixd/tree/master) CLI which allow accessing local element from Remix IDE (see https://remix.readthedocs.io/en/latest/tutorial_remixd_filesystem.html)
Each generally has their own npm package and test suite, as well as basic documentation. Each generally has their own npm package and test suite, as well as basic documentation.
......
...@@ -10,9 +10,12 @@ The code of RemixD can be checked out ...@@ -10,9 +10,12 @@ The code of RemixD can be checked out
Remixd can be globally installed using the following command: Remixd can be globally installed using the following command:
`npm install -g remixd`. `npm install -g remixd`.
Then `remixd -s <absolute-path-to-the-shared-folder>` will start Remixd Then `remixd -s <absolute-path-to-the-shared-folder> --remix-ide <your-remix-ide-URL-instance>` will start Remixd
and share the given folder. and share the given folder.
For example, to sync your local folder to the official Remix IDE,
`remixd -s <absolute-path-to-the-shared-folder> --remix-ide https://remix.ethereum.org`
The folder is shared using a websocket connection between `Remix IDE` The folder is shared using a websocket connection between `Remix IDE`
and `Remixd`. and `Remixd`.
......
...@@ -24,8 +24,12 @@ This execute tests. The execution is run in a separate environment and the resul ...@@ -24,8 +24,12 @@ This execute tests. The execution is run in a separate environment and the resul
| `Assert.greaterThan()` | `uint`, `int` | | `Assert.greaterThan()` | `uint`, `int` |
| `Assert.lesserThan()` | `uint`, `int` | | `Assert.lesserThan()` | `uint`, `int` |
see [https://github.com/ethereum/remix/blob/master/remix-tests/tests/examples_4/SafeMath_test.sol](https://github.com/ethereum/remix/blob/master/remix-tests/tests/examples_4/SafeMath_test.sol) for some code sample
Continuous integration Continuous integration
---------------------- ----------------------
remix-tests is also a CLI, it can be used in a continuous integration environement which support node.js. remix-tests is also a CLI, it can be used in a continuous integration environement which support node.js.
Please find more information in the [remix-test repository](https://github.com/ethereum/remix/tree/master/remix-tests) Please find more information in the [remix-test repository](https://github.com/ethereum/remix/tree/master/remix-tests)
See also: example [Su Squares contract](https://github.com/su-squares/ethereum-contract/tree/e542f37d4f8f6c7b07d90a6554424268384a4186) and [https://travis-ci.org/su-squares/ethereum-contract/builds/446186067](Travis build) that uses remix-tests for continuous integration testing.
...@@ -10,5 +10,5 @@ This tutorial was used in workshops at ethCC, Edcon, and DappCon. ...@@ -10,5 +10,5 @@ This tutorial was used in workshops at ethCC, Edcon, and DappCon.
You can [watch the Edcon presentation talk](https://www.youtube.com/watch?v=nAI_Cr5Y8JY) and here are the [workshop slides](https://slides.com/ninabreznik/deck-11-13#/). You can [watch the Edcon presentation talk](https://www.youtube.com/watch?v=nAI_Cr5Y8JY) and here are the [workshop slides](https://slides.com/ninabreznik/deck-11-13#/).
(May 3, 2018) (May 3, 2018)
Here are the [DappCon slides (hosted on swarm)](https://30400.swarm-gateways.net/bzz:/2271229d214f8aef9b1176bc22dbc09e384cd8c577a87c60ebece68aebc59d3a/) and here are the [DappCon slides (not on swarm)](https://www.updig.is/pdf/remix-at-dappcon.pdf). Here are the [latest slides (hosted on swarm)](http://30400.swarm-gateways.net/bzz:/49277e2a16baf5576c9f54204c70dc403a425c3df85424864fe04ad6dfc609bc/) and here are the [latest slides (not on swarm)](https://www.updig.is/pdf/remix-chez-coinhouse.pdf).
(July 19, 2018) (Oct 16, 2018)
\ No newline at end of file \ No newline at end of file
#!/usr/bin/env node
'use strict';
var gulp = require('gulp');
var exec = require('child_process').exec;
var packageJSON = require('./package.json');
gulp.task('publishTag', function () {
exec("git tag v"+ packageJSON.version +"; git push --tags");
});
...@@ -8,5 +8,14 @@ ...@@ -8,5 +8,14 @@
"remix-tests", "remix-tests",
"remix-simulator" "remix-simulator"
], ],
"command": {
"init": {
"exact": true
},
"publish": {
"exact": true,
"skipGit": true
}
},
"version": "independent" "version": "independent"
} }
{ {
"version": "0.1.3",
"devDependencies": { "devDependencies": {
"gulp": "^3.9.1",
"lerna": "^2.10.2" "lerna": "^2.10.2"
}, },
"scripts": { "scripts": {
"diff": "lerna diff",
"updated": "lerna updated",
"bootstrap": "lerna bootstrap", "bootstrap": "lerna bootstrap",
"publish": "lerna publish" "publish": "lerna publish",
"release": "lerna bootstrap; lerna publish;",
"tag": "gulp; gulp publishTag;"
} }
} }
# Release process
This document details steps for publishing packages and tag the code base accordingly:
- checkout a new branch
- npm run publish
- commit
- increment root package.json version
- commit
- merge the branch
- fetch origin/master
- checkout origin/master
- npm run tag
- github-changes -o ethereum -r remix -a --only-pulls --use-commit-body --only-merges --between-tags <previous>...<next>
- create a new release out of the changelog.md
- in changelog put list of published packages with version
{ {
"name": "remix-analyzer", "name": "remix-analyzer",
"version": "0.2.8", "version": "0.2.12",
"description": "Remix Analyzer", "description": "Remix Analyzer",
"main": "./index.js", "main": "./index.js",
"contributors": [ "contributors": [
...@@ -21,8 +21,7 @@ ...@@ -21,8 +21,7 @@
"babel-eslint": "^7.1.1", "babel-eslint": "^7.1.1",
"babel-plugin-transform-object-assign": "^6.22.0", "babel-plugin-transform-object-assign": "^6.22.0",
"babel-preset-es2015": "^6.24.0", "babel-preset-es2015": "^6.24.0",
"remix-lib": "^0.3.8", "remix-lib": "0.3.12",
"solc": "^0.4.24",
"standard": "^7.0.1", "standard": "^7.0.1",
"tape": "^4.6.0" "tape": "^4.6.0"
}, },
...@@ -38,5 +37,8 @@ ...@@ -38,5 +37,8 @@
}, },
"author": "Remix Team", "author": "Remix Team",
"license": "MIT", "license": "MIT",
"homepage": "https://github.com/ethereum/remix#readme" "homepage": "https://github.com/ethereum/remix#readme",
"devDependencies": {
"npm-install-version": "^6.0.2"
}
} }
...@@ -11,12 +11,18 @@ function lowLevelCalls () { ...@@ -11,12 +11,18 @@ function lowLevelCalls () {
lowLevelCalls.prototype.visit = function (node) { lowLevelCalls.prototype.visit = function (node) {
if (common.isLowLevelCallInst(node)) { if (common.isLowLevelCallInst(node)) {
this.llcNodes.push({node: node, type: common.lowLevelCallTypes.CALL}) this.llcNodes.push({node: node, type: common.lowLevelCallTypes.CALL})
} else if (common.isLowLevelCallInst050(node)) {
this.llcNodes.push({node: node, type: common.lowLevelCallTypes.CALL})
} else if (common.isLowLevelCallcodeInst(node)) { } else if (common.isLowLevelCallcodeInst(node)) {
this.llcNodes.push({node: node, type: common.lowLevelCallTypes.CALLCODE}) this.llcNodes.push({node: node, type: common.lowLevelCallTypes.CALLCODE})
} else if (common.isLowLevelDelegatecallInst(node)) { } else if (common.isLowLevelDelegatecallInst(node)) {
this.llcNodes.push({node: node, type: common.lowLevelCallTypes.DELEGATECALL}) this.llcNodes.push({node: node, type: common.lowLevelCallTypes.DELEGATECALL})
} else if (common.isLowLevelSendInst(node)) { } else if (common.isLowLevelSendInst(node)) {
this.llcNodes.push({node: node, type: common.lowLevelCallTypes.SEND}) this.llcNodes.push({node: node, type: common.lowLevelCallTypes.SEND})
} else if (common.isLowLevelSendInst050(node)) {
this.llcNodes.push({node: node, type: common.lowLevelCallTypes.SEND})
} else if (common.isLLDelegatecallInst050(node)) {
this.llcNodes.push({node: node, type: common.lowLevelCallTypes.DELEGATECALL})
} }
} }
......
...@@ -33,6 +33,7 @@ var basicTypes = { ...@@ -33,6 +33,7 @@ var basicTypes = {
UINT: 'uint256', UINT: 'uint256',
BOOL: 'bool', BOOL: 'bool',
ADDRESS: 'address', ADDRESS: 'address',
PAYABLE_ADDRESS: 'address payable',
BYTES32: 'bytes32', BYTES32: 'bytes32',
STRING_MEM: 'string memory', STRING_MEM: 'string memory',
BYTES_MEM: 'bytes memory', BYTES_MEM: 'bytes memory',
...@@ -52,7 +53,9 @@ var basicRegex = { ...@@ -52,7 +53,9 @@ var basicRegex = {
var basicFunctionTypes = { var basicFunctionTypes = {
SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false), SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false),
CALL: buildFunctionSignature([], [basicTypes.BOOL], true), CALL: buildFunctionSignature([], [basicTypes.BOOL], true),
'CALL-v0.5': buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true),
DELEGATECALL: buildFunctionSignature([], [basicTypes.BOOL], false), DELEGATECALL: buildFunctionSignature([], [basicTypes.BOOL], false),
'DELEGATECALL-v0.5': buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], false),
TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false) TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false)
} }
...@@ -65,6 +68,7 @@ var builtinFunctions = { ...@@ -65,6 +68,7 @@ var builtinFunctions = {
'addmod(uint256,uint256,uint256)': true, 'addmod(uint256,uint256,uint256)': true,
'mulmod(uint256,uint256,uint256)': true, 'mulmod(uint256,uint256,uint256)': true,
'selfdestruct(address)': true, 'selfdestruct(address)': true,
'selfdestruct(address payable)': true,
'revert()': true, 'revert()': true,
'revert(string memory)': true, 'revert(string memory)': true,
'assert(bool)': true, 'assert(bool)': true,
...@@ -77,8 +81,10 @@ var builtinFunctions = { ...@@ -77,8 +81,10 @@ var builtinFunctions = {
var lowLevelCallTypes = { var lowLevelCallTypes = {
CALL: { ident: 'call', type: basicFunctionTypes.CALL }, CALL: { ident: 'call', type: basicFunctionTypes.CALL },
'CALL-v0.5': { ident: 'call', type: basicFunctionTypes['CALL-v0.5'] },
CALLCODE: { ident: 'callcode', type: basicFunctionTypes.CALL }, CALLCODE: { ident: 'callcode', type: basicFunctionTypes.CALL },
DELEGATECALL: { ident: 'delegatecall', type: basicFunctionTypes.DELEGATECALL }, DELEGATECALL: { ident: 'delegatecall', type: basicFunctionTypes.DELEGATECALL },
'DELEGATECALL-v0.5': { ident: 'delegatecall', type: basicFunctionTypes['DELEGATECALL-v0.5'] },
SEND: { ident: 'send', type: basicFunctionTypes.SEND }, SEND: { ident: 'send', type: basicFunctionTypes.SEND },
TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER } TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER }
} }
...@@ -588,7 +594,7 @@ function isStorageVariableDeclaration (node) { ...@@ -588,7 +594,7 @@ function isStorageVariableDeclaration (node) {
* @return {bool} * @return {bool}
*/ */
function isInteraction (node) { function isInteraction (node) {
return isLLCall(node) || isLLSend(node) || isExternalDirectCall(node) || isTransfer(node) return isLLCall(node) || isLLSend(node) || isExternalDirectCall(node) || isTransfer(node) || isLLCall050(node) || isLLSend050(node)
} }
/** /**
...@@ -833,11 +839,25 @@ function isLowLevelCall (node) { ...@@ -833,11 +839,25 @@ function isLowLevelCall (node) {
return isLLCall(node) || return isLLCall(node) ||
isLLCallcode(node) || isLLCallcode(node) ||
isLLDelegatecall(node) || isLLDelegatecall(node) ||
isLLSend(node) isLLSend(node) ||
isLLSend050(node) ||
isLLCall050(node) ||
isLLDelegatecall050(node)
} }
/** /**
* True if low level send * True if low level send (solidity >= 0.5)
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLSend050 (node) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.SEND.type)),
undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident))
}
/**
* True if low level send (solidity < 0.5)
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
...@@ -859,6 +879,17 @@ function isLLCall (node) { ...@@ -859,6 +879,17 @@ function isLLCall (node) {
} }
/** /**
* True if low level payable call (solidity >= 0.5)
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLCall050 (node) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)),
undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident))
}
/**
* True if low level callcode * True if low level callcode
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
...@@ -881,6 +912,17 @@ function isLLDelegatecall (node) { ...@@ -881,6 +912,17 @@ function isLLDelegatecall (node) {
} }
/** /**
* True if low level delegatecall (solidity >= 0.5)
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLDelegatecall050 (node) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['DELEGATECALL-v0.5'].type)),
undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['DELEGATECALL-v0.5'].ident))
}
/**
* True if transfer call * True if transfer call
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
...@@ -888,7 +930,7 @@ function isLLDelegatecall (node) { ...@@ -888,7 +930,7 @@ function isLLDelegatecall (node) {
function isTransfer (node) { function isTransfer (node) {
return isMemberAccess(node, return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.TRANSFER.type)), exactMatch(util.escapeRegExp(lowLevelCallTypes.TRANSFER.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.TRANSFER.ident)) undefined, matches(basicTypes.ADDRESS, basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.TRANSFER.ident))
} }
function isStringToBytesConversion (node) { function isStringToBytesConversion (node) {
...@@ -962,6 +1004,14 @@ function exactMatch (regexStr) { ...@@ -962,6 +1004,14 @@ function exactMatch (regexStr) {
return '^' + regexStr + '$' return '^' + regexStr + '$'
} }
function matches () {
var args = []
for (var k = 0; k < arguments.length; k++) {
args.push(arguments[k])
}
return '(' + args.join('|') + ')'
}
/** /**
* Builds an function signature as used in the AST of the solc-json AST * Builds an function signature as used in the AST of the solc-json AST
* @param {Array} paramTypes * @param {Array} paramTypes
...@@ -1048,6 +1098,9 @@ module.exports = { ...@@ -1048,6 +1098,9 @@ module.exports = {
isTransfer: isTransfer, isTransfer: isTransfer,
isLowLevelCall: isLowLevelCall, isLowLevelCall: isLowLevelCall,
isLowLevelCallInst: isLLCall, isLowLevelCallInst: isLLCall,
isLowLevelCallInst050: isLLCall050,
isLowLevelSendInst050: isLLSend050,
isLLDelegatecallInst050: isLLDelegatecall050,
isLowLevelCallcodeInst: isLLCallcode, isLowLevelCallcodeInst: isLLCallcode,
isLowLevelDelegatecallInst: isLLDelegatecall, isLowLevelDelegatecallInst: isLLDelegatecall,
isLowLevelSendInst: isLLSend, isLowLevelSendInst: isLLSend,
......
...@@ -10,7 +10,7 @@ function txOrigin () { ...@@ -10,7 +10,7 @@ function txOrigin () {
txOrigin.prototype.visit = function (node) { txOrigin.prototype.visit = function (node) {
if (node.name === 'MemberAccess' && if (node.name === 'MemberAccess' &&
node.attributes.member_name === 'origin' && node.attributes.member_name === 'origin' &&
node.attributes.type === 'address' && (node.attributes.type === 'address' || node.attributes.type === 'address payable') &&
node.children && node.children.length && node.children && node.children.length &&
node.children[0].attributes.type === 'tx' && node.children[0].attributes.type === 'tx' &&
node.children[0].attributes.value === 'tx') { node.children[0].attributes.value === 'tx') {
......
var test = require('tape')
var remixLib = require('remix-lib')
var StatRunner = require('../../src/solidity-analyzer')
var compilerInput = remixLib.helpers.compiler.compilerInput
const niv = require('npm-install-version')
niv.install('solc@0.4.24')
var compiler = niv.require('solc@0.4.24')
var fs = require('fs')
var path = require('path')
var folder = 'solidity-v0.4.24'
var testFiles = [
'KingOfTheEtherThrone.sol',
'assembly.sol',
'ballot.sol',
'ballot_reentrant.sol',
'ballot_withoutWarnings.sol',
'cross_contract.sol',
'inheritance.sol',
'modifier1.sol',
'modifier2.sol',
'notReentrant.sol',
'structReentrant.sol',
'thisLocal.sol',
'globals.sol',
'library.sol',
'transfer.sol',
'ctor.sol',
'forgottenReturn.sol',
'selfdestruct.sol',
'deleteDynamicArray.sol',
'deleteFromDynamicArray.sol',
'blockLevelCompare.sol',
'intDivisionTruncate.sol',
'ERC20.sol',
'stringBytesLength.sol',
'forLoopIteratesOverDynamicArray.sol'
]
var testFileAsts = {}
testFiles.forEach((fileName) => {
var content = fs.readFileSync(path.join(__dirname, 'test-contracts/' + folder, fileName), 'utf8')
testFileAsts[fileName] = JSON.parse(compiler.compileStandardWrapper(compilerInput(content)))
})
test('Integration test thisLocal.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/thisLocal')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 1,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 1,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of this local warnings`)
})
})
test('Integration test checksEffectsInteraction.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/checksEffectsInteraction')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 1,
'assembly.sol': 1,
'ballot.sol': 0,
'ballot_reentrant.sol': 1,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 1,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 1,
'thisLocal.sol': 0,
'globals.sol': 1,
'library.sol': 1,
'transfer.sol': 1,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of checks-effects-interaction warnings`)
})
})
test('Integration test constantFunctions.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/constantFunctions')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 1,
'inheritance.sol': 0,
'modifier1.sol': 1,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 1,
'thisLocal.sol': 1,
'globals.sol': 0,
'library.sol': 3,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 1,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of constant warnings`)
})
})
test('Integration test inlineAssembly.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/inlineAssembly')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 2,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of inline assembly warnings`)
})
})
test('Integration test txOrigin.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/txOrigin')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 1,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 1,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of tx.origin warnings`)
})
})
test('Integration test gasCosts.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/gasCosts')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 2,
'assembly.sol': 2,
'ballot.sol': 3,
'ballot_reentrant.sol': 2,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 1,
'inheritance.sol': 1,
'modifier1.sol': 0,
'modifier2.sol': 1,
'notReentrant.sol': 1,
'structReentrant.sol': 1,
'thisLocal.sol': 1,
'globals.sol': 1,
'library.sol': 1,
'transfer.sol': 1,
'ctor.sol': 0,
'forgottenReturn.sol': 3,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 2,
'deleteFromDynamicArray.sol': 1,
'blockLevelCompare.sol': 1,
'intDivisionTruncate.sol': 1,
'ERC20.sol': 2,
'stringBytesLength.sol': 1,
'forLoopIteratesOverDynamicArray.sol': 1
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of gasCost warnings`)
})
})
test('Integration test similarVariableNames.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/similarVariableNames')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 2,
'ballot_reentrant.sol': 3,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 1,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 1,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 1,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of similarVariableNames warnings`)
})
})
test('Integration test inlineAssembly.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/inlineAssembly')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 2,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of inlineAssembly warnings`)
})
})
test('Integration test blockTimestamp.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/blockTimestamp')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 1,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 3,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 2,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of blockTimestamp warnings`)
})
})
test('Integration test lowLevelCalls.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/lowLevelCalls')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 1,
'assembly.sol': 1,
'ballot.sol': 0,
'ballot_reentrant.sol': 7,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 1,
'inheritance.sol': 1,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 1,
'structReentrant.sol': 1,
'thisLocal.sol': 2,
'globals.sol': 1,
'library.sol': 1,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of lowLevelCalls warnings`)
})
})
test('Integration test blockBlockhash.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/blockBlockhash')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0, // was 1 !! @TODO
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of blockBlockhash warnings`)
})
})
test('Integration test noReturn.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/noReturn')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 1,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 1,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 1,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 1,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of noReturn warnings`)
})
})
test('Integration test selfdestruct.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/selfdestruct')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 2,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 3,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'ERC20.sol': 0,
'intDivisionTruncate.sol': 5,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of selfdestruct warnings`)
})
})
test('Integration test guardConditions.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/guardConditions')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 1,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 1,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 1,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 1,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of guardCondition warnings`)
})
})
test('Integration test deleteDynamicArrays.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/deleteDynamicArrays')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 2,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of deleteDynamicArrays warnings`)
})
})
test('Integration test deleteFromDynamicArray.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/deleteFromDynamicArray')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 1,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of deleteFromDynamicArray warnings`)
})
})
test('Integration test assignAndCompare.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/assignAndCompare')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 8,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of assignAndCompare warnings`)
})
})
test('Integration test intDivisionTruncate.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/intDivisionTruncate')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 2,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of intDivisionTruncate warnings`)
})
})
test('Integration test erc20Decimal.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/erc20Decimals')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 1,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of erc20Decimals warnings`)
})
})
test('Integration test stringBytesLength.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/stringBytesLength')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 1,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of stringBytesLength warnings`)
})
})
test('Integration test forLoopIteratesOverDynamicArray.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 2,
'ballot_reentrant.sol': 1,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 1
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of forLoopIteratesOverDynamicArray warnings`)
})
})
// #################### Helpers
function runModuleOnFiles (module, t, cb) {
var statRunner = new StatRunner()
testFiles.forEach((fileName) => {
statRunner.runWithModuleList(testFileAsts[fileName], [{ name: module.name, mod: new module.Module() }], (reports) => {
let report = reports[0].report
if (report.some((x) => x['warning'].includes('INTERNAL ERROR'))) {
t.comment('Error while executing Module: ' + JSON.stringify(report))
}
cb(fileName, report)
})
})
}
...@@ -4,10 +4,13 @@ var remixLib = require('remix-lib') ...@@ -4,10 +4,13 @@ var remixLib = require('remix-lib')
var StatRunner = require('../../src/solidity-analyzer') var StatRunner = require('../../src/solidity-analyzer')
var compilerInput = remixLib.helpers.compiler.compilerInput var compilerInput = remixLib.helpers.compiler.compilerInput
var compiler = require('solc') const niv = require('npm-install-version')
niv.install('solc@0.5.0')
var compiler = niv.require('solc@0.5.0')
var fs = require('fs') var fs = require('fs')
var path = require('path') var path = require('path')
var folder = 'solidity-v0.5'
var testFiles = [ var testFiles = [
'KingOfTheEtherThrone.sol', 'KingOfTheEtherThrone.sol',
...@@ -40,8 +43,8 @@ var testFiles = [ ...@@ -40,8 +43,8 @@ var testFiles = [
var testFileAsts = {} var testFileAsts = {}
testFiles.forEach((fileName) => { testFiles.forEach((fileName) => {
var content = fs.readFileSync(path.join(__dirname, 'test-contracts', fileName), 'utf8') var content = fs.readFileSync(path.join(__dirname, 'test-contracts/' + folder, fileName), 'utf8')
testFileAsts[fileName] = JSON.parse(compiler.compileStandardWrapper(compilerInput(content))) testFileAsts[fileName] = JSON.parse(compiler.compile(compilerInput(content)))
}) })
test('Integration test thisLocal.js', function (t) { test('Integration test thisLocal.js', function (t) {
...@@ -131,7 +134,7 @@ test('Integration test constantFunctions.js', function (t) { ...@@ -131,7 +134,7 @@ test('Integration test constantFunctions.js', function (t) {
'ballot.sol': 0, 'ballot.sol': 0,
'ballot_reentrant.sol': 0, 'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0, 'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 1, 'cross_contract.sol': 0,
'inheritance.sol': 0, 'inheritance.sol': 0,
'modifier1.sol': 1, 'modifier1.sol': 1,
'modifier2.sol': 0, 'modifier2.sol': 0,
...@@ -143,7 +146,7 @@ test('Integration test constantFunctions.js', function (t) { ...@@ -143,7 +146,7 @@ test('Integration test constantFunctions.js', function (t) {
'transfer.sol': 0, 'transfer.sol': 0,
'ctor.sol': 0, 'ctor.sol': 0,
'forgottenReturn.sol': 0, 'forgottenReturn.sol': 0,
'selfdestruct.sol': 1, 'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0, 'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0, 'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0, 'blockLevelCompare.sol': 0,
...@@ -281,7 +284,7 @@ test('Integration test similarVariableNames.js', function (t) { ...@@ -281,7 +284,7 @@ test('Integration test similarVariableNames.js', function (t) {
'KingOfTheEtherThrone.sol': 0, 'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0, 'assembly.sol': 0,
'ballot.sol': 2, 'ballot.sol': 2,
'ballot_reentrant.sol': 3, 'ballot_reentrant.sol': 11,
'ballot_withoutWarnings.sol': 0, 'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0, 'cross_contract.sol': 0,
'inheritance.sol': 0, 'inheritance.sol': 0,
...@@ -462,6 +465,10 @@ test('Integration test blockBlockhash.js', function (t) { ...@@ -462,6 +465,10 @@ test('Integration test blockBlockhash.js', function (t) {
}) })
}) })
/*
! No return gives compilation error with solidity 0.5.0
test('Integration test noReturn.js', function (t) { test('Integration test noReturn.js', function (t) {
t.plan(testFiles.length) t.plan(testFiles.length)
...@@ -499,6 +506,7 @@ test('Integration test noReturn.js', function (t) { ...@@ -499,6 +506,7 @@ test('Integration test noReturn.js', function (t) {
t.equal(report.length, lengthCheck[file], `${file} has right amount of noReturn warnings`) t.equal(report.length, lengthCheck[file], `${file} has right amount of noReturn warnings`)
}) })
}) })
*/
test('Integration test selfdestruct.js', function (t) { test('Integration test selfdestruct.js', function (t) {
t.plan(testFiles.length) t.plan(testFiles.length)
......
...@@ -4,13 +4,16 @@ var remixLib = require('remix-lib') ...@@ -4,13 +4,16 @@ var remixLib = require('remix-lib')
var StatRunner = require('../../src/solidity-analyzer') var StatRunner = require('../../src/solidity-analyzer')
var compilerInput = remixLib.helpers.compiler.compilerInput var compilerInput = remixLib.helpers.compiler.compilerInput
var compiler = require('solc') const niv = require('npm-install-version')
niv.install('solc@0.4.24')
var compiler = niv.require('solc@0.4.24')
var fs = require('fs') var fs = require('fs')
var path = require('path') var path = require('path')
var folder = 'solidity-v0.4.24'
function compile (fileName) { function compile (fileName) {
var content = fs.readFileSync(path.join(__dirname, 'test-contracts', fileName), 'utf8') var content = fs.readFileSync(path.join(__dirname, 'test-contracts/' + folder, fileName), 'utf8')
return JSON.parse(compiler.compileStandardWrapper(compilerInput(content))) return JSON.parse(compiler.compileStandardWrapper(compilerInput(content)))
} }
......
var test = require('tape')
var remixLib = require('remix-lib')
var StatRunner = require('../../src/solidity-analyzer')
var compilerInput = remixLib.helpers.compiler.compilerInput
const niv = require('npm-install-version')
niv.install('solc@0.5.0')
var compiler = niv.require('solc@0.5.0')
var fs = require('fs')
var path = require('path')
var folder = 'solidity-v0.5'
function compile (fileName) {
var content = fs.readFileSync(path.join(__dirname, 'test-contracts/' + folder, fileName), 'utf8')
return JSON.parse(compiler.compile(compilerInput(content)))
}
test('staticAnalysisIssues.functionParameterPassingError', function (t) {
// https://github.com/ethereum/remix-ide/issues/889#issuecomment-351746474
t.plan(2)
var res = compile('functionParameters.sol')
var module = require('../../src/solidity-analyzer/modules/checksEffectsInteraction')
var statRunner = new StatRunner()
t.doesNotThrow(() => {
statRunner.runWithModuleList(res, [{ name: module.name, mod: new module.Module() }], (reports) => {
})
}, true, 'Analysis should not throw')
statRunner.runWithModuleList(res, [{ name: module.name, mod: new module.Module() }], (reports) => {
t.ok(!reports.some((mod) => mod.report.some((rep) => rep.warning.includes('INTERNAL ERROR')), 'Should not have internal errors'))
})
})
pragma solidity >=0.4.9 <0.6.0;
contract EIP20 {
uint public decimals = 12;
// optional
function name() public pure returns (string memory) {
return "MYTOKEN";
}
// optional
function symbol() public pure returns (string memory) {
return "MT";
}
// optional
//function decimals() internal pure returns (uint8) {
// return 12;
//}
function totalSupply() public pure returns (uint256) {
return 12000;
}
function balanceOf(address _owner) public pure returns (uint256) {
return 0;
}
function transfer(address _to, uint256 _value) public pure returns (bool success) {
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public pure returns (bool) {
return true;
}
function approve(address _spender, uint256 _value) public pure returns (bool) {
return true;
}
function allowance(address _owner, address _spender) public pure returns (uint256) {
return 0;
}
}
\ No newline at end of file
// return value send
contract KingOfTheEtherThrone{
struct Monarch {
// address of the king .
address payable ethAddr ;
string name ;
// how much he pays to previous king
uint claimPrice ;
uint coronationTimestamp;
}
Monarch public currentMonarch ;
function claimThrone ( string memory name ) public {
address wizardAddress;
uint compensation = 100;
uint valuePaid = 10;
if ( currentMonarch.ethAddr != wizardAddress )
if (currentMonarch.ethAddr.send( compensation )) revert();
currentMonarch = Monarch(msg.sender,name,valuePaid,block.timestamp);
}
}
pragma solidity >=0.4.9 <0.6.0;
contract test {
address owner;
function at(address _addr) public returns (bytes memory o_code) {
assert(_addr != address(0x0));
assembly {
// retrieve the size of the code, this needs assembly
let size := extcodesize(_addr)
// allocate output byte array - this could also be done without assembly
// by using o_code = new bytes(size)
o_code := mload(0x40)
// new "memory end" including padding
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
// store length in memory
mstore(o_code, size)
// actually retrieve the code, this needs assembly
extcodecopy(_addr, add(o_code, 0x20), 0, size)
}
}
function bla() public {
require(tx.origin == owner);
msg.sender.send(19);
assembly {
}
}
}
pragma solidity >=0.4.9 <0.6.0;
/// @title Voting with delegation.
contract Ballot {
// This declares a new complex type which will
// be used for variables later.
// It will represent a single voter.
struct Voter {
uint weight; // weight is accumulated by delegation
bool voted; // if true, that person already voted
address delegate; // person delegated to
uint vote; // index of the voted proposal
}
// This is a type for a single proposal.
struct Proposal
{
bytes32 name; // short name (up to 32 bytes)
uint voteCount; // number of accumulated votes
}
address public chairperson;
// This declares a state variable that
// stores a `Voter` struct for each possible address.
mapping(address => Voter) public voters;
// A dynamically-sized array of `Proposal` structs.
Proposal[] public proposals;
/// Create a new ballot to choose one of `proposalNames`.
constructor(bytes32[] memory proposalNames) public {
chairperson = msg.sender;
voters[chairperson].weight = 1;
// For each of the provided proposal names,
// create a new proposal object and add it
// to the end of the array.
for (uint i = 0; i < proposalNames.length; i++) {
// `Proposal({...})` creates a temporary
// Proposal object and `proposals.push(...)`
// appends it to the end of `proposals`.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
// Give `voter` the right to vote on this ballot.
// May only be called by `chairperson`.
function giveRightToVote(address voter) public {
if (msg.sender != chairperson || voters[voter].voted) {
// `throw` terminates and reverts all changes to
// the state and to Ether balances. It is often
// a good idea to use this if functions are
// called incorrectly. But watch out, this
// will also consume all provided gas.
revert();
}
voters[voter].weight = 1;
}
/// Delegate your vote to the voter `to`.
function delegate(address to) public {
// assigns reference
Voter memory sender = voters[msg.sender];
if (sender.voted)
revert();
// Forward the delegation as long as
// `to` also delegated.
// In general, such loops are very dangerous,
// because if they run too long, they might
// need more gas than is available in a block.
// In this case, the delegation will not be executed,
// but in other situations, such loops might
// cause a contract to get "stuck" completely.
while (
voters[to].delegate != address(0) &&
voters[to].delegate != msg.sender
) {
to = voters[to].delegate;
}
// We found a loop in the delegation, not allowed.
if (to == msg.sender) {
revert();
}
// Since `sender` is a reference, this
// modifies `voters[msg.sender].voted`
sender.voted = true;
sender.delegate = to;
Voter memory delegate = voters[to];
if (delegate.voted) {
// If the delegate already voted,
// directly add to the number of votes
proposals[delegate.vote].voteCount += sender.weight;
} else {
// If the delegate did not vote yet,
// add to her weight.
delegate.weight += sender.weight;
}
}
/// Give your vote (including votes delegated to you)
/// to proposal `proposals[proposal].name`.
function vote(uint proposal) public {
Voter memory sender = voters[msg.sender];
if (sender.voted)
revert();
sender.voted = true;
sender.vote = proposal;
// If `proposal` is out of the range of the array,
// this will throw automatically and revert all
// changes.
proposals[proposal].voteCount += sender.weight;
}
/// @dev Computes the winning proposal taking all
/// previous votes into account.
function winningProposal() view public
returns (uint winningProposal)
{
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal = p;
}
}
}
// Calls winningProposal() function to get the index
// of the winner contained in the proposals array and then
// returns the name of the winner
function winnerName() view public
returns (bytes32 winnerName)
{
winnerName = proposals[winningProposal()].name;
}
}
pragma solidity >=0.4.9 <0.6.0;
contract InfoFeed {
function info() public payable returns (uint ret);
function call1(uint a) public payable returns (bool);
}
contract Ballot {
InfoFeed feed;
struct Voter {
uint weight;
bool voted;
uint8 vote;
address delegate;
}
struct Proposal {
uint voteCount;
}
address chairperson;
mapping(address => Voter) voters;
Proposal[] proposals;
function send1(address a) public {
giveRightToVote(a,a);
}
/// Create a new ballot with $(_numProposals) different proposals.
constructor(uint8 _numProposals) public {
address payable d;
(bool success, bytes memory data) = d.delegatecall.gas(800)(abi.encodeWithSignature('function_name', 'arg1', 'arg2'));
if(!success) revert();
(bool success2, bytes memory data2) = d.delegatecall.gas(800)(abi.encodeWithSignature('function_name', 'arg1', 'arg2'));
if(!success2) revert();
(bool success3, bytes memory data3) = d.call.value(10).gas(800)(abi.encodeWithSignature('function_name', 'arg1', 'arg2'));
if(!success3) revert();
(bool success4, bytes memory data4) = d.call.value(10).gas(800)(abi.encodeWithSignature('function_name', 'arg1', 'arg2'));
if(!success4) revert();
address payable o = msg.sender;
if(!o.send(1 wei)) revert();
(bool success5, bytes memory data5) = d.call(abi.encodeWithSignature('function_name', 'arg1', 'arg2'));
if(!success5) revert();
uint a = now;
uint c = block.timestamp;
if(block.timestamp < 100){}
chairperson = msg.sender;
voters[chairperson].weight = 1;
proposals.length = _numProposals;
if(!d.send(1 wei)) revert();
feed.info.value(10).gas(800)();
feed.call1(1);
this.send1(d);
}
/// Give $(voter) the right to vote on this ballot.
/// May only be called by $(chairperson).
function giveRightToVote(address voter, address b) public payable returns (bool){
if (msg.sender != chairperson || voters[voter].voted) return false;
voters[voter].weight = 1;
return true;
}
/// Delegate your vote to the voter $(to).
function delegate(address to) public {
Voter memory sender = voters[msg.sender]; // assigns reference
if (sender.voted) return;
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender)
to = voters[to].delegate;
if (to == msg.sender) return;
sender.voted = true;
sender.delegate = to;
Voter memory delegate = voters[to];
if (delegate.voted)
proposals[delegate.vote].voteCount += sender.weight;
else
delegate.weight += sender.weight;
}
/// Give a single vote to proposal $(proposal).
function vote(uint8 proposal) public {
Voter memory sender = voters[msg.sender];
if (sender.voted || proposal >= proposals.length) return;
sender.voted = true;
sender.vote = proposal;
proposals[proposal].voteCount += sender.weight;
}
function winningProposal() view public returns (uint8 winningProposal) {
uint256 winningVoteCount = 0;
for (uint8 proposal = 0; proposal < proposals.length; proposal++)
if (proposals[proposal].voteCount > winningVoteCount) {
winningVoteCount = proposals[proposal].voteCount;
winningProposal = proposal;
}
}
}
pragma solidity >=0.4.9 <0.6.0;
/// @title Voting with delegation.
contract Ballot {
struct Proposal
{
bytes32 name; // short name (up to 32 bytes)
uint voteCount; // number of accumulated votes
}
// A dynamically-sized array of `Proposal` structs.
Proposal[] public proposals;
/// @dev Computes the winning proposal taking all
/// previous votes into account.
function winningProposal() public view
returns (uint winningProposal)
{
winningProposal = 0;
}
// Calls winningProposal() function to get the index
// of the winner contained in the proposals array and then
// returns the name of the winner
function winnerName() public view
returns (bytes32 winnerName)
{
winnerName = proposals[winningProposal()].name;
}
}
pragma solidity >=0.4.9 <0.6.0;
contract grr {
bool breaker;
function() external {
uint a = 1;
string memory sig = "withdraw()";
uint b = 3;
bytes4 selector = bytes4(keccak256(abi.encodePacked(sig)));
abi.encode(a,b);
abi.encodePacked(a,b);
a = -b;
a == b;
if(a == b) {
abi.encodeWithSelector(selector, a, b);
abi.encodeWithSignature(sig, a, b);
}
if(b < 4) { a == b; }
if(b > 4) b == a;
while(true) a == b;
for(int i = 0; i < 3; i++) b == a;
while(false) {
int c = 3;
uint(c) + a;
c == 5;
}
a + b;
breaker = false;
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract a {
uint x;
function foo() public {
x++;
}
}
contract b {
a x;
function bar() public {
address payable a;
a.send(100 wei);
x.foo();
}
}
contract c {
uint x;
uint x_abc;
constructor(uint _x, uint _abc) public {
x=_x;
x_abc=_abc;
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract arr {
uint[] users;
bytes access_rights_per_user;
uint user_index;
address owner;
string grr = "message";
uint[100] last_100_users;
constructor(address owner1) public {
owner = owner1;
user_index = 0;
}
function addUser(uint id, byte rights) public{
users[user_index] = id;
last_100_users[user_index % 100] = id;
access_rights_per_user[user_index] = rights;
user_index++;
}
function resetState() public{
require(msg.sender == owner, grr);
delete users;
delete access_rights_per_user;
delete last_100_users;
}
function bla(string memory bal) public {
grr = bal;
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract arr {
uint[] array = [1,2,3];
function removeAtIndex() public returns (uint[] memory) {
delete array[1];
return array;
}
// TODO: deleteFromDynamicArray should not generate warnings if array item is shifted and removed
/* function safeRemoveAtIndex(uint index) returns (uint[] memory) {
if (index >= array.length) return;
for (uint i = index; i < array.length-1; i++) {
array[i] = array[i+1];
}
delete array[array.length-1];
array.length--;
return array;
} */
}
pragma solidity >=0.4.9 <0.6.0;
contract forLoopArr {
uint[] array;
constructor(uint[] memory _array) public {
array = _array;
}
function shiftArrItem(uint index) public returns(uint[] memory) {
// TODO: for (uint i = index; i < array.length-1; i++) should also generate warning
for (uint i = index; i < array.length; i++) {
array[i] = array[i+1];
}
return array;
}
}
contract Sheep {
string public name;
string public dna;
bool g = true;
constructor(string memory _name, string memory _dna) public {
name = _name;
dna = _dna;
}
function geneticallyEngineer(string memory _dna) public returns (bool) {
dna = _dna;
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract B {
function plus(uint a, uint b) pure internal returns (uint) {
return a + b;
}
function eval(function (uint, uint) pure internal returns (uint) f, uint x, uint y) pure internal returns (uint) {
return f(x, y);
}
function calc(uint x, uint y) pure public returns (uint) {
return eval(plus, x, y);
// return plus(x, y);
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract bla {
uint brr;
function duper() public {
brr++;
}
}
contract a is bla {
function blub() public {
brr++;
}
function r () public payable {
address payable a;
bytes32 hash;
uint8 v;
bytes32 r;
bytes32 s;
blockhash(1);
block.coinbase;
block.difficulty;
block.gaslimit;
block.number;
block.timestamp;
msg.data;
gasleft();
msg.sender;
msg.value;
now;
tx.gasprice;
tx.origin;
// assert(1 == 2);
// require(1 == 1);
keccak256(abi.encodePacked(a));
sha256(abi.encodePacked(a));
ripemd160(abi.encodePacked(a));
ecrecover(hash, v, r, s);
addmod(1, 2, 2);
mulmod(4,4,12);
a.balance;
blub();
a.send(a.balance);
super.duper();
//a.transfer(a.balance);
selfdestruct(a);
//revert();
assert(a.balance == 0);
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract r {
function s() public view {}
}
contract a is r {
uint x = 1;
function getX() public view returns (uint) {
return x;
}
}
contract b is a {
uint y = 2;
uint x = 3;
function getY(uint z, bool r) public returns (uint) {
return y++;
}
function getY(string storage n) internal view returns (uint) { return 10; }
}
contract c is b {
string x;
function d() public returns (uint a, uint b) {
//d();
//sha3("bla");
address payable o = msg.sender;
o.call.gas(200000).value(address(this).balance)(abi.encode("pay()"));
//x++;
getY(x);
a = getX() + getY(1, false);
b = getX() + getY(x);
}
}
pragma solidity >=0.4.9 <0.6.0;
contract CharityCampaign {
mapping (address => uint) contributions;
int128 feePercentage;
uint p2;
address payable processor;
address payable beneficiary;
constructor(address payable _beneficiary, int128 _feePercentage) public {
processor = msg.sender;
beneficiary = _beneficiary;
feePercentage = _feePercentage;
}
function contribute() payable public returns (uint feeCollected) {
uint fee = msg.value * uint256(feePercentage / 100);
fee = msg.value * (p2 / 100);
contributions[msg.sender] = msg.value - fee;
processor.transfer(fee);
return fee;
}
function endCampaign() public returns (bool) {
require(msg.sender == processor || msg.sender == beneficiary);
selfdestruct(beneficiary);
return true;
}
// FALSE POSITIVE FOR SELFDESTRUCT TERMINAL
function endAmbiguous() public {
if(msg.sender == address(0x0)) {
selfdestruct(beneficiary);
} else {
selfdestruct(processor);
}
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
library Set {
// We define a new struct datatype that will be used to
// hold its data in the calling contract.
struct Data { mapping(uint => bool) flags; }
// Note that the first parameter is of type "storage
// reference" and thus only its storage address and not
// its contents is passed as part of the call. This is a
// special feature of library functions. It is idiomatic
// to call the first parameter 'self', if the function can
// be seen as a method of that object.
function insert(Data storage self, uint value) public
returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
function remove(Data storage self, uint value) public
returns (bool)
{
if (!self.flags[value])
return false; // not there
self.flags[value] = false;
return true;
}
function contains(Data storage self, uint value) public
returns (bool)
{
return self.flags[value];
}
}
contract C {
Set.Data knownValues;
function register(uint value) public {
// The library functions can be called without a
// specific instance of the library, since the
// "instance" will be the current contract.
address payable a;
a.send(10 wei);
if (!Set.insert(knownValues, value))
revert();
}
// In this contract, we can also directly access knownValues.flags, if we want.
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract test {
address owner;
modifier onlyOwner {
uint a = 0;
if (msg.sender != owner)
revert();
_;
}
function b(address a) public onlyOwner returns (bool) {
return true;
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract owned {
uint r=0;
modifier ntimes(uint n) {
for(uint i=0;i<n-1;i++){
_;
}
_;
}
modifier plus100 {
uint bla=1;
r+=100;
_;
}
function a() ntimes(10) plus100 public payable returns (uint) {
{
uint bla=5;
r += bla;
}
return r;
}
}
pragma solidity >=0.4.9 <0.6.0;
contract Fund {
/// Mapping of ether shares of the contract.
mapping(address => uint) shares;
/// Withdraw your share.
function withdraw() public {
uint share = shares[msg.sender];
shares[msg.sender] = 0;
if (!msg.sender.send(share))
revert();
}
}
pragma solidity >=0.4.9 <0.6.0;
contract InfoFeed {
uint c;
function info() constant returns (uint ret) {return c;}
function call1(uint a) constant returns (bool) {return true;}
}
// THIS CONTRACT CONTAINS A BUG - DO NOT USE
contract Fund {
/// Mapping of ether shares of the contract.
//mapping(address => uint) shares;
/// Withdraw your share.
uint c = 0;
function withdraw() constant {
InfoFeed f;
//shares[msg.sender] /= 1;
f.info();
//if (msg.sender.send(shares[msg.sender])) throw;
// shares[msg.sender] = 0;
b(true, false);
//shares[msg.sender]++;
//c++;
}
mapping(address => uint) shares;
function b(bool a, bool b) returns (bool) {
mapping(address => uint) c = shares;
c[msg.sender] = 0;
//f();
//withdraw();
//shares[msg.sender]++;
//c++;
return true;
}
function f() {
c++;
withdraw();
}
}
contract sd {
uint x = 0;
function() external payable { }
function c () public {
selfdestruct(address(0xdeadbeef));
}
function b () public {
selfdestruct(address(0xdeadbeef));
x = 1;
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract bytesString {
function length(string memory a) public pure returns(uint) {
bytes memory x = bytes(a);
return x.length;
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract Ballot {
struct Voter {
uint weight;
bool voted;
uint8 vote;
address delegate;
baz foo;
}
struct baz{
uint bar;
}
mapping(address => Voter) voters;
/// Create a new ballot with $(_numProposals) different proposals.
function bla(address payable a) public {
Voter storage x = voters[a];
if (!a.send(10))
revert();
//voters[a] = Voter(10,true,1,a);
//x.foo.bar *= 100;
bli(x);
}
//function bla(){}
function bli(Voter storage x) private {
x.foo.bar++;
}
}
pragma solidity >=0.4.9 <0.6.0;
contract test {
function () external {
address payable x;
this.b(x);
x.call('something');
x.send(1 wei);
}
function b(address a) public returns (bool) {
}
}
contract c {
uint x;
function f(address payable r) public payable {
r.transfer(1);
x = 2;
}
}
\ No newline at end of file
require('./analysis/staticAnalysisCommon-test.js') require('./analysis/staticAnalysisCommon-test.js')
require('./analysis/staticAnalysisIntegration-test.js')
require('./analysis/staticAnalysisIssues-test.js') require('./analysis/staticAnalysisIntegration-test-0.4.24.js')
require('./analysis/staticAnalysisIssues-test-0.4.24.js')
require('./analysis/staticAnalysisIntegration-test-0.5.0.js')
require('./analysis/staticAnalysisIssues-test-0.5.0.js')
{ {
"name": "remix-debug", "name": "remix-debug",
"version": "0.2.9", "version": "0.2.13",
"description": "Ethereum IDE and tools for the web", "description": "Ethereum IDE and tools for the web",
"contributors": [ "contributors": [
{ {
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
"fast-async": "^6.1.2", "fast-async": "^6.1.2",
"notify-error": "^1.2.0", "notify-error": "^1.2.0",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"remix-lib": "^0.3.8", "remix-lib": "0.3.12",
"solc": "^0.4.24" "solc": "^0.5.0"
}, },
"devDependencies": { "devDependencies": {
"standard": "^7.0.1", "standard": "^7.0.1",
......
...@@ -6,10 +6,10 @@ module.exports = { ...@@ -6,10 +6,10 @@ module.exports = {
enum enum1 { e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76, e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91, e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105, e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117, e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128, e129, e130, e131, e132, e133, e134, e135, e136, e137, e138, e139, e140, e141, e142, e143, e144, e145, e146, e147, e148, e149, e150, e151, e152, e153, e154, e155, e156, e157, e158, e159, e160, e161, e162, e163, e164, e165, e166, e167, e168, e169, e170, e171, e172, e173, e174, e175, e176, e177, e178, e179, e180, e181, e182, e183, e184, e185, e186, e187, e188, e189, e190, e191, e192, e193, e194, e195, e196, e197, e198, e199, e200, e201, e202, e203, e204, e205, e206, e207, e208, e209, e210, e211, e212, e213, e214, e215, e216, e217, e218, e219, e220, e221, e222, e223, e224, e225, e226, e227, e228, e229, e230, e231, e232, e233, e234, e235, e236, e237, e238, e239, e240, e241, e242, e243, e244, e245, e246, e247, e248, e249, e250, e251, e252, e253, e254, e255, e256, e257, e258, e259, e260 } enum enum1 { e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76, e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91, e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105, e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117, e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128, e129, e130, e131, e132, e133, e134, e135, e136, e137, e138, e139, e140, e141, e142, e143, e144, e145, e146, e147, e148, e149, e150, e151, e152, e153, e154, e155, e156, e157, e158, e159, e160, e161, e162, e163, e164, e165, e166, e167, e168, e169, e170, e171, e172, e173, e174, e175, e176, e177, e178, e179, e180, e181, e182, e183, e184, e185, e186, e187, e188, e189, e190, e191, e192, e193, e194, e195, e196, e197, e198, e199, e200, e201, e202, e203, e204, e205, e206, e207, e208, e209, e210, e211, e212, e213, e214, e215, e216, e217, e218, e219, e220, e221, e222, e223, e224, e225, e226, e227, e228, e229, e230, e231, e232, e233, e234, e235, e236, e237, e238, e239, e240, e241, e242, e243, e244, e245, e246, e247, e248, e249, e250, e251, e252, e253, e254, e255, e256, e257, e258, e259, e260 }
bool b1 = false; bool b1 = false;
address a1 = 0xfe350f199f244ac9a79038d254400b632a633225; address a1 = 0xfE350f199F244ac9A79038d254400b632a633225;
bool b2 = true; bool b2 = true;
bytes dynb1 = "dynamicbytes"; bytes dynb1 = "dynamicbytes";
byte stab = 0x1; byte stab = 0x01;
bytes1 stab1 = hex"12"; bytes1 stab1 = hex"12";
bytes2 stab2 = hex"1579"; bytes2 stab2 = hex"1579";
bytes3 stab3 = hex"359356"; bytes3 stab3 = hex"359356";
......
...@@ -9,7 +9,7 @@ contract proxy { ...@@ -9,7 +9,7 @@ contract proxy {
} }
} }
contract intLocal { contract intLocal {
function intLocal () { constructor () public {
proxy.testStruct memory p; proxy.testStruct memory p;
uint8 ui8 = 130; uint8 ui8 = 130;
uint16 ui16 = 456; uint16 ui16 = 456;
...@@ -31,11 +31,11 @@ contract intLocal { ...@@ -31,11 +31,11 @@ contract intLocal {
level11(); level11();
} }
function level11() { function level11() public {
uint8 ui8 = 123; uint8 ui8 = 123;
level12(); level12();
} }
function level12() { function level12() public {
uint8 ui81 = 12; uint8 ui81 = 12;
} }
} }
......
module.exports = { module.exports = {
contract: ` contract: `
pragma solidity ^0.4.19; pragma solidity ^0.5.0;
contract SimpleMappingState { contract SimpleMappingState {
uint _num; uint _num;
mapping(string => uint) _iBreakSolidityState; mapping(string => uint) _iBreakSolidityState;
mapping(uint => uint) _iBreakSolidityStateInt; mapping(uint => uint) _iBreakSolidityStateInt;
function updateNum(uint num, string str) public { function updateNum(uint num, string memory str) public {
_num = num; _num = num;
_iBreakSolidityState[str] = num; _iBreakSolidityState[str] = num;
_iBreakSolidityStateInt[num] = num; _iBreakSolidityStateInt[num] = num;
......
...@@ -9,7 +9,7 @@ contract miscLocal { ...@@ -9,7 +9,7 @@ contract miscLocal {
three, three,
four four
} }
function miscLocal () { constructor () public {
bool boolFalse = false; bool boolFalse = false;
bool boolTrue = true; bool boolTrue = true;
enumDef testEnum; enumDef testEnum;
...@@ -31,7 +31,7 @@ contract miscLocal { ...@@ -31,7 +31,7 @@ contract miscLocal {
} }
contract miscLocal2 { contract miscLocal2 {
function miscLocal2 () { constructor () public {
bytes memory dynbytes = "dynamicbytes"; bytes memory dynbytes = "dynamicbytes";
string memory smallstring = "test_test_test"; string memory smallstring = "test_test_test";
} }
......
...@@ -17,6 +17,7 @@ module.exports = ` ...@@ -17,6 +17,7 @@ module.exports = `
contract test1 { contract test1 {
struct str { struct str {
uint8 ui;
} }
} }
......
...@@ -24,7 +24,7 @@ contract structArrayLocal { ...@@ -24,7 +24,7 @@ contract structArrayLocal {
enumdef c; enumdef c;
} }
function structArrayLocal () { constructor () public {
bytes memory bytesSimple = "test_super"; bytes memory bytesSimple = "test_super";
teststruct memory e; teststruct memory e;
e.a = "test"; e.a = "test";
......
...@@ -25,7 +25,7 @@ module.exports = { ...@@ -25,7 +25,7 @@ module.exports = {
string str; string str;
} }
simpleStruct[][3] arrayStruct; simpleStruct[][3] arrayStruct;
function structArrayStorage () { constructor () public {
intStructDec.i8 = 32; intStructDec.i8 = 32;
intStructDec.i16 = -54; intStructDec.i16 = -54;
intStructDec.ui32 = 128; intStructDec.ui32 = 128;
......
...@@ -12,7 +12,7 @@ var util = require('../../src/solidity-decoder/types/util') ...@@ -12,7 +12,7 @@ var util = require('../../src/solidity-decoder/types/util')
tape('solidity', function (t) { tape('solidity', function (t) {
t.test('astHelper, decodeInfo', function (st) { t.test('astHelper, decodeInfo', function (st) {
var output = compiler.compileStandardWrapper(compilerInput(contracts)) var output = compiler.compile(compilerInput(contracts))
output = JSON.parse(output) output = JSON.parse(output)
var state = astHelper.extractStateDefinitions('test.sol:contractUint', output.sources) var state = astHelper.extractStateDefinitions('test.sol:contractUint', output.sources)
...@@ -65,9 +65,8 @@ tape('solidity', function (t) { ...@@ -65,9 +65,8 @@ tape('solidity', function (t) {
parsedType = decodeInfo.parseType(stateDef[5].attributes.type, states, 'contractSmallVariable', util.extractLocationFromAstVariable(stateDef[5])) parsedType = decodeInfo.parseType(stateDef[5].attributes.type, states, 'contractSmallVariable', util.extractLocationFromAstVariable(stateDef[5]))
checkDecodeInfo(st, parsedType, 1, 2, 'int16') checkDecodeInfo(st, parsedType, 1, 2, 'int16')
output = compiler.compileStandardWrapper(compilerInput(simplecontracts)) output = compiler.compile(compilerInput(simplecontracts))
output = JSON.parse(output) output = JSON.parse(output)
state = astHelper.extractStateDefinitions('test.sol:simpleContract', output.sources) state = astHelper.extractStateDefinitions('test.sol:simpleContract', output.sources)
states = astHelper.extractStatesDefinitions(output.sources) states = astHelper.extractStatesDefinitions(output.sources)
stateDef = state.stateDefinitions stateDef = state.stateDefinitions
...@@ -81,10 +80,10 @@ tape('solidity', function (t) { ...@@ -81,10 +80,10 @@ tape('solidity', function (t) {
state = astHelper.extractStateDefinitions('test.sol:test2', output.sources) state = astHelper.extractStateDefinitions('test.sol:test2', output.sources)
stateDef = state.stateDefinitions stateDef = state.stateDefinitions
parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'test1', util.extractLocationFromAstVariable(stateDef[0])) parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'test1', util.extractLocationFromAstVariable(stateDef[0]))
checkDecodeInfo(st, parsedType, 0, 32, 'struct test1.str') checkDecodeInfo(st, parsedType, 1, 32, 'struct test1.str')
state = stateDecoder.extractStateVariables('test.sol:test2', output.sources) state = stateDecoder.extractStateVariables('test.sol:test2', output.sources)
checkDecodeInfo(st, parsedType, 0, 32, 'struct test1.str') checkDecodeInfo(st, parsedType, 1, 32, 'struct test1.str')
st.end() st.end()
}) })
......
...@@ -21,16 +21,16 @@ tape('solidity', function (t) { ...@@ -21,16 +21,16 @@ tape('solidity', function (t) {
}) })
function test (st, vm, privateKey) { function test (st, vm, privateKey) {
var output = compiler.compileStandardWrapper(compilerInput(intLocal.contract)) var output = compiler.compile(compilerInput(intLocal.contract))
output = JSON.parse(output) output = JSON.parse(output)
intLocalTest(st, vm, privateKey, output.contracts['test.sol']['intLocal'].evm.bytecode.object, output, function () { intLocalTest(st, vm, privateKey, output.contracts['test.sol']['intLocal'].evm.bytecode.object, output, function () {
output = compiler.compileStandardWrapper(compilerInput(miscLocal.contract)) output = compiler.compile(compilerInput(miscLocal.contract))
output = JSON.parse(output) output = JSON.parse(output)
miscLocalTest(st, vm, privateKey, output.contracts['test.sol']['miscLocal'].evm.bytecode.object, output, function () { miscLocalTest(st, vm, privateKey, output.contracts['test.sol']['miscLocal'].evm.bytecode.object, output, function () {
output = compiler.compileStandardWrapper(compilerInput(miscLocal.contract)) output = compiler.compile(compilerInput(miscLocal.contract))
output = JSON.parse(output) output = JSON.parse(output)
misc2LocalTest(st, vm, privateKey, output.contracts['test.sol']['miscLocal2'].evm.bytecode.object, output, function () { misc2LocalTest(st, vm, privateKey, output.contracts['test.sol']['miscLocal2'].evm.bytecode.object, output, function () {
output = compiler.compileStandardWrapper(compilerInput(structArrayLocal.contract)) output = compiler.compile(compilerInput(structArrayLocal.contract))
output = JSON.parse(output) output = JSON.parse(output)
structArrayLocalTest(st, vm, privateKey, output.contracts['test.sol']['structArrayLocal'].evm.bytecode.object, output, function () { structArrayLocalTest(st, vm, privateKey, output.contracts['test.sol']['structArrayLocal'].evm.bytecode.object, output, function () {
st.end() st.end()
......
...@@ -13,7 +13,7 @@ module.exports = function testMappingStorage (st, cb) { ...@@ -13,7 +13,7 @@ module.exports = function testMappingStorage (st, cb) {
var mappingStorage = require('../contracts/mappingStorage') var mappingStorage = require('../contracts/mappingStorage')
var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex') var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex')
var vm = vmCall.initVM(st, privateKey) var vm = vmCall.initVM(st, privateKey)
var output = compiler.compileStandardWrapper(compilerInput(mappingStorage.contract)) var output = compiler.compile(compilerInput(mappingStorage.contract))
output = JSON.parse(output) output = JSON.parse(output)
vmCall.sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['SimpleMappingState'].evm.bytecode.object, function (error, txHash) { vmCall.sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['SimpleMappingState'].evm.bytecode.object, function (error, txHash) {
if (error) { if (error) {
...@@ -48,7 +48,7 @@ function testMapping (st, vm, privateKey, contractAddress, output, cb) { ...@@ -48,7 +48,7 @@ function testMapping (st, vm, privateKey, contractAddress, output, cb) {
var traceManager = new TraceManager({web3: vm.web3}) var traceManager = new TraceManager({web3: vm.web3})
traceManager.resolveTrace(tx, () => { traceManager.resolveTrace(tx, () => {
var storageViewer = new StorageViewer({ var storageViewer = new StorageViewer({
stepIndex: 213, stepIndex: 268,
tx: tx, tx: tx,
address: contractAddress address: contractAddress
}, new StorageResolver({web3: vm.web3}), traceManager) }, new StorageResolver({web3: vm.web3}), traceManager)
......
...@@ -23,7 +23,7 @@ tape('solidity', function (t) { ...@@ -23,7 +23,7 @@ tape('solidity', function (t) {
function testIntStorage (st, cb) { function testIntStorage (st, cb) {
var intStorage = require('./contracts/intStorage') var intStorage = require('./contracts/intStorage')
var output = compiler.compileStandardWrapper(compilerInput(intStorage.contract)) var output = compiler.compile(compilerInput(intStorage.contract))
output = JSON.parse(output) output = JSON.parse(output)
var mockStorageResolver var mockStorageResolver
for (var storage of [intStorage.fullStorage, shrinkStorage(intStorage.fullStorage)]) { for (var storage of [intStorage.fullStorage, shrinkStorage(intStorage.fullStorage)]) {
...@@ -70,7 +70,7 @@ function testIntStorage (st, cb) { ...@@ -70,7 +70,7 @@ function testIntStorage (st, cb) {
function testByteStorage (st, cb) { function testByteStorage (st, cb) {
var byteStorage = require('./contracts/byteStorage') var byteStorage = require('./contracts/byteStorage')
var output = compiler.compileStandardWrapper(compilerInput(byteStorage.contract)) var output = compiler.compile(compilerInput(byteStorage.contract))
output = JSON.parse(output) output = JSON.parse(output)
var mockStorageResolver var mockStorageResolver
for (var storage of [byteStorage.storage, shrinkStorage(byteStorage.storage)]) { for (var storage of [byteStorage.storage, shrinkStorage(byteStorage.storage)]) {
...@@ -183,7 +183,7 @@ function shrinkStorage (storage) { ...@@ -183,7 +183,7 @@ function shrinkStorage (storage) {
function testStructArrayStorage (st, cb) { function testStructArrayStorage (st, cb) {
var structArrayStorage = require('./contracts/structArrayStorage') var structArrayStorage = require('./contracts/structArrayStorage')
var output = compiler.compileStandardWrapper(compilerInput(structArrayStorage.contract)) var output = compiler.compile(compilerInput(structArrayStorage.contract))
output = JSON.parse(output) output = JSON.parse(output)
var mockStorageResolver = new MockStorageResolver(structArrayStorage.storage) var mockStorageResolver = new MockStorageResolver(structArrayStorage.storage)
stateDecoder.solidityState(mockStorageResolver, output.sources, 'structArrayStorage').then((decoded) => { stateDecoder.solidityState(mockStorageResolver, output.sources, 'structArrayStorage').then((decoded) => {
......
...@@ -8,7 +8,7 @@ var compilerInput = remixLib.helpers.compiler.compilerInput ...@@ -8,7 +8,7 @@ var compilerInput = remixLib.helpers.compiler.compilerInput
tape('solidity', function (t) { tape('solidity', function (t) {
t.test('storage location', function (st) { t.test('storage location', function (st) {
var output = compiler.compileStandardWrapper(compilerInput(contracts)) var output = compiler.compile(compilerInput(contracts))
output = JSON.parse(output) output = JSON.parse(output)
var stateDec = stateDecoder.extractStateVariables('contractUint', output.sources) var stateDec = stateDecoder.extractStateVariables('contractUint', output.sources)
checkLocation(st, stateDec[0].storagelocation, 0, 0) checkLocation(st, stateDec[0].storagelocation, 0, 0)
......
...@@ -17,7 +17,7 @@ tape('debug contract', function (t) { ...@@ -17,7 +17,7 @@ tape('debug contract', function (t) {
t.plan(12) t.plan(12)
var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex') var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex')
var vm = vmCall.initVM(t, privateKey) var vm = vmCall.initVM(t, privateKey)
var output = compiler.compileStandardWrapper(compilerInput(ballot)) var output = compiler.compile(compilerInput(ballot))
output = JSON.parse(output) output = JSON.parse(output)
var web3VM = new remixLib.vm.Web3VMProvider() var web3VM = new remixLib.vm.Web3VMProvider()
web3VM.setVM(vm) web3VM.setVM(vm)
...@@ -109,8 +109,8 @@ function testDebugging (t, debugManager) { ...@@ -109,8 +109,8 @@ function testDebugging (t, debugManager) {
breakPointManager.event.register('breakpointHit', function (sourceLocation, step) { breakPointManager.event.register('breakpointHit', function (sourceLocation, step) {
console.log('breakpointHit') console.log('breakpointHit')
t.equal(JSON.stringify(sourceLocation), JSON.stringify({ start: 591, length: 1, file: 0, jump: '-' })) t.equal(JSON.stringify(sourceLocation), JSON.stringify({ start: 587, length: 1, file: 0, jump: '-' }))
t.equal(step, 75) t.equal(step, 74)
}) })
breakPointManager.event.register('noBreakpointHit', function () { breakPointManager.event.register('noBreakpointHit', function () {
...@@ -120,7 +120,7 @@ function testDebugging (t, debugManager) { ...@@ -120,7 +120,7 @@ function testDebugging (t, debugManager) {
breakPointManager.jumpNextBreakpoint(0, true) breakPointManager.jumpNextBreakpoint(0, true)
} }
var ballot = `pragma solidity ^0.4.0; var ballot = `pragma solidity ^0.5.0;
contract Ballot { contract Ballot {
struct Voter { struct Voter {
...@@ -138,13 +138,13 @@ contract Ballot { ...@@ -138,13 +138,13 @@ contract Ballot {
Proposal[] proposals; Proposal[] proposals;
/// Create a new ballot with $(_numProposals) different proposals. /// Create a new ballot with $(_numProposals) different proposals.
function Ballot() public { constructor() public {
uint p = 45; uint p = 45;
chairperson = msg.sender; chairperson = msg.sender;
address addressLocal = msg.sender; // copy of state variable address addressLocal = msg.sender; // copy of state variable
voters[chairperson].weight = 1; voters[chairperson].weight = 1;
proposals.length = 1; proposals.length = 1;
Proposal[] proposalsLocals = proposals; // copy of state variable Proposal[] storage proposalsLocals = proposals; // copy of state variable
} }
/// Give $(toVoter) the right to vote on this ballot. /// Give $(toVoter) the right to vote on this ballot.
...@@ -179,7 +179,7 @@ contract Ballot { ...@@ -179,7 +179,7 @@ contract Ballot {
proposals[toProposal].voteCount += sender.weight; proposals[toProposal].voteCount += sender.weight;
} }
function winningProposal() public constant returns (uint8 _winningProposal) { function winningProposal() public view returns (uint8 _winningProposal) {
uint256 winningVoteCount = 0; uint256 winningVoteCount = 0;
for (uint8 prop = 0; prop < proposals.length; prop++) for (uint8 prop = 0; prop < proposals.length; prop++)
if (proposals[prop].voteCount > winningVoteCount) { if (proposals[prop].voteCount > winningVoteCount) {
......
{ {
"name": "remix-lib", "name": "remix-lib",
"version": "0.3.8", "version": "0.3.12",
"description": "Ethereum IDE and tools for the web", "description": "Ethereum IDE and tools for the web",
"contributors": [ "contributors": [
{ {
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
"ethereumjs-vm": "^2.3.3", "ethereumjs-vm": "^2.3.3",
"ethers": "^3.0.15", "ethers": "^3.0.15",
"fast-async": "^6.1.2", "fast-async": "^6.1.2",
"solc": "^0.4.13", "solc": "^0.5.0",
"standard": "^7.0.1", "standard": "^7.0.1",
"tape": "^4.6.0", "tape": "^4.6.0",
"web3": "0.20.6" "web3": "0.20.6"
......
...@@ -85,6 +85,7 @@ function ExecutionContext () { ...@@ -85,6 +85,7 @@ function ExecutionContext () {
this.blockGasLimitDefault = 4300000 this.blockGasLimitDefault = 4300000
this.blockGasLimit = this.blockGasLimitDefault this.blockGasLimit = this.blockGasLimitDefault
this.customNetWorks = {}
this.init = function (config) { this.init = function (config) {
if (config.get('settings/always-use-vm')) { if (config.get('settings/always-use-vm')) {
...@@ -134,6 +135,20 @@ function ExecutionContext () { ...@@ -134,6 +135,20 @@ function ExecutionContext () {
} }
} }
this.removeProvider = function (name) {
if (name && this.customNetWorks[name]) {
delete this.customNetWorks[name]
self.event.trigger('removeProvider', [name])
}
}
this.addProvider = function (network) {
if (network && network.name && network.url) {
this.customNetWorks[network.name] = network
self.event.trigger('addProvider', [network])
}
}
this.internalWeb3 = function () { this.internalWeb3 = function () {
return web3 return web3
} }
...@@ -182,6 +197,11 @@ function ExecutionContext () { ...@@ -182,6 +197,11 @@ function ExecutionContext () {
if (context === 'web3') { if (context === 'web3') {
confirmCb(cb) confirmCb(cb)
} }
if (this.customNetWorks[context]) {
var provider = this.customNetWorks[context]
setProviderFromEndpoint(provider.url, provider.name, () => { cb() })
}
} }
this.currentblockGasLimit = function () { this.currentblockGasLimit = function () {
......
...@@ -122,6 +122,7 @@ web3VmProvider.prototype.txProcessed = function (self, data) { ...@@ -122,6 +122,7 @@ web3VmProvider.prototype.txProcessed = function (self, data) {
} }
self.txsReceipt[self.processingHash].logs = logs self.txsReceipt[self.processingHash].logs = logs
self.txsReceipt[self.processingHash].transactionHash = self.processingHash self.txsReceipt[self.processingHash].transactionHash = self.processingHash
self.txsReceipt[self.processingHash].status = '0x' + data.vm.exception.toString(16)
if (data.createdAddress) { if (data.createdAddress) {
var address = util.hexConvert(data.createdAddress) var address = util.hexConvert(data.createdAddress)
......
...@@ -7,7 +7,7 @@ var compilerInput = require('../src/helpers/compilerHelper').compilerInput ...@@ -7,7 +7,7 @@ var compilerInput = require('../src/helpers/compilerHelper').compilerInput
tape('SourceMappingDecoder', function (t) { tape('SourceMappingDecoder', function (t) {
t.test('SourceMappingDecoder.findNodeAtInstructionIndex', function (st) { t.test('SourceMappingDecoder.findNodeAtInstructionIndex', function (st) {
var output = compiler.compileStandardWrapper(compilerInput(contracts)) var output = compiler.compile(compilerInput(contracts))
output = JSON.parse(output) output = JSON.parse(output)
var sourceMappingDecoder = new SourceMappingDecoder() var sourceMappingDecoder = new SourceMappingDecoder()
var node = sourceMappingDecoder.findNodeAtInstructionIndex('FunctionDefinition', 2, output.contracts['test.sol']['test'].evm.deployedBytecode.sourceMap, output.sources['test.sol']) var node = sourceMappingDecoder.findNodeAtInstructionIndex('FunctionDefinition', 2, output.contracts['test.sol']['test'].evm.deployedBytecode.sourceMap, output.sources['test.sol'])
...@@ -107,12 +107,12 @@ tape('SourceMappingDecoder', function (t) { ...@@ -107,12 +107,12 @@ tape('SourceMappingDecoder', function (t) {
}) })
var contracts = `contract test { var contracts = `contract test {
function f1() returns (uint) { function f1() public returns (uint) {
uint t = 4; uint t = 4;
return t; return t;
} }
function f2() { function f2() public {
} }
} }
......
...@@ -11,11 +11,11 @@ var executionContext = require('../src/execution/execution-context') ...@@ -11,11 +11,11 @@ var executionContext = require('../src/execution/execution-context')
var context var context
tape('ContractParameters - (TxFormat.buildData) - format input parameters', function (t) { tape('ContractParameters - (TxFormat.buildData) - format input parameters', function (t) {
var output = compiler.compileStandardWrapper(compilerInput(uintContract)) var output = compiler.compile(compilerInput(uintContract))
output = JSON.parse(output) output = JSON.parse(output)
var contract = output.contracts['test.sol']['uintContractTest'] var contract = output.contracts['test.sol']['uintContractTest']
context = { output, contract } context = { output, contract }
var bytecode = '608060405234801561001057600080fd5b50610111806100206000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634b521953146044575b600080fd5b348015604f57600080fd5b50609660048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506098565b005b8260008190555081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505600a165627a7a7230582028c4b7d4bd450fb198ccfdf15510df1721e4f8abda2487d4b452c533bed8880b0029' var bytecode = '608060405234801561001057600080fd5b5061011e806100206000396000f3fe608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634b521953146044575b600080fd5b348015604f57600080fd5b5060a360048036036060811015606457600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505060a5565b005b8260008190555081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505056fea165627a7a7230582053a6bee96a62b9079722b2a0004a405aa29803abc12ed6dd0322007ebb44a5f60029'
t.test('(TxFormat.buildData)', function (st) { t.test('(TxFormat.buildData)', function (st) {
st.plan(3) st.plan(3)
testWithInput(st, '123123, "0xf7a10e525d4b168f45f74db1b61f63d3e7619ea8", "34"', bytecode + '000000000000000000000000000000000000000000000000000000000001e0f3000000000000000000000000f7a10e525d4b168f45f74db1b61f63d3e7619ea80000000000000000000000000000000000000000000000000000000000000022') testWithInput(st, '123123, "0xf7a10e525d4b168f45f74db1b61f63d3e7619ea8", "34"', bytecode + '000000000000000000000000000000000000000000000000000000000001e0f3000000000000000000000000f7a10e525d4b168f45f74db1b61f63d3e7619ea80000000000000000000000000000000000000000000000000000000000000022')
...@@ -29,7 +29,7 @@ function testWithInput (st, params, expected) { ...@@ -29,7 +29,7 @@ function testWithInput (st, params, expected) {
txFormat.buildData('uintContractTest', context.contract, context.output.contracts, true, context.contract.abi[0], params, (error, data) => { txFormat.buildData('uintContractTest', context.contract, context.output.contracts, true, context.contract.abi[0], params, (error, data) => {
if (error) { return st.fails(error) } if (error) { return st.fails(error) }
console.log(data) console.log(data)
st.equal(data.dataHex, expected) st.equal(expected, data.dataHex)
}, () => {}, () => {}) }, () => {}, () => {})
} }
...@@ -37,7 +37,7 @@ function testWithInput (st, params, expected) { ...@@ -37,7 +37,7 @@ function testWithInput (st, params, expected) {
tape('ContractParameters - (TxFormat.buildData) - link Libraries', function (t) { tape('ContractParameters - (TxFormat.buildData) - link Libraries', function (t) {
executionContext.setContext('vm') executionContext.setContext('vm')
var compileData = compiler.compileStandardWrapper(compilerInput(deploySimpleLib)) var compileData = compiler.compile(compilerInput(deploySimpleLib))
var fakeDeployedContracts = { var fakeDeployedContracts = {
lib1: '0xf7a10e525d4b168f45f74db1b61f63d3e7619e11', lib1: '0xf7a10e525d4b168f45f74db1b61f63d3e7619e11',
...@@ -96,7 +96,8 @@ function testLinkLibrary2 (st, callbackDeployLibraries) { ...@@ -96,7 +96,8 @@ function testLinkLibrary2 (st, callbackDeployLibraries) {
'lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2': '0xf7a10e525d4b168f45f74db1b61f63d3e7619e33' 'lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2': '0xf7a10e525d4b168f45f74db1b61f63d3e7619e33'
} }
} }
var data = '608060405234801561001057600080fd5b5061026b806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14610046575b600080fd5b34801561005257600080fd5b5061005b61005d565b005b73f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b1580156100bd57600080fd5b505af41580156100d1573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801561013557600080fd5b505af4158015610149573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b1580156101ad57600080fd5b505af41580156101c1573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801561022557600080fd5b505af4158015610239573d6000803e3d6000fd5b505050505600a165627a7a7230582007a22a440570c53944d704e68b3fd4ba3ba4a0fba71c4abd66b195d87f065bcd0029'
var data = '608060405234801561001057600080fd5b5061026b806100206000396000f3fe608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14610046575b600080fd5b34801561005257600080fd5b5061005b61005d565b005b73f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b1580156100bd57600080fd5b505af41580156100d1573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801561013557600080fd5b505af4158015610149573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b1580156101ad57600080fd5b505af41580156101c1573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801561022557600080fd5b505af4158015610239573d6000803e3d6000fd5b5050505056fea165627a7a72305820d2fdcf2968ba13c89dd82748af1cac609a670e333fce635bc2212c2a50508be70029'
var deployMsg = ['creation of library test.sol:lib1 pending...', var deployMsg = ['creation of library test.sol:lib1 pending...',
'creation of library test.sol:lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 pending...'] 'creation of library test.sol:lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 pending...']
...@@ -140,7 +141,7 @@ tape('EncodeParameter', function (t) { ...@@ -140,7 +141,7 @@ tape('EncodeParameter', function (t) {
}) })
function encodeFunctionCallTest (st) { function encodeFunctionCallTest (st) {
var output = compiler.compileStandardWrapper(compilerInput(encodeFunctionCall)) var output = compiler.compile(compilerInput(encodeFunctionCall))
output = JSON.parse(output) output = JSON.parse(output)
var contract = output.contracts['test.sol']['testContractLinkLibrary'] var contract = output.contracts['test.sol']['testContractLinkLibrary']
txFormat.encodeFunctionCall('123, "test string"', contract.abi[0], (error, encoded) => { txFormat.encodeFunctionCall('123, "test string"', contract.abi[0], (error, encoded) => {
...@@ -154,7 +155,7 @@ function encodeFunctionCallTest (st) { ...@@ -154,7 +155,7 @@ function encodeFunctionCallTest (st) {
tape('test fallback function', function (t) { tape('test fallback function', function (t) {
t.test('(fallback)', function (st) { t.test('(fallback)', function (st) {
st.plan(2) st.plan(2)
var output = compiler.compileStandardWrapper(compilerInput(fallbackFunction)) var output = compiler.compile(compilerInput(fallbackFunction))
output = JSON.parse(output) output = JSON.parse(output)
var contract = output.contracts['test.sol']['fallbackFunctionContract'] var contract = output.contracts['test.sol']['fallbackFunctionContract']
st.equal(txHelper.encodeFunctionId(contract.abi[0]), '0x805da4ad') st.equal(txHelper.encodeFunctionId(contract.abi[0]), '0x805da4ad')
...@@ -171,7 +172,7 @@ tape('test abiEncoderV2', function (t) { ...@@ -171,7 +172,7 @@ tape('test abiEncoderV2', function (t) {
var decodedData = `[${value1}, ${value2}, "${value3}"], 23` var decodedData = `[${value1}, ${value2}, "${value3}"], 23`
t.test('(abiEncoderV2)', function (st) { t.test('(abiEncoderV2)', function (st) {
st.plan(2) st.plan(2)
var output = compiler.compileStandardWrapper(compilerInput(abiEncoderV2)) var output = compiler.compile(compilerInput(abiEncoderV2))
output = JSON.parse(output) output = JSON.parse(output)
var contract = output.contracts['test.sol']['test'] var contract = output.contracts['test.sol']['test']
txFormat.encodeFunctionCall(decodedData, contract.abi[0], (error, encoded) => { txFormat.encodeFunctionCall(decodedData, contract.abi[0], (error, encoded) => {
...@@ -194,7 +195,7 @@ tape('test abiEncoderV2 array of tuple', function (t) { ...@@ -194,7 +195,7 @@ tape('test abiEncoderV2 array of tuple', function (t) {
*/ */
st.plan(2) st.plan(2)
var output = compiler.compileStandardWrapper(compilerInput(abiEncoderV2ArrayOfTuple)) var output = compiler.compile(compilerInput(abiEncoderV2ArrayOfTuple))
output = JSON.parse(output) output = JSON.parse(output)
var contract = output.contracts['test.sol']['test'] var contract = output.contracts['test.sol']['test']
txFormat.encodeParams('[34, "test"]', contract.abi[0], (error, encoded) => { txFormat.encodeParams('[34, "test"]', contract.abi[0], (error, encoded) => {
...@@ -216,26 +217,26 @@ tape('test abiEncoderV2 array of tuple', function (t) { ...@@ -216,26 +217,26 @@ tape('test abiEncoderV2 array of tuple', function (t) {
var uintContract = `contract uintContractTest { var uintContract = `contract uintContractTest {
uint _tp; uint _tp;
address _ap; address _ap;
function test(uint _t, address _a, uint _i) { function test(uint _t, address _a, uint _i) public {
_tp = _t; _tp = _t;
_ap = _a; _ap = _a;
} }
}` }`
var deploySimpleLib = `pragma solidity ^0.4.4; var deploySimpleLib = `pragma solidity ^0.5.0;
library lib1 { library lib1 {
function getEmpty () { function getEmpty () public {
} }
} }
library lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 { library lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 {
function getEmpty () { function getEmpty () public {
} }
} }
contract testContractLinkLibrary { contract testContractLinkLibrary {
function get () { function get () public {
lib1.getEmpty(); lib1.getEmpty();
lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2.getEmpty(); lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2.getEmpty();
lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2.getEmpty(); lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2.getEmpty();
...@@ -243,22 +244,20 @@ contract testContractLinkLibrary { ...@@ -243,22 +244,20 @@ contract testContractLinkLibrary {
} }
}` }`
var encodeFunctionCall = `pragma solidity ^0.4.4; var encodeFunctionCall = `pragma solidity ^0.5.0;
contract testContractLinkLibrary { contract testContractLinkLibrary {
function get (uint _p, string _o) { function get (uint _p, string memory _o) public {
} }
}` }`
var fallbackFunction = `pragma solidity ^0.4.4; var fallbackFunction = `pragma solidity ^0.5.0;
contract fallbackFunctionContract { contract fallbackFunctionContract {
function get (uint _p, string _o) { function get (uint _p, string memory _o) public {
} }
function () {} function () external {}
}` }`
var abiEncoderV2 = `pragma experimental ABIEncoderV2; var abiEncoderV2 = `pragma experimental ABIEncoderV2;
...@@ -269,12 +268,12 @@ contract test { ...@@ -269,12 +268,12 @@ contract test {
uint b; uint b;
string s; string s;
} }
function t (p _p, uint _i) returns (p) { function t (p memory _p, uint _i) public returns (p memory) {
return _p; return _p;
} }
function t () returns (p) { function t () public returns (p memory) {
p mm; p memory mm;
mm.a = 123; mm.a = 123;
mm.b = 133; mm.b = 133;
return mm; return mm;
...@@ -286,15 +285,15 @@ contract test { ...@@ -286,15 +285,15 @@ contract test {
struct MyStruct {uint256 num; string _string;} struct MyStruct {uint256 num; string _string;}
constructor (MyStruct[] _structs, string _str) { constructor (MyStruct[] memory _structs, string memory _str) public {
} }
function addStructs(MyStruct[] _structs) public returns (MyStruct[] strucmts) { function addStructs(MyStruct[] memory _structs) public returns (MyStruct[] memory strucmts) {
strucmts = _structs; strucmts = _structs;
} }
function addStructs(MyStruct _structs) public returns (MyStruct _strucmts) { function addStructs(MyStruct memory _structs) public returns (MyStruct memory _strucmts) {
_strucmts = _structs; _strucmts = _structs;
} }
}` }`
{ {
"name": "remix-simulator", "name": "remix-simulator",
"version": "0.0.4", "version": "0.0.7",
"description": "Ethereum IDE and tools for the web", "description": "Ethereum IDE and tools for the web",
"contributors": [ "contributors": [
{ {
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
"main": "./index.js", "main": "./index.js",
"dependencies": { "dependencies": {
"ansi-gray": "^0.1.1", "ansi-gray": "^0.1.1",
"babel-eslint": "^7.1.1",
"babel-plugin-transform-object-assign": "^6.22.0", "babel-plugin-transform-object-assign": "^6.22.0",
"babel-preset-es2017": "^6.24.1", "babel-preset-es2017": "^6.24.1",
"babelify": "^7.3.0", "babelify": "^7.3.0",
...@@ -23,7 +24,7 @@ ...@@ -23,7 +24,7 @@
"express": "^4.16.3", "express": "^4.16.3",
"fast-async": "^6.3.7", "fast-async": "^6.3.7",
"merge": "^1.2.0", "merge": "^1.2.0",
"remix-lib": "^0.2.5", "remix-lib": "0.3.12",
"standard": "^10.0.3", "standard": "^10.0.3",
"time-stamp": "^2.0.0", "time-stamp": "^2.0.0",
"web3": "1.0.0-beta.27" "web3": "1.0.0-beta.27"
......
...@@ -3,10 +3,15 @@ var Web3 = require('web3') ...@@ -3,10 +3,15 @@ var Web3 = require('web3')
var Accounts = function () { var Accounts = function () {
this.web3 = new Web3() this.web3 = new Web3()
// TODO: make it random and/or use remix-libs // TODO: make it random and/or use remix-libs
this.accounts = [this.web3.eth.accounts.create(['abcd'])] this.accounts = [this.web3.eth.accounts.create(['abcd']), this.web3.eth.accounts.create(['ef12']), this.web3.eth.accounts.create(['ef34'])]
this.accounts[this.accounts[0].address.toLowerCase()] = this.accounts[0] this.accounts[this.accounts[0].address.toLowerCase()] = this.accounts[0]
this.accounts[this.accounts[1].address.toLowerCase()] = this.accounts[1]
this.accounts[this.accounts[2].address.toLowerCase()] = this.accounts[2]
this.accounts[this.accounts[0].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[0].address.toLowerCase()].privateKey.slice(2), 'hex') this.accounts[this.accounts[0].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[0].address.toLowerCase()].privateKey.slice(2), 'hex')
this.accounts[this.accounts[1].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[1].address.toLowerCase()].privateKey.slice(2), 'hex')
this.accounts[this.accounts[2].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[2].address.toLowerCase()].privateKey.slice(2), 'hex')
} }
Accounts.prototype.methods = function () { Accounts.prototype.methods = function () {
......
...@@ -39,7 +39,7 @@ Transactions.prototype.eth_getTransactionReceipt = function (payload, cb) { ...@@ -39,7 +39,7 @@ Transactions.prototype.eth_getTransactionReceipt = function (payload, cb) {
'cumulativeGasUsed': '0x06345f', 'cumulativeGasUsed': '0x06345f',
'contractAddress': receipt.contractAddress, 'contractAddress': receipt.contractAddress,
'logs': receipt.logs, 'logs': receipt.logs,
'status': 1 'status': receipt.status
} }
cb(null, r) cb(null, r)
......
{ {
"name": "remix-solidity", "name": "remix-solidity",
"version": "0.2.8", "version": "0.2.13",
"description": "Ethereum IDE and tools for the web", "description": "Ethereum IDE and tools for the web",
"contributors": [ "contributors": [
{ {
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
"ethereumjs-vm": "^2.3.3", "ethereumjs-vm": "^2.3.3",
"fast-async": "^6.1.2", "fast-async": "^6.1.2",
"npm-run-all": "^4.0.2", "npm-run-all": "^4.0.2",
"remix-lib": "^0.3.8", "remix-lib": "0.3.12",
"solc": "^0.4.24", "solc": "^0.5.0",
"standard": "^7.0.1", "standard": "^7.0.1",
"tape": "^4.6.0", "tape": "^4.6.0",
"webworkify": "^1.2.1" "webworkify": "^1.2.1"
......
...@@ -22,7 +22,7 @@ module.exports = function (self) { ...@@ -22,7 +22,7 @@ module.exports = function (self) {
compileJSON = function (input) { compileJSON = function (input) {
try { try {
return compiler.compileStandardWrapper(input, function (path) { return compiler.compile(input, function (path) {
missingInputs.push(path) missingInputs.push(path)
return { 'error': 'Deferred import' } return { 'error': 'Deferred import' }
}) })
......
...@@ -90,7 +90,7 @@ function Compiler (handleImportCall) { ...@@ -90,7 +90,7 @@ function Compiler (handleImportCall) {
var result var result
try { try {
var input = compilerInput(source.sources, {optimize: optimize, target: source.target}) var input = compilerInput(source.sources, {optimize: optimize, target: source.target})
result = compiler.compileStandardWrapper(input, missingInputsCallback) result = compiler.compile(input, missingInputsCallback)
result = JSON.parse(result) result = JSON.parse(result)
} catch (exception) { } catch (exception) {
result = { error: { formattedMessage: 'Uncaught JavaScript exception:\n' + exception, severity: 'error', mode: 'panic' } } result = { error: { formattedMessage: 'Uncaught JavaScript exception:\n' + exception, severity: 'error', mode: 'panic' } }
...@@ -313,7 +313,7 @@ function Compiler (handleImportCall) { ...@@ -313,7 +313,7 @@ function Compiler (handleImportCall) {
while ((match = importRegex.exec(files[fileName].content))) { while ((match = importRegex.exec(files[fileName].content))) {
var importFilePath = match[1] var importFilePath = match[1]
if (importFilePath.startsWith('./')) { if (importFilePath.startsWith('./')) {
var path = /(.*\/).*/.exec(target) var path = /(.*\/).*/.exec(fileName)
if (path !== null) { if (path !== null) {
importFilePath = importFilePath.replace('./', path[1]) importFilePath = importFilePath.replace('./', path[1])
} else { } else {
......
[![Build Status](https://travis-ci.org/ethereum/remix-tests.svg?branch=master)](https://travis-ci.org/ethereum/remix-tests)
Remix-Tests Remix-Tests
--- ---
...@@ -43,6 +41,8 @@ contract MyTest { ...@@ -43,6 +41,8 @@ contract MyTest {
} }
``` ```
See also: example [Su Squares contract](https://github.com/su-squares/ethereum-contract/tree/e542f37d4f8f6c7b07d90a6554424268384a4186) and [https://travis-ci.org/su-squares/ethereum-contract/builds/446186067](Travis build) that uses remix-tests for continuous integration testing.
Available special functions: Available special functions:
* `beforeEach()` - runs before each test * `beforeEach()` - runs before each test
* `beforeAll()` - runs before all tests * `beforeAll()` - runs before all tests
......
pragma solidity ^0.4.7; pragma solidity ^0.5.0;
contract SimpleStorage { contract SimpleStorage {
uint public storedData; uint public storedData;
function SimpleStorage() public { constructor() public {
storedData = 100; storedData = 100;
} }
......
pragma solidity ^0.4.7; pragma solidity ^0.5.0;
import "remix_tests.sol"; import "remix_tests.sol";
import "./simple_storage.sol"; import "./simple_storage.sol";
contract MyTest2 { contract MyTest2 {
SimpleStorage foo; SimpleStorage storage foo;
uint i = 0; uint storage i = 0;
function beforeAll() { function beforeAll() public {
foo = new SimpleStorage(); foo = new SimpleStorage();
} }
function beforeEach() { function beforeEach() public {
if (i == 1) { if (i == 1) {
foo.set(200); foo.set(200);
} }
i += 1; i += 1;
} }
function initialValueShouldBe100() public constant returns (bool) { function initialValueShouldBe100() public view returns (bool) {
return Assert.equal(foo.get(), 100, "initial value is not correct"); return Assert.equal(foo.get(), 100, "initial value is not correct");
} }
function initialValueShouldBe200() public constant returns (bool) { function initialValueShouldBe200() public view returns (bool) {
return Assert.equal(foo.get(), 200, "initial value is not correct"); return Assert.equal(foo.get(), 200, "initial value is not correct");
} }
......
pragma solidity ^0.4.7; pragma solidity ^0.5.0;
import "./simple_storage.sol"; import "./simple_storage.sol";
contract MyTest { contract MyTest {
SimpleStorage foo; SimpleStorage storage foo;
uint i = 0; uint storage i = 0;
function beforeAll() { function beforeAll() public {
foo = new SimpleStorage(); foo = new SimpleStorage();
} }
function beforeEach() { function beforeEach() public {
if (i == 1) { if (i == 1) {
foo.set(200); foo.set(200);
} }
......
{ {
"name": "remix-tests", "name": "remix-tests",
"version": "0.0.13", "version": "0.0.19",
"description": "Tests for the Ethereum tool suite Remix", "description": "Tests for the Ethereum tool suite Remix",
"main": "./src/index.js", "main": "./src/index.js",
"contributors": [ "contributors": [
...@@ -41,13 +41,13 @@ ...@@ -41,13 +41,13 @@
"change-case": "^3.0.1", "change-case": "^3.0.1",
"colors": "^1.1.2", "colors": "^1.1.2",
"commander": "^2.13.0", "commander": "^2.13.0",
"remix-lib": "^0.3.8", "remix-lib": "0.3.12",
"remix-simulator": "^0.0.4", "remix-simulator": "0.0.7",
"remix-solidity": "^0.2.8", "remix-solidity": "0.2.13",
"signale": "^1.2.1", "signale": "^1.2.1",
"solc": "^0.4.24", "solc": "^0.5.0",
"standard": "^10.0.3", "standard": "^10.0.3",
"web3": "1.0.0-beta.34", "web3": "1.0.0-beta.36",
"winston": "^3.0.0" "winston": "^3.0.0"
}, },
"peerDependencies": { "peerDependencies": {
......
module.exports = ` module.exports = `
pragma solidity ^0.4.7;
library Assert { library Assert {
event AssertionEvent( event AssertionEvent(
...@@ -8,107 +6,107 @@ library Assert { ...@@ -8,107 +6,107 @@ library Assert {
string message string message
); );
function ok(bool a, string message) public returns (bool result) { function ok(bool a, string memory message) public returns (bool result) {
result = a; result = a;
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function equal(uint a, uint b, string message) public returns (bool result) { function equal(uint a, uint b, string memory message) public returns (bool result) {
result = (a == b); result = (a == b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function equal(int a, int b, string message) public returns (bool result) { function equal(int a, int b, string memory message) public returns (bool result) {
result = (a == b); result = (a == b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function equal(bool a, bool b, string message) public returns (bool result) { function equal(bool a, bool b, string memory message) public returns (bool result) {
result = (a == b); result = (a == b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
// TODO: only for certain versions of solc // TODO: only for certain versions of solc
//function equal(fixed a, fixed b, string message) public returns (bool result) { //function equal(fixed a, fixed b, string memory message) public returns (bool result) {
// result = (a == b); // result = (a == b);
// emit AssertionEvent(result, message); // emit AssertionEvent(result, message);
//} //}
// TODO: only for certain versions of solc // TODO: only for certain versions of solc
//function equal(ufixed a, ufixed b, string message) public returns (bool result) { //function equal(ufixed a, ufixed b, string memory message) public returns (bool result) {
// result = (a == b); // result = (a == b);
// emit AssertionEvent(result, message); // emit AssertionEvent(result, message);
//} //}
function equal(address a, address b, string message) public returns (bool result) { function equal(address a, address b, string memory message) public returns (bool result) {
result = (a == b); result = (a == b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function equal(bytes32 a, bytes32 b, string message) public returns (bool result) { function equal(bytes32 a, bytes32 b, string memory message) public returns (bool result) {
result = (a == b); result = (a == b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function equal(string a, string b, string message) public returns (bool result) { function equal(string memory a, string memory b, string memory message) public returns (bool result) {
result = (keccak256(a) == keccak256(b)); result = (keccak256(abi.encode(a)) == keccak256(abi.encode(b)));
AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function notEqual(uint a, uint b, string message) public returns (bool result) { function notEqual(uint a, uint b, string memory message) public returns (bool result) {
result = (a != b); result = (a != b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function notEqual(int a, int b, string message) public returns (bool result) { function notEqual(int a, int b, string memory message) public returns (bool result) {
result = (a != b); result = (a != b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function notEqual(bool a, bool b, string message) public returns (bool result) { function notEqual(bool a, bool b, string memory message) public returns (bool result) {
result = (a != b); result = (a != b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
// TODO: only for certain versions of solc // TODO: only for certain versions of solc
//function notEqual(fixed a, fixed b, string message) public returns (bool result) { //function notEqual(fixed a, fixed b, string memory message) public returns (bool result) {
// result = (a != b); // result = (a != b);
// emit AssertionEvent(result, message); // emit AssertionEvent(result, message);
//} //}
// TODO: only for certain versions of solc // TODO: only for certain versions of solc
//function notEqual(ufixed a, ufixed b, string message) public returns (bool result) { //function notEqual(ufixed a, ufixed b, string memory message) public returns (bool result) {
// result = (a != b); // result = (a != b);
// emit AssertionEvent(result, message); // emit AssertionEvent(result, message);
//} //}
function notEqual(address a, address b, string message) public returns (bool result) { function notEqual(address a, address b, string memory message) public returns (bool result) {
result = (a != b); result = (a != b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function notEqual(bytes32 a, bytes32 b, string message) public returns (bool result) { function notEqual(bytes32 a, bytes32 b, string memory message) public returns (bool result) {
result = (a != b); result = (a != b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function notEqual(string a, string b, string message) public returns (bool result) { function notEqual(string memory a, string memory b, string memory message) public returns (bool result) {
result = (keccak256(a) != keccak256(b)); result = (keccak256(abi.encode(a)) != keccak256(abi.encode(b)));
AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
/*----------------- Greater than --------------------*/ /*----------------- Greater than --------------------*/
function greaterThan(uint a, uint b, string message) public constant returns (bool result) { function greaterThan(uint a, uint b, string memory message) public returns (bool result) {
result = (a > b); result = (a > b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function greaterThan(int a, int b, string message) public constant returns (bool result) { function greaterThan(int a, int b, string memory message) public returns (bool result) {
result = (a > b); result = (a > b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
// TODO: safely compare between uint and int // TODO: safely compare between uint and int
function greaterThan(uint a, int b, string message) public constant returns (bool result) { function greaterThan(uint a, int b, string memory message) public returns (bool result) {
if(b < int(0)) { if(b < int(0)) {
// int is negative uint "a" always greater // int is negative uint "a" always greater
result = true; result = true;
...@@ -117,7 +115,7 @@ library Assert { ...@@ -117,7 +115,7 @@ library Assert {
} }
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function greaterThan(int a, uint b, string message) public constant returns (bool result) { function greaterThan(int a, uint b, string memory message) public returns (bool result) {
if(a < int(0)) { if(a < int(0)) {
// int is negative uint "b" always greater // int is negative uint "b" always greater
result = false; result = false;
...@@ -127,17 +125,17 @@ library Assert { ...@@ -127,17 +125,17 @@ library Assert {
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
/*----------------- Lesser than --------------------*/ /*----------------- Lesser than --------------------*/
function lesserThan(uint a, uint b, string message) public constant returns (bool result) { function lesserThan(uint a, uint b, string memory message) public returns (bool result) {
result = (a < b); result = (a < b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function lesserThan(int a, int b, string message) public constant returns (bool result) { function lesserThan(int a, int b, string memory message) public returns (bool result) {
result = (a < b); result = (a < b);
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
// TODO: safely compare between uint and int // TODO: safely compare between uint and int
function lesserThan(uint a, int b, string message) public constant returns (bool result) { function lesserThan(uint a, int b, string memory message) public returns (bool result) {
if(b < int(0)) { if(b < int(0)) {
// int is negative int "b" always lesser // int is negative int "b" always lesser
result = false; result = false;
...@@ -147,7 +145,7 @@ library Assert { ...@@ -147,7 +145,7 @@ library Assert {
emit AssertionEvent(result, message); emit AssertionEvent(result, message);
} }
function lesserThan(int a, uint b, string message) public constant returns (bool result) { function lesserThan(int a, uint b, string memory message) public returns (bool result) {
if(a < int(0)) { if(a < int(0)) {
// int is negative int "a" always lesser // int is negative int "a" always lesser
result = true; result = true;
......
module.exports = `
library TestsAccounts {
function getAccount(uint index) public returns (address) {
>accounts<
return accounts[index];
}
}
`
...@@ -9,18 +9,30 @@ String.prototype.regexIndexOf = function (regex, startpos) { ...@@ -9,18 +9,30 @@ String.prototype.regexIndexOf = function (regex, startpos) {
return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf
} }
function writeTestAccountsContract (accounts) {
var testAccountContract = require('../sol/tests_accounts.sol.js')
var body = 'address[' + accounts.length + '] memory accounts;'
if (!accounts.length) body += ';'
else {
accounts.map((address, index) => {
body += `\naccounts[${index}] = ${address};\n`
})
}
return testAccountContract.replace('>accounts<', body)
}
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-' var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-'
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1)
// TODO: replace this with remix's own compiler code // TODO: replace this with remix's own compiler code
function compileFileOrFiles (filename, isDirectory, cb) { function compileFileOrFiles (filename, isDirectory, opts, cb) {
let compiler, filepath let compiler, filepath
let accounts = opts.accounts || []
const sources = { const sources = {
'tests.sol': { content: require('../sol/tests.sol.js') }, 'tests.sol': { content: require('../sol/tests.sol.js') },
'remix_tests.sol': { content: require('../sol/tests.sol.js') } 'remix_tests.sol': { content: require('../sol/tests.sol.js') },
'remix_accounts.sol': { content: writeTestAccountsContract(accounts) }
} }
// TODO: for now assumes filepath dir contains all tests, later all this // TODO: for now assumes filepath dir contains all tests, later all this
// should be replaced with remix's & browser solidity compiler code // should be replaced with remix's & browser solidity compiler code
filepath = (isDirectory ? filename : path.dirname(filename)) filepath = (isDirectory ? filename : path.dirname(filename))
...@@ -62,12 +74,13 @@ function compileFileOrFiles (filename, isDirectory, cb) { ...@@ -62,12 +74,13 @@ function compileFileOrFiles (filename, isDirectory, cb) {
}) })
} }
function compileContractSources (sources, importFileCb, cb) { function compileContractSources (sources, importFileCb, opts, cb) {
let compiler, filepath let compiler, filepath
let accounts = opts.accounts || []
// Iterate over sources keys. Inject test libraries. Inject test library import statements. // Iterate over sources keys. Inject test libraries. Inject test library import statements.
if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) { if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) {
sources['remix_tests.sol'] = { content: require('../sol/tests.sol.js') } sources['remix_tests.sol'] = { content: require('../sol/tests.sol.js') }
sources['remix_accounts.sol'] = { content: writeTestAccountsContract(accounts) }
} }
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm
let includeTestLibs = '\nimport \'remix_tests.sol\';\n' let includeTestLibs = '\nimport \'remix_tests.sol\';\n'
......
...@@ -16,13 +16,22 @@ var createWeb3Provider = function () { ...@@ -16,13 +16,22 @@ var createWeb3Provider = function () {
return web3 return web3
} }
var runTestSources = function (contractSources, testCallback, resultCallback, finalCallback, importFileCb) { var runTestSources = function (contractSources, testCallback, resultCallback, finalCallback, importFileCb, opts) {
opts = opts || {}
let web3 = opts.web3 || createWeb3Provider()
let accounts = opts.accounts || null
async.waterfall([ async.waterfall([
function getAccountList (next) {
if (accounts) return next()
web3.eth.getAccounts((_err, _accounts) => {
accounts = _accounts
next()
})
},
function compile (next) { function compile (next) {
Compiler.compileContractSources(contractSources, importFileCb, next) Compiler.compileContractSources(contractSources, importFileCb, { accounts }, next)
}, },
function deployAllContracts (compilationResult, next) { function deployAllContracts (compilationResult, next) {
let web3 = createWeb3Provider()
Deployer.deployAll(compilationResult, web3, function (err, contracts) { Deployer.deployAll(compilationResult, web3, function (err, contracts) {
if (err) { if (err) {
next(err) next(err)
...@@ -33,19 +42,21 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi ...@@ -33,19 +42,21 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi
}, },
function determineTestContractsToRun (compilationResult, contracts, next) { function determineTestContractsToRun (compilationResult, contracts, next) {
let contractsToTest = [] let contractsToTest = []
let contractsToTestDetails = []
for (let filename in compilationResult) { for (let filename in compilationResult) {
if (filename.indexOf('_test.sol') < 0) { if (filename.indexOf('_test.sol') < 0) {
continue continue
} }
Object.keys(compilationResult[filename]).forEach(contractName => { Object.keys(compilationResult[filename]).forEach(contractName => {
contractsToTestDetails.push(compilationResult[filename][contractName])
contractsToTest.push(contractName) contractsToTest.push(contractName)
}) })
} }
next(null, contractsToTest, contracts) next(null, contractsToTest, contractsToTestDetails, contracts)
}, },
function runTests (contractsToTest, contracts, next) { function runTests (contractsToTest, contractsToTestDetails, contracts, next) {
let totalPassing = 0 let totalPassing = 0
let totalFailing = 0 let totalFailing = 0
let totalTime = 0 let totalTime = 0
...@@ -67,7 +78,7 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi ...@@ -67,7 +78,7 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi
} }
async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => {
TestRunner.runTest(contractName, contracts[contractName], _testCallback, (err, result) => { TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, _testCallback, (err, result) => {
if (err) { if (err) {
return cb(err) return cb(err)
} }
...@@ -95,7 +106,8 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi ...@@ -95,7 +106,8 @@ var runTestSources = function (contractSources, testCallback, resultCallback, fi
], finalCallback) ], finalCallback)
} }
var runTestFiles = function (filepath, isDirectory, web3) { var runTestFiles = function (filepath, isDirectory, web3, opts) {
opts = opts || {}
const { Signale } = require('signale') const { Signale } = require('signale')
// signale configuration // signale configuration
const options = { const options = {
...@@ -118,37 +130,49 @@ var runTestFiles = function (filepath, isDirectory, web3) { ...@@ -118,37 +130,49 @@ var runTestFiles = function (filepath, isDirectory, web3) {
} }
} }
const signale = new Signale(options) const signale = new Signale(options)
let accounts = opts.accounts || null
async.waterfall([ async.waterfall([
function getAccountList (next) {
if (accounts) return next(null)
web3.eth.getAccounts((_err, _accounts) => {
accounts = _accounts
next(null)
})
},
function compile (next) { function compile (next) {
Compiler.compileFileOrFiles(filepath, isDirectory, next) Compiler.compileFileOrFiles(filepath, isDirectory, { accounts }, next)
}, },
function deployAllContracts (compilationResult, next) { function deployAllContracts (compilationResult, next) {
Deployer.deployAll(compilationResult, web3, function (err, contracts) { Deployer.deployAll(compilationResult, web3, function (err, contracts) {
if (err) { if (err) {
next(err) next(err)
} }
next(null, compilationResult, contracts) next(null, compilationResult, contracts)
}) })
}, },
function determineTestContractsToRun (compilationResult, contracts, next) { function determineTestContractsToRun (compilationResult, contracts, next) {
let contractsToTest = [] let contractsToTest = []
if (isDirectory) { let contractsToTestDetails = []
fs.readdirSync(filepath).forEach(filename => { var gatherContractsFrom = (filename) => {
if (filename.indexOf('_test.sol') < 0) { if (filename.indexOf('_test.sol') < 0) {
return return
} }
Object.keys(compilationResult[path.basename(filename)]).forEach(contractName => { Object.keys(compilationResult[path.basename(filename)]).forEach(contractName => {
contractsToTest.push(contractName) contractsToTest.push(contractName)
contractsToTestDetails.push(compilationResult[path.basename(filename)][contractName])
}) })
}
if (isDirectory) {
fs.readdirSync(filepath).forEach(filename => {
gatherContractsFrom(filename)
}) })
} else { } else {
contractsToTest = Object.keys(compilationResult[path.basename(filepath)]) gatherContractsFrom(filepath)
} }
next(null, contractsToTest, contractsToTestDetails, contracts)
next(null, contractsToTest, contracts)
}, },
function runTests (contractsToTest, contracts, next) { function runTests (contractsToTest, contractsToTestDetails, contracts, next) {
let totalPassing = 0 let totalPassing = 0
let totalFailing = 0 let totalFailing = 0
let totalTime = 0 let totalTime = 0
...@@ -172,7 +196,7 @@ var runTestFiles = function (filepath, isDirectory, web3) { ...@@ -172,7 +196,7 @@ var runTestFiles = function (filepath, isDirectory, web3) {
} }
async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => {
TestRunner.runTest(contractName, contracts[contractName], testCallback, (err, result) => { TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, testCallback, (err, result) => {
if (err) { if (err) {
return cb(err) return cb(err)
} }
......
...@@ -2,6 +2,20 @@ var async = require('async') ...@@ -2,6 +2,20 @@ var async = require('async')
var changeCase = require('change-case') var changeCase = require('change-case')
var Web3 = require('web3') var Web3 = require('web3')
function getFunctionFullName (signature, methodIdentifiers) {
for (var method in methodIdentifiers) {
if (signature.replace('0x', '') === methodIdentifiers[method].replace('0x', '')) {
return method
}
}
return null
}
function getOverridedSender (userdoc, signature, methodIdentifiers) {
let fullName = getFunctionFullName(signature, methodIdentifiers)
return fullName && userdoc.methods[fullName] ? userdoc.methods[fullName].notice : null
}
function getAvailableFunctions (jsonInterface) { function getAvailableFunctions (jsonInterface) {
return jsonInterface.reverse().filter((x) => x.type === 'function').map((x) => x.name) return jsonInterface.reverse().filter((x) => x.type === 'function').map((x) => x.name)
} }
...@@ -24,7 +38,7 @@ function createRunList (jsonInterface) { ...@@ -24,7 +38,7 @@ function createRunList (jsonInterface) {
if (availableFunctions.indexOf('beforeEach') >= 0) { if (availableFunctions.indexOf('beforeEach') >= 0) {
runList.push({name: 'beforeEach', type: 'internal', constant: false}) runList.push({name: 'beforeEach', type: 'internal', constant: false})
} }
runList.push({name: func.name, type: 'test', constant: func.constant}) runList.push({name: func.name, signature: func.signature, type: 'test', constant: func.constant})
if (availableFunctions.indexOf('afterEach') >= 0) { if (availableFunctions.indexOf('afterEach') >= 0) {
runList.push({name: 'afterEach', type: 'internal', constant: false}) runList.push({name: 'afterEach', type: 'internal', constant: false})
} }
...@@ -37,7 +51,7 @@ function createRunList (jsonInterface) { ...@@ -37,7 +51,7 @@ function createRunList (jsonInterface) {
return runList return runList
} }
function runTest (testName, testObject, testCallback, resultsCallback) { function runTest (testName, testObject, contractDetails, opts, testCallback, resultsCallback) {
let runList = createRunList(testObject._jsonInterface) let runList = createRunList(testObject._jsonInterface)
let passingNum = 0 let passingNum = 0
...@@ -45,12 +59,32 @@ function runTest (testName, testObject, testCallback, resultsCallback) { ...@@ -45,12 +59,32 @@ function runTest (testName, testObject, testCallback, resultsCallback) {
let timePassed = 0 let timePassed = 0
let web3 = new Web3() let web3 = new Web3()
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-'
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1)
if (!isBrowser) {
let signale = require('signale')
signale.warn('DO NOT TRY TO ACCESS (IN YOUR SOLIDITY TEST) AN ACCOUNT GREATER THAN THE LENGTH OF THE FOLLOWING ARRAY (' + opts.accounts.length + ') :')
signale.warn(opts.accounts)
signale.warn('e.g: the following code won\'t work in the current context:')
signale.warn('TestsAccounts.getAccount(' + opts.accounts.length + ')')
}
testCallback({type: 'contract', value: testName, filename: testObject.filename}) testCallback({type: 'contract', value: testName, filename: testObject.filename})
async.eachOfLimit(runList, 1, function (func, index, next) { async.eachOfLimit(runList, 1, function (func, index, next) {
let sender
if (func.signature) {
sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers)
if (opts.accounts) {
sender = opts.accounts[sender]
}
}
let sendParams
if (sender) sendParams = { from: sender }
let method = testObject.methods[func.name].apply(testObject.methods[func.name], []) let method = testObject.methods[func.name].apply(testObject.methods[func.name], [])
let startTime = Date.now() let startTime = Date.now()
if (func.constant) { if (func.constant) {
method.call().then((result) => { method.call(sendParams).then((result) => {
let time = Math.ceil((Date.now() - startTime) / 1000.0) let time = Math.ceil((Date.now() - startTime) / 1000.0)
if (result) { if (result) {
testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName}) testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName})
...@@ -63,7 +97,7 @@ function runTest (testName, testObject, testCallback, resultsCallback) { ...@@ -63,7 +97,7 @@ function runTest (testName, testObject, testCallback, resultsCallback) {
next() next()
}) })
} else { } else {
method.send().on('receipt', function (receipt) { method.send(sendParams).on('receipt', function (receipt) {
try { try {
let time = Math.ceil((Date.now() - startTime) / 1000.0) let time = Math.ceil((Date.now() - startTime) / 1000.0)
let topic = Web3.utils.sha3('AssertionEvent(bool,string)') let topic = Web3.utils.sha3('AssertionEvent(bool,string)')
...@@ -95,11 +129,12 @@ function runTest (testName, testObject, testCallback, resultsCallback) { ...@@ -95,11 +129,12 @@ function runTest (testName, testObject, testCallback, resultsCallback) {
return next(err) return next(err)
} }
}).on('error', function (err) { }).on('error', function (err) {
console.error(err)
next(err) next(err)
}) })
} }
}, function () { }, function (error) {
resultsCallback(null, { resultsCallback(error, {
passingNum: passingNum, passingNum: passingNum,
failureNum: failureNum, failureNum: failureNum,
timePassed: timePassed timePassed: timePassed
......
pragma solidity ^0.4.7; pragma solidity ^0.5.0;
contract SimpleStorage { contract SimpleStorage {
uint public storedData; uint public storedData;
function SimpleStorage() public { constructor() public {
storedData = 100; storedData = 100;
} }
......
pragma solidity ^0.4.7; pragma solidity ^0.5.0;
import "./simple_storage.sol"; import "./simple_storage.sol";
contract MyTest { contract MyTest {
SimpleStorage foo; SimpleStorage foo;
function beforeAll() { function beforeAll() public {
foo = new SimpleStorage(); foo = new SimpleStorage();
} }
function initialValueShouldBe100() public constant returns (bool) { function initialValueShouldBe100() public view returns (bool) {
//return Assert.equal(foo.get(), 100, "initial value is not correct"); //return Assert.equal(foo.get(), 100, "initial value is not correct");
return foo.get() == 100; return foo.get() == 100;
} }
function initialValueShouldBe200() public constant returns (bool) { function initialValueShouldBe200() public view returns (bool) {
//return Assert.equal(foo.get(), 200, "initial value is not correct"); //return Assert.equal(foo.get(), 200, "initial value is not correct");
return foo.get() == 200; return foo.get() == 200;
} }
......
pragma solidity ^0.4.7; pragma solidity ^0.5.0;
contract SimpleStorage { contract SimpleStorage {
uint public storedData; uint public storedData;
function SimpleStorage() public { constructor() public {
storedData = 100; storedData = 100;
} }
......
pragma solidity ^0.4.7; pragma solidity ^0.5.0;
import "./simple_storage.sol"; import "./simple_storage.sol";
contract MyTest { contract MyTest {
SimpleStorage foo; SimpleStorage foo;
uint i = 0; uint i = 0;
function beforeEach() { function beforeEach() public {
foo = new SimpleStorage(); foo = new SimpleStorage();
if (i == 1) { if (i == 1) {
foo.set(200); foo.set(200);
...@@ -13,12 +13,12 @@ contract MyTest { ...@@ -13,12 +13,12 @@ contract MyTest {
i += 1; i += 1;
} }
function initialValueShouldBe100() public constant returns (bool) { function initialValueShouldBe100() public view returns (bool) {
//return Assert.equal(foo.get(), 100, "initial value is not correct"); //return Assert.equal(foo.get(), 100, "initial value is not correct");
return foo.get() == 100; return foo.get() == 100;
} }
function initialValueShouldBe200() public constant returns (bool) { function initialValueShouldBe200() public view returns (bool) {
//return Assert.equal(foo.get(), 200, "initial value is not correct"); //return Assert.equal(foo.get(), 200, "initial value is not correct");
return foo.get() == 200; return foo.get() == 200;
} }
......
pragma solidity ^0.4.7; pragma solidity ^0.5.0;
contract SimpleString { contract SimpleString {
string public storedData; string public storedData;
function SimpleString() public { constructor() public {
storedData = "Hello world!"; storedData = "Hello world!";
} }
function get() public view returns (string retVal) { function get() public view returns (string memory retVal) {
return storedData; return storedData;
} }
} }
pragma solidity ^0.4.7; pragma solidity ^0.5.0;
import "./simple_string.sol"; import "./simple_string.sol";
contract StringTest { contract StringTest {
SimpleString foo; SimpleString foo;
function beforeAll() { function beforeAll() public {
foo = new SimpleString(); foo = new SimpleString();
} }
function initialValueShouldBeHello() public constant returns (bool) { function initialValueShouldBeHello() public returns (bool) {
return Assert.equal(foo.get(), "Hello world!", "initial value is not correct"); return Assert.equal(foo.get(), "Hello world!", "initial value is not correct");
} }
function valueShouldNotBeHelloWorld() public constant returns (bool) { function valueShouldNotBeHelloWorld() public returns (bool) {
return Assert.notEqual(foo.get(), "Hello wordl!", "initial value is not correct"); return Assert.notEqual(foo.get(), "Hello wordl!", "initial value is not correct");
} }
function valueShouldBeHelloWorld() public constant returns (bool) { function valueShouldBeHelloWorld() public returns (bool) {
return Assert.equal(foo.get(), "Hello wordl!", "initial value is not correct"); return Assert.equal(foo.get(), "Hello wordl!", "initial value is not correct");
} }
} }
...@@ -10,7 +10,7 @@ contract SafeMathTest { ...@@ -10,7 +10,7 @@ contract SafeMathTest {
safemathproxy = new SafeMathProxy(); safemathproxy = new SafeMathProxy();
} }
function unsafeMultiplicationShouldOverflow() public constant returns (bool) { function unsafeMultiplicationShouldOverflow() public view returns (bool) {
uint256 a = 4; uint256 a = 4;
uint256 b = 2 ** 256 - 1; uint256 b = 2 ** 256 - 1;
return Assert.equal( return Assert.equal(
...@@ -20,7 +20,7 @@ contract SafeMathTest { ...@@ -20,7 +20,7 @@ contract SafeMathTest {
); );
} }
function safeMultiplicationShouldRevert() public constant returns (bool) { function safeMultiplicationShouldRevert() public view returns (bool) {
uint256 a = 4; uint256 a = 4;
uint256 b = 2 ** 256 - 1; uint256 b = 2 ** 256 - 1;
return Assert.equal( return Assert.equal(
...@@ -30,7 +30,7 @@ contract SafeMathTest { ...@@ -30,7 +30,7 @@ contract SafeMathTest {
); );
} }
function safeDivisionByZeroShouldRevert() public constant returns (bool) { function safeDivisionByZeroShouldRevert() public view returns (bool) {
uint256 a = 4; uint256 a = 4;
uint256 b = 0; uint256 b = 0;
return Assert.equal( return Assert.equal(
...@@ -40,7 +40,7 @@ contract SafeMathTest { ...@@ -40,7 +40,7 @@ contract SafeMathTest {
); );
} }
function unsafeSubtractShouldUnderflow() public constant returns (bool) { function unsafeSubtractShouldUnderflow() public view returns (bool) {
uint256 a = 0; uint256 a = 0;
uint256 b = a - 1; uint256 b = a - 1;
return Assert.equal( return Assert.equal(
......
pragma solidity ^0.4.24; pragma solidity ^0.5.0;
contract IntegerTest { contract IntegerTest {
// GREATER THAN [>] tests // GREATER THAN [>] tests
function _2_shouldBeGreaterThan_1() public constant returns (bool) { function _2_shouldBeGreaterThan_1() public returns (bool) {
return Assert.greaterThan(uint(2), uint(1), "2 is greater than 1"); return Assert.greaterThan(uint(2), uint(1), "2 is greater than 1");
} }
function _0_shouldBeGreaterThan_neg_1() public constant returns (bool) { function _0_shouldBeGreaterThan_neg_1() public returns (bool) {
return Assert.greaterThan(uint(0), int(-1), "0 is greater than -1"); return Assert.greaterThan(uint(0), int(-1), "0 is greater than -1");
} }
function _neg_1_shouldNotBeGreaterThan_1() public constant returns (bool) { function _neg_1_shouldNotBeGreaterThan_1() public returns (bool) {
return Assert.greaterThan(int(-1), uint(1), "-1 is not greater than 1"); return Assert.greaterThan(int(-1), uint(1), "-1 is not greater than 1");
} }
function _1_shouldBeGreaterThan_neg_1() public constant returns (bool) { function _1_shouldBeGreaterThan_neg_1() public returns (bool) {
return Assert.greaterThan(uint(1), int(-1), "1 is greater than -1"); return Assert.greaterThan(uint(1), int(-1), "1 is greater than -1");
} }
// LESSER THAN [<] tests // LESSER THAN [<] tests
function _1_shouldBeLesserThan_2() public constant returns (bool) { function _1_shouldBeLesserThan_2() public returns (bool) {
return Assert.lesserThan(uint(1), uint(2), "1 is lesser than 2"); return Assert.lesserThan(uint(1), uint(2), "1 is lesser than 2");
} }
function _neg_1_shouldBeLesserThan_0() public constant returns (bool) { function _neg_1_shouldBeLesserThan_0() public returns (bool) {
return Assert.lesserThan(int(-1), uint(0), "-1 is lesser than 0"); return Assert.lesserThan(int(-1), uint(0), "-1 is lesser than 0");
} }
function _neg_2_shouldBeLesserThan_neg_1() public constant returns (bool) { function _neg_2_shouldBeLesserThan_neg_1() public returns (bool) {
return Assert.lesserThan(int(-2), int(-1), "-2 is lesser than -1"); return Assert.lesserThan(int(-2), int(-1), "-2 is lesser than -1");
} }
function _0_shouldNotBeLesserThan_neg_1() public constant returns (bool) { function _0_shouldNotBeLesserThan_neg_1() public returns (bool) {
return Assert.lesserThan(uint(0), int(-1), "0 is not lesser than -1"); return Assert.lesserThan(uint(0), int(-1), "0 is not lesser than -1");
} }
} }
...@@ -10,19 +10,28 @@ const Provider = require('remix-simulator').Provider ...@@ -10,19 +10,28 @@ const Provider = require('remix-simulator').Provider
function compileAndDeploy (filename, callback) { function compileAndDeploy (filename, callback) {
let web3 = new Web3() let web3 = new Web3()
web3.setProvider(new Provider()) web3.setProvider(new Provider())
let compilationData
let accounts
async.waterfall([ async.waterfall([
function getAccountList (next) {
web3.eth.getAccounts((_err, _accounts) => {
accounts = _accounts
next(_err)
})
},
function compile (next) { function compile (next) {
Compiler.compileFileOrFiles(filename, false, next) Compiler.compileFileOrFiles(filename, false, {accounts}, next)
}, },
function deployAllContracts (compilationResult, next) { function deployAllContracts (compilationResult, next) {
compilationData = compilationResult
Deployer.deployAll(compilationResult, web3, next) Deployer.deployAll(compilationResult, web3, next)
} }
], function (_err, contracts) { ], function (_err, contracts) {
callback(null, contracts) callback(null, compilationData, contracts, accounts)
}) })
} }
describe('testRunner', function () { describe('testRunner', function () {
describe('#runTest', function() { describe('#runTest', function() {
describe('test with beforeAll', function () { describe('test with beforeAll', function () {
...@@ -30,7 +39,7 @@ describe('testRunner', function () { ...@@ -30,7 +39,7 @@ describe('testRunner', function () {
let tests = [], results = {} let tests = [], results = {}
before(function (done) { before(function (done) {
compileAndDeploy(filename, function (_err, contracts) { compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) { var testCallback = function (test) {
tests.push(test) tests.push(test)
} }
...@@ -38,7 +47,7 @@ describe('testRunner', function () { ...@@ -38,7 +47,7 @@ describe('testRunner', function () {
results = _results results = _results
done() done()
} }
TestRunner.runTest('MyTest', contracts.MyTest, testCallback, resultsCallback) TestRunner.runTest('MyTest', contracts.MyTest, compilationData['simple_storage_test.sol']['MyTest'], { accounts }, testCallback, resultsCallback)
}) })
}) })
...@@ -66,7 +75,7 @@ describe('testRunner', function () { ...@@ -66,7 +75,7 @@ describe('testRunner', function () {
let tests = [], results = {} let tests = [], results = {}
before(function (done) { before(function (done) {
compileAndDeploy(filename, function (_err, contracts) { compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) { var testCallback = function (test) {
tests.push(test) tests.push(test)
} }
...@@ -74,7 +83,7 @@ describe('testRunner', function () { ...@@ -74,7 +83,7 @@ describe('testRunner', function () {
results = _results results = _results
done() done()
} }
TestRunner.runTest('MyTest', contracts.MyTest, testCallback, resultsCallback) TestRunner.runTest('MyTest', contracts.MyTest, compilationData['simple_storage_test.sol']['MyTest'], { accounts }, testCallback, resultsCallback)
}) })
}) })
...@@ -101,7 +110,7 @@ describe('testRunner', function () { ...@@ -101,7 +110,7 @@ describe('testRunner', function () {
let tests = [], results = {} let tests = [], results = {}
before(function (done) { before(function (done) {
compileAndDeploy(filename, function (_err, contracts) { compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) { var testCallback = function (test) {
tests.push(test) tests.push(test)
} }
...@@ -109,8 +118,8 @@ describe('testRunner', function () { ...@@ -109,8 +118,8 @@ describe('testRunner', function () {
results = _results results = _results
done() done()
} }
TestRunner.runTest('StringTest', contracts.StringTest, testCallback, resultsCallback) TestRunner.runTest('StringTest', contracts.StringTest, compilationData['simple_string_test.sol']['StringTest'], { accounts }, testCallback, resultsCallback)
TestRunner.runTest('StringTest2', contracts.StringTest2, testCallback, resultsCallback) TestRunner.runTest('StringTest2', contracts.StringTest2, compilationData['simple_string_test.sol']['StringTest2'], { accounts }, testCallback, resultsCallback)
}) })
}) })
...@@ -125,7 +134,7 @@ describe('testRunner', function () { ...@@ -125,7 +134,7 @@ describe('testRunner', function () {
it('should returns 3 messages', function () { it('should returns 3 messages', function () {
assert.deepEqual(tests, [ assert.deepEqual(tests, [
{ type: 'contract', value: 'StringTest', filename: 'simple_string_test.sol' }, { type: 'contract', value: 'StringTest', filename: 'simple_string_test.sol' },
{ type: 'testFailure', value: 'Value should be hello world', time: 1, context: 'StringTest', "errMsg": "function returned false" }, { type: 'testFailure', value: 'Value should be hello world', time: 1, context: 'StringTest', "errMsg": "initial value is not correct" },
{ type: 'testPass', value: 'Value should not be hello world', time: 1, context: 'StringTest' }, { type: 'testPass', value: 'Value should not be hello world', time: 1, context: 'StringTest' },
{ type: 'testPass', value: 'Initial value should be hello', time: 1, context: 'StringTest' }, { type: 'testPass', value: 'Initial value should be hello', time: 1, context: 'StringTest' },
]) ])
...@@ -138,7 +147,7 @@ describe('testRunner', function () { ...@@ -138,7 +147,7 @@ describe('testRunner', function () {
let tests = [], results = {} let tests = [], results = {}
before(function (done) { before(function (done) {
compileAndDeploy(filename, function (_err, contracts) { compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) { var testCallback = function (test) {
tests.push(test) tests.push(test)
} }
...@@ -146,7 +155,7 @@ describe('testRunner', function () { ...@@ -146,7 +155,7 @@ describe('testRunner', function () {
results = _results results = _results
done() done()
} }
TestRunner.runTest('IntegerTest', contracts.IntegerTest, testCallback, resultsCallback) TestRunner.runTest('IntegerTest', contracts.IntegerTest, compilationData['number_test.sol']['IntegerTest'], { accounts }, testCallback, resultsCallback)
}) })
}) })
...@@ -157,5 +166,33 @@ describe('testRunner', function () { ...@@ -157,5 +166,33 @@ describe('testRunner', function () {
assert.equal(results.failureNum, 2) assert.equal(results.failureNum, 2)
}) })
}) })
// Test Transaction with different sender
describe('various sender', function () {
let filename = 'tests/various_sender/sender_test.sol'
let tests = [], results = {}
before(function (done) {
compileAndDeploy(filename, function (_err, compilationData, contracts, accounts) {
var testCallback = function (test) {
tests.push(test)
}
var resultsCallback = function (_err, _results) {
results = _results
done()
}
TestRunner.runTest('SenderTest', contracts.SenderTest, compilationData['sender_test.sol']['SenderTest'], { accounts }, testCallback, resultsCallback)
})
})
it('should have 4 passing tests', function () {
assert.equal(results.passingNum, 4)
})
it('should have 1 failing tests', function () {
assert.equal(results.failureNum, 0)
})
})
}) })
}) })
import "remix_tests.sol"; // this import is automatically injected by Remix.
import "remix_accounts.sol";
contract SenderTest {
function beforeAll () public {}
/// 1
function checkSenderIs1 () public {
Assert.equal(msg.sender, TestsAccounts.getAccount(1), "wrong sender in checkSenderIs1");
}
/// 0
function checkSenderIs0 () public {
Assert.equal(msg.sender, TestsAccounts.getAccount(0), "wrong sender in checkSenderIs0");
}
/// 1
function checkSenderIsNt0 () public {
Assert.notEqual(msg.sender, TestsAccounts.getAccount(0), "wrong sender in checkSenderIsNot0");
}
/// 2
function checkSenderIsnt2 () public {
Assert.notEqual(msg.sender, TestsAccounts.getAccount(1), "wrong sender in checkSenderIsnt2");
}
}
Subproject commit 1a9ec3230e7a3c278ddc6344e5c89d488a316910
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment