Skip to content

Commit e7c1a17

Browse files
Merge pull request #691 from protofire/fix-gas-incrementBy1-rule
fix rule to support backward expression
2 parents ec78e8b + bb2913c commit e7c1a17

File tree

3 files changed

+47
-78
lines changed

3 files changed

+47
-78
lines changed

docs/rules/gas-consumption/gas-increment-by-one.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ This rule accepts a string option for rule severity. Must be one of "error", "wa
2424
```
2525

2626
### Notes
27-
- This rule only works for expressions like this: [ j = j + 1 ] but will fail if the code is written like this: [ j = 1 + j ]
2827
- [source 1](https://coinsbench.com/comprehensive-guide-tips-and-tricks-for-gas-optimization-in-solidity-5380db734404) of the rule initiative (Incrementing/Decrementing By 1)
2928
- [source 2](https://www.rareskills.io/post/gas-optimization?postId=c9db474a-ff97-4fa3-a51d-fe13ccb8fe3b#viewer-8rekj) of the rule initiative
3029

lib/rules/gas-consumption/gas-increment-by-one.js

Lines changed: 34 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ const meta = {
99
description: 'Suggest increments by one, like this ++i instead of other type',
1010
category: 'Gas Consumption Rules',
1111
notes: [
12-
{
13-
note: 'This rule only works for expressions like this: [ j = j + 1 ] but will fail if the code is written like this: [ j = 1 + j ]',
14-
},
1512
{
1613
note: '[source 1](https://coinsbench.com/comprehensive-guide-tips-and-tricks-for-gas-optimization-in-solidity-5380db734404) of the rule initiative (Incrementing/Decrementing By 1)',
1714
},
@@ -57,25 +54,43 @@ class GasIncrementByOne extends BaseChecker {
5754
}
5855

5956
isVariableIncrementOrDecrement(left, right, operator) {
60-
const leftVar = this.extractVariableName(left)
61-
let rightValue
57+
const leftVar = this.extractVariableName(left)
6258

63-
// assignment and operation
64-
if (operator === '+=' || operator === '-=') {
65-
rightValue = right.type === 'NumberLiteral' && parseInt(right.number) === 1
66-
return { result: leftVar && rightValue, varName: leftVar }
67-
}
68-
// regular assignment
69-
else if (operator === '=') {
70-
const rightVar = this.extractVariableName(right.left)
71-
rightValue =
72-
right.right && right.right.type === 'NumberLiteral' && parseInt(right.right.number) === 1
73-
return { result: leftVar === rightVar && rightValue, varName: leftVar }
74-
}
59+
// assignment and operation
60+
if (operator === '+=' || operator === '-=') {
61+
const rightIsOne = right.type === 'NumberLiteral' && parseInt(right.number) === 1
62+
return { result: leftVar && rightIsOne, varName: leftVar }
63+
}
64+
65+
// regular assignment
66+
if (operator === '=') {
67+
if (right.type !== 'BinaryOperation') return { result: false }
68+
69+
const rightLeftVar = this.extractVariableName(right.left)
70+
const rightRightVar = this.extractVariableName(right.right)
7571

76-
return false
72+
const isLeftOne = right.left.type === 'NumberLiteral' && parseInt(right.left.number) === 1
73+
const isRightOne = right.right.type === 'NumberLiteral' && parseInt(right.right.number) === 1
74+
75+
const isIncrement =
76+
right.operator === '+' &&
77+
(
78+
(leftVar === rightLeftVar && isRightOne) ||
79+
(leftVar === rightRightVar && isLeftOne)
80+
)
81+
82+
const isDecrement =
83+
right.operator === '-' &&
84+
leftVar === rightLeftVar &&
85+
isRightOne
86+
87+
return { result: isIncrement || isDecrement, varName: leftVar }
7788
}
7889

90+
return { result: false }
91+
}
92+
93+
7994
extractVariableName(node) {
8095
if (node.type === 'Identifier') {
8196
return node.name
@@ -96,53 +111,4 @@ class GasIncrementByOne extends BaseChecker {
96111
}
97112
}
98113

99-
module.exports = GasIncrementByOne
100-
101-
// SourceUnit(node) {
102-
// this.findVariableUpdates(node)
103-
// }
104-
105-
// findVariableUpdates(node) {
106-
// if (node === null || typeof node !== 'object') {
107-
// return
108-
// }
109-
110-
// // Check for assignment in a function body
111-
// if (node.type === 'FunctionDefinition') {
112-
// this.findVariableUpdates(node.body)
113-
// return
114-
// }
115-
116-
// if (node.type === 'ExpressionStatement' && node.expression.type === 'BinaryOperation') {
117-
// const expr = node.expression
118-
// if (expr.operator === '=' || expr.operator === '+=' || expr.operator === '-=') {
119-
// if (this.isVariableIncrementOrDecrement(expr.left, expr.right, expr.operator)) {
120-
// this.reportError(node, this.extractVariableName(expr.left))
121-
// }
122-
// }
123-
// }
124-
125-
// Object.values(node).forEach((value) => {
126-
// if (typeof value === 'object') {
127-
// this.findVariableUpdates(value)
128-
// }
129-
// })
130-
// }
131-
132-
// isVariableIncrementOrDecrement(left, right, operator) {
133-
// const leftVar = this.extractVariableName(left)
134-
// let rightVar, rightValue
135-
136-
// if (operator === '+=' || operator === '-=') {
137-
// // For compound assignment, the operation is directly on the variable
138-
// rightValue = right.type === 'NumberLiteral' && parseInt(right.number) === 1
139-
// return leftVar && rightValue
140-
// } else if (operator === '=') {
141-
// rightVar = this.extractVariableName(right.left)
142-
// rightValue =
143-
// right.right && right.right.type === 'NumberLiteral' && parseInt(right.right.number) === 1
144-
// return leftVar === rightVar && rightValue
145-
// }
146-
147-
// return false
148-
// }
114+
module.exports = GasIncrementByOne

test/rules/gas-consumption/gas-increment-by-one.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,19 @@ const RAISE_ERRORS = [
4040
statement: 'anotherVar -= 1;',
4141
varName: 'anotherVar',
4242
},
43-
// {
44-
// statement:
45-
// 'complexMapping[user].balances[asset] = complexMapping[user].balances[asset] + 1 + someFunctionCall();',
46-
// varName: 'complexMapping',
47-
// },
48-
// {
49-
// statement: 'anotherMapping[user][token].count = anotherMapping[user][token].count - 1 + 5;',
50-
// varName: 'anotherMapping',
51-
// },
43+
{
44+
statement: 'complexMapping[user].balances[asset] = complexMapping[user].balances[asset] + 1;',
45+
varName: 'complexMapping',
46+
},
47+
{
48+
statement: 'amount = 1 + amount;',
49+
varName: 'amount',
50+
},
51+
{
52+
statement:
53+
'complexMappingBackward[user].balances[asset] = 1 + complexMappingBackward[user].balances[asset];',
54+
varName: 'complexMappingBackward',
55+
},
5256
]
5357

5458
const NOT_RAISE_ERRORS = [

0 commit comments

Comments
 (0)