forked from Picodes/4naly3er
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dravee giving back some love (Picodes#43)
* Removing dups * Adding solc versions * Compilation fixes * Giving back some love * This was better before * More flexibility --------- Co-authored-by: Picodes <41673773+Picodes@users.noreply.github.com>
- Loading branch information
1 parent
098627c
commit 8a9d1eb
Showing
150 changed files
with
3,142 additions
and
102 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,12 @@ | ||
import { IssueTypes, RegexIssue } from '../../types'; | ||
|
||
const issue: RegexIssue = { | ||
regexOrAST: 'Regex', | ||
type: IssueTypes.GAS, | ||
title: 'Use ERC721A instead ERC721', | ||
description: | ||
"ERC721A standard, ERC721A is an improvement standard for ERC721 tokens. It was proposed by the Azuki team and used for developing their NFT collection. Compared with ERC721, ERC721A is a more gas-efficient standard to mint a lot of of NFTs simultaneously. It allows developers to mint multiple NFTs at the same gas price. This has been a great improvement due to Ethereum's sky-rocketing gas fee.\n\n Reference: https://nextrope.com/erc721-vs-erc721a-2/", | ||
regex: /import.+openz.+ERC721\.sol/gi, | ||
}; | ||
|
||
export default issue; |
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,12 @@ | ||
import { IssueTypes, RegexIssue } from '../../types'; | ||
|
||
const issue: RegexIssue = { | ||
regexOrAST: 'Regex', | ||
type: IssueTypes.GAS, | ||
title: "Don't use `_msgSender()` if not supporting EIP-2771", | ||
description: | ||
"Use `msg.sender` if the code does not implement [EIP-2771 trusted forwarder](https://eips.ethereum.org/EIPS/eip-2771) support", | ||
regex: /_msgSender\(\)/gi, | ||
}; | ||
|
||
export default issue; |
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,12 @@ | ||
import { IssueTypes, RegexIssue } from '../../types'; | ||
|
||
const issue: RegexIssue = { | ||
regexOrAST: 'Regex', | ||
type: IssueTypes.GAS, | ||
title: '`a = a + b` is more gas effective than `a += b` for state variables (excluding arrays and mappings)', | ||
description: | ||
'This saves **16 gas per instance.**', | ||
regex: /\+=/gi, | ||
}; | ||
|
||
export default issue; |
This file was deleted.
Oops, something went wrong.
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,12 @@ | ||
import { IssueTypes, RegexIssue } from '../../types'; | ||
|
||
const issue: RegexIssue = { | ||
regexOrAST: 'Regex', | ||
type: IssueTypes.GAS, | ||
title: 'Comparing to a Boolean constant', | ||
description: | ||
'Comparing to a constant (`true` or `false`) is a bit more expensive than directly checking the returned boolean value.\n\nConsider using `if(directValue)` instead of `if(directValue == true)` and `if(!directValue)` instead of `if(directValue == false)`', | ||
regex: /(== true)|(== false)/gi, // storage variable | part of mapping | struct | ||
}; | ||
|
||
export default issue; |
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,12 @@ | ||
import { IssueTypes, RegexIssue } from '../../types'; | ||
|
||
const issue: RegexIssue = { | ||
regexOrAST: 'Regex', | ||
type: IssueTypes.GAS, | ||
title: 'Avoid contract existence checks by using low level calls', | ||
description: | ||
"Prior to 0.8.10 the compiler inserted extra code, including `EXTCODESIZE` (**100 gas**), to check for contract existence for external function calls. In more recent solidity versions, the compiler will not insert these checks if the external call has a return value. Similar behavior can be achieved in earlier versions by using low-level calls, since low level calls never check for contract existence", | ||
regex: /\.delegatecall|\.balanceOf\(|\.recover\(/gi, | ||
}; | ||
|
||
export default issue; |
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,52 @@ | ||
import { findAll } from 'solidity-ast/utils'; | ||
import { ASTIssue, InputType, Instance, IssueTypes, RegexIssue } from '../../types'; | ||
import { instanceFromSRC } from '../../utils'; | ||
import util from 'util'; | ||
|
||
const issue: ASTIssue = { | ||
regexOrAST: 'AST', | ||
type: IssueTypes.GAS, | ||
title: 'Stack variable used as a cheaper cache for a state variable is only used once', | ||
description: | ||
"If the variable is only accessed once, it's cheaper to use the state variable directly that one time, and save the **3 gas** the extra stack assignment would spend", | ||
detector: (files: InputType): Instance[] => { | ||
let instances: Instance[] = []; | ||
for (const file of files) { | ||
if (!!file.ast) { | ||
for (const a of findAll('FunctionDefinition', file.ast)) { | ||
for (const b of findAll('VariableDeclarationStatement', a)) { | ||
if ( | ||
b.declarations && | ||
b.declarations[0] && | ||
b.declarations[0].name && | ||
b.initialValue && | ||
b.initialValue['name'] | ||
) { | ||
let isStateVar = 0; | ||
for (const c of findAll('VariableDeclaration', file.ast)) { | ||
if ((c.stateVariable || c.storageLocation == "storage") && b.initialValue['name'] + '' == c.name) { | ||
isStateVar++; | ||
} | ||
} | ||
if (isStateVar > 0) { | ||
let accessCounter = 0; | ||
for (const c of findAll('Identifier', a)) { | ||
if (c.name == b.declarations[0].name) { | ||
accessCounter++; | ||
// console.log("accessCounter: ",accessCounter); | ||
} | ||
} | ||
if (accessCounter == 1) { | ||
instances.push(instanceFromSRC(file, b.src)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return instances; | ||
}, | ||
}; | ||
|
||
export default issue; |
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,64 @@ | ||
import { ContractDefinition } from 'solidity-ast'; | ||
import { findAll } from 'solidity-ast/utils'; | ||
import { ASTIssue, InputType, Instance, IssueTypes, RegexIssue } from '../../types'; | ||
import { instanceFromSRC, topLevelFiles, getStorageVariable } from '../../utils'; | ||
|
||
const issue: ASTIssue = { | ||
regexOrAST: 'AST', | ||
type: IssueTypes.GAS, | ||
title: 'State variables only set in the constructor should be declared `immutable`', | ||
description: | ||
'Variables only set in the constructor and never edited afterwards should be marked as immutable, as it would avoid the expensive storage-writing operation in the constructor (around **20 000 gas** per variable) and replace the expensive storage-reading operations (around **2100 gas** per reading) to a less expensive value reading (**3 gas**)', | ||
detector: (files: InputType): Instance[] => { | ||
let instances: Instance[] = []; | ||
|
||
for (const file of files) { | ||
if (!!file.ast) { | ||
let storageVariables; | ||
let assignSrcs = new Map<string, string>(); | ||
for (const contract of findAll('ContractDefinition', file.ast)) { | ||
/** Build list of storage variables */ | ||
storageVariables = getStorageVariable(contract); | ||
// Counting assigments in a mapping? | ||
for (const func of findAll('FunctionDefinition', contract)) { | ||
if (func.kind === 'constructor') { | ||
for (const assign of findAll('Assignment', func)) { | ||
if ( | ||
assign.leftHandSide.nodeType === 'Identifier' && | ||
storageVariables.includes(assign.leftHandSide.name) && | ||
(!assign.rightHandSide || | ||
!assign.rightHandSide['kind'] || | ||
assign.rightHandSide['kind'] != 'structConstructorCall') | ||
) { | ||
const assignName = assign.leftHandSide.name; | ||
assignSrcs.set(assignName, assign.src); | ||
} | ||
} | ||
} | ||
} | ||
|
||
for (const func of findAll('FunctionDefinition', contract)) { | ||
if (func.kind !== 'constructor') { | ||
for (const assign of findAll('Assignment', func)) { | ||
if (assign.leftHandSide.nodeType === 'Identifier' && assignSrcs.has(assign.leftHandSide.name)) { | ||
const assignName = assign.leftHandSide.name; | ||
assignSrcs.set(assignName, ''); | ||
} | ||
} | ||
} | ||
} | ||
|
||
for (const assignSrc of assignSrcs.keys()) { | ||
const src = assignSrcs.get(assignSrc); | ||
if (!!src && src != '' && src != 'owner') { | ||
instances.push(instanceFromSRC(file, src)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return instances; | ||
}, | ||
}; | ||
|
||
export default issue; |
Oops, something went wrong.