-
Notifications
You must be signed in to change notification settings - Fork 179
/
Copy pathcheck-send-result.js
84 lines (71 loc) · 2.27 KB
/
check-send-result.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
const BaseChecker = require('../base-checker')
const TreeTraversing = require('../../common/tree-traversing')
const traversing = new TreeTraversing()
const ruleId = 'check-send-result'
const meta = {
type: 'security',
docs: {
description: `Check result of "send" call.`,
category: 'Security Rules',
examples: {
good: [
{
description: 'result of "send" call checked with if statement',
code: 'if(x.send(55)) {}',
},
{
description: 'result of "send" call checked within a require',
code: 'require(payable(walletAddress).send(moneyAmount), "Failed to send moneyAmount");',
},
],
bad: [
{
description: 'result of "send" call ignored',
code: 'x.send(55);',
},
],
},
notes: [
{
note: 'Rule will rise false positive on this: `bool success = walletAddress.send(amount); require(success, "Failed to send"); ` ',
},
{ note: 'Rule will skip ERC777 "send" function to prevent false positives' },
],
},
isDefault: false,
recommended: true,
defaultSetup: 'warn',
schema: null,
}
class CheckSendResultChecker extends BaseChecker {
constructor(reporter) {
super(reporter, ruleId, meta)
}
MemberAccess(node) {
this.validateSend(node)
}
validateSend(node) {
if (node.memberName === 'send') {
if (this.isNotErc777Token(node)) {
const hasVarDeclaration = traversing.statementNotContains(node, 'VariableDeclaration')
const hasIfStatement = traversing.statementNotContains(node, 'IfStatement')
const hasRequire = traversing.someParent(node, this.isRequire)
const hasAssert = traversing.someParent(node, this.isAssert)
if (!hasIfStatement && !hasVarDeclaration && !hasRequire && !hasAssert) {
this.error(node, 'Check result of "send" call')
}
}
}
}
isNotErc777Token(node) {
const isErc777 = node.parent.type === 'FunctionCall' && node.parent.arguments.length >= 3
return !isErc777
}
isRequire(node) {
return node.type === 'FunctionCall' && node.expression.name === 'require'
}
isAssert(node) {
return node.type === 'FunctionCall' && node.expression.name === 'assert'
}
}
module.exports = CheckSendResultChecker