Merge pull request #318 from sc-forks/leapdao

Support Solidity 0.5.x
pull/332/head
cgewecke 5 years ago committed by GitHub
commit 81e59cb12f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      .circleci/config.yml
  2. 3
      .gitmodules
  3. 2
      README.md
  4. 7
      lib/app.js
  5. 27
      lib/coverageMap.js
  6. 14
      lib/instrumentSolidity.js
  7. 80
      lib/instrumenter.js
  8. 77
      lib/parse.js
  9. 117
      lib/preprocessor.js
  10. 7
      lib/truffleConfig.js
  11. 4490
      package-lock.json
  12. 17
      package.json
  13. 12
      test/app.js
  14. 24
      test/assembly.js
  15. 5
      test/cli/events.js
  16. 14
      test/cli/sign.js
  17. 2
      test/cli/testrpc-options.js
  18. 24
      test/cli/totallyPure.js
  19. 5
      test/cli/wallet.js
  20. 8
      test/comments.js
  21. 1
      test/conditional.js
  22. 4
      test/expressions.js
  23. 46
      test/function.js
  24. 23
      test/if.js
  25. 9
      test/return.js
  26. 18
      test/sources/assembly/spaces-in-function.sol
  27. 4
      test/sources/assert/Assert.sol
  28. 4
      test/sources/assert/RequireMultiline.sol
  29. 4
      test/sources/cli/CLibrary.sol
  30. 2
      test/sources/cli/Empty.sol
  31. 10
      test/sources/cli/Events.sol
  32. 4
      test/sources/cli/Expensive.sol
  33. 2
      test/sources/cli/Face.sol
  34. 17
      test/sources/cli/Migrations.sol
  35. 4
      test/sources/cli/OnlyCall.sol
  36. 4
      test/sources/cli/Owned.sol
  37. 4
      test/sources/cli/Proxy.sol
  38. 7
      test/sources/cli/PureView.sol
  39. 6
      test/sources/cli/Simple.sol
  40. 6
      test/sources/cli/SimpleError.sol
  41. 12
      test/sources/cli/TotallyPure.sol
  42. 12
      test/sources/cli/Wallet.sol
  43. 8
      test/sources/comments/postContractComment.sol
  44. 6
      test/sources/comments/postFunctionDeclarationComment.sol
  45. 4
      test/sources/comments/postIfStatementComment.sol
  46. 8
      test/sources/comments/postLineComment.sol
  47. 8
      test/sources/conditional/declarative-exp-assignment-alternate.sol
  48. 10
      test/sources/conditional/identifier-assignment-alternate.sol
  49. 4
      test/sources/conditional/mapping-assignment.sol
  50. 8
      test/sources/conditional/multiline-alternate.sol
  51. 8
      test/sources/conditional/multiline-consequent.sol
  52. 8
      test/sources/conditional/sameline-alternate.sol
  53. 8
      test/sources/conditional/sameline-consequent.sol
  54. 10
      test/sources/conditional/variable-decl-assignment-alternate.sol
  55. 6
      test/sources/expressions/new-expression.sol
  56. 4
      test/sources/expressions/single-binary-expression.sol
  57. 4
      test/sources/function/abstract.sol
  58. 7
      test/sources/function/calldata.sol
  59. 6
      test/sources/function/chainable-new.sol
  60. 8
      test/sources/function/chainable-value.sol
  61. 6
      test/sources/function/chainable.sol
  62. 6
      test/sources/function/constructor-keyword.sol
  63. 4
      test/sources/function/empty-body.sol
  64. 6
      test/sources/function/function-call.sol
  65. 4
      test/sources/function/function.sol
  66. 11
      test/sources/function/modifier.sol
  67. 8
      test/sources/function/multiple.sol
  68. 6
      test/sources/if/else-with-brackets.sol
  69. 6
      test/sources/if/else-without-brackets.sol
  70. 21
      test/sources/if/if-elseif-else.sol
  71. 4
      test/sources/if/if-no-brackets-multiline.sol
  72. 4
      test/sources/if/if-no-brackets.sol
  73. 4
      test/sources/if/if-with-brackets-multiline.sol
  74. 4
      test/sources/if/if-with-brackets.sol
  75. 4
      test/sources/if/nested-if-missing-else.sol
  76. 8
      test/sources/loops/for-no-brackets.sol
  77. 8
      test/sources/loops/for-with-brackets.sol
  78. 6
      test/sources/loops/while-no-brackets.sol
  79. 6
      test/sources/loops/while-with-brackets.sol
  80. 7
      test/sources/return/return-null.sol
  81. 4
      test/sources/return/return.sol
  82. 2
      test/sources/statements/compilation-error.sol
  83. 4
      test/sources/statements/emit-coverage.sol
  84. 4
      test/sources/statements/emit-instrument.sol
  85. 2
      test/sources/statements/empty-contract-ala-melonport.sol
  86. 2
      test/sources/statements/empty-contract-body.sol
  87. 10
      test/sources/statements/fn-argument-multiline.sol
  88. 8
      test/sources/statements/fn-argument.sol
  89. 6
      test/sources/statements/fn-struct.sol
  90. 2
      test/sources/statements/library.sol
  91. 8
      test/sources/statements/multiple.sol
  92. 4
      test/sources/statements/post-close-brace.sol
  93. 6
      test/sources/statements/single.sol
  94. 10
      test/sources/statements/tuple.sol
  95. 1
      test/sources/zeppelin
  96. 58
      test/sources/zeppelin/Bounty.sol
  97. 30
      test/sources/zeppelin/Claimable.sol
  98. 73
      test/sources/zeppelin/DayLimit.sol
  99. 15
      test/sources/zeppelin/Killable.sol
  100. 18
      test/sources/zeppelin/LimitBalance.sol
  101. Some files were not shown because too many files have changed in this diff Show More

@ -2,7 +2,7 @@ version: 2.0
jobs:
build:
docker:
- image: circleci/node:7.10.0
- image: circleci/node:8.15.0
steps:
- checkout
- run:
@ -13,6 +13,10 @@ jobs:
name: Install dependencies
command: |
npm install
- run:
name: Get submodules
command: |
git submodule update --init
- run:
name: Run tests
command: |

3
.gitmodules vendored

@ -0,0 +1,3 @@
[submodule "test/sources/openzeppelin-solidity"]
path = test/sources/zeppelin
url = https://github.com/OpenZeppelin/openzeppelin-solidity

@ -156,3 +156,5 @@ also lint your submission with `npm run lint`. Bugs can be reported in the
+ [@DimitarSD](https://github.com/DimitarSD)
+ [@sohkai](https://github.com/sohkai)
+ [@bingen](https://github.com/bingen)
+ [@pinkiebell](https://github.com/pinkiebell)
+ [@obernardovieira](https://github.com/obernardovieira)

@ -209,11 +209,11 @@ class App {
return new Promise((resolve, reject) => {
if (!this.norpc) {
const defaultRpcOptions = `--accounts ${this.accounts} --port ${this.port}`;
const options = (this.testrpcOptions || defaultRpcOptions) + ` --gasLimit ${gasLimitHex}`;
const command = require.resolve('ethereumjs-testrpc-sc/build/cli.node.js');
const options = (this.testrpcOptions || defaultRpcOptions) + ` --gasLimit ${gasLimitHex} --allowUnlimitedContractSize`;
const command = require.resolve('ethereumjs-testrpc-sc/cli.js');
// Launch
const execOpts = {maxBuffer: 1024 * 1024 * 10};
const execOpts = {maxBuffer: 1024 * 1024 * 100};
this.testrpcProcess = childprocess.exec(`node ${command} ${options}`, execOpts, (err, stdout, stderr) => {
if (err) {
if (stdout) this.log(`testRpc stdout:\n${stdout}`);
@ -272,6 +272,7 @@ class App {
const defaultCommand = `truffle compile ${this.network} ${this.silence}`;
const command = this.compileCommand || defaultCommand;
this.log(`Running: ${command}\n(this can take a few seconds)...`);
shell.cd(this.coverageDir);
shell.exec(command);
this.testsErrored = shell.error();

@ -3,7 +3,8 @@
* This file contains methods that produce a coverage map to pass to instanbul
* from data generated by `instrumentSolidity.js`
*/
const SolidityCoder = require('web3/lib/solidity/coder.js');
const { AbiCoder } = require('web3-eth-abi');
const SolidityCoder = AbiCoder();
const path = require('path');
const keccak = require('keccakjs');
const fs = require('fs');
@ -103,29 +104,29 @@ module.exports = class CoverageMap {
const event = JSON.parse(events[idx]);
if (event.topics.filter(t => this.lineTopics.indexOf(t) >= 0).length > 0) {
const data = SolidityCoder.decodeParams(['string', 'uint256'], event.data.replace('0x', ''));
const data = SolidityCoder.decodeParameters(['string', 'uint256'], `0x${event.data}`);
const canonicalContractPath = data[0];
this.coverage[canonicalContractPath].l[data[1].toNumber()] += 1;
this.coverage[canonicalContractPath].l[parseInt(data[1], 10)] += 1;
} else if (event.topics.filter(t => this.functionTopics.indexOf(t) >= 0).length > 0) {
const data = SolidityCoder.decodeParams(['string', 'uint256'], event.data.replace('0x', ''));
const data = SolidityCoder.decodeParameters(['string', 'uint256'], `0x${event.data}`);
const canonicalContractPath = data[0];
this.coverage[canonicalContractPath].f[data[1].toNumber()] += 1;
this.coverage[canonicalContractPath].f[parseInt(data[1], 10)] += 1;
} else if (event.topics.filter(t => this.branchTopics.indexOf(t) >= 0).length > 0) {
const data = SolidityCoder.decodeParams(['string', 'uint256', 'uint256'], event.data.replace('0x', ''));
const data = SolidityCoder.decodeParameters(['string', 'uint256', 'uint256'], `0x${event.data}`);
const canonicalContractPath = data[0];
this.coverage[canonicalContractPath].b[data[1].toNumber()][data[2].toNumber()] += 1;
this.coverage[canonicalContractPath].b[parseInt(data[1], 10)][parseInt(data[2], 10)] += 1;
} else if (event.topics.filter(t => this.statementTopics.indexOf(t) >= 0).length > 0) {
const data = SolidityCoder.decodeParams(['string', 'uint256'], event.data.replace('0x', ''));
const data = SolidityCoder.decodeParameters(['string', 'uint256'], `0x${event.data}`);
const canonicalContractPath = data[0];
this.coverage[canonicalContractPath].s[data[1].toNumber()] += 1;
this.coverage[canonicalContractPath].s[parseInt(data[1], 10)] += 1;
} else if (event.topics.filter(t => this.assertPreTopics.indexOf(t) >= 0).length > 0) {
const data = SolidityCoder.decodeParams(['string', 'uint256'], event.data.replace('0x', ''));
const data = SolidityCoder.decodeParameters(['string', 'uint256'], `0x${event.data}`);
const canonicalContractPath = data[0];
this.assertCoverage[canonicalContractPath][data[1].toNumber()].preEvents += 1;
this.assertCoverage[canonicalContractPath][parseInt(data[1], 10)].preEvents += 1;
} else if (event.topics.filter(t => this.assertPostTopics.indexOf(t) >= 0).length > 0) {
const data = SolidityCoder.decodeParams(['string', 'uint256'], event.data.replace('0x', ''));
const data = SolidityCoder.decodeParameters(['string', 'uint256'], `0x${event.data}`);
const canonicalContractPath = data[0];
this.assertCoverage[canonicalContractPath][data[1].toNumber()].postEvents += 1;
this.assertCoverage[canonicalContractPath][parseInt(data[1], 10)].postEvents += 1;
}
}
// Finally, interpret the assert pre/post events

@ -1,4 +1,4 @@
const SolidityParser = require('solidity-parser-sc');
const SolidityParser = require('solidity-parser-antlr');
const preprocessor = require('./preprocessor');
const injector = require('./injector');
const parse = require('./parse');
@ -20,7 +20,7 @@ module.exports = function instrumentSolidity(contractSource, fileName) {
contract.injectionPoints = {};
// First, we run over the original contract to get the source mapping.
let ast = SolidityParser.parse(contract.source);
let ast = SolidityParser.parse(contract.source, {range: true});
parse[ast.type](contract, ast);
const retValue = JSON.parse(JSON.stringify(contract));
@ -36,12 +36,10 @@ module.exports = function instrumentSolidity(contractSource, fileName) {
contract.preprocessed = preprocessor.run(contract.source);
contract.instrumented = contract.preprocessed;
ast = SolidityParser.parse(contract.preprocessed);
const contractStatement = ast.body.filter(node => (node.type === 'ContractStatement' ||
node.type === 'LibraryStatement' ||
node.type === 'InterfaceStatement'));
ast = SolidityParser.parse(contract.preprocessed, {range: true});
const contractStatement = ast.children.filter(node => (node.type === 'ContractDefinition' ||
node.type === 'LibraryDefinition' ||
node.type === 'InterfaceDefinition'));
contract.contractName = contractStatement[0].name;
parse[ast.type](contract, ast);

@ -14,7 +14,7 @@ function createOrAppendInjectionPoint(contract, key, value) {
instrumenter.prePosition = function prePosition(expression) {
if (expression.right.type === 'ConditionalExpression' &&
expression.left.type === 'MemberExpression') {
expression.start -= 2;
expression.range[0] -= 2;
}
};
@ -31,15 +31,15 @@ instrumenter.instrumentAssignmentExpression = function instrumentAssignmentExpre
if (expression.left.type === 'DeclarativeExpression' || expression.left.type === 'Identifier') {
// Then we need to go from bytes32 varname = (conditional expression)
// to bytes32 varname; (,varname) = (conditional expression)
createOrAppendInjectionPoint(contract, expression.left.end, {
createOrAppendInjectionPoint(contract, expression.left.range[1], {
type: 'literal', string: '; (,' + expression.left.name + ')',
});
instrumenter.instrumentConditionalExpression(contract, expression.right);
} else if (expression.left.type === 'MemberExpression') {
createOrAppendInjectionPoint(contract, expression.left.start, {
createOrAppendInjectionPoint(contract, expression.left.range[0], {
type: 'literal', string: '(,',
});
createOrAppendInjectionPoint(contract, expression.left.end, {
createOrAppendInjectionPoint(contract, expression.left.range[1], {
type: 'literal', string: ')',
});
instrumenter.instrumentConditionalExpression(contract, expression.right);
@ -61,12 +61,12 @@ instrumenter.instrumentConditionalExpression = function instrumentConditionalExp
/*contract.branchId += 1;
const startline = (contract.instrumented.slice(0, expression.start).match(/\n/g) || []).length + 1;
const startcol = expression.start - contract.instrumented.slice(0, expression.start).lastIndexOf('\n') - 1;
const consequentStartCol = startcol + (contract, expression.consequent.start - expression.start);
const consequentEndCol = consequentStartCol + (contract, expression.consequent.end - expression.consequent.start);
const alternateStartCol = startcol + (contract, expression.alternate.start - expression.start);
const alternateEndCol = alternateStartCol + (contract, expression.alternate.end - expression.alternate.start);
const startline = (contract.instrumented.slice(0, expression.range[0]).match(/\n/g) || []).length + 1;
const startcol = expression.range[0] - contract.instrumented.slice(0, expression.range[0]).lastIndexOf('\n') - 1;
const consequentStartCol = startcol + (contract, expression.trueBody.range[0] - expression.range[0]);
const consequentEndCol = consequentStartCol + (contract, expression.trueBody.range[1] - expression.trueBody.range[0]);
const alternateStartCol = startcol + (contract, expression.falseBody.range[0] - expression.range[0]);
const alternateEndCol = alternateStartCol + (contract, expression.falseBody.range[1] - expression.falseBody.range[0]);
// NB locations for conditional branches in istanbul are length 1 and associated with the : and ?.
contract.branchMap[contract.branchId] = {
line: startline,
@ -95,24 +95,24 @@ instrumenter.instrumentConditionalExpression = function instrumentConditionalExp
// Wrap the consequent
createOrAppendInjectionPoint(contract, expression.consequent.start, {
createOrAppendInjectionPoint(contract, expression.trueBody.range[0], {
type: 'openParen',
});
createOrAppendInjectionPoint(contract, expression.consequent.start, {
createOrAppendInjectionPoint(contract, expression.trueBody.range[0], {
type: 'callBranchEvent', comma: true, branchId: contract.branchId, locationIdx: 0,
});
createOrAppendInjectionPoint(contract, expression.consequent.end, {
createOrAppendInjectionPoint(contract, expression.trueBody.range[1], {
type: 'closeParen',
});
// Wrap the alternate
createOrAppendInjectionPoint(contract, expression.alternate.start, {
createOrAppendInjectionPoint(contract, expression.falseBody.range[0], {
type: 'openParen',
});
createOrAppendInjectionPoint(contract, expression.alternate.start, {
createOrAppendInjectionPoint(contract, expression.falseBody.range[0], {
type: 'callBranchEvent', comma: true, branchId: contract.branchId, locationIdx: 1,
});
createOrAppendInjectionPoint(contract, expression.alternate.end, {
createOrAppendInjectionPoint(contract, expression.falseBody.range[1], {
type: 'closeParen',
});*/
};
@ -120,14 +120,14 @@ instrumenter.instrumentConditionalExpression = function instrumentConditionalExp
instrumenter.instrumentStatement = function instrumentStatement(contract, expression) {
contract.statementId += 1;
// We need to work out the lines and columns the expression starts and ends
const startline = (contract.instrumented.slice(0, expression.start).match(/\n/g) || []).length + 1;
const startcol = expression.start - contract.instrumented.slice(0, expression.start).lastIndexOf('\n') - 1;
const expressionContent = contract.instrumented.slice(expression.start, expression.end);
const startline = (contract.instrumented.slice(0, expression.range[0]).match(/\n/g) || []).length + 1;
const startcol = expression.range[0] - contract.instrumented.slice(0, expression.range[0]).lastIndexOf('\n') - 1;
const expressionContent = contract.instrumented.slice(expression.range[0], expression.range[1] + 1);
const endline = startline + (contract, expressionContent.match('/\n/g') || []).length;
let endcol;
if (expressionContent.lastIndexOf('\n') >= 0) {
endcol = contract.instrumented.slice(expressionContent.lastIndexOf('\n'), expression.end).length - 1;
endcol = contract.instrumented.slice(expressionContent.lastIndexOf('\n'), expression.range[1]).length;
} else {
endcol = startcol + (contract, expressionContent.length - 1);
}
@ -139,15 +139,15 @@ instrumenter.instrumentStatement = function instrumentStatement(contract, expres
line: endline, column: endcol,
},
};
createOrAppendInjectionPoint(contract, expression.start, {
createOrAppendInjectionPoint(contract, expression.range[0], {
type: 'statement', statementId: contract.statementId,
});
};
instrumenter.instrumentLine = function instrumentLine(contract, expression) {
// what's the position of the most recent newline?
const startchar = expression.start;
const endchar = expression.end;
const startchar = expression.range[0];
const endchar = expression.range[1] + 1;
const lastNewLine = contract.instrumented.slice(0, startchar).lastIndexOf('\n');
const nextNewLine = startchar + contract.instrumented.slice(startchar).indexOf('\n');
const contractSnipped = contract.instrumented.slice(lastNewLine, nextNewLine);
@ -160,7 +160,7 @@ instrumenter.instrumentLine = function instrumentLine(contract, expression) {
});
} else if (contract.instrumented.slice(lastNewLine, startchar).replace('{', '').trim().length === 0 &&
contract.instrumented.slice(endchar, nextNewLine).replace(/[;}]/g, '').trim().length === 0) {
createOrAppendInjectionPoint(contract, expression.start, {
createOrAppendInjectionPoint(contract, expression.range[0], {
type: 'callEvent',
});
}
@ -169,15 +169,15 @@ instrumenter.instrumentLine = function instrumentLine(contract, expression) {
instrumenter.instrumentFunctionDeclaration = function instrumentFunctionDeclaration(contract, expression) {
contract.fnId += 1;
const startline = (contract.instrumented.slice(0, expression.start).match(/\n/g) || []).length + 1;
const startline = (contract.instrumented.slice(0, expression.range[0]).match(/\n/g) || []).length + 1;
// We need to work out the lines and columns the function declaration starts and ends
const startcol = expression.start - contract.instrumented.slice(0, expression.start).lastIndexOf('\n') - 1;
const endlineDelta = contract.instrumented.slice(expression.start).indexOf('{');
const functionDefinition = contract.instrumented.slice(expression.start, expression.start + endlineDelta);
const startcol = expression.range[0] - contract.instrumented.slice(0, expression.range[0]).lastIndexOf('\n') - 1;
const endlineDelta = contract.instrumented.slice(expression.range[0]).indexOf('{');
const functionDefinition = contract.instrumented.slice(expression.range[0], expression.range[0] + endlineDelta);
const endline = startline + (functionDefinition.match(/\n/g) || []).length;
const endcol = functionDefinition.length - functionDefinition.lastIndexOf('\n');
contract.fnMap[contract.fnId] = {
name: expression.name,
name: expression.isConstructor ? 'constructor' : expression.name,
line: startline,
loc: {
start: {
@ -188,15 +188,15 @@ instrumenter.instrumentFunctionDeclaration = function instrumentFunctionDeclarat
},
},
};
createOrAppendInjectionPoint(contract, expression.start + endlineDelta + 1, {
createOrAppendInjectionPoint(contract, expression.range[0] + endlineDelta + 1, {
type: 'callFunctionEvent', fnId: contract.fnId,
});
};
instrumenter.addNewBranch = function addNewBranch(contract, expression) {
contract.branchId += 1;
const startline = (contract.instrumented.slice(0, expression.start).match(/\n/g) || []).length + 1;
const startcol = expression.start - contract.instrumented.slice(0, expression.start).lastIndexOf('\n') - 1;
const startline = (contract.instrumented.slice(0, expression.range[0]).match(/\n/g) || []).length + 1;
const startcol = expression.range[0] - contract.instrumented.slice(0, expression.range[0]).lastIndexOf('\n') - 1;
// NB locations for if branches in istanbul are zero length and associated with the start of the if.
contract.branchMap[contract.branchId] = {
line: startline,
@ -221,31 +221,31 @@ instrumenter.addNewBranch = function addNewBranch(contract, expression) {
instrumenter.instrumentAssertOrRequire = function instrumentAssertOrRequire(contract, expression) {
instrumenter.addNewBranch(contract, expression);
createOrAppendInjectionPoint(contract, expression.start, {
createOrAppendInjectionPoint(contract, expression.range[0], {
type: 'callAssertPreEvent', branchId: contract.branchId,
});
createOrAppendInjectionPoint(contract, expression.end + 1, {
createOrAppendInjectionPoint(contract, expression.range[1] + 2, {
type: 'callAssertPostEvent', branchId: contract.branchId,
});
};
instrumenter.instrumentIfStatement = function instrumentIfStatement(contract, expression) {
instrumenter.addNewBranch(contract, expression);
if (expression.consequent.type === 'BlockStatement') {
createOrAppendInjectionPoint(contract, expression.consequent.start + 1, {
if (expression.trueBody.type === 'Block') {
createOrAppendInjectionPoint(contract, expression.trueBody.range[0] + 1, {
type: 'callBranchEvent', branchId: contract.branchId, locationIdx: 0,
});
}
if (expression.alternate && expression.alternate.type === 'IfStatement') {
if (expression.falseBody && expression.falseBody.type === 'IfStatement') {
// Do nothing - we must be pre-preprocessor, so don't bother instrumenting -
// when we're actually instrumenting, this will never happen (we've wrapped it in
// a block statement)
} else if (expression.alternate && expression.alternate.type === 'BlockStatement') {
createOrAppendInjectionPoint(contract, expression.alternate.start + 1, {
} else if (expression.falseBody && expression.falseBody.type === 'Block') {
createOrAppendInjectionPoint(contract, expression.falseBody.range[0] + 1, {
type: 'callBranchEvent', branchId: contract.branchId, locationIdx: 1,
});
} else {
createOrAppendInjectionPoint(contract, expression.consequent.end, {
createOrAppendInjectionPoint(contract, expression.trueBody.range[1] + 1, {
type: 'callEmptyBranchEvent', branchId: contract.branchId, locationIdx: 1,
});
}

@ -15,26 +15,31 @@ parse.AssignmentExpression = function parseAssignmentExpression(contract, expres
instrumenter.instrumentAssignmentExpression(contract, expression);
};
parse.BlockStatement = function parseBlockStatement(contract, expression) {
for (let x = 0; x < expression.body.length; x++) {
instrumenter.instrumentLine(contract, expression.body[x]);
parse[expression.body[x].type] &&
parse[expression.body[x].type](contract, expression.body[x]);
parse.Block = function parseBlock(contract, expression) {
for (let x = 0; x < expression.statements.length; x++) {
instrumenter.instrumentLine(contract, expression.statements[x]);
parse[expression.statements[x].type] &&
parse[expression.statements[x].type](contract, expression.statements[x]);
}
};
parse.CallExpression = function parseCallExpression(contract, expression) {
// In any given chain of call expressions, only the head callee is an Identifier node
if (expression.callee.type === 'Identifier') {
parse.BinaryOperation = function parseBinaryOperation(contract, expression) {
instrumenter.instrumentStatement(contract, expression);
}
parse.FunctionCall = function parseCallExpression(contract, expression) {
// In any given chain of call expressions, only the last one will fail this check. This makes sure
// we don't instrument a chain of expressions multiple times.
if (expression.expression.type !== 'FunctionCall') {
instrumenter.instrumentStatement(contract, expression);
if (expression.callee.name === 'assert' || expression.callee.name === 'require') {
if (expression.expression.name === 'assert' || expression.expression.name === 'require') {
instrumenter.instrumentAssertOrRequire(contract, expression);
}
parse[expression.callee.type] &&
parse[expression.callee.type](contract, expression.callee);
parse[expression.expression.type] &&
parse[expression.expression.type](contract, expression.expression);
} else {
parse[expression.callee.type] &&
parse[expression.callee.type](contract, expression.callee);
parse[expression.expression.type] &&
parse[expression.expression.type](contract, expression.expression);
}
};
@ -43,25 +48,25 @@ parse.ConditionalExpression = function parseConditionalExpression(contract, expr
instrumenter.instrumentConditionalExpression(contract, expression);
};
parse.ContractStatement = function ParseContractStatement(contract, expression) {
parse.ContractDefinition = function ParseContractStatement(contract, expression) {
parse.ContractOrLibraryStatement(contract, expression);
};
parse.ContractOrLibraryStatement = function parseContractOrLibraryStatement(contract, expression) {
// From the start of this contract statement, find the first '{', and inject there.
const injectionPoint = expression.start + contract.instrumented.slice(expression.start).indexOf('{') + 1;
const injectionPoint = expression.range[0] + contract.instrumented.slice(expression.range[0]).indexOf('{') + 1;
if (contract.injectionPoints[injectionPoint]) {
contract.injectionPoints[expression.start + contract.instrumented.slice(expression.start).indexOf('{') + 1].push({
contract.injectionPoints[expression.range[0] + contract.instrumented.slice(expression.range[0]).indexOf('{') + 1].push({
type: 'eventDefinition',
});
} else {
contract.injectionPoints[expression.start + contract.instrumented.slice(expression.start).indexOf('{') + 1] = [{
contract.injectionPoints[expression.range[0] + contract.instrumented.slice(expression.range[0]).indexOf('{') + 1] = [{
type: 'eventDefinition',
}];
}
if (expression.body) {
expression.body.forEach(construct => {
if (expression.subNodes) {
expression.subNodes.forEach(construct => {
parse[construct.type] &&
parse[construct.type](contract, construct);
});
@ -83,11 +88,10 @@ parse.ForStatement = function parseForStatement(contract, expression) {
parse[expression.body.type](contract, expression.body);
};
parse.FunctionDeclaration = function parseFunctionDeclaration(contract, expression) {
parse.FunctionDefinition = function parseFunctionDefinition(contract, expression) {
parse.Modifiers(contract, expression.modifiers);
if (expression.body) {
instrumenter.instrumentFunctionDeclaration(contract, expression);
parse[expression.body.type] &&
parse[expression.body.type](contract, expression.body);
}
@ -96,13 +100,12 @@ parse.FunctionDeclaration = function parseFunctionDeclaration(contract, expressi
parse.IfStatement = function parseIfStatement(contract, expression) {
instrumenter.instrumentStatement(contract, expression);
instrumenter.instrumentIfStatement(contract, expression);
parse[expression.trueBody.type] &&
parse[expression.trueBody.type](contract, expression.trueBody);
parse[expression.consequent.type] &&
parse[expression.consequent.type](contract, expression.consequent);
if (expression.alternate) {
parse[expression.alternate.type] &&
parse[expression.alternate.type](contract, expression.alternate);
if (expression.falseBody) {
parse[expression.falseBody.type] &&
parse[expression.falseBody.type](contract, expression.falseBody);
}
};
@ -127,19 +130,19 @@ parse.Modifiers = function parseModifier(contract, modifiers) {
}
};
parse.ModifierDeclaration = function parseModifierDeclaration(contract, expression) {
parse.ModifierDefinition = function parseModifierDefinition(contract, expression) {
instrumenter.instrumentFunctionDeclaration(contract, expression);
parse[expression.body.type] &&
parse[expression.body.type](contract, expression.body);
};
parse.NewExpression = function parseNewExpression(contract, expression) {
parse[expression.callee.type] &&
parse[expression.callee.type](contract, expression.callee);
parse[expression.typeName.type] &&
parse[expression.typeName.type](contract, expression.typeName);
};
parse.Program = function parseProgram(contract, expression) {
expression.body.forEach(construct => {
parse.SourceUnit = function parseSourceUnit(contract, expression) {
expression.children.forEach(construct => {
parse[construct.type] &&
parse[construct.type](contract, construct);
});
@ -149,10 +152,6 @@ parse.ReturnStatement = function parseReturnStatement(contract, expression) {
instrumenter.instrumentStatement(contract, expression);
};
parse.ThrowStatement = function parseThrowStatement(contract, expression) {
instrumenter.instrumentStatement(contract, expression);
};
parse.UnaryExpression = function parseUnaryExpression(contract, expression) {
parse[expression.argument.type] &&
parse[expression.argument.type](contract, expression.argument);
@ -163,10 +162,10 @@ parse.UsingStatement = function parseUsingStatement(contract, expression) {
parse[expression.for.type](contract, expression.for);
};
parse.VariableDeclaration = function parseVariableDeclaration(contract, expression) {
parse.VariableDeclarationStatement = function parseVariableDeclarationStatement(contract, expression) {
instrumenter.instrumentStatement(contract, expression);
parse[expression.declarations[0].id.type] &&
parse[expression.declarations[0].id.type](contract, expression.declarations[0].id);
// parse[expression.declarations[0].id.type] &&
// parse[expression.declarations[0].id.type](contract, expression.declarations[0].id);
};
parse.VariableDeclarationTuple = function parseVariableDeclarationTuple(contract, expression) {

@ -1,5 +1,5 @@
const SolExplore = require('sol-explore');
const SolidityParser = require('solidity-parser-sc');
const SolidityParser = require('solidity-parser-antlr');
const crRegex = /[\r\n ]+$/g;
/**
@ -9,21 +9,27 @@ const crRegex = /[\r\n ]+$/g;
* @return {String} contract
*/
function blockWrap(contract, expression) {
return contract.slice(0, expression.start) + '{' + contract.slice(expression.start, expression.end) + '}' + contract.slice(expression.end);
return contract.slice(0, expression.range[0]) + '{' + contract.slice(expression.range[0], expression.range[1] + 1) + '}' + contract.slice(expression.range[1] + 1);
}
/**
* Captures carriage returns at modifiers we'll remove. These need to be re-injected into the
* source to keep line report alignments accurate.
/** Remove 'pure' and 'view' from the function declaration.
* @param {String} contract solidity source
* @param {Object} modifier AST node
* @return {String} whitespace around the modifier
*/
function getModifierWhitespace(contract, modifier){
const source = contract.slice(modifier.start, modifier.end);
const whitespace = source.match(crRegex) || [];
return whitespace.join('');
* @param {Object} function AST node
* @return {String} contract with the modifiers removed from the given function.
*/
function removePureView(contract, node){
let fDefStart = node.range[0];
if (node.body){
fDefEnd = node.body.range[0];
} else if (node.returnParameters) {
fDefEnd = node.returnParameters.range[0];
} else {
fDefEnd = node.range[1];
}
let fDef = contract.slice(fDefStart, fDefEnd + 1);
fDef = fDef.replace(/\bview\b/i, ' ');
fDef = fDef.replace(/\bpure\b/i, ' ');
return contract.slice(0, fDefStart) + fDef + contract.slice(fDefEnd + 1);
}
/**
@ -38,55 +44,44 @@ function getModifierWhitespace(contract, modifier){
* @return {String} contract
*/
module.exports.run = function r(contract) {
let keepRunning = true;
while (keepRunning) {
try {
const ast = SolidityParser.parse(contract);
keepRunning = false;
SolExplore.traverse(ast, {
enter(node, parent) { // eslint-disable-line no-loop-func
// If consequents
if (node.type === 'IfStatement' && node.consequent.type !== 'BlockStatement') {
contract = blockWrap(contract, node.consequent);
keepRunning = true;
this.stopTraversal();
// If alternates
} else if (
node.type === 'IfStatement' &&
node.alternate &&
node.alternate.type !== 'BlockStatement') {
contract = blockWrap(contract, node.alternate);
keepRunning = true;
this.stopTraversal();
// Loops
} else if (
(node.type === 'ForStatement' || node.type === 'WhileStatement') &&
node.body.type !== 'BlockStatement') {
contract = blockWrap(contract, node.body);
keepRunning = true;
this.stopTraversal();
} else if (node.type === 'FunctionDeclaration' && node.modifiers) {
// We want to remove constant / pure / view from functions
for (let i = 0; i < node.modifiers.length; i++) {
if (['pure', 'constant', 'view'].indexOf(node.modifiers[i].name) > -1) {
let whitespace = getModifierWhitespace(contract, node.modifiers[i]);
contract = contract.slice(0, node.modifiers[i].start) +
whitespace +
contract.slice(node.modifiers[i].end);
keepRunning = true;
this.stopTraversal();
}
}
}
},
});
} catch (err) {
contract = err;
keepRunning = false;
}
try {
const ast = SolidityParser.parse(contract, { range: true });
blocksToWrap = [];
viewPureToRemove = [];
SolidityParser.visit(ast, {
IfStatement: function(node) {
if (node.trueBody.type !== 'Block') {
blocksToWrap.push(node.trueBody);
} else if (node.falseBody && node.falseBody.type !== 'Block'){
blocksToWrap.push(node.falseBody);
}
},
ForStatement: function(node){
if (node.body.type !== 'Block'){
blocksToWrap.push(node.body);
}
},
WhileStatement: function(node){
if (node.body.type !== 'Block'){
blocksToWrap.push(node.body);
}
},
FunctionDefinition: function(node){
if (node.stateMutability === 'view' || node.stateMutability === 'pure'){
viewPureToRemove.push(node);
}
}
})
// Firstly, remove pures and views. Note that we replace 'pure' and 'view' with spaces, so
// character counts remain the same, so we can do this in any order
viewPureToRemove.forEach(node => contract = removePureView(contract, node));
// We apply the blocks we found in reverse order to avoid extra characters messing things up.
blocksToWrap.sort((a,b) => a.range[0] < b.range[0]);
blocksToWrap.forEach(block => contract = blockWrap(contract, block))
} catch (err) {
contract = err;
keepRunning = false;
}
return contract;
};

@ -9,6 +9,11 @@ module.exports = function truffleConfig(port, gasLimit, gasPrice) {
gas: ${gasLimit},
gasPrice: ${gasPrice}
}
},
compilers: {
solc: {
version: "0.5.3",
}
}
};`;
};`;
};

4490
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{
"name": "solidity-coverage",
"version": "0.5.11",
"version": "0.6.0-beta.5",
"description": "",
"bin": {
"solidity-coverage": "./bin/exec.js"
@ -22,15 +22,16 @@
"license": "ISC",
"dependencies": {
"death": "^1.1.0",
"ethereumjs-testrpc-sc": "6.1.6",
"ethereumjs-testrpc-sc": "6.4.1",
"istanbul": "^0.4.5",
"keccakjs": "^0.2.1",
"req-cwd": "^1.0.1",
"shelljs": "^0.7.4",
"sol-explore": "^1.6.2",
"solidity-parser-sc": "0.4.11",
"solidity-parser-antlr": "^0.4.1",
"tree-kill": "^1.2.0",
"web3": "^0.20.6"
"web3": "^1.0.0-beta.50",
"web3-eth-abi": "1.0.0-beta.50"
},
"devDependencies": {
"crypto-js": "^3.1.9-1",
@ -41,11 +42,11 @@
"ethereumjs-account": "~2.0.4",
"ethereumjs-tx": "^1.2.2",
"ethereumjs-util": "^5.0.1",
"ethereumjs-vm": "https://github.com/sc-forks/ethereumjs-vm-sc.git#6be86e6f12634b711423203e6744cafe07c38e69",
"ethereumjs-vm": "git+https://github.com/sc-forks/ethereumjs-vm-sc.git#3c328147a2c48a379af775930f52c439813a21e2",
"merkle-patricia-tree": "~2.1.2",
"mocha": "^4.1.0",
"request": "^2.81.0",
"solc": "^0.4.24",
"truffle": "^4.1.14"
"request": "^2.88.0",
"solc": "^0.5.3",
"truffle": "^5.0.0"
}
}

@ -155,6 +155,14 @@ describe('app', () => {
port: 8999,
network_id: "*"
}
},
compilers: {
solc: {
version: "0.5.3",
settings: {
evmVersion: "constantinople"
}
}
}
};`;
@ -305,6 +313,7 @@ describe('app', () => {
});
it.skip('contract sends / transfers to instrumented fallback: coverage, cleanup & exit(0)', () => {
// Skipped due to https://github.com/sc-forks/solidity-coverage/issues/106
// Validate ethereumjs-vm hack to remove gas constraints on transfer() and send()
assert(pathExists('./coverage') === false, 'should start without: coverage');
assert(pathExists('./coverage.json') === false, 'should start without: coverage.json');
@ -337,8 +346,7 @@ describe('app', () => {
const produced = JSON.parse(fs.readFileSync('./coverage.json', 'utf8'));
const ownedPath = Object.keys(produced)[0];
const proxyPath = Object.keys(produced)[1];
assert(produced[ownedPath].fnMap['1'].name === 'Owned', 'coverage.json should map "Owned"');
assert(produced[ownedPath].fnMap['1'].name === 'constructor', 'coverage.json should map "constructor"');
assert(produced[proxyPath].fnMap['1'].name === 'isOwner', 'coverage.json should map "isOwner"');
collectGarbage();
});

@ -0,0 +1,24 @@
/* eslint-env node, mocha */
const solc = require('solc');
const getInstrumentedVersion = require('./../lib/instrumentSolidity.js');
const util = require('./util/util.js');
const path = require('path');
/**
* NB: passing '1' to solc as an option activates the optimiser
* NB: solc will throw if there is a compilation error, causing the test to fail
* and passing the error to mocha.
*/
describe('generic expressions', () => {
const filePath = path.resolve('./test.sol');
it('should compile after instrumenting an assembly function with spaces in parameters', () => {
const contract = util.getCode('assembly/spaces-in-function.sol');
const info = getInstrumentedVersion(contract, filePath);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
console.log(info)
util.report(output.errors);
});
});

@ -8,12 +8,13 @@ contract('Events', accounts => {
const loggedEvents = [];
Events.deployed().then(instance => {
const allEvents = instance.allEvents();
allEvents.watch((error, event) => { loggedEvents.push(event); });
allEvents.on("data", event => { loggedEvents.push(event); });
instance.test(5).then(() => {
const bad = loggedEvents.filter(e => e.event !== 'LogEventOne' && e.event !== 'LogEventTwo');
assert(bad.length === 0, 'Did not filter events correctly');
allEvents.stopWatching(done);
done();
});
});
});

@ -1,23 +1,23 @@
/* eslint-env node, mocha */
/* global artifacts, contract, assert */
const Web3 = require('web3');
const ethUtil = require('ethereumjs-util');
const provider = new Web3.providers.HttpProvider('http://localhost:8555'); // testrpc-sc
const web3 = new Web3(provider);
const Simple = artifacts.require('./Simple.sol');
contract('Simple', accounts => {
it('should set x to 5', () => {
let simple;
let messageSha3;
return Simple.deployed()
.then(instance => instance.test(5)) // We need this line to generate some coverage
.then(() => {
const message = 'Enclosed is my formal application for permanent residency in New Zealand';
const messageSha3 = web3.sha3(message);
const signature = web3.eth.sign(accounts[0], messageSha3);
messageSha3 = web3.utils.sha3(message);
const signature = web3.eth.sign(messageSha3, accounts[0]);
return signature;
})
.then((signature) => {
const messageBuffer = new Buffer(messageSha3.replace('0x', ''), 'hex');
const messagePersonalHash = ethUtil.hashPersonalMessage(messageBuffer);
@ -25,7 +25,7 @@ contract('Simple', accounts => {
const publicKey = ethUtil.ecrecover(messagePersonalHash, sigParams.v, sigParams.r, sigParams.s);
const senderBuffer = ethUtil.pubToAddress(publicKey);
const sender = ethUtil.bufferToHex(senderBuffer);
assert.equal(sender, accounts[0]);
assert.equal(sender, accounts[0].toLowerCase());
});
});
});

@ -6,7 +6,7 @@ const Simple = artifacts.require('./Simple.sol');
contract('Simple', accounts => {
// Crash truffle if the account loaded in the options string isn't found here.
it('should load with expected account', () => {
assert(accounts[0] === '0xa4860cedd5143bd63f347cab453bf91425f8404f');
assert(accounts[0] === '0xA4860CEDd5143Bd63F347CaB453Bf91425f8404f');
});
// Generate some coverage so the script doesn't exit(1) because there are no events

@ -21,12 +21,6 @@ contract('TotallyPure', accounts => {
assert.equal(value.toNumber(), 5);
});
it('calls an imported, inherited constant function', async () => {
const instance = await TotallyPure.deployed();
const value = await instance.isConstant();
assert.equal(value.toNumber(), 99);
});
it('overrides an imported, inherited abstract pure function', async () => {
const instance = await TotallyPure.deployed();
const value = await instance.bePure(4, 5);
@ -39,18 +33,6 @@ contract('TotallyPure', accounts => {
assert.equal(value.toNumber(), 99);
});
it('overrides an imported, inherited abstract constant function', async () => {
const instance = await TotallyPure.deployed();
const value = await instance.beConstant();
assert.equal(value.toNumber(), 99);
});
it('overrides an imported, inherited abstract constant function, and uses .call()', async () => {
const instance = await TotallyPure.deployed();
const value = await instance.beConstant.call();
assert.equal(value.toNumber(), 99);
});
it('calls a pure method implemented in an inherited class', async() => {
const instance = await TotallyPure.deployed();
const value = await instance.inheritedPure(4, 5);
@ -63,12 +45,6 @@ contract('TotallyPure', accounts => {
assert.equal(value.toNumber(), 5);
});
it('calls a constant method implemented in an inherited class', async () => {
const instance = await TotallyPure.deployed();
const value = await instance.inheritedConstant();
assert.equal(value.toNumber(), 5);
});
it('calls a view method whose modifiers span lines', async () => {
const instance = await TotallyPure.deployed();
const value = await instance.multiline(5, 7)

@ -9,14 +9,17 @@ contract('Wallet', accounts => {
const walletB = await Wallet.new();
await walletA.sendTransaction({
value: web3.toBigNumber(100), from: accounts[0],
value: web3.utils.toBN(100), from: accounts[0],
});
console.log('transaction done')
await walletA.sendPayment(50, walletB.address, {
from: accounts[0],
});
console.log('transaction done')
await walletA.transferPayment(50, walletB.address, {
from: accounts[0],
});
console.log('transaction done')
const balance = await walletB.getBalance();
assert.equal(balance.toNumber(), 100);
});

@ -13,26 +13,26 @@ describe('comments', () => {
it('should cover functions even if comments are present immediately after the opening {', () => {
const contract = util.getCode('comments/postFunctionDeclarationComment.sol');
const info = getInstrumentedVersion(contract, filePath);
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should cover lines even if comments are present', () => {
const contract = util.getCode('comments/postLineComment.sol');
const info = getInstrumentedVersion(contract, filePath);
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
assert.deepEqual([6, 5], info.runnableLines);
util.report(output.errors);
});
it('should cover contracts even if comments are present', () => {
const contract = util.getCode('comments/postContractComment.sol');
const info = getInstrumentedVersion(contract, filePath);
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should cover if statements even if comments are present immediately after opening { ', () => {
const contract = util.getCode('comments/postIfStatementComment.sol');
const info = getInstrumentedVersion(contract, filePath);
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
});

@ -14,7 +14,6 @@ describe.skip('conditional statements', () => {
it('should cover a conditional that reaches the consequent (same-line)', done => {
const contract = util.getCode('conditional/sameline-consequent.sol');
const info = getInstrumentedVersion(contract, filePath);
console.log(info.contract)
const coverage = new CoverageMap();
coverage.addContract(info, filePath);

@ -16,14 +16,14 @@ describe('generic expressions', () => {
it('should compile after instrumenting a single binary expression', () => {
const contract = util.getCode('expressions/single-binary-expression.sol');
const info = getInstrumentedVersion(contract, filePath);
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should compile after instrumenting a new expression', () => {
const contract = util.getCode('expressions/new-expression.sol');
const info = getInstrumentedVersion(contract, filePath);
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
});

@ -20,49 +20,56 @@ describe('function declarations', () => {
it('should compile after instrumenting an ordinary function declaration', () => {
const contract = util.getCode('function/function.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should compile after instrumenting an abstract function declaration', () => {
const contract = util.getCode('function/abstract.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should compile after instrumenting a function declaration with an empty body', () => {
const contract = util.getCode('function/empty-body.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should compile after instrumenting lots of declarations in row', () => {
const contract = util.getCode('function/multiple.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should compile after instrumenting a new->constructor-->method chain', () => {
const contract = util.getCode('function/chainable-new.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should compile after instrumenting a constructor call that chains to a method call', () => {
const contract = util.getCode('function/chainable.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should compile after instrumenting a function with calldata keyword', () => {
const contract = util.getCode('function/calldata.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
it('should compile after instrumenting a constructor-->method-->value chain', () => {
const contract = util.getCode('function/chainable-value.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
@ -89,6 +96,29 @@ describe('function declarations', () => {
}).catch(done);
});
it('should cover a modifier used on a function', done => {
const contract = util.getCode('function/modifier.sol');
const info = getInstrumentedVersion(contract, filePath);
const coverage = new CoverageMap();
coverage.addContract(info, filePath);
vm.execute(info.contract, 'a', [0]).then(events => {
const mapping = coverage.generate(events, pathPrefix);
assert.deepEqual(mapping[filePath].l, {
5: 1, 6: 1, 9: 1,
});
assert.deepEqual(mapping[filePath].b, {});
assert.deepEqual(mapping[filePath].s, {
1: 1
});
assert.deepEqual(mapping[filePath].f, {
1: 1,
2: 1,
});
done();
}).catch(done);
});
it('should cover a constructor that uses the `constructor` keyword', done => {
const contract = util.getCode('function/constructor-keyword.sol');
const info = getInstrumentedVersion(contract, filePath);
@ -102,7 +132,7 @@ describe('function declarations', () => {
});
assert.deepEqual(mapping[filePath].b, {});
assert.deepEqual(mapping[filePath].s, {
1: 1,
1: 1, 2: 1
});
assert.deepEqual(mapping[filePath].f, {
1: 1,

@ -208,4 +208,27 @@ describe('if, else, and else if statements', () => {
done();
}).catch(done);
});
it('should cover if-elseif-else statements that are at the same depth as each other', done => {
const contract = util.getCode('if/if-elseif-else.sol');
const info = getInstrumentedVersion(contract, filePath);
const coverage = new CoverageMap();
coverage.addContract(info, filePath);
vm.execute(info.contract, 'a', [2, 3, 3]).then(events => {
const mapping = coverage.generate(events, pathPrefix);
assert.deepEqual(mapping[filePath].l, {
5: 1, 6: 0, 8: 1, 10: 0, 13: 1, 14: 0, 16: 1, 18: 0,
});
assert.deepEqual(mapping[filePath].b, {
1: [0, 1], 2: [1, 0], 3: [0, 1], 4: [1, 0]
});
assert.deepEqual(mapping[filePath].s, {
1: 1, 2: 0, 3: 1, 4: 1, 5: 0, 6: 1, 7: 0, 8: 1, 9: 1, 10: 0,
});
assert.deepEqual(mapping[filePath].f, {
1: 1,
});
done();
}).catch(done);
});
});

@ -8,14 +8,7 @@ describe('return statements', () => {
it('should compile after instrumenting function that returns true', () => {
const contract = util.getCode('return/return.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = solc.compile(info.contract, 1);
util.report(output.errors);
});
it('should compile after instrumenting function that returns without specifying val (null)', () => {
const contract = util.getCode('return/return-null.sol');
const info = getInstrumentedVersion(contract, 'test.sol');
const output = solc.compile(info.contract, 1);
const output = JSON.parse(solc.compile(util.codeToCompilerInput(info.contract)));
util.report(output.errors);
});
});

@ -0,0 +1,18 @@
pragma solidity ^0.5.0;
contract Test {
function a() public {
assembly {
function power(base, exponent) -> result {
switch exponent
case 0 { result := 1 }
case 1 { result := base }
default {
result := power(mul(base, base), div(exponent, 2))
switch mod(exponent, 2)
case 1 { result := mul(base, result) }
}
}
}
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.13;
pragma solidity ^0.5.0;
contract Test {
function a(bool test){
function a(bool test) public {
assert(test);
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.13;
pragma solidity ^0.5.0;
contract Test {
function a(bool a, bool b, bool c){
function a(bool a, bool b, bool c) public {
require(a &&
b &&
c);

@ -1,8 +1,8 @@
pragma solidity ^0.4.17;
pragma solidity ^0.5.0;
library CLibrary {
uint constant x = 1;
function a() public constant returns (uint) {
function a() public view returns (uint) {
return x;
}
}

@ -1,4 +1,4 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Empty {
}

@ -1,4 +1,4 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Events {
uint x = 0;
@ -7,14 +7,14 @@ contract Events {
event LogEventOne( uint x, address y);
event LogEventTwo( uint x, address y);
function test(uint val) {
function test(uint val) public {
// Assert / Require events
require(true);
// Contract Events
LogEventOne(100, msg.sender);
emit LogEventOne(100, msg.sender);
x = x + val;
LogEventTwo(200, msg.sender);
emit LogEventTwo(200, msg.sender);
// Branch events
if (true) {
@ -24,7 +24,7 @@ contract Events {
}
}
function getX() returns (uint){
function getX() public view returns (uint){
return x;
}
}

@ -2,11 +2,11 @@
// Block gas limit is: 0x47e7c4
// Should throw out of gas on unmodified truffle
// Should pass solcover truffle
pragma solidity ^0.4.2;
pragma solidity ^0.5.0;
contract Expensive {
mapping (uint => address) map;
function Expensive(){
constructor() public {
for(uint i = 0; i < 1000; i++ ){
map[i] = address(this);
}

@ -1,4 +1,4 @@
pragma solidity ^0.4.21;
pragma solidity ^0.5.0;
interface Face {
function stare(uint a, uint b) external;

@ -1,20 +1,25 @@
pragma solidity ^0.4.4;
pragma solidity ^0.5.0;
contract Migrations {
address public owner;
uint public last_completed_migration;
modifier restricted() {if (msg.sender == owner) _;}
modifier restricted() {
if (msg.sender == owner) { _; }
}
function Migrations() {
constructor() public {
owner = msg.sender;
}
function setCompleted(uint completed) restricted {
function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}
function upgrade(address new_address) restricted {
function upgrade(address new_address) public restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}
}

@ -2,10 +2,10 @@
* This contract contains a single function that is accessed using method.call
* With an unpatched testrpc it should not generate any events.
*/
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract OnlyCall {
function addTwo(uint val) returns (uint){
function addTwo(uint val) public pure returns (uint){
val = val + 2;
return val;
}

@ -1,6 +1,6 @@
pragma solidity ^0.4.4;
pragma solidity ^0.5.0;
contract Owned {
function Owned() { owner = msg.sender; }
constructor() public { owner = msg.sender; }
address owner;
}

@ -1,9 +1,9 @@
pragma solidity ^0.4.4;
pragma solidity ^0.5.0;
import "./Owned.sol";
contract Proxy is Owned {
function isOwner() returns (bool) {
function isOwner() public returns (bool) {
if (msg.sender == owner) {
return true;
} else {

@ -1,4 +1,4 @@
pragma solidity ^0.4.21;
pragma solidity ^0.5.0;
contract PureView {
@ -8,7 +8,6 @@ contract PureView {
// Abstract functions to inherit from an uninstrumented, imported file.
function bePure(uint a, uint b) public pure returns (uint);
function beView() public view returns (uint);
function beConstant() public constant returns (uint);
function inheritedPure(uint a, uint b) public pure returns(uint){
return a + b;
@ -17,8 +16,4 @@ contract PureView {
function inheritedView() public view returns (uint){
return notpureview;
}
function inheritedConstant() public constant returns (uint){
return notpureview;
}
}

@ -1,13 +1,13 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.3;
contract Simple {
uint x = 0;
function test(uint val) {
function test(uint val) public {
x = x + val;
}
function getX() returns (uint){
function getX() public view returns (uint){
return x;
}
}

@ -1,14 +1,14 @@
// This contract should throw a parse error in instrumentSolidity.js
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract SimpleError {
uint x = 0;
function test(uint val) {
function test(uint val) public {
x = x + val // <-- no semi-colon
}
function getX() returns (uint){
function getX() public returns (uint){
return x;
}
}

@ -1,4 +1,4 @@
pragma solidity ^0.4.21;
pragma solidity ^0.5.0;
import "./../assets/Face.sol";
import "./../assets/PureView.sol";
@ -7,7 +7,7 @@ import "./../assets/CLibrary.sol";
contract TotallyPure is PureView, Face {
uint onehundred = 99;
function usesThem() {
function usesThem() public view {
uint y = isPure(1,2);
uint z = isView();
}
@ -20,11 +20,7 @@ contract TotallyPure is PureView, Face {
return notpureview;
}
function isConstant() public constant returns (uint){
return onehundred;
}
function beConstant() public constant returns (uint){
function isConstant() public view returns (uint){
return onehundred;
}
@ -36,7 +32,7 @@ contract TotallyPure is PureView, Face {
return onehundred;
}
function usesLibrary() public constant returns (uint){
function usesLibrary() public view returns (uint){
return CLibrary.a();
}

@ -1,25 +1,25 @@
pragma solidity ^0.4.4;
pragma solidity ^0.5.0;
contract Wallet {
event Deposit(address indexed _sender, uint _value);
function transferPayment(uint payment, address recipient){
function transferPayment(uint payment, address payable recipient) public {
recipient.transfer(payment);
}
function sendPayment(uint payment, address recipient){
function sendPayment(uint payment, address payable recipient) public {
if (!recipient.send(payment))
revert();
}
function getBalance() constant returns(uint){
function getBalance() public view returns(uint){
return address(this).balance;
}
function() payable
function() external payable
{
if (msg.value > 0)
Deposit(msg.sender, msg.value);
emit Deposit(msg.sender, msg.value);
}
}

@ -1,8 +1,8 @@
pragma solidity ^0.4.13;
pragma solidity ^0.5.0;
contract Test {//Comment immediately after contract declaration
function a(bool test){
var x = 1;
var y = 2;
function a(bool test) public {
uint8 x = 1;
uint8 y = 2;
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.13;
pragma solidity ^0.5.0;
contract Test {
function a(bool test){//Comment immediately after function declaration
function a(bool test) public {//Comment immediately after function declaration
}
function b(bool test){var x=1;}//Comment immediately after function closes
function b(bool test) public {uint8 x=1;}//Comment immediately after function closes
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.13;
pragma solidity ^0.5.0;
contract Test {
function a(bool x){
function a(bool x) public {
int y;
if (x){//Comment straight after {
y = 1;

@ -1,8 +1,8 @@
pragma solidity ^0.4.13;
pragma solidity ^0.5.0;
contract Test {
function a(bool test){
var x = 1;//Comment immediately after line
var y = 2;
function a(bool test) public {
uint x = 1;//Comment immediately after line
uint y = 2;
}
}

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
var x = false;
var y = false;
function a() public {
bool x = false;
bool y = false;
bool z = (x) ? false : true;
}
}

@ -1,10 +1,10 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
var x = false;
var y = false;
var z = false;
function a() public {
bool x = false;
bool y = false;
bool z = false;
z = (x) ? false : true;
}
}

@ -1,4 +1,4 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
struct Vote {
@ -7,7 +7,7 @@ contract Test {
Vote vote;
function a(){
function a() public {
var isYay = false;
vote.voted[msg.sender] = isYay ? 1 : 2;
}

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
var x = false;
var y = false;
function a() public {
bool x = false;
bool y = false;
(x)
? y = false
: y = false;

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
var x = true;
var y = false;
function a() public {
bool x = true;
bool y = false;
(x)
? y = false
: y = false;

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
var x = false;
var y = false;
function a() public {
bool x = false;
bool y = false;
(x) ? y = false : y = false;
}
}

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
var x = true;
var y = false;
function a() public {
bool x = true;
bool y = false;
(x) ? y = false : y = false;
}
}

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
var x = false;
var y = false;
var z = (x) ? false : true;
function a() public {
bool x = false;
bool y = false;
bool z = (x) ? false : true;
}
}

@ -1,12 +1,12 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
function a(uint x) public {
new Test2(x);
}
}
contract Test2 {
function Test2(uint x) {
constructor(uint x) public {
x+1;
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
function a(uint x) public {
x+1;
}
}

@ -1,5 +1,5 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function abstractFn(uint x);
function abstractFn(uint x) public;
}

@ -0,0 +1,7 @@
pragma solidity ^0.5.0;
contract Test {
function a(string calldata x) external {
x;
}
}

@ -1,12 +1,12 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
// This is for a test that verifies solcover can instrument a
// chained constructor/method call invoked by the new operator.
contract Chainable {
function chainWith(uint y, uint z) {}
function chainWith(uint y, uint z) public {}
}
contract Test {
function a(){
function a() public {
new Chainable().chainWith(3, 4);
}
}

@ -1,12 +1,12 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
// This is for a test that verifies solcover can instrument a
// another kind of long CallExpression chain
contract Test {
function paySomeone(address x, address y) payable {
function paySomeone(address x, address y) public payable {
}
function a() payable {
Test(0x00).paySomeone.value(msg.value)(0x00, 0x00);
function a() public payable {
Test(0x00).paySomeone.value(msg.value)(0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000);
}
}

@ -1,11 +1,11 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
// This is for a test that verifies solcover can instrument a
// chained constructor/method call.
contract Test {
function chainWith(uint y, uint z) {}
function chainWith(uint y, uint z) public {}
function a(){
function a() public {
Test(0x00).chainWith(3, 4);
}
}

@ -1,13 +1,13 @@
pragma solidity ^0.4.23;
pragma solidity ^0.5.0;
contract UsesConstructor {
uint z;
constructor(){
constructor() public {
z = 5;
}
}
contract Test {
function a(){
function a() public {
new UsesConstructor();
}
}

@ -1,5 +1,5 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function emptyBody(uint x){}
function emptyBody(uint x) public {}
}

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
// This test verifies that an invoked function gets logged as a statement
contract Test {
function loggedAsStatement(uint x) {}
function a(){
function loggedAsStatement(uint x) public {}
function a() public {
loggedAsStatement(5);
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(bytes32 x) {
function a(bytes32 x) public {
x;
}
}

@ -0,0 +1,11 @@
pragma solidity ^0.5.0;
contract Test {
modifier b(){
uint y;
_;
}
function a(uint x) b public {
x;
}
}

@ -1,15 +1,15 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function f1(bytes32 x) {
function f1(uint x) public {
x = 1;
}
function f2(uint x){ x = 2; }
function f2(uint x) public { x = 2; }
address a;
function f3(uint y){
function f3(uint y) public {
y = 1;
}
}

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
function a(uint x) public {
if (x == 1) {
throw;
revert();
} else {
x = 5;
}

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
function a(uint x) public {
if (x == 1) {
throw;
revert();
} else
x = 5;
}

@ -0,0 +1,21 @@
pragma solidity ^0.5.0;
contract Test {
function a(uint x,uint y, uint z) public {
if (x == y) {
z = 0;
} else if (x == 2) {
z = 1;
} else {
z = 2;
}
if (x == y) {
z = 0;
} else if (x == 2) {
z = 1;
} else {
z = 2;
}
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
function a(uint x) public {
if (x == 1)
x = 2;
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
function a(uint x) public {
if (x == 1) x = 2;
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
function a(uint x) public {
if (x == 1) {
x = 3;
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
function a(uint x) public {
if (x == 1) {x = 3;}
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x,uint y, uint z) {
function a(uint x,uint y, uint z) public {
if (x==y){
} else if (x==2){
if (y==z){

@ -1,8 +1,8 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
for(var x = 0; x < 10; x++)
sha3(x);
function a() public {
for(uint x = 0; x < 10; x++)
keccak256(abi.encodePacked(x));
}
}

@ -1,9 +1,9 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
for(var x = 0; x < 10; x++){
sha3(x);
function a() public {
for(uint x = 0; x < 10; x++){
keccak256(abi.encodePacked(x));
}
}
}

@ -1,8 +1,8 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
var t = true;
function a() public {
bool t = true;
while(t)
t = false;
}

@ -1,8 +1,8 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a() {
var t = true;
function a() public {
bool t = true;
while(t){
t = false;
}

@ -1,7 +0,0 @@
pragma solidity ^0.4.3;
contract Test {
function a(uint x) returns (bool) {
return;
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) returns (bool) {
function a(uint x) public returns (bool) {
return true;
}
}

@ -1,4 +1,4 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
address a;

@ -1,8 +1,8 @@
pragma solidity ^0.4.23;
pragma solidity ^0.5.0;
contract Test {
event TestEvent();
function a(uint x) {
function a(uint x) public {
emit TestEvent();
}
}

@ -1,8 +1,8 @@
pragma solidity ^0.4.23;
pragma solidity ^0.5.0;
contract Test {
event TestEvent();
function a(uint x) {
function a(uint x) public {
if(true)
emit TestEvent();
}

@ -1,3 +1,3 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {}

@ -1,4 +1,4 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
}

@ -1,4 +1,4 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
@ -6,17 +6,17 @@ contract Test {
uint a,
uint b,
uint c,
bytes32 d)
bytes32 d) public
{
var x = a;
uint x = a;
}
function Test(){
constructor() public {
multiline(
1,
2,
3,
sha3('hello')
keccak256(abi.encodePacked('hello'))
);
}
}

@ -1,11 +1,11 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(bytes32 x) {
function a(bytes32 x) public {
x;
}
function b (){
a(sha3(0));
function b () public {
a(keccak256(abi.encodePacked(uint256(0))));
}
}

@ -1,8 +1,6 @@
pragma experimental "v0.5.0";
contract Test {
struct Fn {
function(bytes32) internal constant returns(bool) startConditions;
function(bytes32) internal constant endConditions;
function(bytes32) internal view returns(bool) startConditions;
function(bytes32) internal view endConditions;
}
}

@ -15,7 +15,7 @@ contract Test {
using Boolean for Boolean.Value;
Boolean.Value b;
function not() returns (bool) {
function not() public returns (bool) {
return b.flip();
}
}

@ -1,8 +1,8 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
sha3(x);
sha3(0);
function a(uint x) public {
keccak256(abi.encodePacked(x));
keccak256(abi.encodePacked(uint256(0)));
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
function a(uint x) public {
if (x>1){
x=3;
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function a(uint x) {
sha3(x);
function a(uint x) public {
keccak256(abi.encodePacked(x));
}
}

@ -1,13 +1,13 @@
pragma solidity ^0.4.3;
pragma solidity ^0.5.0;
contract Test {
function returnTuple() returns (uint x, uint y) {
function returnTuple() public returns (uint x, uint y) {
return (10, 20);
}
function a() {
var (a, b) = (10, 20);
var (x, y) = returnTuple();
function a() public {
(uint a, uint b) = (10, 20);
(a, b) = returnTuple();
}
}

@ -0,0 +1 @@
Subproject commit 0dded493a03623c93845c2d58634c229862ab54a

@ -1,58 +0,0 @@
pragma solidity ^0.4.4;
import './PullPayment.sol';
import './Killable.sol';
/*
* Bounty
*
* This bounty will pay out to a researcher if they break invariant logic of the contract.
*/
contract Bounty is PullPayment, Killable {
Target target;
bool public claimed;
mapping(address => address) public researchers;
event TargetCreated(address createdAddress);
function() payable {
if (claimed) throw;
}
function createTarget() returns(Target) {
target = Target(deployContract());
researchers[target] = msg.sender;
TargetCreated(target);
return target;
}
function deployContract() internal returns(address);
function checkInvariant() returns(bool){
return target.checkInvariant();
}
function claim(Target target) {
address researcher = researchers[target];
if (researcher == 0) throw;
// Check Target contract invariants
if (target.checkInvariant()) {
throw;
}
asyncSend(researcher, this.balance);
claimed = true;
}
}
/*
* Target
*
* Your main contract should inherit from this class and implement the checkInvariant method. This is a function that should check everything your contract assumes to be true all the time. If this function returns false, it means your contract was broken in some way and is in an inconsistent state. This is what security researchers will try to acomplish when trying to get the bounty.
*/
contract Target {
function checkInvariant() returns(bool);
}

@ -1,30 +0,0 @@
pragma solidity ^0.4.0;
import './Ownable.sol';
/*
* Claimable
*
* Extension for the Ownable contract, where the ownership needs to be claimed. This allows the new owner to accept the transfer.
*/
contract Claimable is Ownable {
address public pendingOwner;
modifier onlyPendingOwner() {
if (msg.sender == pendingOwner)
_;
}
function transfer(address newOwner) onlyOwner {
pendingOwner = newOwner;
}
function claimOwnership() onlyPendingOwner {
owner = pendingOwner;
pendingOwner = 0x0;
}
}

@ -1,73 +0,0 @@
pragma solidity ^0.4.4;
import './Shareable.sol';
/*
* DayLimit
*
* inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable)
* on a particular resource per calendar day. is multiowned to allow the limit to be altered. resource that method
* uses is specified in the modifier.
*/
contract DayLimit is Shareable {
// FIELDS
uint public dailyLimit;
uint public spentToday;
uint public lastDay;
// MODIFIERS
// simple modifier for daily limit.
modifier limitedDaily(uint _value) {
if (underLimit(_value))
_;
}
// CONSTRUCTOR
// stores initial daily limit and records the present day's index.
function DayLimit(uint _limit) {
dailyLimit = _limit;
lastDay = today();
}
// METHODS
// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external {
dailyLimit = _newLimit;
}
// resets the amount already spent today. needs many of the owners to confirm
function resetSpentToday() onlymanyowners(sha3(msg.data)) external {
spentToday = 0;
}
// INTERNAL METHODS
// checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and
// returns true. otherwise just returns false.
function underLimit(uint _value) internal onlyOwner returns (bool) {
// reset the spend limit if we're on a different day to last time.
if (today() > lastDay) {
spentToday = 0;
lastDay = today();
}
// check to see if there's enough left - if so, subtract and return true.
// overflow protection // dailyLimit check
if (spentToday + _value >= spentToday && spentToday + _value <= dailyLimit) {
spentToday += _value;
return true;
}
return false;
}
// determines today's index.
function today() private constant returns (uint) {
return now / 1 days;
}
}

@ -1,15 +0,0 @@
pragma solidity ^0.4.4;
import "./Ownable.sol";
/*
* Killable
* Base contract that can be killed by owner. All funds in contract will be sent to the owner.
*/
contract Killable is Ownable {
function kill() onlyOwner {
selfdestruct(owner);
}
}

@ -1,18 +0,0 @@
pragma solidity ^0.4.4;
contract LimitBalance {
uint public limit;
function LimitBalance(uint _limit) {
limit = _limit;
}
modifier limitedPayable() {
if (this.balance > limit) {
throw;
}
_;
}
}

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

Loading…
Cancel
Save