Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implemented struct packing and added more abstraction #6

Merged
merged 1 commit into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
462 changes: 129 additions & 333 deletions artifacts/contract.sol/Counter1.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions cache/solidity-files-cache.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
},
"files": {
"src/contract.sol": {
"lastModificationDate": 1700762187306,
"contentHash": "4cfab11a6c48fe1603a2ee6922e55b0a",
"lastModificationDate": 1700945211440,
"contentHash": "1a8e4caa9ef81d181c8999b58c93d77f",
"sourceName": "src/contract.sol",
"solcConfig": {
"settings": {
Expand Down
6 changes: 5 additions & 1 deletion report.json
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
{}
{
"line_7": [
"struct is arraged wrongly should be arranged in this way [\"uint8\", \"bytes20\", \"uint\", \"string\"]"
]
}
13 changes: 7 additions & 6 deletions src/contract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
pragma solidity 0.8.12;

contract Counter1 {
uint256 public number;
string private ionize;
bool private localize;


function increment() public {
require(10 > number);
require(20 > number);
struct red {
uint errrr;
string unite;
uint8 ras3;
bytes20 dear;
}

}

26 changes: 5 additions & 21 deletions src/loader.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use reqwest;
use reqwest::Error;
use crate::optimizor;
use serde_json::{Map, Value};
use std::fs;
use crate::optimizor;

fn read_sol_file(file_path: &str) -> Result<String, std::io::Error> {
// Read the contents of the Solidity file into a string
Expand All @@ -11,41 +9,28 @@ fn read_sol_file(file_path: &str) -> Result<String, std::io::Error> {
Ok(content)
}

// async fn read_from_github(path: &str) -> Result<String, Error> {
// // Send an HTTP GET request to fetch the raw content
// //Path should be in this format: https://raw.githubusercontent.com/user/repo/master/contract.sol
// let client = reqwest::Client::new();
// let response = client.get(path).send().await?;
// let contract_content = response.text().await?;
// println!("{}", contract_content);

// Ok(contract_content)

// }


pub async fn loader() {

// // Parse command-line arguments using the config module
// let (input_file, github_url) = config::parse_args();

// // Initialize the contract variable
// let contract: String;

// if let Some(url) = github_url {
// // Read from a GitHub URL
// contract = read_from_github(&url).await.unwrap();
// } else {
// // Read from a local file
let contract = read_sol_file("src/contract.sol").unwrap();
let contract = read_sol_file("src/contract.sol").unwrap();
// }

//Generate the ast
optimizor::ast::ast();

//create new JSON Object to store gas
//create new JSON Object to store gas
let mut gas_inefficiencies = Map::new();

optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0);
optimizor::cache_state_variables::cache_state_variables(&mut gas_inefficiencies, 0);
optimizor::write_zero_to_storage::write_zero_to_storage(&mut gas_inefficiencies, 0);
optimizor::bytes32::bytes32(&contract, &mut gas_inefficiencies);
Expand All @@ -70,5 +55,4 @@ pub async fn loader() {
// Save the JSON to a file
let json_file_path = "report.json";
fs::write(json_file_path, gas_inefficiencies_json).expect("Unable to write JSON file");

}
2 changes: 0 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use tokio;
mod config;
mod loader;
mod optimizor;
mod utils;


#[tokio::main]
async fn main() {
loader::loader().await;
Expand Down
2 changes: 1 addition & 1 deletion src/optimizor/ast.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"absolutePath":"src/contract.sol","id":25,"exportedSymbols":{"Counter1":[24]},"nodeType":"SourceUnit","src":"32:230:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".12"]},{"id":24,"nodeType":"ContractDefinition","src":"57:203:0","nodes":[{"id":3,"nodeType":"VariableDeclaration","src":"81:21:0","nodes":[],"constant":false,"functionSelector":"8381f58a","mutability":"mutable","name":"number","nameLocation":"96:6:0","scope":24,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":2,"name":"uint256","nodeType":"ElementaryTypeName","src":"81:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":5,"nodeType":"VariableDeclaration","src":"108:21:0","nodes":[],"constant":false,"mutability":"mutable","name":"ionize","nameLocation":"123:6:0","scope":24,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_string_storage","typeString":"string"},"typeName":{"id":4,"name":"string","nodeType":"ElementaryTypeName","src":"108:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"private"},{"id":7,"nodeType":"VariableDeclaration","src":"135:21:0","nodes":[],"constant":false,"mutability":"mutable","name":"localize","nameLocation":"148:8:0","scope":24,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":6,"name":"bool","nodeType":"ElementaryTypeName","src":"135:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"private"},{"id":23,"nodeType":"FunctionDefinition","src":"163:95:0","nodes":[],"body":{"id":22,"nodeType":"Block","src":"191:67:0","nodes":[],"statements":[{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":13,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"hexValue":"3130","id":11,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"209:2:0","typeDescriptions":{"typeIdentifier":"t_rational_10_by_1","typeString":"int_const 10"},"value":"10"},"nodeType":"BinaryOperation","operator":">","rightExpression":{"id":12,"name":"number","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":3,"src":"214:6:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"209:11:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":10,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"201:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":14,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"201:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":15,"nodeType":"ExpressionStatement","src":"201:20:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":19,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"hexValue":"3230","id":17,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"239:2:0","typeDescriptions":{"typeIdentifier":"t_rational_20_by_1","typeString":"int_const 20"},"value":"20"},"nodeType":"BinaryOperation","operator":">","rightExpression":{"id":18,"name":"number","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":3,"src":"244:6:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"239:11:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":16,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"231:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":20,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"231:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":21,"nodeType":"ExpressionStatement","src":"231:20:0"}]},"functionSelector":"d09de08a","implemented":true,"kind":"function","modifiers":[],"name":"increment","nameLocation":"172:9:0","parameters":{"id":8,"nodeType":"ParameterList","parameters":[],"src":"181:2:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[],"src":"191:0:0"},"scope":24,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"Counter1","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[24],"name":"Counter1","nameLocation":"66:8:0","scope":25,"usedErrors":[]}],"license":"MIT"}
{"absolutePath":"src/contract.sol","id":12,"exportedSymbols":{"Counter1":[11]},"nodeType":"SourceUnit","src":"32:159:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".12"]},{"id":11,"nodeType":"ContractDefinition","src":"57:132:0","nodes":[{"id":10,"nodeType":"StructDefinition","src":"84:102:0","nodes":[],"canonicalName":"Counter1.red","members":[{"constant":false,"id":3,"mutability":"mutable","name":"errrr","nameLocation":"110:5:0","nodeType":"VariableDeclaration","scope":10,"src":"105:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":2,"name":"uint","nodeType":"ElementaryTypeName","src":"105:4:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"unite","nameLocation":"132:5:0","nodeType":"VariableDeclaration","scope":10,"src":"125:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"},"typeName":{"id":4,"name":"string","nodeType":"ElementaryTypeName","src":"125:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":7,"mutability":"mutable","name":"ras3","nameLocation":"153:4:0","nodeType":"VariableDeclaration","scope":10,"src":"147:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint8","typeString":"uint8"},"typeName":{"id":6,"name":"uint8","nodeType":"ElementaryTypeName","src":"147:5:0","typeDescriptions":{"typeIdentifier":"t_uint8","typeString":"uint8"}},"visibility":"internal"},{"constant":false,"id":9,"mutability":"mutable","name":"dear","nameLocation":"175:4:0","nodeType":"VariableDeclaration","scope":10,"src":"167:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes20","typeString":"bytes20"},"typeName":{"id":8,"name":"bytes20","nodeType":"ElementaryTypeName","src":"167:7:0","typeDescriptions":{"typeIdentifier":"t_bytes20","typeString":"bytes20"}},"visibility":"internal"}],"name":"red","nameLocation":"91:3:0","scope":11,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"Counter1","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[11],"name":"Counter1","nameLocation":"66:8:0","scope":12,"usedErrors":[]}],"license":"MIT"}
30 changes: 14 additions & 16 deletions src/optimizor/ast.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
use std::fs;
use ethers_solc;
use ethers_solc::{Project};
use ethers_solc::Project;
use std::fs;

pub fn ast() {
// create a project from a configuration file
let project = Project::builder().build().unwrap();
let output = project
.compile_files(vec!["src/contract.sol"])
.unwrap();
let artifacts = output.output().sources.0;
let mut s_ast = artifacts.values();
let mut binding = s_ast.next();
let mut binding = binding.iter_mut().next();
let s_asts = binding.as_mut().unwrap();
let ast = s_asts.get(0).unwrap().source_file.ast.clone().unwrap();
let ast_json = serde_json::to_string(&ast).unwrap();
fs::write("src/optimizor/ast.json", ast_json).expect("failed to write ast");
}
// create a project from a configuration file
let project = Project::builder().build().unwrap();
let output = project.compile_files(vec!["src/contract.sol"]).unwrap();
let artifacts = output.output().sources.0;
let mut s_ast = artifacts.values();
let mut binding = s_ast.next();
let mut binding = binding.iter_mut().next();
let s_asts = binding.as_mut().unwrap();
let ast = s_asts.get(0).unwrap().source_file.ast.clone().unwrap();
let ast_json = serde_json::to_string(&ast).unwrap();
fs::write("src/optimizor/ast.json", ast_json).expect("failed to write ast");
}
2 changes: 1 addition & 1 deletion src/optimizor/bytes32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ pub fn bytes32(contract: &str, gas_inefficiencies: &mut Map<String, serde_json::
);
}
}
}
}
4 changes: 2 additions & 2 deletions src/optimizor/cache_state_variables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub fn cache_state_variables(
.and_then(Value::as_array)
{
for argument in arguments {
if let Some(left_E) =
if let Some(_left_e) =
argument.get("leftExpression")
{
let name = argument
Expand Down Expand Up @@ -174,7 +174,7 @@ fn get_line_number_zero(src: &str, mut _prev: usize) -> usize {
_prev = line_number + 1;
break;
}
times = times + 1;
times += 1;
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions src/optimizor/constructor_check_absence.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use regex::Regex;
use serde_json::json;
use serde_json::Map;

pub fn check_constructor_absence(contract: &str) {
let constructor_regex = Regex::new(r"constructor\s*\(.*\)").unwrap();
Expand Down
2 changes: 1 addition & 1 deletion src/optimizor/do_while.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ pub fn do_while(contract: &str, gas_inefficiencies: &mut Map<String, serde_json:
println!("use do while loops instead of for loops ");
}
}
}
}
11 changes: 3 additions & 8 deletions src/optimizor/mapping_instead_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,17 @@ pub fn mapping_instead_array(
let mut existing_arr: Vec<String> =
serde_json::from_value(existing_value.clone()).unwrap_or_default();

existing_arr.push(
"Use mapping instead of array: Modifier:"
.to_string(),
);
existing_arr.push("Use mapping instead of array: Modifier:".to_string());

// Update the value in the map
gas_inefficiencies.insert(inefficiency_id, json!(existing_arr));
} else {
// Slot doesn't exist, create a new entry with a new array
let new_arr = vec![
"Use mapping instead of array: Modifier:",
];
let new_arr = vec!["Use mapping instead of array: Modifier:"];
gas_inefficiencies.insert(inefficiency_id, json!(new_arr));
}

println!("Use mapping instead of array: Modifier:");
}
}
}
}
23 changes: 12 additions & 11 deletions src/optimizor/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
pub mod ast;
pub mod token;
pub mod bytes32;
pub mod safemath;
pub mod openzeppelin;
pub mod revert_32;
pub mod cache_state_variables;
pub mod constructor_check_absence;
pub mod do_while;
pub mod emit_loops;
pub mod write_zero_to_storage;
pub mod cache_state_variables;
pub mod uint256_instead_bool;
pub mod require_double_logic;
pub mod mapping_instead_array;
pub mod priv_constants_immut;
pub mod openzeppelin;
pub mod pack_related_vars;
pub mod use_named_returns;
pub mod priv_constants_immut;
pub mod require_double_logic;
pub mod revert_32;
pub mod safemath;
pub mod struct_packing;
pub mod token;
pub mod uint256_instead_bool;
pub mod uint_incur_overhead;
pub mod constructor_check_absence;
pub mod use_named_returns;
pub mod write_zero_to_storage;
1 change: 0 additions & 1 deletion src/optimizor/openzeppelin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use regex::Regex;
use serde_json::json;
use serde_json::Map;


pub fn openzepplin(contract: &str, gas_inefficiencies: &mut Map<String, serde_json::Value>) {
let variable_declaration_regex = Regex::new(r"openzeppelin").unwrap();

Expand Down
1 change: 1 addition & 0 deletions src/optimizor/pack_related_vars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

2 changes: 1 addition & 1 deletion src/optimizor/priv_constants_immut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ pub fn priv_constants_immut(
println!("variables that are constant should have a visibility of private");
}
}
}
}
1 change: 0 additions & 1 deletion src/optimizor/safemath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use regex::Regex;
use serde_json::json;
use serde_json::Map;


pub fn safemath(contract: &str, gas_inefficiencies: &mut Map<String, serde_json::Value>) {
let variable_declaration_regex = Regex::new(r"SafeMath").unwrap();

Expand Down
72 changes: 72 additions & 0 deletions src/optimizor/struct_packing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use crate::utils::{extract_struct_node, number_to_types, update_gas_ineffiency_map};
use regex::Regex;
use serde_json::Map;
use std::fs;

pub fn struct_packing(gas_inefficiencies: &mut Map<String, serde_json::Value>, mut _prev: usize) {
let mut _name = "";
let (old_arr, _name) = extract_struct_node::extract_struct_node();
let mut old_arrs: Vec<f64> = Vec::new();
let mut new_arr: Vec<f64> = Vec::new();
let mut new_arr_str: Vec<String> = Vec::new();

for str_to_f64 in old_arr {
if let Ok(parsed_number) = str_to_f64.parse::<f64>() {
new_arr.push(parsed_number);
old_arrs.push(parsed_number);
new_arr.sort_by(|a, b| a.partial_cmp(b).unwrap());
}
}

//Update gas_inefficiencies map
for str_new_arr in new_arr.clone() {
new_arr_str.push(
number_to_types::number_to_types()
.get(&str_new_arr.to_string())
.unwrap()
.to_string().trim_matches('"').to_string(),
);
}

if old_arrs != new_arr {
println!("{:?}", true);
_prev = get_line_number_zero(_name.as_str(), _prev);
let mut _inefficiency_id = format!("line_{}", get_line_number_zero(_name.as_str(), _prev));

get_line_number_zero(_name.as_str(), _prev);
_inefficiency_id = format!("line_{}", _prev);

update_gas_ineffiency_map::update_gas_inefficency_map(
_inefficiency_id,
gas_inefficiencies,
format!(
"struct is arraged wrongly should be arranged in this way {:?}",
new_arr_str
),
)
}
}

fn get_line_number_zero(src: &str, mut _prev: usize) -> usize {
// Read the source file as a string
let contract = fs::read_to_string("src/contract.sol").expect("Failed to read");

// Split the contract content into lines
let lines: Vec<&str> = contract.lines().collect();

// Format the string with " = 0" at the end
let strss = format!(r"struct {}", src);

// Compile the regex pattern
let variable_declaration_regex = Regex::new(&strss).unwrap();

for (line_number, line) in lines.iter().enumerate() {
if let Some(_capture) = variable_declaration_regex.captures(line) {
if line_number > _prev {
_prev = line_number + 1;
break;
}
}
}
_prev
}
Loading
Loading