Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
baas-ide
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
guxukai
baas-ide
Commits
5e61196a
Commit
5e61196a
authored
Mar 22, 2017
by
chriseth
Committed by
GitHub
Mar 22, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #484 from soad003/master
Static analysis, this on local calls.
parents
eca5243d
ff3db096
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
349 additions
and
3 deletions
+349
-3
list.js
src/app/staticanalysis/modules/list.js
+2
-1
staticAnalysisCommon.js
src/app/staticanalysis/modules/staticAnalysisCommon.js
+156
-0
thisLocal.js
src/app/staticanalysis/modules/thisLocal.js
+30
-0
staticAnalysisView.js
src/app/staticanalysis/staticAnalysisView.js
+1
-1
utils.js
src/app/utils.js
+11
-1
index.js
test/index.js
+1
-0
staticAnalysisCommon-test.js
test/staticanalysis/staticAnalysisCommon-test.js
+132
-0
util-test.js
test/util-test.js
+16
-0
No files found.
src/app/staticanalysis/modules/list.js
View file @
5e61196a
module
.
exports
=
[
module
.
exports
=
[
require
(
'./txOrigin'
),
require
(
'./txOrigin'
),
require
(
'./gasCosts'
)
require
(
'./gasCosts'
),
require
(
'./thisLocal'
)
]
]
src/app/staticanalysis/modules/staticAnalysisCommon.js
0 → 100644
View file @
5e61196a
'use strict'
var
utils
=
require
(
'../../utils'
)
var
nodeTypes
=
{
IDENTIFIER
:
'Identifier'
,
MEMBERACCESS
:
'MemberAccess'
,
FUNCTIONCALL
:
'FunctionCall'
}
var
basicTypes
=
{
UINT
:
'uint256'
,
BOOL
:
'bool'
,
ADDRESS
:
'address'
,
BYTES32
:
'bytes32'
}
var
basicRegex
=
{
CONTRACTTYPE
:
'^contract '
,
FUNCTIONTYPE
:
'^function
\\
('
}
var
basicFunctionTypes
=
{
SEND
:
buildFunctionSignature
([
basicTypes
.
UINT
],
[
basicTypes
.
BOOL
],
false
),
CALL
:
buildFunctionSignature
([],
[
basicTypes
.
BOOL
],
true
),
DELEGATECALL
:
buildFunctionSignature
([],
[
basicTypes
.
BOOL
],
false
)
}
var
lowLevelCallTypes
=
{
CALL
:
{
ident
:
'call'
,
type
:
basicFunctionTypes
.
CALL
},
CALLCODE
:
{
ident
:
'callcode'
,
type
:
basicFunctionTypes
.
CALL
},
DELEGATECALL
:
{
ident
:
'delegatecall'
,
type
:
basicFunctionTypes
.
DELEGATECALL
},
SEND
:
{
ident
:
'send'
,
type
:
basicFunctionTypes
.
SEND
}
}
var
specialVariables
=
{
BLOCKTIMESTAMP
:
{
obj
:
'block'
,
member
:
'timestamp'
,
type
:
basicTypes
.
UINT
},
BLOCKHASH
:
{
obj
:
'block'
,
member
:
'blockhash'
,
type
:
buildFunctionSignature
([
basicTypes
.
UINT
],
[
basicTypes
.
BYTES32
],
false
)
}
}
// usage of now special variable
function
isNowAccess
(
node
)
{
return
nodeType
(
node
,
nodeTypes
.
IDENTIFIER
)
&&
expressionType
(
node
,
basicTypes
.
UINT
)
&&
name
(
node
,
'now'
)
}
// usage of block timestamp
function
isBlockTimestampAccess
(
node
)
{
return
isSpecialVariableAccess
(
node
,
specialVariables
.
BLOCKTIMESTAMP
)
}
function
isSpecialVariableAccess
(
node
,
varType
)
{
return
isMemberAccess
(
node
,
varType
.
type
,
varType
.
obj
,
varType
.
obj
,
varType
.
member
)
}
function
isThisLocalCall
(
node
)
{
return
isMemberAccess
(
node
,
basicRegex
.
FUNCTIONTYPE
,
'this'
,
basicRegex
.
CONTRACTTYPE
,
undefined
)
}
function
isLowLevelCall
(
node
)
{
return
isLLCall
(
node
)
||
isLLCallcode
(
node
)
||
isLLDelegatecall
(
node
)
||
isLLSend
(
node
)
}
function
isLLSend
(
node
)
{
return
isMemberAccess
(
node
,
utils
.
escapeRegExp
(
lowLevelCallTypes
.
SEND
.
type
),
undefined
,
basicTypes
.
ADDRESS
,
lowLevelCallTypes
.
SEND
.
ident
)
}
function
isLLCall
(
node
)
{
return
isMemberAccess
(
node
,
utils
.
escapeRegExp
(
lowLevelCallTypes
.
CALL
.
type
),
undefined
,
basicTypes
.
ADDRESS
,
lowLevelCallTypes
.
CALL
.
ident
)
}
function
isLLCallcode
(
node
)
{
return
isMemberAccess
(
node
,
utils
.
escapeRegExp
(
lowLevelCallTypes
.
CALLCODE
.
type
),
undefined
,
basicTypes
.
ADDRESS
,
lowLevelCallTypes
.
CALLCODE
.
ident
)
}
function
isLLDelegatecall
(
node
)
{
return
isMemberAccess
(
node
,
utils
.
escapeRegExp
(
lowLevelCallTypes
.
DELEGATECALL
.
type
),
undefined
,
basicTypes
.
ADDRESS
,
lowLevelCallTypes
.
DELEGATECALL
.
ident
)
}
function
isMemberAccess
(
node
,
retType
,
accessor
,
accessorType
,
memberName
)
{
return
nodeType
(
node
,
nodeTypes
.
MEMBERACCESS
)
&&
expressionType
(
node
,
retType
)
&&
name
(
node
,
memberName
)
&&
nrOfChildren
(
node
,
1
)
&&
name
(
node
.
children
[
0
],
accessor
)
&&
expressionType
(
node
.
children
[
0
],
accessorType
)
}
function
nrOfChildren
(
node
,
nr
)
{
return
(
node
&&
(
nr
===
undefined
||
nr
===
null
))
||
(
node
&&
node
.
children
&&
node
.
children
.
length
===
nr
)
}
function
expressionType
(
node
,
typeRegex
)
{
return
(
node
&&
!
typeRegex
)
||
(
node
&&
node
.
attributes
&&
new
RegExp
(
typeRegex
).
test
(
node
.
attributes
.
type
))
}
function
nodeType
(
node
,
typeRegex
)
{
return
(
node
&&
!
typeRegex
)
||
(
node
&&
new
RegExp
(
typeRegex
).
test
(
node
.
name
))
}
function
name
(
node
,
nameRegex
)
{
var
regex
=
new
RegExp
(
nameRegex
)
return
(
node
&&
!
nameRegex
)
||
(
node
&&
node
.
attributes
&&
(
regex
.
test
(
node
.
attributes
.
value
)
||
regex
.
test
(
node
.
attributes
.
member_name
)))
}
/**
* Builds an function signature as used in the AST of the solc-json AST
* @param {Array} paramTypes
* list of parameter type names
* @param {Array} returnTypes
* list of return type names
* @return {Boolean} isPayable
* CAUTION: only needed in low level call signature or message-calls (other contracts, this.)
*/
function
buildFunctionSignature
(
paramTypes
,
returnTypes
,
isPayable
)
{
return
'function ('
+
utils
.
concatWithSeperator
(
paramTypes
,
','
)
+
')'
+
((
isPayable
)
?
' payable'
:
''
)
+
((
returnTypes
.
length
)
?
' returns ('
+
utils
.
concatWithSeperator
(
returnTypes
,
','
)
+
')'
:
''
)
}
module
.
exports
=
{
isNowAccess
:
isNowAccess
,
isBlockTimestampAccess
:
isBlockTimestampAccess
,
isThisLocalCall
:
isThisLocalCall
,
isLowLevelCall
:
isLowLevelCall
,
isLowLevelCallInst
:
isLLCall
,
isLowLevelCallcodeInst
:
isLLCallcode
,
isLowLevelDelegatecallInst
:
isLLDelegatecall
,
isLowLevelSendInst
:
isLLSend
,
nodeTypes
:
nodeTypes
,
basicTypes
:
basicTypes
,
basicFunctionTypes
:
basicFunctionTypes
,
lowLevelCallTypes
:
lowLevelCallTypes
,
specialVariables
:
specialVariables
,
helpers
:
{
nrOfChildren
:
nrOfChildren
,
expressionType
:
expressionType
,
nodeType
:
nodeType
,
name
:
name
,
buildFunctionSignature
:
buildFunctionSignature
}
}
src/app/staticanalysis/modules/thisLocal.js
0 → 100644
View file @
5e61196a
var
name
=
'this on local'
var
desc
=
'Invocation of local functions via this'
var
categories
=
require
(
'./categories'
)
var
common
=
require
(
'./staticAnalysisCommon'
)
function
thisLocal
()
{
this
.
warningNodes
=
[]
}
thisLocal
.
prototype
.
visit
=
function
(
node
)
{
if
(
common
.
isThisLocalCall
(
node
))
this
.
warningNodes
.
push
(
node
)
}
thisLocal
.
prototype
.
report
=
function
(
compilationResults
)
{
this
.
warningNowNodes
=
[]
return
this
.
warningNodes
.
map
(
function
(
item
,
i
)
{
return
{
warning
:
`Use of "this" for local functions: Never use this to call functions in the same contract, it only consumes more gas than normal local calls.`
,
location
:
item
.
src
,
more
:
'http://solidity.readthedocs.io/en/develop/control-structures.html#external-function-calls'
}
})
}
module
.
exports
=
{
name
:
name
,
description
:
desc
,
category
:
categories
.
GAS
,
Module
:
thisLocal
}
src/app/staticanalysis/staticAnalysisView.js
View file @
5e61196a
...
@@ -77,7 +77,7 @@ staticAnalysisView.prototype.run = function () {
...
@@ -77,7 +77,7 @@ staticAnalysisView.prototype.run = function () {
location
=
self
.
appAPI
.
offsetToLineColumn
(
location
,
file
)
location
=
self
.
appAPI
.
offsetToLineColumn
(
location
,
file
)
location
=
self
.
lastCompilationResult
.
sourceList
[
file
]
+
':'
+
(
location
.
start
.
line
+
1
)
+
':'
+
(
location
.
start
.
column
+
1
)
+
':'
location
=
self
.
lastCompilationResult
.
sourceList
[
file
]
+
':'
+
(
location
.
start
.
line
+
1
)
+
':'
+
(
location
.
start
.
column
+
1
)
+
':'
}
}
self
.
appAPI
.
renderWarning
(
location
+
' '
+
item
.
warning
,
warningContainer
,
{
type
:
'warning'
,
useSpan
:
true
,
isHTML
:
true
})
self
.
appAPI
.
renderWarning
(
location
+
' '
+
item
.
warning
+
((
item
.
more
)
?
'<br><a href="'
+
item
.
more
+
'" target="blank">more</a>'
:
''
)
,
warningContainer
,
{
type
:
'warning'
,
useSpan
:
true
,
isHTML
:
true
})
})
})
})
})
if
(
warningContainer
.
html
()
===
''
)
{
if
(
warningContainer
.
html
()
===
''
)
{
...
...
src/app/utils.js
View file @
5e61196a
...
@@ -14,7 +14,17 @@ function groupBy (arr, key) {
...
@@ -14,7 +14,17 @@ function groupBy (arr, key) {
},
{})
},
{})
}
}
function
concatWithSeperator
(
list
,
seperator
)
{
return
list
.
reduce
((
sum
,
item
)
=>
sum
+
item
+
seperator
,
''
).
slice
(
0
,
-
seperator
.
length
)
}
function
escapeRegExp
(
str
)
{
return
str
.
replace
(
/
[
-[
\]/
{}()+?.
\\
^$|
]
/g
,
'
\\
$&'
)
}
module
.
exports
=
{
module
.
exports
=
{
errortype
:
errortype
,
errortype
:
errortype
,
groupBy
:
groupBy
groupBy
:
groupBy
,
concatWithSeperator
:
concatWithSeperator
,
escapeRegExp
:
escapeRegExp
}
}
test/index.js
View file @
5e61196a
...
@@ -4,3 +4,4 @@ require('./compiler-test')
...
@@ -4,3 +4,4 @@ require('./compiler-test')
require
(
'./gist-handler-test'
)
require
(
'./gist-handler-test'
)
require
(
'./query-params-test'
)
require
(
'./query-params-test'
)
require
(
'./util-test'
)
require
(
'./util-test'
)
require
(
'./staticanalysis/staticAnalysisCommon-test'
)
test/staticanalysis/staticAnalysisCommon-test.js
0 → 100644
View file @
5e61196a
var
test
=
require
(
'tape'
)
var
common
=
require
(
'../../babelify-src/app/staticanalysis/modules/staticAnalysisCommon'
)
var
utils
=
require
(
'../../babelify-src/app/utils'
)
test
(
'staticAnalysisCommon.helpers.buildFunctionSignature'
,
function
(
t
)
{
t
.
plan
(
7
)
t
.
equal
(
common
.
helpers
.
buildFunctionSignature
([
common
.
basicTypes
.
UINT
,
common
.
basicTypes
.
ADDRESS
],
[
common
.
basicTypes
.
BOOL
],
false
),
'function (uint256,address) returns (bool)'
,
'two params and return value without payable'
)
t
.
equal
(
common
.
helpers
.
buildFunctionSignature
([
common
.
basicTypes
.
UINT
,
common
.
basicTypes
.
BYTES32
,
common
.
basicTypes
.
BYTES32
],
[],
true
),
'function (uint256,bytes32,bytes32) payable'
,
'three params and no return with payable'
)
t
.
equal
(
common
.
helpers
.
buildFunctionSignature
([
common
.
basicTypes
.
BOOL
],
[
common
.
basicTypes
.
BYTES32
,
common
.
basicTypes
.
ADDRESS
],
true
),
'function (bool) payable returns (bytes32,address)'
,
'one param and two return values with payable'
)
t
.
equal
(
common
.
lowLevelCallTypes
.
CALL
.
type
,
'function () payable returns (bool)'
,
'check fixed call type'
)
t
.
equal
(
common
.
lowLevelCallTypes
.
CALLCODE
.
type
,
'function () payable returns (bool)'
,
'check fixed callcode type'
)
t
.
equal
(
common
.
lowLevelCallTypes
.
SEND
.
type
,
'function (uint256) returns (bool)'
,
'check fixed send type'
)
t
.
equal
(
common
.
lowLevelCallTypes
.
DELEGATECALL
.
type
,
'function () returns (bool)'
,
'check fixed call type'
)
})
test
(
'staticAnalysisCommon.helpers.name'
,
function
(
t
)
{
t
.
plan
(
9
)
var
node
=
{
attributes
:
{
value
:
'now'
}
}
var
node2
=
{
attributes
:
{
member_name
:
'call'
}
}
t
.
ok
(
common
.
helpers
.
name
(
node
,
'now'
),
'should work for values'
)
t
.
ok
(
common
.
helpers
.
name
(
node2
,
'call'
),
'should work for member_name'
)
t
.
ok
(
common
.
helpers
.
name
(
node2
,
'.all'
),
'regex should work'
)
lowlevelAccessersCommon
(
t
,
common
.
helpers
.
name
,
node
)
})
test
(
'staticAnalysisCommon.helpers.nodeType'
,
function
(
t
)
{
t
.
plan
(
9
)
var
node
=
{
name
:
'Identifier'
,
attributes
:
{
name
:
'now'
}
}
var
node2
=
{
name
:
'FunctionCall'
,
attributes
:
{
member_name
:
'call'
}
}
t
.
ok
(
common
.
helpers
.
nodeType
(
node
,
common
.
nodeTypes
.
IDENTIFIER
),
'should work for ident'
)
t
.
ok
(
common
.
helpers
.
nodeType
(
node2
,
common
.
nodeTypes
.
FUNCTIONCALL
),
'should work for funcall'
)
t
.
ok
(
common
.
helpers
.
nodeType
(
node2
,
'^F'
),
'regex should work for funcall'
)
lowlevelAccessersCommon
(
t
,
common
.
helpers
.
nodeType
,
node
)
})
test
(
'staticAnalysisCommon.helpers.expressionType'
,
function
(
t
)
{
t
.
plan
(
9
)
var
node
=
{
name
:
'Identifier'
,
attributes
:
{
value
:
'now'
,
type
:
'uint256'
}
}
var
node2
=
{
name
:
'FunctionCall'
,
attributes
:
{
member_name
:
'call'
,
type
:
'function () payable returns (bool)'
}
}
t
.
ok
(
common
.
helpers
.
expressionType
(
node
,
common
.
basicTypes
.
UINT
),
'should work for ident'
)
t
.
ok
(
common
.
helpers
.
expressionType
(
node2
,
utils
.
escapeRegExp
(
common
.
basicFunctionTypes
.
CALL
)),
'should work for funcall'
)
t
.
ok
(
common
.
helpers
.
expressionType
(
node2
,
'^function
\\
('
),
'regex should work'
)
lowlevelAccessersCommon
(
t
,
common
.
helpers
.
expressionType
,
node
)
})
test
(
'staticAnalysisCommon.helpers.nrOfChildren'
,
function
(
t
)
{
t
.
plan
(
10
)
var
node
=
{
name
:
'Identifier'
,
children
:
[
'a'
,
'b'
],
attributes
:
{
value
:
'now'
,
type
:
'uint256'
}
}
var
node2
=
{
name
:
'FunctionCall'
,
children
:
[],
attributes
:
{
member_name
:
'call'
,
type
:
'function () payable returns (bool)'
}
}
var
node3
=
{
name
:
'FunctionCall'
,
attributes
:
{
member_name
:
'call'
,
type
:
'function () payable returns (bool)'
}
}
t
.
ok
(
common
.
helpers
.
nrOfChildren
(
node
,
2
),
'should work for 2 children'
)
t
.
notOk
(
common
.
helpers
.
nrOfChildren
(
node
,
'1+2'
),
'regex should not work'
)
t
.
ok
(
common
.
helpers
.
nrOfChildren
(
node2
,
0
),
'should work for 0 children'
)
t
.
notOk
(
common
.
helpers
.
nrOfChildren
(
node3
,
0
),
'should not work without children arr'
)
lowlevelAccessersCommon
(
t
,
common
.
helpers
.
nrOfChildren
,
node
)
})
function
lowlevelAccessersCommon
(
t
,
f
,
someNode
)
{
t
.
ok
(
f
(
someNode
),
'always ok if type is undefinded'
)
t
.
ok
(
f
(
someNode
,
undefined
),
'always ok if name is undefinded 2'
)
t
.
notOk
(
f
(
null
,
undefined
),
'false on no node'
)
t
.
notOk
(
f
(
null
,
'call'
),
'false on no node'
)
t
.
notOk
(
f
(
undefined
,
null
),
'false on no node'
)
t
.
notOk
(
f
(),
'false on no params'
)
}
test
(
'staticAnalysisCommon.helpers.isLowLevelCall'
,
function
(
t
)
{
t
.
plan
(
4
)
var
sendAst
=
{
name
:
'MemberAccess'
,
children
:
[{
attributes
:
{
value
:
'd'
,
type
:
'address'
}}],
attributes
:
{
value
:
'send'
,
type
:
'function (uint256) returns (bool)'
}
}
var
callAst
=
{
name
:
'MemberAccess'
,
children
:
[{
attributes
:
{
value
:
'f'
,
type
:
'address'
}}],
attributes
:
{
member_name
:
'call'
,
type
:
'function () payable returns (bool)'
}
}
var
callcodeAst
=
{
name
:
'MemberAccess'
,
children
:
[{
attributes
:
{
value
:
'f'
,
type
:
'address'
}}],
attributes
:
{
member_name
:
'callcode'
,
type
:
'function () payable returns (bool)'
}
}
var
delegatecallAst
=
{
name
:
'MemberAccess'
,
children
:
[{
attributes
:
{
value
:
'g'
,
type
:
'address'
}}],
attributes
:
{
member_name
:
'delegatecall'
,
type
:
'function () returns (bool)'
}
}
t
.
ok
(
common
.
isLowLevelSendInst
(
sendAst
)
&&
common
.
isLowLevelCall
(
sendAst
),
'send is llc should work'
)
t
.
ok
(
common
.
isLowLevelCallInst
(
callAst
)
&&
common
.
isLowLevelCall
(
callAst
),
'call is llc should work'
)
t
.
ok
(
common
.
isLowLevelCallcodeInst
(
callcodeAst
)
&&
common
.
isLowLevelCall
(
callcodeAst
),
'callcode is llc should work'
)
t
.
ok
(
common
.
isLowLevelDelegatecallInst
(
delegatecallAst
)
&&
common
.
isLowLevelCall
(
delegatecallAst
),
'delegatecall is llc should work'
)
})
test
(
'staticAnalysisCommon.helpers.isThisLocalCall'
,
function
(
t
)
{
t
.
plan
(
3
)
var
node
=
{
name
:
'MemberAccess'
,
children
:
[{
attributes
:
{
value
:
'this'
,
type
:
'contract test'
}}],
attributes
:
{
value
:
'b'
,
type
:
'function (bytes32,address) returns (bool)'
}
}
t
.
ok
(
common
.
isThisLocalCall
(
node
),
'is this.local_method() used should 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.helpers.isBlockTimestampAccess'
,
function
(
t
)
{
t
.
plan
(
3
)
var
node
=
{
name
:
'MemberAccess'
,
children
:
[{
attributes
:
{
value
:
'block'
,
type
:
'block'
}}],
attributes
:
{
value
:
'timestamp'
,
type
:
'uint256'
}
}
t
.
notOk
(
common
.
isThisLocalCall
(
node
),
'is this.local_method() used should not work'
)
t
.
ok
(
common
.
isBlockTimestampAccess
(
node
),
'is block.timestamp used should work'
)
t
.
notOk
(
common
.
isNowAccess
(
node
),
'is now used should not work'
)
})
test
(
'staticAnalysisCommon.helpers.isNowAccess'
,
function
(
t
)
{
t
.
plan
(
3
)
var
node
=
{
name
:
'Identifier'
,
attributes
:
{
value
:
'now'
,
type
:
'uint256'
}
}
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
.
ok
(
common
.
isNowAccess
(
node
),
'is now used should work'
)
})
test/util-test.js
View file @
5e61196a
...
@@ -24,3 +24,19 @@ test('util.groupBy on valid input', function (t) {
...
@@ -24,3 +24,19 @@ test('util.groupBy on valid input', function (t) {
t
.
deepEqual
(
result
,
expectedResult
)
t
.
deepEqual
(
result
,
expectedResult
)
})
})
test
(
'util.concatWithSeperator valid output'
,
function
(
t
)
{
t
.
plan
(
4
)
t
.
notEqual
(
utils
.
concatWithSeperator
([
'a'
,
'b'
,
'c'
],
','
),
'a, b, c'
,
'Concat with comma should not produce spaces'
)
t
.
equal
(
utils
.
concatWithSeperator
([
'a'
,
'b'
,
'c'
],
','
),
'a,b,c'
,
'Concat with comma should not produce spaces'
)
t
.
equal
(
utils
.
concatWithSeperator
([
'a'
,
'b'
,
'c'
],
', '
),
'a, b, c'
,
'Concat with comma space should not produce trailing comma'
)
t
.
equal
(
utils
.
concatWithSeperator
([
'a'
,
'b'
,
'c'
],
'+'
),
'a+b+c'
,
'Concat with plus'
)
})
test
(
'util.escapeRegExp'
,
function
(
t
)
{
t
.
plan
(
3
)
var
original
=
'function (uint256) returns (bool)'
t
.
equal
(
utils
.
escapeRegExp
(
'abcd'
),
'abcd'
,
'String with no regex'
)
t
.
equal
(
utils
.
escapeRegExp
(
original
),
'function
\\
(uint256
\\
) returns
\\
(bool
\\
)'
,
'function string with regex'
)
t
.
ok
(
new
RegExp
(
utils
.
escapeRegExp
(
original
)).
test
(
original
),
'should still test for original string'
)
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment