-
Notifications
You must be signed in to change notification settings - Fork 174
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #542 from protofire/gc-small-strings
GC: small strings check
- Loading branch information
Showing
8 changed files
with
530 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--- | ||
warning: "This is a dynamically generated file. Do not edit manually." | ||
layout: "default" | ||
title: "gas-small-strings | Solhint" | ||
--- | ||
|
||
# gas-small-strings | ||
![Category Badge](https://img.shields.io/badge/-Gas%20Consumption%20Rules-informational) | ||
![Default Severity Badge warn](https://img.shields.io/badge/Default%20Severity-warn-yellow) | ||
|
||
## Description | ||
Keep strings smaller than 32 bytes | ||
|
||
## Options | ||
This rule accepts a string option of rule severity. Must be one of "error", "warn", "off". Default to warn. | ||
|
||
### Example Config | ||
```json | ||
{ | ||
"rules": { | ||
"gas-small-strings": "warn" | ||
} | ||
} | ||
``` | ||
|
||
### Notes | ||
- [source](https://www.rareskills.io/post/gas-optimization?postId=c9db474a-ff97-4fa3-a51d-fe13ccb8fe3b#viewer-ck1vq) of the rule initiciative | ||
|
||
## Examples | ||
This rule does not have examples. | ||
|
||
## Version | ||
This rule is introduced in the latest version. | ||
|
||
## Resources | ||
- [Rule source](https://github.com/protofire/solhint/tree/master/lib/rules/gas-consumption/gas-small-strings.js) | ||
- [Document source](https://github.com/protofire/solhint/tree/master/docs/rules/gas-consumption/gas-small-strings.md) | ||
- [Test cases](https://github.com/protofire/solhint/tree/master/test/rules/gas-consumption/gas-small-strings.js) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
const BaseChecker = require('../base-checker') | ||
|
||
const ruleId = 'gas-small-strings' | ||
const meta = { | ||
type: 'gas-consumption', | ||
|
||
docs: { | ||
description: 'Keep strings smaller than 32 bytes', | ||
category: 'Gas Consumption Rules', | ||
notes: [ | ||
{ | ||
note: '[source](https://www.rareskills.io/post/gas-optimization?postId=c9db474a-ff97-4fa3-a51d-fe13ccb8fe3b#viewer-ck1vq) of the rule initiciative', | ||
}, | ||
], | ||
}, | ||
|
||
isDefault: false, | ||
recommended: false, | ||
defaultSetup: 'warn', | ||
|
||
schema: null, | ||
} | ||
|
||
class GasSmallStrings extends BaseChecker { | ||
constructor(reporter) { | ||
super(reporter, ruleId, meta) | ||
} | ||
|
||
FileLevelConstant(node) { | ||
let isLarger = false | ||
|
||
if (node.typeName.name === 'string') { | ||
isLarger = this.isStringLargerThan32Bytes(node.initialValue.value) | ||
} | ||
|
||
if (isLarger) { | ||
this.reportError(node) | ||
} | ||
} | ||
|
||
VariableDeclaration(node) { | ||
let isLarger = false | ||
|
||
if (node.parent.type === 'StateVariableDeclaration' && node.typeName.name === 'string') { | ||
isLarger = this.isStringLargerThan32Bytes(node.expression.value) | ||
} | ||
|
||
if ( | ||
node.parent.type === 'StateVariableDeclaration' && | ||
node.typeName.type === 'ArrayTypeName' && | ||
node.typeName.baseTypeName.name === 'string' | ||
) { | ||
let isComponentLarger = false | ||
const componentsSize = node.expression.components.length | ||
|
||
let i = 0 | ||
while (i < componentsSize) { | ||
isComponentLarger = this.isStringLargerThan32Bytes(node.expression.components[i].value) | ||
i++ | ||
if (isComponentLarger) { | ||
// update the result | ||
isLarger = true | ||
// if there is one larger this loop can be exited | ||
i = componentsSize + 1 | ||
} | ||
} | ||
} | ||
|
||
if (node.parent.type === 'VariableDeclarationStatement' && node.typeName.name === 'string') { | ||
isLarger = this.isStringLargerThan32Bytes(node.parent.initialValue.value) | ||
} | ||
|
||
if (isLarger) { | ||
this.reportError(node) | ||
} | ||
} | ||
|
||
BinaryOperation(node) { | ||
let isLarger = false | ||
|
||
if (node.right.type === 'StringLiteral') { | ||
isLarger = this.isStringLargerThan32Bytes(node.right.value) | ||
} | ||
|
||
if (isLarger) { | ||
this.reportError(node) | ||
} | ||
} | ||
|
||
FunctionCall(node) { | ||
let isLarger = false | ||
let isArgumentLarger = false | ||
const argumentsSize = node.arguments.length | ||
|
||
let i = 0 | ||
while (i < argumentsSize) { | ||
if (node.arguments[i].type === 'StringLiteral') { | ||
isArgumentLarger = this.isStringLargerThan32Bytes(node.arguments[i].value) | ||
if (isArgumentLarger) { | ||
// update the result | ||
isLarger = true | ||
// if there is one larger this loop can be exited | ||
i = argumentsSize | ||
} | ||
} | ||
i++ | ||
} | ||
|
||
if (isLarger) { | ||
this.reportError(node) | ||
} | ||
} | ||
|
||
ReturnStatement(node) { | ||
let isLarger = false | ||
let isComponentLarger = false | ||
const componentsSize = node.expression.components.length | ||
|
||
let i = 0 | ||
while (i < componentsSize) { | ||
if ( | ||
node.expression.components[i].type === 'StringLiteral' | ||
// && | ||
// node.parent.parent.returnParameters[i].typeName.name === 'string' | ||
) { | ||
isComponentLarger = this.isStringLargerThan32Bytes(node.expression.components[i].value) | ||
if (isComponentLarger) { | ||
// update the result | ||
isLarger = true | ||
// if there is one larger this loop can be exited | ||
i = componentsSize | ||
} | ||
} | ||
i++ | ||
} | ||
|
||
if (isLarger) { | ||
this.reportError(node) | ||
} | ||
} | ||
|
||
isStringLargerThan32Bytes(inputString) { | ||
if (inputString.startsWith('0x') && inputString.length === 42) { | ||
// Check if the input is a valid Ethereum address | ||
return false | ||
} else { | ||
// Convert the string to Buffer and get its byte length | ||
const byteLength = Buffer.from(inputString, 'utf8').length | ||
// Check if the byte length is greater than 32 | ||
return byteLength > 32 | ||
} | ||
} | ||
|
||
reportError(node) { | ||
this.error(node, 'GC: String exceeds 32 bytes') | ||
} | ||
} | ||
|
||
module.exports = GasSmallStrings |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,12 @@ | ||
const GasMultitoken1155 = require('./gas-multitoken1155') | ||
const GasSmallStrings = require('./gas-small-strings') | ||
// const GasIndexedEvents = require('./gas-indexed-events') | ||
|
||
// module.exports = function checkers(reporter, config, tokens) { | ||
module.exports = function checkers(reporter, config) { | ||
return [new GasMultitoken1155(reporter, config)] | ||
return [ | ||
new GasMultitoken1155(reporter, config), | ||
new GasSmallStrings(reporter, config), | ||
// new GasIndexedEvents(reporter, config), | ||
] | ||
} |
Oops, something went wrong.