Commit f9f03813 authored by Michael Fröwis's avatar Michael Fröwis Committed by chriseth

Static Analysis: Builtin Functions, Super keyword

parent b2a5eafa
...@@ -9,7 +9,7 @@ function checksEffectsInteraction () { ...@@ -9,7 +9,7 @@ function checksEffectsInteraction () {
this.contracts = [] this.contracts = []
checksEffectsInteraction.prototype.visit = new AbstractAst().builder( checksEffectsInteraction.prototype.visit = new AbstractAst().builder(
(node) => common.isInteraction(node) || common.isEffect(node) || (common.isLocalCall(node) && !common.isBuiltinFunctionCall(node)), (node) => common.isInteraction(node) || common.isEffect(node) || common.isLocalCallGraphRelevantNode(node),
this.contracts this.contracts
) )
} }
...@@ -64,7 +64,7 @@ function isPotentialVulnerableFunction (func, context) { ...@@ -64,7 +64,7 @@ function isPotentialVulnerableFunction (func, context) {
} }
function isLocalCallWithStateChange (node, context) { function isLocalCallWithStateChange (node, context) {
if (common.isLocalCall(node)) { if (common.isLocalCallGraphRelevantNode(node)) {
var func = callGraph.resolveCallGraphSymbol(context.cg, common.getFullQualifiedFunctionCallIdent(context.currentContract.node, node)) var func = callGraph.resolveCallGraphSymbol(context.cg, common.getFullQualifiedFunctionCallIdent(context.currentContract.node, node))
return !func || (func && func.node.changesState) return !func || (func && func.node.changesState)
} }
......
...@@ -9,7 +9,7 @@ function constantFunctions () { ...@@ -9,7 +9,7 @@ function constantFunctions () {
this.contracts = [] this.contracts = []
constantFunctions.prototype.visit = new AbstractAst().builder( constantFunctions.prototype.visit = new AbstractAst().builder(
(node) => common.isLowLevelCall(node) || common.isExternalDirectCall(node) || common.isEffect(node) || (common.isLocalCall(node) && !common.isBuiltinFunctionCall(node)) || common.isInlineAssembly(node), (node) => common.isLowLevelCall(node) || common.isExternalDirectCall(node) || common.isEffect(node) || common.isLocalCallGraphRelevantNode(node) || common.isInlineAssembly(node),
this.contracts this.contracts
) )
} }
......
...@@ -19,7 +19,7 @@ function buildLocalFuncCallGraphInternal (functions, nodeFilter, extractNodeIden ...@@ -19,7 +19,7 @@ function buildLocalFuncCallGraphInternal (functions, nodeFilter, extractNodeIden
function buildGlobalFuncCallGraph (contracts) { function buildGlobalFuncCallGraph (contracts) {
var callGraph = {} var callGraph = {}
contracts.forEach((contract) => { contracts.forEach((contract) => {
var filterNodes = (node) => { return common.isLocalCall(node) || common.isThisLocalCall(node) || common.isExternalDirectCall(node) } var filterNodes = (node) => { return common.isLocalCallGraphRelevantNode(node) || common.isExternalDirectCall(node) }
var getNodeIdent = (node) => { return common.getFullQualifiedFunctionCallIdent(contract.node, node) } var getNodeIdent = (node) => { return common.getFullQualifiedFunctionCallIdent(contract.node, node) }
var getFunDefIdent = (funcDef) => { return common.getFullQuallyfiedFuncDefinitionIdent(contract.node, funcDef.node, funcDef.parameters) } var getFunDefIdent = (funcDef) => { return common.getFullQuallyfiedFuncDefinitionIdent(contract.node, funcDef.node, funcDef.parameters) }
...@@ -36,7 +36,7 @@ function analyseCallGraph (cg, funcName, context, nodeCheck) { ...@@ -36,7 +36,7 @@ function analyseCallGraph (cg, funcName, context, nodeCheck) {
function analyseCallGraphInternal (cg, funcName, context, combinator, nodeCheck, visited) { function analyseCallGraphInternal (cg, funcName, context, combinator, nodeCheck, visited) {
var current = resolveCallGraphSymbol(cg, funcName) var current = resolveCallGraphSymbol(cg, funcName)
if (!current || visited[funcName]) return true if (current === undefined || visited[funcName] === true) return true
visited[funcName] = true visited[funcName] = true
return combinator(current.node.relevantNodes.reduce((acc, val) => combinator(acc, nodeCheck(val, context)), false), return combinator(current.node.relevantNodes.reduce((acc, val) => combinator(acc, nodeCheck(val, context)), false),
...@@ -48,33 +48,31 @@ function resolveCallGraphSymbol (cg, funcName) { ...@@ -48,33 +48,31 @@ function resolveCallGraphSymbol (cg, funcName) {
} }
function resolveCallGraphSymbolInternal (cg, funcName, silent) { function resolveCallGraphSymbolInternal (cg, funcName, silent) {
var current = null var current
if (funcName.includes('.')) { if (funcName.includes('.')) {
var parts = funcName.split('.') var parts = funcName.split('.')
var contractPart = parts[0] var contractPart = parts[0]
var functionPart = parts[1] var functionPart = parts[1]
var currentContract = cg[contractPart] var currentContract = cg[contractPart]
if (currentContract) { if (!(currentContract === undefined)) {
current = currentContract.functions[funcName] current = currentContract.functions[funcName]
// resolve inheritance hierarchy // resolve inheritance hierarchy
if (!current) { if (current === undefined) {
// resolve inheritance lookup in linearized fashion // resolve inheritance lookup in linearized fashion
var inheritsFromNames = currentContract.contract.inheritsFrom.reverse() var inheritsFromNames = currentContract.contract.inheritsFrom.reverse()
for (var i = 0; i < inheritsFromNames.length; i++) { for (var i = 0; i < inheritsFromNames.length; i++) {
var res = resolveCallGraphSymbolInternal(cg, inheritsFromNames[i] + '.' + functionPart, true) var res = resolveCallGraphSymbolInternal(cg, inheritsFromNames[i] + '.' + functionPart, true)
if (res) return res if (!(res === undefined)) return res
} }
} }
} else {
if (!silent) console.log(`static analysis functionCallGraph.js: Contract ${contractPart} not found in function call graph.`)
} }
} else { } else {
throw new Error('functionCallGraph.js: function does not have full qualified name.') throw new Error('functionCallGraph.js: function does not have full qualified name.')
} }
if (!current) { if (current === undefined && !silent) console.log(`static analysis functionCallGraph.js: ${funcName} not found in function call graph.`)
if (!silent) console.log(`static analysis functionCallGraph.js: ${funcName} not found in function call graph.`)
return null
} else {
return current return current
}
} }
module.exports = { module.exports = {
......
var name = 'gas costs: ' var name = 'Gas Costs: '
var desc = 'warn if the gas requiremets of functions are too high' var desc = 'Warn if the gas requiremets of functions are too high.'
var categories = require('./categories') var categories = require('./categories')
function gasCosts () { function gasCosts () {
......
...@@ -77,8 +77,8 @@ function getType (node) { ...@@ -77,8 +77,8 @@ function getType (node) {
// #################### Complex Getters // #################### Complex Getters
function getFunctionCallType (func) { function getFunctionCallType (func) {
if (!(isExternalDirectCall(func) || isThisLocalCall(func) || isLocalCall(func))) throw new Error('staticAnalysisCommon.js: not function call Node') if (!(isExternalDirectCall(func) || isThisLocalCall(func) || isSuperLocalCall(func) || isLocalCall(func))) throw new Error('staticAnalysisCommon.js: not function call Node')
if (isExternalDirectCall(func) || isThisLocalCall(func)) return func.attributes.type if (isExternalDirectCall(func) || isThisLocalCall(func) || isSuperLocalCall(func)) return func.attributes.type
return findFirstSubNodeLTR(func, exactMatch(nodeTypes.IDENTIFIER)).attributes.type return findFirstSubNodeLTR(func, exactMatch(nodeTypes.IDENTIFIER)).attributes.type
} }
...@@ -97,6 +97,11 @@ function getThisLocalCallName (localCallNode) { ...@@ -97,6 +97,11 @@ function getThisLocalCallName (localCallNode) {
return localCallNode.attributes.value return localCallNode.attributes.value
} }
function getSuperLocalCallName (localCallNode) {
if (!isSuperLocalCall(localCallNode)) throw new Error('staticAnalysisCommon.js: not an super local call Node')
return localCallNode.attributes.member_name
}
function getExternalDirectCallContractName (extDirectCall) { function getExternalDirectCallContractName (extDirectCall) {
if (!isExternalDirectCall(extDirectCall)) throw new Error('staticAnalysisCommon.js: not an external direct call Node') if (!isExternalDirectCall(extDirectCall)) throw new Error('staticAnalysisCommon.js: not an external direct call Node')
return extDirectCall.children[0].attributes.type.replace(new RegExp(basicRegex.CONTRACTTYPE), '') return extDirectCall.children[0].attributes.type.replace(new RegExp(basicRegex.CONTRACTTYPE), '')
...@@ -149,6 +154,7 @@ function getFunctionCallTypeParameterType (func) { ...@@ -149,6 +154,7 @@ function getFunctionCallTypeParameterType (func) {
function getFullQualifiedFunctionCallIdent (contract, func) { function getFullQualifiedFunctionCallIdent (contract, func) {
if (isLocalCall(func)) return getContractName(contract) + '.' + getLocalCallName(func) + '(' + getFunctionCallTypeParameterType(func) + ')' if (isLocalCall(func)) return getContractName(contract) + '.' + getLocalCallName(func) + '(' + getFunctionCallTypeParameterType(func) + ')'
else if (isThisLocalCall(func)) return getThisLocalCallContractName(func) + '.' + getThisLocalCallName(func) + '(' + getFunctionCallTypeParameterType(func) + ')' else if (isThisLocalCall(func)) return getThisLocalCallContractName(func) + '.' + getThisLocalCallName(func) + '(' + getFunctionCallTypeParameterType(func) + ')'
else if (isSuperLocalCall(func)) return getContractName(contract) + '.' + getSuperLocalCallName(func) + '(' + getFunctionCallTypeParameterType(func) + ')'
else if (isExternalDirectCall(func)) return getExternalDirectCallContractName(func) + '.' + getExternalDirectCallMemberName(func) + '(' + getFunctionCallTypeParameterType(func) + ')' else if (isExternalDirectCall(func)) return getExternalDirectCallContractName(func) + '.' + getExternalDirectCallMemberName(func) + '(' + getFunctionCallTypeParameterType(func) + ')'
else throw new Error('staticAnalysisCommon.js: Can not get function name form non function call node') else throw new Error('staticAnalysisCommon.js: Can not get function name form non function call node')
} }
...@@ -193,6 +199,10 @@ function isInlineAssembly (node) { ...@@ -193,6 +199,10 @@ function isInlineAssembly (node) {
// #################### Complex Node Identification // #################### Complex Node Identification
function isLocalCallGraphRelevantNode (node) {
return ((isLocalCall(node) || isSuperLocalCall(node)) && !isBuiltinFunctionCall(node))
}
function isBuiltinFunctionCall (node) { function isBuiltinFunctionCall (node) {
return isLocalCall(node) && builtinFunctions[getLocalCallName(node) + '(' + getFunctionCallTypeParameterType(node) + ')'] === true return isLocalCall(node) && builtinFunctions[getLocalCallName(node) + '(' + getFunctionCallTypeParameterType(node) + ')'] === true
} }
...@@ -238,7 +248,7 @@ function isCallToNonConstLocalFunction (node) { ...@@ -238,7 +248,7 @@ function isCallToNonConstLocalFunction (node) {
} }
function isExternalDirectCall (node) { function isExternalDirectCall (node) {
return isMemberAccess(node, basicRegex.EXTERNALFUNCTIONTYPE, undefined, basicRegex.CONTRACTTYPE, undefined) && !isThisLocalCall(node) return isMemberAccess(node, basicRegex.EXTERNALFUNCTIONTYPE, undefined, basicRegex.CONTRACTTYPE, undefined) && !isThisLocalCall(node) && !isSuperLocalCall(node)
} }
function isNowAccess (node) { function isNowAccess (node) {
...@@ -259,6 +269,10 @@ function isThisLocalCall (node) { ...@@ -259,6 +269,10 @@ function isThisLocalCall (node) {
return isMemberAccess(node, basicRegex.FUNCTIONTYPE, exactMatch('this'), basicRegex.CONTRACTTYPE, undefined) return isMemberAccess(node, basicRegex.FUNCTIONTYPE, exactMatch('this'), basicRegex.CONTRACTTYPE, undefined)
} }
function isSuperLocalCall (node) {
return isMemberAccess(node, basicRegex.FUNCTIONTYPE, exactMatch('super'), basicRegex.CONTRACTTYPE, undefined)
}
function isLocalCall (node) { function isLocalCall (node) {
return nodeType(node, exactMatch(nodeTypes.FUNCTIONCALL)) && return nodeType(node, exactMatch(nodeTypes.FUNCTIONCALL)) &&
minNrOfChildren(node, 1) && minNrOfChildren(node, 1) &&
...@@ -377,6 +391,7 @@ module.exports = { ...@@ -377,6 +391,7 @@ module.exports = {
getType: getType, getType: getType,
// #################### Complex Getters // #################### Complex Getters
getThisLocalCallName: getThisLocalCallName, getThisLocalCallName: getThisLocalCallName,
getSuperLocalCallName: getSuperLocalCallName,
getFunctionCallType: getFunctionCallType, getFunctionCallType: getFunctionCallType,
getContractName: getContractName, getContractName: getContractName,
getEffectedVariableName: getEffectedVariableName, getEffectedVariableName: getEffectedVariableName,
...@@ -400,6 +415,8 @@ module.exports = { ...@@ -400,6 +415,8 @@ module.exports = {
isBlockTimestampAccess: isBlockTimestampAccess, isBlockTimestampAccess: isBlockTimestampAccess,
isBlockBlockHashAccess: isBlockBlockHashAccess, isBlockBlockHashAccess: isBlockBlockHashAccess,
isThisLocalCall: isThisLocalCall, isThisLocalCall: isThisLocalCall,
isSuperLocalCall: isSuperLocalCall,
isLocalCallGraphRelevantNode: isLocalCallGraphRelevantNode,
isLocalCall: isLocalCall, isLocalCall: isLocalCall,
isWriteOnStateVariable: isWriteOnStateVariable, isWriteOnStateVariable: isWriteOnStateVariable,
isStateVariable: isStateVariable, isStateVariable: isStateVariable,
......
var name = 'this on local: ' var name = 'this on local calls: '
var desc = 'invocation of local functions via this' var desc = 'Invocation of local functions via this'
var categories = require('./categories') var categories = require('./categories')
var common = require('./staticAnalysisCommon') var common = require('./staticAnalysisCommon')
......
var name = 'tx origin: ' var name = 'tx.origin: '
var desc = 'warn if tx.origin is used' var desc = 'Warn if tx.origin is used'
var categories = require('./categories') var categories = require('./categories')
function txOrigin () { function txOrigin () {
...@@ -20,7 +20,7 @@ txOrigin.prototype.visit = function (node) { ...@@ -20,7 +20,7 @@ txOrigin.prototype.visit = function (node) {
txOrigin.prototype.report = function () { txOrigin.prototype.report = function () {
return this.txOriginNodes.map(function (item, i) { return this.txOriginNodes.map(function (item, i) {
return { return {
warning: `use of tx.origin: "tx.origin" is useful only in very exceptional cases.<br /> warning: `Use of tx.origin: "tx.origin" is useful only in very exceptional cases.<br />
If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.`, If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.`,
location: item.src location: item.src
} }
......
...@@ -394,6 +394,80 @@ test('staticAnalysisCommon.getThisLocalCallName', function (t) { ...@@ -394,6 +394,80 @@ test('staticAnalysisCommon.getThisLocalCallName', function (t) {
t.throws(() => common.getThisLocalCallName(localCall), undefined, 'throws on other nodes') t.throws(() => common.getThisLocalCallName(localCall), undefined, 'throws on other nodes')
}) })
test('staticAnalysisCommon.getSuperLocalCallName', function (t) {
t.plan(4)
var superLocal = {
'attributes': {
'member_name': 'duper',
'type': 'function ()'
},
'children': [
{
'attributes': {
'type': 'contract super a',
'value': 'super'
},
'name': 'Identifier'
}
],
'name': 'MemberAccess'
}
var localCall = {
'attributes': {
'type': 'tuple()',
'type_conversion': false
},
'children': [
{
'attributes': {
'type': 'function (struct Ballot.Voter storage pointer)',
'value': 'bli'
},
'id': 37,
'name': 'Identifier',
'src': '540:3:0'
},
{
'attributes': {
'type': 'struct Ballot.Voter storage pointer',
'value': 'x'
},
'id': 38,
'name': 'Identifier',
'src': '544:1:0'
}
],
'id': 39,
'name': 'FunctionCall',
'src': '540:6:0'
}
var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } }
var externalDirect = {
attributes: {
member_name: 'info',
type: 'function () payable external returns (uint256)'
},
children: [
{
attributes: {
type: 'contract InfoFeed',
value: 'f'
},
id: 30,
name: 'Identifier',
src: '405:1:0'
}
],
id: 32,
name: 'MemberAccess',
src: '405:6:0'
}
t.equal(common.getSuperLocalCallName(superLocal), 'duper', 'get local name from super local call')
t.throws(() => common.getSuperLocalCallName(thisLocalCall), 'throws on other nodes')
t.throws(() => common.getSuperLocalCallName(externalDirect), undefined, 'throws on other nodes')
t.throws(() => common.getSuperLocalCallName(localCall), undefined, 'throws on other nodes')
})
test('staticAnalysisCommon.getExternalDirectCallContractName', function (t) { test('staticAnalysisCommon.getExternalDirectCallContractName', function (t) {
t.plan(3) t.plan(3)
var localCall = { var localCall = {
...@@ -737,7 +811,6 @@ test('staticAnalysisCommon.getStateVariableDeclarationsFormContractNode', functi ...@@ -737,7 +811,6 @@ test('staticAnalysisCommon.getStateVariableDeclarationsFormContractNode', functi
'name': 'ContractDefinition' 'name': 'ContractDefinition'
} }
var res = common.getStateVariableDeclarationsFormContractNode(contract).map(common.getDeclaredVariableName) var res = common.getStateVariableDeclarationsFormContractNode(contract).map(common.getDeclaredVariableName)
t.comment(res)
t.ok(res[0] === 'chairperson', 'var 1 should be ') t.ok(res[0] === 'chairperson', 'var 1 should be ')
t.ok(res[1] === 'voters', 'var 2 should be ') t.ok(res[1] === 'voters', 'var 2 should be ')
t.ok(res[2] === 'proposals', 'var 3 should be ') t.ok(res[2] === 'proposals', 'var 3 should be ')
...@@ -1673,6 +1746,30 @@ test('staticAnalysisCommon.isThisLocalCall', function (t) { ...@@ -1673,6 +1746,30 @@ test('staticAnalysisCommon.isThisLocalCall', function (t) {
t.notOk(common.isNowAccess(node), 'is now used should not work') t.notOk(common.isNowAccess(node), 'is now used should not work')
}) })
test('staticAnalysisCommon.isSuperLocalCall', function (t) {
t.plan(4)
var node = {
'attributes': {
'member_name': 'duper',
'type': 'function ()'
},
'children': [
{
'attributes': {
'type': 'contract super a',
'value': 'super'
},
'name': 'Identifier'
}
],
'name': 'MemberAccess'
}
t.ok(common.isSuperLocalCall(node), 'is super.local_method() used should work')
t.notOk(common.isThisLocalCall(node), 'is this.local_method() used should not work')
t.notOk(common.isBlockTimestampAccess(node), 'is block.timestamp used should not work')
t.notOk(common.isNowAccess(node), 'is now used should not work')
})
test('staticAnalysisCommon.isLocalCall', function (t) { test('staticAnalysisCommon.isLocalCall', function (t) {
t.plan(5) t.plan(5)
var node1 = { var node1 = {
......
...@@ -20,7 +20,8 @@ var testFiles = [ ...@@ -20,7 +20,8 @@ var testFiles = [
'modifier2.sol', 'modifier2.sol',
'notReentrant.sol', 'notReentrant.sol',
'structReentrant.sol', 'structReentrant.sol',
'thisLocal.sol' 'thisLocal.sol',
'globals.sol'
] ]
var testFileAsts = {} var testFileAsts = {}
...@@ -47,7 +48,8 @@ test('Integration test thisLocal.js', function (t) { ...@@ -47,7 +48,8 @@ test('Integration test thisLocal.js', function (t) {
'modifier2.sol': 0, 'modifier2.sol': 0,
'notReentrant.sol': 0, 'notReentrant.sol': 0,
'structReentrant.sol': 0, 'structReentrant.sol': 0,
'thisLocal.sol': 1 'thisLocal.sol': 1,
'globals.sol': 0
} }
runModuleOnFiles(module, t, (file, report) => { runModuleOnFiles(module, t, (file, report) => {
...@@ -72,7 +74,8 @@ test('Integration test checksEffectsInteraction.js', function (t) { ...@@ -72,7 +74,8 @@ test('Integration test checksEffectsInteraction.js', function (t) {
'modifier2.sol': 1, 'modifier2.sol': 1,
'notReentrant.sol': 0, 'notReentrant.sol': 0,
'structReentrant.sol': 1, 'structReentrant.sol': 1,
'thisLocal.sol': 0 'thisLocal.sol': 0,
'globals.sol': 1
} }
runModuleOnFiles(module, t, (file, report) => { runModuleOnFiles(module, t, (file, report) => {
...@@ -80,7 +83,7 @@ test('Integration test checksEffectsInteraction.js', function (t) { ...@@ -80,7 +83,7 @@ test('Integration test checksEffectsInteraction.js', function (t) {
}) })
}) })
test('Integration test constatnFunctions.js', function (t) { test('Integration test constantFunctions.js', function (t) {
t.plan(testFiles.length) t.plan(testFiles.length)
var module = require('../../src/app/staticanalysis/modules/constantFunctions') var module = require('../../src/app/staticanalysis/modules/constantFunctions')
...@@ -97,7 +100,8 @@ test('Integration test constatnFunctions.js', function (t) { ...@@ -97,7 +100,8 @@ test('Integration test constatnFunctions.js', function (t) {
'modifier2.sol': 1, 'modifier2.sol': 1,
'notReentrant.sol': 0, 'notReentrant.sol': 0,
'structReentrant.sol': 0, 'structReentrant.sol': 0,
'thisLocal.sol': 1 'thisLocal.sol': 1,
'globals.sol': 0
} }
runModuleOnFiles(module, t, (file, report) => { runModuleOnFiles(module, t, (file, report) => {
...@@ -105,7 +109,7 @@ test('Integration test constatnFunctions.js', function (t) { ...@@ -105,7 +109,7 @@ test('Integration test constatnFunctions.js', function (t) {
}) })
}) })
test('Integration test constantFunctions.js', function (t) { test('Integration test inlineAssembly.js', function (t) {
t.plan(testFiles.length) t.plan(testFiles.length)
var module = require('../../src/app/staticanalysis/modules/inlineAssembly') var module = require('../../src/app/staticanalysis/modules/inlineAssembly')
...@@ -122,7 +126,8 @@ test('Integration test constantFunctions.js', function (t) { ...@@ -122,7 +126,8 @@ test('Integration test constantFunctions.js', function (t) {
'modifier2.sol': 0, 'modifier2.sol': 0,
'notReentrant.sol': 0, 'notReentrant.sol': 0,
'structReentrant.sol': 0, 'structReentrant.sol': 0,
'thisLocal.sol': 0 'thisLocal.sol': 0,
'globals.sol': 0
} }
runModuleOnFiles(module, t, (file, report) => { runModuleOnFiles(module, t, (file, report) => {
...@@ -147,7 +152,8 @@ test('Integration test txOrigin.js', function (t) { ...@@ -147,7 +152,8 @@ test('Integration test txOrigin.js', function (t) {
'modifier2.sol': 0, 'modifier2.sol': 0,
'notReentrant.sol': 0, 'notReentrant.sol': 0,
'structReentrant.sol': 0, 'structReentrant.sol': 0,
'thisLocal.sol': 0 'thisLocal.sol': 0,
'globals.sol': 1
} }
runModuleOnFiles(module, t, (file, report) => { runModuleOnFiles(module, t, (file, report) => {
...@@ -172,7 +178,8 @@ test('Integration test gasCosts.js', function (t) { ...@@ -172,7 +178,8 @@ test('Integration test gasCosts.js', function (t) {
'modifier2.sol': 1, 'modifier2.sol': 1,
'notReentrant.sol': 1, 'notReentrant.sol': 1,
'structReentrant.sol': 1, 'structReentrant.sol': 1,
'thisLocal.sol': 2 'thisLocal.sol': 2,
'globals.sol': 1
} }
runModuleOnFiles(module, t, (file, report) => { runModuleOnFiles(module, t, (file, report) => {
......
pragma solidity ^0.4.9;
contract bla {
uint brr;
function duper() {
brr++;
}
}
contract a is bla {
function blub() {
brr++;
}
function r () {
address a;
bytes32 hash;
uint8 v;
bytes32 r;
bytes32 s;
block.blockhash(1);
block.coinbase;
block.difficulty;
block.gaslimit;
block.number;
block.timestamp;
msg.data;
msg.gas;
msg.sender;
msg.value;
now;
tx.gasprice;
tx.origin;
//assert(now == block.timestamp);
//require(now == block.timestamp);
keccak256(a);
sha3(a);
sha256(a);
ripemd160(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();
}
}
\ No newline at end of file
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