diff --git a/Cargo.lock b/Cargo.lock index cab9670..de4eda1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,6 +47,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "arrayvec" version = "0.7.4" @@ -59,7 +71,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" dependencies = [ - "term", + "term 0.7.0", ] [[package]] @@ -197,6 +209,17 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "constant_time_eq", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -355,6 +378,15 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clippy" +version = "0.0.302" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d911ee15579a3f50880d8c1d59ef6e79f9533127a3bd342462f5d584f5e8c294" +dependencies = [ + "term 0.5.2", +] + [[package]] name = "coins-bip32" version = "0.8.7" @@ -590,6 +622,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +dependencies = [ + "libc", + "redox_users 0.3.5", + "winapi", +] + [[package]] name = "dirs" version = "5.0.1" @@ -617,7 +660,7 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", "option-ext", - "redox_users", + "redox_users 0.4.3", "windows-sys", ] @@ -628,7 +671,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.3", "winapi", ] @@ -892,7 +935,7 @@ version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0a17f0708692024db9956b31d7a20163607d2745953f5ae8125ab368ba280ad" dependencies = [ - "arrayvec", + "arrayvec 0.7.4", "bytes", "cargo_metadata", "chrono", @@ -1022,7 +1065,7 @@ checksum = "de34e484e7ae3cab99fbfd013d6c5dc7f9013676a4e0e414d8b12e1213e8b3ba" dependencies = [ "cfg-if", "const-hex", - "dirs", + "dirs 5.0.1", "dunce", "ethers-core", "glob", @@ -1269,6 +1312,7 @@ name = "gas_analyzer" version = "0.1.0" dependencies = [ "clap", + "clippy", "ethers", "ethers-solc", "regex", @@ -1289,6 +1333,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -1297,7 +1352,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -1710,7 +1765,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "string_cache", - "term", + "term 0.7.0", "tiny-keccak", "unicode-xid", ] @@ -1808,7 +1863,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] @@ -1919,7 +1974,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" dependencies = [ - "arrayvec", + "arrayvec 0.7.4", "auto_impl", "bytes", "ethereum-types", @@ -2000,7 +2055,7 @@ version = "3.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" dependencies = [ - "arrayvec", + "arrayvec 0.7.4", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", @@ -2368,7 +2423,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.10", ] [[package]] @@ -2400,6 +2455,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + [[package]] name = "redox_syscall" version = "0.2.16" @@ -2418,13 +2479,24 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom 0.1.16", + "redox_syscall 0.1.57", + "rust-argon2", +] + [[package]] name = "redox_users" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom", + "getrandom 0.2.10", "redox_syscall 0.2.16", "thiserror", ] @@ -2539,7 +2611,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" dependencies = [ "cc", - "getrandom", + "getrandom 0.2.10", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -2577,6 +2649,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64 0.13.1", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -3048,7 +3132,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597e3a746727984cb7ea2487b6a40726cad0dbe86628e7d429aa6b8c4c153db4" dependencies = [ - "dirs", + "dirs 5.0.1", "fs2", "hex", "once_cell", @@ -3124,6 +3208,17 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "term" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" +dependencies = [ + "byteorder", + "dirs 1.0.5", + "winapi", +] + [[package]] name = "term" version = "0.7.0" @@ -3506,7 +3601,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom", + "getrandom 0.2.10", "serde", ] @@ -3541,6 +3636,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 902e7e9..dd62950 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] clap = "3.0.0-beta.5" +clippy = "0.0.302" ethers = "2.0.10" ethers-solc = "2.0.10" regex = "1.10.2" @@ -16,7 +17,7 @@ snap = "1.1.0" tokio = {version = "1", features = ["full"]} - [[bin]] name = "analyzer" path = "src/main.rs" + diff --git a/artifacts/contract.sol/Counter1.json b/artifacts/contract.sol/Counter1.json index dea7a98..00257b1 100644 --- a/artifacts/contract.sol/Counter1.json +++ b/artifacts/contract.sol/Counter1.json @@ -1,26 +1,64 @@ { - "abi": [], + "abi": [ + { + "inputs": [], + "name": "e", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ers", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "red", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], "bytecode": { - "object": "0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea26469706673582212207d5b2e024befc9ab05740da99af14e58cd223eb400daf9e08f6fd35c433a2da564736f6c634300080c0033", - "sourceMap": "57:132:0:-:0;;;;;;;;;;;;;;;;;;;", + "object": "0x608060405260226000556020600160006101000a81548160ff021916908360ff16021790555034801561003157600080fd5b50610150806100416000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80632930cf24146100465780637ac9d73814610050578063ffae15ba1461006e575b600080fd5b61004e61008c565b005b610058610096565b60405161006591906100cb565b60405180910390f35b6100766100a9565b60405161008391906100ff565b60405180910390f35b6004600081905550565b600160009054906101000a900460ff1681565b60005481565b600060ff82169050919050565b6100c5816100af565b82525050565b60006020820190506100e060008301846100bc565b92915050565b6000819050919050565b6100f9816100e6565b82525050565b600060208201905061011460008301846100f0565b9291505056fea26469706673582212204978008c55b04f0bc9f8787ff40dd7ac86b5f46a2291b130f450685c9c23417264736f6c634300080c0033", + "sourceMap": "57:110:0:-:0;;;95:2;79:18;;120:2;101:21;;;;;;;;;;;;;;;;;;;;57:110;;;;;;;;;;;;;;;;", "linkReferences": {} }, "deployedBytecode": { - "object": "0x6080604052600080fdfea26469706673582212207d5b2e024befc9ab05740da99af14e58cd223eb400daf9e08f6fd35c433a2da564736f6c634300080c0033", - "sourceMap": "57:132:0:-:0;;;;;", + "object": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80632930cf24146100465780637ac9d73814610050578063ffae15ba1461006e575b600080fd5b61004e61008c565b005b610058610096565b60405161006591906100cb565b60405180910390f35b6100766100a9565b60405161008391906100ff565b60405180910390f35b6004600081905550565b600160009054906101000a900460ff1681565b60005481565b600060ff82169050919050565b6100c5816100af565b82525050565b60006020820190506100e060008301846100bc565b92915050565b6000819050919050565b6100f9816100e6565b82525050565b600060208201905061011460008301846100f0565b9291505056fea26469706673582212204978008c55b04f0bc9f8787ff40dd7ac86b5f46a2291b130f450685c9c23417264736f6c634300080c0033", + "sourceMap": "57:110:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;127:38;;;:::i;:::-;;101:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79:18;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;127:38;159:1;155;:5;;;;127:38::o;101:21::-;;;;;;;;;;;;;:::o;79:18::-;;;;:::o;7:86:1:-;42:7;82:4;75:5;71:16;60:27;;7:86;;;:::o;99:112::-;182:22;198:5;182:22;:::i;:::-;177:3;170:35;99:112;;:::o;217:214::-;306:4;344:2;333:9;329:18;321:26;;357:67;421:1;410:9;406:17;397:6;357:67;:::i;:::-;217:214;;;;:::o;437:77::-;474:7;503:5;492:16;;437:77;;;:::o;520:118::-;607:24;625:5;607:24;:::i;:::-;602:3;595:37;520:118;;:::o;644:222::-;737:4;775:2;764:9;760:18;752:26;;788:71;856:1;845:9;841:17;832:6;788:71;:::i;:::-;644:222;;;;:::o", "linkReferences": {} }, - "methodIdentifiers": {}, + "methodIdentifiers": { + "e()": "ffae15ba", + "ers()": "7ac9d738", + "red()": "2930cf24" + }, "ast": { "absolutePath": "src/contract.sol", - "id": 12, + "id": 17, "exportedSymbols": { "Counter1": [ - 11 + 16 ] }, "nodeType": "SourceUnit", - "src": "32:159:0", + "src": "32:137:0", "nodes": [ { "id": 1, @@ -34,129 +72,181 @@ ] }, { - "id": 11, + "id": 16, "nodeType": "ContractDefinition", - "src": "57:132:0", + "src": "57:110:0", "nodes": [ { - "id": 10, - "nodeType": "StructDefinition", - "src": "84:102:0", + "id": 4, + "nodeType": "VariableDeclaration", + "src": "79:18: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, + "functionSelector": "ffae15ba", + "mutability": "mutable", + "name": "e", + "nameLocation": "91:1:0", + "scope": 16, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "79:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": { + "hexValue": "3334", + "id": 3, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "95:2:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_34_by_1", + "typeString": "int_const 34" }, - { - "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" + "value": "34" + }, + "visibility": "public" + }, + { + "id": 7, + "nodeType": "VariableDeclaration", + "src": "101:21:0", + "nodes": [], + "constant": false, + "functionSelector": "7ac9d738", + "mutability": "mutable", + "name": "ers", + "nameLocation": "114:3:0", + "scope": 16, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "typeName": { + "id": 5, + "name": "uint8", + "nodeType": "ElementaryTypeName", + "src": "101:5:0", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" } - ], + }, + "value": { + "hexValue": "3332", + "id": 6, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "120:2:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_32_by_1", + "typeString": "int_const 32" + }, + "value": "32" + }, + "visibility": "public" + }, + { + "id": 15, + "nodeType": "FunctionDefinition", + "src": "127:38:0", + "nodes": [], + "body": { + "id": 14, + "nodeType": "Block", + "src": "149:16:0", + "nodes": [], + "statements": [ + { + "expression": { + "id": 12, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 10, + "name": "e", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 4, + "src": "155:1:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "hexValue": "34", + "id": 11, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "159:1:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_4_by_1", + "typeString": "int_const 4" + }, + "value": "4" + }, + "src": "155:5:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 13, + "nodeType": "ExpressionStatement", + "src": "155:5:0" + } + ] + }, + "functionSelector": "2930cf24", + "implemented": true, + "kind": "function", + "modifiers": [], "name": "red", - "nameLocation": "91:3:0", - "scope": 11, + "nameLocation": "136:3:0", + "parameters": { + "id": 8, + "nodeType": "ParameterList", + "parameters": [], + "src": "139:2:0" + }, + "returnParameters": { + "id": 9, + "nodeType": "ParameterList", + "parameters": [], + "src": "149:0:0" + }, + "scope": 16, + "stateMutability": "nonpayable", + "virtual": false, "visibility": "public" } ], @@ -167,11 +257,11 @@ "contractKind": "contract", "fullyImplemented": true, "linearizedBaseContracts": [ - 11 + 16 ], "name": "Counter1", "nameLocation": "66:8:0", - "scope": 12, + "scope": 17, "usedErrors": [] } ], diff --git a/cache/solidity-files-cache.json b/cache/solidity-files-cache.json index 377d986..c11c211 100644 --- a/cache/solidity-files-cache.json +++ b/cache/solidity-files-cache.json @@ -12,8 +12,8 @@ }, "files": { "src/contract.sol": { - "lastModificationDate": 1700945211440, - "contentHash": "1a8e4caa9ef81d181c8999b58c93d77f", + "lastModificationDate": 1700985740020, + "contentHash": "e171a88723ee64aba45007932b4cd2ca", "sourceName": "src/contract.sol", "solcConfig": { "settings": { diff --git a/report.json b/report.json index d93465c..863cbc3 100644 --- a/report.json +++ b/report.json @@ -1,5 +1,8 @@ { - "line_7": [ - "struct is arraged wrongly should be arranged in this way [\"uint8\", \"bytes20\", \"uint\", \"string\"]" + "line_0": [ + "cache state variables" + ], + "line_10": [ + "state variables is arraged wrongly should be arranged in this way [\"bool\", \"uint8\", \"address\", \"bytes20\", \"uint\", \"string\"]" ] } \ No newline at end of file diff --git a/src/contract.sol b/src/contract.sol index fca4d71..93eecc8 100644 --- a/src/contract.sol +++ b/src/contract.sol @@ -2,14 +2,15 @@ pragma solidity 0.8.12; contract Counter1 { - - - struct red { - uint errrr; - string unite; - uint8 ras3; - bytes20 dear; - } + bool public baol; + string private redss; + uint public tinu; + uint8 public vv; + address public erd; + bytes20 public sad; + function red() public { + e = 4; + } } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..4ab6c67 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +pub mod utils; +pub mod optimizor; \ No newline at end of file diff --git a/src/loader.rs b/src/loader.rs index aacf70a..d3939fc 100644 --- a/src/loader.rs +++ b/src/loader.rs @@ -31,6 +31,7 @@ pub async fn loader() { //create new JSON Object to store gas let mut gas_inefficiencies = Map::new(); optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + optimizor::pack_related_vars::pack_related_vars(&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); diff --git a/src/main.rs b/src/main.rs index 3791c8d..4ffd815 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod loader; mod optimizor; mod utils; + #[tokio::main] async fn main() { loader::loader().await; diff --git a/src/optimizor/ast.json b/src/optimizor/ast.json index b41556e..64667b9 100644 --- a/src/optimizor/ast.json +++ b/src/optimizor/ast.json @@ -1 +1 @@ -{"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"} \ No newline at end of file +{"absolutePath":"src/contract.sol","id":23,"exportedSymbols":{"Counter1":[22]},"nodeType":"SourceUnit","src":"32:217:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".12"]},{"id":22,"nodeType":"ContractDefinition","src":"57:190:0","nodes":[{"id":3,"nodeType":"VariableDeclaration","src":"79:16:0","nodes":[],"constant":false,"functionSelector":"327db563","mutability":"mutable","name":"baol","nameLocation":"91:4:0","scope":22,"stateVariable":true,"storageLocation":"default","typeDescriptions":{},"typeName":{"id":2,"name":"bool","nodeType":"ElementaryTypeName","src":"79:4:0","typeDescriptions":{}},"visibility":"public"},{"id":5,"nodeType":"VariableDeclaration","src":"99:20:0","nodes":[],"constant":false,"mutability":"mutable","name":"redss","nameLocation":"114:5:0","scope":22,"stateVariable":true,"storageLocation":"default","typeDescriptions":{},"typeName":{"id":4,"name":"string","nodeType":"ElementaryTypeName","src":"99:6:0","typeDescriptions":{}},"visibility":"private"},{"id":7,"nodeType":"VariableDeclaration","src":"123:16:0","nodes":[],"constant":false,"functionSelector":"8929d36d","mutability":"mutable","name":"tinu","nameLocation":"135:4:0","scope":22,"stateVariable":true,"storageLocation":"default","typeDescriptions":{},"typeName":{"id":6,"name":"uint","nodeType":"ElementaryTypeName","src":"123:4:0","typeDescriptions":{}},"visibility":"public"},{"id":9,"nodeType":"VariableDeclaration","src":"143:15:0","nodes":[],"constant":false,"functionSelector":"e73d9fbb","mutability":"mutable","name":"vv","nameLocation":"156:2:0","scope":22,"stateVariable":true,"storageLocation":"default","typeDescriptions":{},"typeName":{"id":8,"name":"uint8","nodeType":"ElementaryTypeName","src":"143:5:0","typeDescriptions":{}},"visibility":"public"},{"id":11,"nodeType":"VariableDeclaration","src":"162:18:0","nodes":[],"constant":false,"functionSelector":"d9152ee6","mutability":"mutable","name":"erd","nameLocation":"177:3:0","scope":22,"stateVariable":true,"storageLocation":"default","typeDescriptions":{},"typeName":{"id":10,"name":"address","nodeType":"ElementaryTypeName","src":"162:7:0","stateMutability":"nonpayable","typeDescriptions":{}},"visibility":"public"},{"id":13,"nodeType":"VariableDeclaration","src":"184:18:0","nodes":[],"constant":false,"functionSelector":"88288ffa","mutability":"mutable","name":"sad","nameLocation":"199:3:0","scope":22,"stateVariable":true,"storageLocation":"default","typeDescriptions":{},"typeName":{"id":12,"name":"bytes20","nodeType":"ElementaryTypeName","src":"184:7:0","typeDescriptions":{}},"visibility":"public"},{"id":21,"nodeType":"FunctionDefinition","src":"207:38:0","nodes":[],"body":{"id":20,"nodeType":"Block","src":"229:16:0","nodes":[],"statements":[{"expression":{"id":18,"leftHandSide":{"id":16,"name":"e","nodeType":"Identifier","overloadedDeclarations":[],"src":"235:1:0","typeDescriptions":{}},"nodeType":"Assignment","operator":"=","rightHandSide":{"hexValue":"34","id":17,"kind":"number","nodeType":"Literal","src":"239:1:0","typeDescriptions":{},"value":"4"},"src":"235:5:0","typeDescriptions":{}},"id":19,"nodeType":"ExpressionStatement","src":"235:5:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"red","nameLocation":"216:3:0","parameters":{"id":14,"nodeType":"ParameterList","parameters":[],"src":"219:2:0"},"returnParameters":{"id":15,"nodeType":"ParameterList","parameters":[],"src":"229:0:0"},"scope":22,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"Counter1","contractDependencies":[],"contractKind":"contract","linearizedBaseContracts":[22],"name":"Counter1","nameLocation":"66:8:0","scope":23,"usedErrors":[]}],"license":"MIT"} \ No newline at end of file diff --git a/src/optimizor/bytes32.rs b/src/optimizor/bytes32.rs index 13261c5..70c87fc 100644 --- a/src/optimizor/bytes32.rs +++ b/src/optimizor/bytes32.rs @@ -41,4 +41,4 @@ pub fn bytes32(contract: &str, gas_inefficiencies: &mut Map usize { //get number of times let mut times = 0; - println!("{}", "erere"); // Read the source file as a string let contract = fs::read_to_string("src/contract.sol").expect("Failed to read"); @@ -159,7 +158,7 @@ fn get_line_number_zero(src: &str, mut _prev: usize) -> usize { let lines: Vec<&str> = contract.lines().collect(); // Format the string with " = 0" at the end - let strss = format!(r"{}", src); + let strss = src.to_string(); // Compile the regex pattern for any function declaration let any_function_declaration_regex = Regex::new(r"function\s+\w*\s*\(").unwrap(); diff --git a/src/optimizor/mapping_instead_array.rs b/src/optimizor/mapping_instead_array.rs index 6f8e208..5b02b49 100644 --- a/src/optimizor/mapping_instead_array.rs +++ b/src/optimizor/mapping_instead_array.rs @@ -21,13 +21,13 @@ pub fn mapping_instead_array( let mut existing_arr: Vec = 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".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"]; gas_inefficiencies.insert(inefficiency_id, json!(new_arr)); } diff --git a/src/optimizor/pack_related_vars.rs b/src/optimizor/pack_related_vars.rs index 8b13789..65e1c97 100644 --- a/src/optimizor/pack_related_vars.rs +++ b/src/optimizor/pack_related_vars.rs @@ -1 +1,72 @@ +use crate::utils::{extract_state_vars, number_to_types, update_gas_ineffiency_map}; +use regex::Regex; +use serde_json::Map; +use std::fs; +pub fn pack_related_vars(gas_inefficiencies: &mut Map, mut _prev: usize) { + let mut _name = ""; + let (old_arr, _name) = extract_state_vars::extract_state_node(); + let mut old_arrs: Vec = Vec::new(); + let mut new_arr: Vec = Vec::new(); + let mut new_arr_str: Vec = Vec::new(); + + for str_to_f64 in old_arr { + if let Ok(parsed_number) = str_to_f64.parse::() { + new_arr.push(parsed_number); + old_arrs.push(parsed_number); + new_arr.sort_by(|a, b: &f64| 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!( + "state variables 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"(bytes32|bytes4|uint8|uint256|bytes20|uint128|uint|uint160|string|int8|int256|int) (public|private|internal) {}", 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 +} diff --git a/src/optimizor/state_vars_used_once.rs b/src/optimizor/state_vars_used_once.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/optimizor/uint_incur_overhead.rs b/src/optimizor/uint_incur_overhead.rs index b40e67d..a19342e 100644 --- a/src/optimizor/uint_incur_overhead.rs +++ b/src/optimizor/uint_incur_overhead.rs @@ -7,7 +7,7 @@ pub fn uint_incur_overhead( gas_inefficiencies: &mut Map, ) { let variable_declaration_regex = - Regex::new(r#"\((uint24|uint8|uint160|uint16)\s*(public|private|internal)\s*[^}]*bool"#) + Regex::new(r"\((uint24|uint8|uint160|uint16)\s*(public|private|internal)\s*[^}]*bool") .unwrap(); let lines: Vec<&str> = contract.lines().collect(); diff --git a/src/optimizor/write_zero_to_storage.rs b/src/optimizor/write_zero_to_storage.rs index 9cb2441..d73520c 100644 --- a/src/optimizor/write_zero_to_storage.rs +++ b/src/optimizor/write_zero_to_storage.rs @@ -45,56 +45,51 @@ pub fn write_zero_to_storage( if let Some(right_hand_side) = expression.get("rightHandSide") { - if right_hand_side.get("value") - == Some(&Value::String("0".to_string())) - { - if !right_hand_side + if right_hand_side.get("value") == Some(&Value::String("0".to_string())) && !right_hand_side .get("isConstant") .unwrap_or(&Value::Bool(true)) .as_bool() - .unwrap_or(true) - { - _prev = get_line_number_zero( - _name, _prev, - ); - let mut _inefficiency_id = format!( - "line_{}", - get_line_number_zero( - _name, _prev - ) - ); + .unwrap_or(true) { + _prev = get_line_number_zero( + _name, _prev, + ); + let mut _inefficiency_id = format!( + "line_{}", + get_line_number_zero( + _name, _prev + ) + ); - get_line_number_zero(_name, _prev); - _inefficiency_id = - format!("line_{}", _prev); - // Check if the slot exists in the map - if let Some(existing_value) = - gas_inefficiencies - .get_mut(&_inefficiency_id) - { - // Slot exists, append the new issue to the existing array - let mut existing_arr: Vec< - String, - > = serde_json::from_value( - existing_value.clone(), - ) - .unwrap_or_default(); + get_line_number_zero(_name, _prev); + _inefficiency_id = + format!("line_{}", _prev); + // Check if the slot exists in the map + if let Some(existing_value) = + gas_inefficiencies + .get_mut(&_inefficiency_id) + { + // Slot exists, append the new issue to the existing array + let mut existing_arr: Vec< + String, + > = serde_json::from_value( + existing_value.clone(), + ) + .unwrap_or_default(); - existing_arr.push("avoid writing zero to storage slot".to_string()); + existing_arr.push("avoid writing zero to storage slot".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!["avoid writing zero to storage slot"]; - gas_inefficiencies.insert( - _inefficiency_id, - json!(new_arr), - ); - } + // 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!["avoid writing zero to storage slot"]; + gas_inefficiencies.insert( + _inefficiency_id, + json!(new_arr), + ); } } } diff --git a/src/utils/extract_state_vars.rs b/src/utils/extract_state_vars.rs new file mode 100644 index 0000000..5db902a --- /dev/null +++ b/src/utils/extract_state_vars.rs @@ -0,0 +1,48 @@ +use crate::utils::types_to_numbers; +use serde_json::Value; +use std::fs; + +pub fn extract_state_node() -> (Vec, String) { + let ast_json = fs::read_to_string("src/optimizor/ast.json").expect("Failed to read"); + let ast: Value = serde_json::from_str(&ast_json).expect("Failed to deserialize"); + let mut arr = Vec::new(); + let mut name = ""; + if let Some(nodes) = ast.get("nodes").and_then(Value::as_array) { + for node in nodes { + if let Some(node_type) = node.get("nodeType").and_then(Value::as_str) { + if node_type == "ContractDefinition" { + if let Some(contract_nodes) = node.get("nodes").and_then(Value::as_array) { + for contract_node in contract_nodes { + if let Some(func_node) = contract_node.as_object() { + if func_node.get("nodeType").and_then(Value::as_str) + == Some("VariableDeclaration") + { + + name = func_node.get("name").unwrap().as_str().unwrap(); + + if let Some(type_name) = func_node.get("typeName") { + if let Some(name) = + type_name.get("name").and_then(Value::as_str) + { + let t_to_n = types_to_numbers::_types_to_number(); + if let Some(val) = + t_to_n.get(name).and_then(|v| v.as_str()) + { + arr.push(val.to_string()); + // Clone and push the value + } else { + // Handle the case when the value is not found or not a string + println!("Warning: Value not found or not a string for name '{}'", name); + } + } + } + } + } + } + } + } + } + } + } + (arr, name.to_owned()) +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 72f8deb..fcf8d1f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -3,4 +3,5 @@ pub mod update_gas_ineffiency_map; pub mod data_types; pub mod types_to_numbers; pub mod number_to_types; -pub mod extract_struct_node; \ No newline at end of file +pub mod extract_struct_node; +pub mod extract_state_vars; \ No newline at end of file diff --git a/tests/all_test.rs b/tests/all_test.rs new file mode 100644 index 0000000..9da6e16 --- /dev/null +++ b/tests/all_test.rs @@ -0,0 +1,248 @@ +#[cfg(test)] +mod expect_revert_tests { + use gas_analyzer::{optimizor}; + use serde_json::{Map, Value}; + use std::fs; + + fn read_sol_file(file_path: &str) -> Result { + // Read the contents of the Solidity file into a string + let content = fs::read_to_string(file_path)?; + + Ok(content) + } + #[test] + #[should_panic] + fn test_singe_bytes32() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::bytes32::bytes32(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("Use Uint256 instead of bytes32 to store constant") + ); + } + + #[test] + #[should_panic] + fn test_openzepplin() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::openzeppelin::openzepplin(&contract, &mut gas_inefficiencies); + assert_eq!(gas_inefficiencies.get("line_0").and_then(Value::as_str), Some("instead of using openzeppelin we can use solady which is way cheaper and way efficient [https://github.com/Vectorized/solady")); + } + + #[test] + #[should_panic] + fn test_constrcutor_check() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::openzeppelin::openzepplin(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("making the constructor payable saves gas in deployment cost") + ); + } + + #[test] + #[should_panic] + fn test_do_while() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::do_while::do_while(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("do while loops are cheaper than loops and consume less gas") + ); + } + + #[test] + #[should_panic] + fn test_emit_loops() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::do_while::do_while(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("emiting events in loops cost more, and should be done using other means") + ); + } + + #[test] + #[should_panic] + fn test_mapping_array() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::do_while::do_while(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("Use mapping instead of array") + ); + } + + #[test] + #[should_panic] + fn test_priv_constants_immut() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::priv_constants_immut::priv_constants_immut(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("variables that are constant should have a visibility of private") + ); + } + + #[test] + #[should_panic] + fn test_require_double_logic() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::require_double_logic::require_double_logic(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("split require statements that use && into two seperate parts to save gas") + ); + } + + #[test] + #[should_panic] + fn test_revert32() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::revert_32::revert_32(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("revert statement that has it's string longer than 32 length is always more expensive") + ); + } + + #[test] + #[should_panic] + fn test_safemath() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::safemath::safemath(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("SafeMath is no longer needed since solidity version 0.8.0, use of safeMath can be considered unnessary") + ); + } + + #[test] + #[should_panic] + fn test_token() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::token::token(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("For string of length less than 33, its better to use uint256 to store them") + ); + } + + #[test] + #[should_panic] + fn test_uint_incur_overhead() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::uint_incur_overhead::uint_incur_overhead(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("instead of a uint24, uint16 or any uint and int type apart from uint256 or int256, it's way better to use uint256 or int256") + ); + } + + #[test] + #[should_panic] + fn test_uint_instead_bool() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::uint256_instead_bool::uint256_instead_bool(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("Use uint256 type to store boolean value instead of bool") + ); + } + + #[test] + #[should_panic] + fn test_named_returns() { + //Generate the ast + optimizor::ast::ast(); + + //create new JSON Object to store gas + let mut gas_inefficiencies = Map::new(); + optimizor::struct_packing::struct_packing(&mut gas_inefficiencies, 0); + let contract = read_sol_file("regex_expect_revert.sol").unwrap(); + optimizor::use_named_returns::use_named_retunrs(&contract, &mut gas_inefficiencies); + assert_eq!( + gas_inefficiencies.get("line_0").and_then(Value::as_str), + Some("Use named returns") + ); + } + +} diff --git a/tests/gas_tricks_test.rs b/tests/gas_tricks_test.rs deleted file mode 100644 index 44bf10a..0000000 --- a/tests/gas_tricks_test.rs +++ /dev/null @@ -1,59 +0,0 @@ -// use std::fs; - -// fn read_sol_file(file_path: &str) -> Result { -// // Read the contents of the Solidity file into a string -// let content = fs::read_to_string(file_path)?; - -// Ok(content) -// } - -// mod optimizor { -// pub mod gas_tricks; -// } - -// #[cfg(test)] -// mod tests { - -// use super::*; - -// mod src { - -// } - -// #[test] -// fn test_bytes32() { -// let contract: &str = &read_sol_file("./revm/example.t.sol").unwrap(); -// optimizor::gas_tricks::bytes32(contract); -// } - -// #[test] -// fn test_openzeppelin() { -// let contract: &str = &read_sol_file("./revm/example.t.sol").unwrap(); -// optimizor::gas_tricks::openzepplin(contract); -// } - -// #[test] -// fn safemath() { -// let contract: &str = &read_sol_file("./revm/example.t.sol").unwrap(); -// optimizor::gas_tricks::safemath(contract); -// } - -// #[test] -// fn token() { -// let contract: &str = &read_sol_file("./revm/example.t.sol").unwrap(); -// optimizor::gas_tricks::token(contract); -// } - -// #[test] -// fn uint_incur_overhead() { -// let contract: &str = &read_sol_file("/home/malik/Desktop/revm/example.t.sol").unwrap(); -// optimizor::gas_tricks::uint_incur_overhead(contract); -// } - -// #[test] -// fn constructor() { -// let contract: &str = &read_sol_file("/home/malik/Desktop/revm/example.t.sol").unwrap(); -// optimizor::gas_tricks::check_constructor_absence(contract); -// } - -// } diff --git a/tests/optimizor/gas_tricks.rs b/tests/optimizor/gas_tricks.rs deleted file mode 100644 index 3bdbf66..0000000 --- a/tests/optimizor/gas_tricks.rs +++ /dev/null @@ -1,84 +0,0 @@ -use regex::Regex; - -pub fn bytes32(contract: &str) { - let variable_declaration_regex = Regex::new( - r"(bytes32 (public|private|internal) (constant|immutable))\s*\b([a-zA-Z_]\w*)\b\s*=\s*(.*)", - ) - .unwrap(); - - for capture in variable_declaration_regex.captures_iter(contract) { - let modifier = capture.get(1).map_or("default", |m| m.as_str()); - let variable_name = capture.get(4).unwrap().as_str(); - println!( - "Use Uint256 instead of bytes32 to store constant: Modifier: {}, variable_name: {}", - modifier, variable_name - ); - } -} - -pub fn openzepplin(contract: &str) { - let variable_declaration_regex = Regex::new(r"openzeppelin").unwrap(); - - for capture in variable_declaration_regex.captures_iter(contract) { - let modifier = capture.get(0).map_or("default", |m| m.as_str()); - println!( - "instead of using openzeppelin we can use solady which is way cheaper and way efficient [https://github.com/Vectorized/solady: {}", - modifier - ); - } -} - -pub fn safemath(contract: &str) { - let variable_declaration_regex = Regex::new(r"SafeMath").unwrap(); - - for capture in variable_declaration_regex.captures_iter(contract) { - let modifier = capture.get(0).map_or("default", |m| m.as_str()); - println!( - "SafeMath is no longer needed since solidity version 0.8.0, use of safeMath can be considered unnessary: {}", - modifier - ); - } -} - -pub fn token(contract: &str) { - let variable_declaration_regex = - Regex::new(r"(string (public|private|))\s*\b([a-zA-Z_]\w*)\b\s*=\s*(.*)").unwrap(); - - for capture in variable_declaration_regex.captures_iter(contract) { - let modifier = capture.get(0).map_or("default", |m| m.as_str()); - println!( - "For string of length less than 33, its better to use uint256 to store them: {}", - modifier - ); - } -} - -pub fn uint_incur_overhead(contract: &str) { - let variable_declaration_regex = - Regex::new(r#"\((uint24|uint8|uint160|uint16)\s*(public|private|internal)\s*[^}]*bool"#) - .unwrap(); - - for capture in variable_declaration_regex.captures_iter(contract) { - let modifier = capture.get(0).map_or("default", |m| m.as_str()); - println!( - "instead of a uint24, uint16 or any uint and int type apart from uint256 or int256, it's way better to use uint256 or int256: {}", - modifier - ); - } -} - -pub fn check_constructor_absence(contract: &str) { - let constructor_regex = Regex::new(r"constructor\s*\(.*\)").unwrap(); - - if constructor_regex.is_match(contract) { - let constructor_regex_payable = Regex::new(r"constructor\s*\(.*\)").unwrap(); - - if constructor_regex_payable.is_match(contract) { - println!("making the constructor payable saves gas in deployment cost"); - } - } else { - println!( - "Adding constructor to the code and making it payable saves gas in deployment cost" - ); - } -} diff --git a/tests/regex_expect_revert.sol b/tests/regex_expect_revert.sol new file mode 100644 index 0000000..ea84e84 --- /dev/null +++ b/tests/regex_expect_revert.sol @@ -0,0 +1,3 @@ +contract regex_expect_revert { + +} \ No newline at end of file