From a27111e6c4ef33265c8bc3667e8c3354f58ad8fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Thu, 19 Sep 2024 23:22:04 -0400 Subject: [PATCH 1/4] Add performance tests for bindings API --- Cargo.lock | 1 + crates/solidity/testing/perf/Cargo.toml | 5 +- .../testing/perf/benches/iai/dataset.rs | 55 +++++++++++++++++++ .../solidity/testing/perf/benches/iai/main.rs | 18 +++++- 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62746c612..69dd7078b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2460,6 +2460,7 @@ name = "solidity_testing_perf" version = "0.17.0" dependencies = [ "iai-callgrind", + "metaslang_bindings", "semver", "slang_solidity", ] diff --git a/crates/solidity/testing/perf/Cargo.toml b/crates/solidity/testing/perf/Cargo.toml index 2e05458bb..5a504564e 100644 --- a/crates/solidity/testing/perf/Cargo.toml +++ b/crates/solidity/testing/perf/Cargo.toml @@ -8,7 +8,10 @@ publish = false [dev-dependencies] iai-callgrind = { workspace = true } semver = { workspace = true } -slang_solidity = { workspace = true } +metaslang_bindings = { workspace = true } +slang_solidity = { workspace = true, features = [ + "__experimental_bindings_api", +] } [[bench]] name = "iai" diff --git a/crates/solidity/testing/perf/benches/iai/dataset.rs b/crates/solidity/testing/perf/benches/iai/dataset.rs index 44213f2a8..276129eae 100644 --- a/crates/solidity/testing/perf/benches/iai/dataset.rs +++ b/crates/solidity/testing/perf/benches/iai/dataset.rs @@ -1,6 +1,9 @@ use std::collections::BTreeSet; +use std::sync::Arc; +use metaslang_bindings::PathResolver; use semver::Version; +use slang_solidity::bindings::{self, Bindings}; use slang_solidity::cst::Node; use slang_solidity::kinds::{EdgeLabel, NonterminalKind}; use slang_solidity::language::Language; @@ -243,3 +246,55 @@ pub fn run_query(trees: &Vec) { "Function names don't match: {results:#?}" ); } + +struct NoOpResolver; + +impl PathResolver for NoOpResolver { + fn resolve_path(&self, _context_path: &str, path_to_resolve: &str) -> Option { + Some(path_to_resolve.to_string()) + } +} + +pub fn run_create_bindings() { + let _ = bindings::create_with_resolver(SOLC_VERSION, Arc::new(NoOpResolver {})); +} + +pub fn run_bindings(trees: &Vec) -> Vec { + let mut result = vec![]; + let mut definition_count = 0_usize; + + for tree in trees { + let mut bindings = bindings::create_with_resolver(SOLC_VERSION, Arc::new(NoOpResolver {})); + bindings.add_file("input.sol", tree.cursor_with_offset(TextIndex::ZERO)); + definition_count += bindings.all_definitions().count(); + result.push(bindings); + } + + // 723 definitions + println!("A total of {definition_count} definitions were found"); + + result +} + +pub fn prepare_bindings() -> Vec { + let trees = run_parser(); + run_bindings(&trees) +} + +pub fn run_resolve_references(bindings_vec: &Vec) { + let mut reference_count = 0_usize; + let mut resolved_references = 0_usize; + + for bindings in bindings_vec { + for reference in bindings.all_references() { + reference_count += 1; + let resolution = reference.jump_to_definition(); + if resolution.is_ok() { + resolved_references += 1; + } + } + } + + // 1491 references, 1170 resolved + println!("Out of a total of {reference_count} references found, {resolved_references} were unambiguously resolved"); +} diff --git a/crates/solidity/testing/perf/benches/iai/main.rs b/crates/solidity/testing/perf/benches/iai/main.rs index 066906d27..fa838fdca 100644 --- a/crates/solidity/testing/perf/benches/iai/main.rs +++ b/crates/solidity/testing/perf/benches/iai/main.rs @@ -15,6 +15,7 @@ use iai_callgrind::{ library_benchmark, library_benchmark_group, main, Direction, FlamegraphConfig, LibraryBenchmarkConfig, Tool, ValgrindTool, }; +use slang_solidity::bindings::Bindings; use slang_solidity::cst::Node; #[library_benchmark] @@ -32,10 +33,25 @@ fn query(trees: Vec) { black_box(dataset::run_query(&trees)); } +#[library_benchmark] +fn create_bindings() { + black_box(dataset::run_create_bindings()); +} + +#[library_benchmark(setup = dataset::run_parser)] +fn bindings(trees: Vec) { + black_box(dataset::run_bindings(&trees)); +} + +#[library_benchmark(setup = dataset::prepare_bindings)] +fn resolve_references(bindings: Vec) { + black_box(dataset::run_resolve_references(&bindings)); +} + library_benchmark_group!( name = benchmarks; - benchmarks = parser, cursor, query + benchmarks = parser, cursor, query, create_bindings, bindings, resolve_references ); main!( From 1a28a64e002b912ec562a168ac8dbcc3d09837f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Fri, 20 Sep 2024 14:50:00 -0400 Subject: [PATCH 2/4] Use asserts in place of printlns and simplify resolve test setup --- .../testing/perf/benches/iai/dataset.rs | 27 +++++++++---------- .../solidity/testing/perf/benches/iai/main.rs | 14 ++++------ 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/crates/solidity/testing/perf/benches/iai/dataset.rs b/crates/solidity/testing/perf/benches/iai/dataset.rs index 276129eae..6adea697f 100644 --- a/crates/solidity/testing/perf/benches/iai/dataset.rs +++ b/crates/solidity/testing/perf/benches/iai/dataset.rs @@ -255,11 +255,7 @@ impl PathResolver for NoOpResolver { } } -pub fn run_create_bindings() { - let _ = bindings::create_with_resolver(SOLC_VERSION, Arc::new(NoOpResolver {})); -} - -pub fn run_bindings(trees: &Vec) -> Vec { +pub fn run_build_bindings(trees: &Vec) -> Vec { let mut result = vec![]; let mut definition_count = 0_usize; @@ -270,17 +266,14 @@ pub fn run_bindings(trees: &Vec) -> Vec { result.push(bindings); } - // 723 definitions - println!("A total of {definition_count} definitions were found"); + assert!( + definition_count >= 723, + "Only found {definition_count} definitions" + ); result } -pub fn prepare_bindings() -> Vec { - let trees = run_parser(); - run_bindings(&trees) -} - pub fn run_resolve_references(bindings_vec: &Vec) { let mut reference_count = 0_usize; let mut resolved_references = 0_usize; @@ -295,6 +288,12 @@ pub fn run_resolve_references(bindings_vec: &Vec) { } } - // 1491 references, 1170 resolved - println!("Out of a total of {reference_count} references found, {resolved_references} were unambiguously resolved"); + assert!( + reference_count >= 1491, + "Only found {reference_count} references" + ); + assert!( + resolved_references >= 1170, + "Only resolved {resolved_references} references" + ); } diff --git a/crates/solidity/testing/perf/benches/iai/main.rs b/crates/solidity/testing/perf/benches/iai/main.rs index fa838fdca..9f0dd0d0b 100644 --- a/crates/solidity/testing/perf/benches/iai/main.rs +++ b/crates/solidity/testing/perf/benches/iai/main.rs @@ -33,17 +33,13 @@ fn query(trees: Vec) { black_box(dataset::run_query(&trees)); } -#[library_benchmark] -fn create_bindings() { - black_box(dataset::run_create_bindings()); -} - #[library_benchmark(setup = dataset::run_parser)] -fn bindings(trees: Vec) { - black_box(dataset::run_bindings(&trees)); +fn build_bindings(trees: Vec) { + black_box(dataset::run_build_bindings(&trees)); } -#[library_benchmark(setup = dataset::prepare_bindings)] +#[library_benchmark(setup = dataset::run_build_bindings)] +#[bench::run(args = (&dataset::run_parser()))] fn resolve_references(bindings: Vec) { black_box(dataset::run_resolve_references(&bindings)); } @@ -51,7 +47,7 @@ fn resolve_references(bindings: Vec) { library_benchmark_group!( name = benchmarks; - benchmarks = parser, cursor, query, create_bindings, bindings, resolve_references + benchmarks = parser, cursor, query, build_bindings, resolve_references ); main!( From 79ce1649d5d27b8c6f88691a4e98a355c2d5bfd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Fri, 20 Sep 2024 14:59:41 -0400 Subject: [PATCH 3/4] Use a single Bindings object instead of one per source file --- .../testing/perf/benches/iai/dataset.rs | 27 +++++++++---------- .../solidity/testing/perf/benches/iai/main.rs | 2 +- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/crates/solidity/testing/perf/benches/iai/dataset.rs b/crates/solidity/testing/perf/benches/iai/dataset.rs index 6adea697f..7b2bdd3de 100644 --- a/crates/solidity/testing/perf/benches/iai/dataset.rs +++ b/crates/solidity/testing/perf/benches/iai/dataset.rs @@ -255,15 +255,14 @@ impl PathResolver for NoOpResolver { } } -pub fn run_build_bindings(trees: &Vec) -> Vec { - let mut result = vec![]; +pub fn run_build_bindings(trees: &[Node]) -> Bindings { let mut definition_count = 0_usize; + let mut bindings = bindings::create_with_resolver(SOLC_VERSION, Arc::new(NoOpResolver {})); - for tree in trees { - let mut bindings = bindings::create_with_resolver(SOLC_VERSION, Arc::new(NoOpResolver {})); - bindings.add_file("input.sol", tree.cursor_with_offset(TextIndex::ZERO)); + for (index, tree) in trees.iter().enumerate() { + let path = format!("input{index}.sol"); + bindings.add_file(&path, tree.cursor_with_offset(TextIndex::ZERO)); definition_count += bindings.all_definitions().count(); - result.push(bindings); } assert!( @@ -271,20 +270,18 @@ pub fn run_build_bindings(trees: &Vec) -> Vec { "Only found {definition_count} definitions" ); - result + bindings } -pub fn run_resolve_references(bindings_vec: &Vec) { +pub fn run_resolve_references(bindings: &Bindings) { let mut reference_count = 0_usize; let mut resolved_references = 0_usize; - for bindings in bindings_vec { - for reference in bindings.all_references() { - reference_count += 1; - let resolution = reference.jump_to_definition(); - if resolution.is_ok() { - resolved_references += 1; - } + for reference in bindings.all_references() { + reference_count += 1; + let resolution = reference.jump_to_definition(); + if resolution.is_ok() { + resolved_references += 1; } } diff --git a/crates/solidity/testing/perf/benches/iai/main.rs b/crates/solidity/testing/perf/benches/iai/main.rs index 9f0dd0d0b..ba2d0c505 100644 --- a/crates/solidity/testing/perf/benches/iai/main.rs +++ b/crates/solidity/testing/perf/benches/iai/main.rs @@ -40,7 +40,7 @@ fn build_bindings(trees: Vec) { #[library_benchmark(setup = dataset::run_build_bindings)] #[bench::run(args = (&dataset::run_parser()))] -fn resolve_references(bindings: Vec) { +fn resolve_references(bindings: Bindings) { black_box(dataset::run_resolve_references(&bindings)); } From b8c9dd17a538d718b4550e2add1e64313c7530a5 Mon Sep 17 00:00:00 2001 From: OmarTawfik <15987992+OmarTawfik@users.noreply.github.com> Date: Tue, 24 Sep 2024 03:23:00 -0700 Subject: [PATCH 4/4] use perf dataset from npm --- .github/dependabot.yml | 3 + Cargo.lock | 1 + crates/solidity/testing/perf/Cargo.toml | 1 + .../testing/perf/benches/iai/dataset.rs | 306 +---- .../solidity/testing/perf/benches/iai/main.rs | 38 +- .../perf/benches/iai/sources/ERC20.sol | 317 ----- .../perf/benches/iai/sources/ERC721.sol | 484 ------- .../benches/iai/sources/EnumerableMap.sol | 534 -------- .../perf/benches/iai/sources/Governor.sol | 851 ------------ .../perf/benches/iai/sources/SafeCast.sol | 1154 ----------------- .../testing/perf/benches/iai/tests/cursor.rs | 27 + .../perf/benches/iai/tests/definitions.rs | 48 + .../testing/perf/benches/iai/tests/mod.rs | 5 + .../testing/perf/benches/iai/tests/parser.rs | 43 + .../testing/perf/benches/iai/tests/query.rs | 36 + .../perf/benches/iai/tests/references.rs | 33 + crates/solidity/testing/perf/package.json | 7 + package-lock.json | 17 + package.json | 1 + 19 files changed, 265 insertions(+), 3641 deletions(-) delete mode 100644 crates/solidity/testing/perf/benches/iai/sources/ERC20.sol delete mode 100644 crates/solidity/testing/perf/benches/iai/sources/ERC721.sol delete mode 100644 crates/solidity/testing/perf/benches/iai/sources/EnumerableMap.sol delete mode 100644 crates/solidity/testing/perf/benches/iai/sources/Governor.sol delete mode 100644 crates/solidity/testing/perf/benches/iai/sources/SafeCast.sol create mode 100644 crates/solidity/testing/perf/benches/iai/tests/cursor.rs create mode 100644 crates/solidity/testing/perf/benches/iai/tests/definitions.rs create mode 100644 crates/solidity/testing/perf/benches/iai/tests/mod.rs create mode 100644 crates/solidity/testing/perf/benches/iai/tests/parser.rs create mode 100644 crates/solidity/testing/perf/benches/iai/tests/query.rs create mode 100644 crates/solidity/testing/perf/benches/iai/tests/references.rs create mode 100644 crates/solidity/testing/perf/package.json diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7171cbf0c..964644f07 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -34,6 +34,9 @@ updates: update-types: - "minor" - "patch" + ignore: + # openzeppelin contracts used in perf tests. don't update/change, to prevent variations/failures in results: + - dependency-name: "@openzeppelin/contracts" - package-ecosystem: "github-actions" directory: "/" diff --git a/Cargo.lock b/Cargo.lock index 69dd7078b..03b0f0dce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2460,6 +2460,7 @@ name = "solidity_testing_perf" version = "0.17.0" dependencies = [ "iai-callgrind", + "infra_utils", "metaslang_bindings", "semver", "slang_solidity", diff --git a/crates/solidity/testing/perf/Cargo.toml b/crates/solidity/testing/perf/Cargo.toml index 5a504564e..932f817b3 100644 --- a/crates/solidity/testing/perf/Cargo.toml +++ b/crates/solidity/testing/perf/Cargo.toml @@ -7,6 +7,7 @@ publish = false [dev-dependencies] iai-callgrind = { workspace = true } +infra_utils = { workspace = true } semver = { workspace = true } metaslang_bindings = { workspace = true } slang_solidity = { workspace = true, features = [ diff --git a/crates/solidity/testing/perf/benches/iai/dataset.rs b/crates/solidity/testing/perf/benches/iai/dataset.rs index 7b2bdd3de..96038a0bd 100644 --- a/crates/solidity/testing/perf/benches/iai/dataset.rs +++ b/crates/solidity/testing/perf/benches/iai/dataset.rs @@ -1,296 +1,36 @@ -use std::collections::BTreeSet; -use std::sync::Arc; +use std::path::PathBuf; -use metaslang_bindings::PathResolver; +use infra_utils::cargo::CargoWorkspace; +use infra_utils::paths::PathExtensions; use semver::Version; -use slang_solidity::bindings::{self, Bindings}; -use slang_solidity::cst::Node; -use slang_solidity::kinds::{EdgeLabel, NonterminalKind}; -use slang_solidity::language::Language; -use slang_solidity::query::Query; -use slang_solidity::text_index::TextIndex; -const SOLC_VERSION: Version = Version::new(0, 8, 20); +pub const SOLC_VERSION: Version = Version::new(0, 8, 20); const SOURCES: &[&str] = &[ - include_str!("./sources/EnumerableMap.sol"), - include_str!("./sources/ERC20.sol"), - include_str!("./sources/ERC721.sol"), - include_str!("./sources/Governor.sol"), - include_str!("./sources/SafeCast.sol"), + "node_modules/@openzeppelin/contracts/governance/Governor.sol", + "node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol", + "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol", + "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol", + "node_modules/@openzeppelin/contracts/utils/structs/EnumerableMap.sol", ]; -const FUNCTION_NAMES: &[&str] = &[ - "CLOCK_MODE", - "_approve", - "_baseURI", - "_burn", - "_cancel", - "_castVote", - "_checkAuthorized", - "_checkGovernance", - "_checkOnERC721Received", - "_countVote", - "_defaultParams", - "_encodeStateBitmap", - "_executeOperations", - "_executor", - "_getApproved", - "_getVotes", - "_increaseBalance", - "_isAuthorized", - "_isValidDescriptionForProposer", - "_mint", - "_ownerOf", - "_propose", - "_queueOperations", - "_quorumReached", - "_requireOwned", - "_safeMint", - "_safeTransfer", - "_setApprovalForAll", - "_spendAllowance", - "_transfer", - "_tryHexToUint", - "_update", - "_validateStateBitmap", - "_voteSucceeded", - "allowance", - "approve", - "at", - "balanceOf", - "cancel", - "castVote", - "castVoteBySig", - "castVoteWithReason", - "castVoteWithReasonAndParams", - "castVoteWithReasonAndParamsBySig", - "clock", - "contains", - "decimals", - "execute", - "get", - "getApproved", - "getVotes", - "getVotesWithParams", - "hashProposal", - "isApprovedForAll", - "keys", - "length", - "name", - "onERC1155BatchReceived", - "onERC1155Received", - "onERC721Received", - "ownerOf", - "proposalDeadline", - "proposalEta", - "proposalNeedsQueuing", - "proposalProposer", - "proposalSnapshot", - "proposalThreshold", - "propose", - "queue", - "quorum", - "relay", - "remove", - "safeTransferFrom", - "set", - "setApprovalForAll", - "state", - "supportsInterface", - "symbol", - "toInt104", - "toInt112", - "toInt120", - "toInt128", - "toInt136", - "toInt144", - "toInt152", - "toInt16", - "toInt160", - "toInt168", - "toInt176", - "toInt184", - "toInt192", - "toInt200", - "toInt208", - "toInt216", - "toInt224", - "toInt232", - "toInt24", - "toInt240", - "toInt248", - "toInt256", - "toInt32", - "toInt40", - "toInt48", - "toInt56", - "toInt64", - "toInt72", - "toInt8", - "toInt80", - "toInt88", - "toInt96", - "toUint104", - "toUint112", - "toUint120", - "toUint128", - "toUint136", - "toUint144", - "toUint152", - "toUint16", - "toUint160", - "toUint168", - "toUint176", - "toUint184", - "toUint192", - "toUint200", - "toUint208", - "toUint216", - "toUint224", - "toUint232", - "toUint24", - "toUint240", - "toUint248", - "toUint256", - "toUint32", - "toUint40", - "toUint48", - "toUint56", - "toUint64", - "toUint72", - "toUint8", - "toUint80", - "toUint88", - "toUint96", - "tokenURI", - "totalSupply", - "transfer", - "transferFrom", - "tryGet", - "version", - "votingDelay", - "votingPeriod", -]; - -pub fn run_parser() -> Vec { - let language = Language::new(SOLC_VERSION).unwrap(); - - let mut trees = vec![]; - - for source in SOURCES { - let parse_output = language.parse(Language::ROOT_KIND, source); - - assert!( - parse_output.is_valid(), - "Found parse errors:\n{0:#?}", - parse_output.errors(), - ); - - trees.push(parse_output.tree()); - } - - trees -} - -pub fn run_cursor(trees: &Vec) { - let mut results = BTreeSet::new(); - - for tree in trees { - let mut cursor = tree.cursor_with_offset(TextIndex::ZERO); - - while cursor.go_to_next_nonterminal_with_kind(NonterminalKind::FunctionDefinition) { - results.extend( - cursor - .node() - .children() - .iter() - .filter(|edge| edge.label == Some(EdgeLabel::Name)) - .map(|edge| edge.node.clone().unparse().trim().to_owned()), - ); - } - } - - assert!( - results.iter().eq(FUNCTION_NAMES.iter()), - "Function names don't match: {results:#?}" - ); -} - -pub fn run_query(trees: &Vec) { - let mut results = BTreeSet::new(); - - let queries = vec![Query::parse( - "[FunctionDefinition - @name name: [_] - ]", - ) - .unwrap()]; - - for tree in trees { - let cursor = tree.cursor_with_offset(TextIndex::ZERO); - - for query_match in cursor.query(queries.clone()) { - assert_eq!(query_match.captures.len(), 1); - - results.extend( - query_match.captures["name"] - .iter() - .map(|cursor| cursor.node().unparse().trim().to_owned()), - ); - } - } - - assert!( - results.iter().eq(FUNCTION_NAMES.iter()), - "Function names don't match: {results:#?}" - ); -} - -struct NoOpResolver; - -impl PathResolver for NoOpResolver { - fn resolve_path(&self, _context_path: &str, path_to_resolve: &str) -> Option { - Some(path_to_resolve.to_string()) - } +pub struct SourceFile { + pub path: PathBuf, + pub contents: String, } -pub fn run_build_bindings(trees: &[Node]) -> Bindings { - let mut definition_count = 0_usize; - let mut bindings = bindings::create_with_resolver(SOLC_VERSION, Arc::new(NoOpResolver {})); - - for (index, tree) in trees.iter().enumerate() { - let path = format!("input{index}.sol"); - bindings.add_file(&path, tree.cursor_with_offset(TextIndex::ZERO)); - definition_count += bindings.all_definitions().count(); - } - - assert!( - definition_count >= 723, - "Only found {definition_count} definitions" - ); - - bindings -} +impl SourceFile { + pub fn load_all() -> Vec { + let crate_dir = CargoWorkspace::locate_source_crate("solidity_testing_perf").unwrap(); -pub fn run_resolve_references(bindings: &Bindings) { - let mut reference_count = 0_usize; - let mut resolved_references = 0_usize; + SOURCES + .iter() + .map(|relative_path| { + let path = crate_dir.join(relative_path); + let contents = path.read_to_string().unwrap(); - for reference in bindings.all_references() { - reference_count += 1; - let resolution = reference.jump_to_definition(); - if resolution.is_ok() { - resolved_references += 1; - } + Self { path, contents } + }) + .collect() } - - assert!( - reference_count >= 1491, - "Only found {reference_count} references" - ); - assert!( - resolved_references >= 1170, - "Only resolved {resolved_references} references" - ); } diff --git a/crates/solidity/testing/perf/benches/iai/main.rs b/crates/solidity/testing/perf/benches/iai/main.rs index ba2d0c505..7c4565299 100644 --- a/crates/solidity/testing/perf/benches/iai/main.rs +++ b/crates/solidity/testing/perf/benches/iai/main.rs @@ -8,6 +8,7 @@ #![allow(clippy::unit_arg)] mod dataset; +mod tests; use std::hint::black_box; @@ -16,38 +17,39 @@ use iai_callgrind::{ LibraryBenchmarkConfig, Tool, ValgrindTool, }; use slang_solidity::bindings::Bindings; -use slang_solidity::cst::Node; -#[library_benchmark] -fn parser() { - black_box(dataset::run_parser()); +use crate::dataset::SourceFile; +use crate::tests::parser::ParsedFile; + +#[library_benchmark(setup = tests::parser::setup)] +fn parser(files: Vec) { + black_box(tests::parser::run(files)); } -#[library_benchmark(setup = dataset::run_parser)] -fn cursor(trees: Vec) { - black_box(dataset::run_cursor(&trees)); +#[library_benchmark(setup = tests::cursor::setup)] +fn cursor(files: Vec) { + black_box(tests::cursor::run(&files)); } -#[library_benchmark(setup = dataset::run_parser)] -fn query(trees: Vec) { - black_box(dataset::run_query(&trees)); +#[library_benchmark(setup = tests::query::setup)] +fn query(files: Vec) { + black_box(tests::query::run(&files)); } -#[library_benchmark(setup = dataset::run_parser)] -fn build_bindings(trees: Vec) { - black_box(dataset::run_build_bindings(&trees)); +#[library_benchmark(setup = tests::definitions::setup)] +fn definitions(files: Vec) { + black_box(tests::definitions::run(&files)); } -#[library_benchmark(setup = dataset::run_build_bindings)] -#[bench::run(args = (&dataset::run_parser()))] -fn resolve_references(bindings: Bindings) { - black_box(dataset::run_resolve_references(&bindings)); +#[library_benchmark(setup = tests::references::setup)] +fn references(bindings: Bindings) { + black_box(tests::references::run(&bindings)); } library_benchmark_group!( name = benchmarks; - benchmarks = parser, cursor, query, build_bindings, resolve_references + benchmarks = parser, cursor, query, definitions, references ); main!( diff --git a/crates/solidity/testing/perf/benches/iai/sources/ERC20.sol b/crates/solidity/testing/perf/benches/iai/sources/ERC20.sol deleted file mode 100644 index dfaf9aec8..000000000 --- a/crates/solidity/testing/perf/benches/iai/sources/ERC20.sol +++ /dev/null @@ -1,317 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) -// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC20/ERC20.sol - -pragma solidity ^0.8.20; - -import {IERC20} from "./IERC20.sol"; -import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; -import {Context} from "../../utils/Context.sol"; -import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; - -/** - * @dev Implementation of the {IERC20} interface. - * - * This implementation is agnostic to the way tokens are created. This means - * that a supply mechanism has to be added in a derived contract using {_mint}. - * - * TIP: For a detailed writeup see our guide - * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How - * to implement supply mechanisms]. - * - * The default value of {decimals} is 18. To change this, you should override - * this function so it returns a different value. - * - * We have followed general OpenZeppelin Contracts guidelines: functions revert - * instead returning `false` on failure. This behavior is nonetheless - * conventional and does not conflict with the expectations of ERC20 - * applications. - * - * Additionally, an {Approval} event is emitted on calls to {transferFrom}. - * This allows applications to reconstruct the allowance for all accounts just - * by listening to said events. Other implementations of the EIP may not emit - * these events, as it isn't required by the specification. - */ -abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { - mapping(address account => uint256) private _balances; - - mapping(address account => mapping(address spender => uint256)) private _allowances; - - uint256 private _totalSupply; - - string private _name; - string private _symbol; - - /** - * @dev Sets the values for {name} and {symbol}. - * - * All two of these values are immutable: they can only be set once during - * construction. - */ - constructor(string memory name_, string memory symbol_) { - _name = name_; - _symbol = symbol_; - } - - /** - * @dev Returns the name of the token. - */ - function name() public view virtual returns (string memory) { - return _name; - } - - /** - * @dev Returns the symbol of the token, usually a shorter version of the - * name. - */ - function symbol() public view virtual returns (string memory) { - return _symbol; - } - - /** - * @dev Returns the number of decimals used to get its user representation. - * For example, if `decimals` equals `2`, a balance of `505` tokens should - * be displayed to a user as `5.05` (`505 / 10 ** 2`). - * - * Tokens usually opt for a value of 18, imitating the relationship between - * Ether and Wei. This is the default value returned by this function, unless - * it's overridden. - * - * NOTE: This information is only used for _display_ purposes: it in - * no way affects any of the arithmetic of the contract, including - * {IERC20-balanceOf} and {IERC20-transfer}. - */ - function decimals() public view virtual returns (uint8) { - return 18; - } - - /** - * @dev See {IERC20-totalSupply}. - */ - function totalSupply() public view virtual returns (uint256) { - return _totalSupply; - } - - /** - * @dev See {IERC20-balanceOf}. - */ - function balanceOf(address account) public view virtual returns (uint256) { - return _balances[account]; - } - - /** - * @dev See {IERC20-transfer}. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - the caller must have a balance of at least `value`. - */ - function transfer(address to, uint256 value) public virtual returns (bool) { - address owner = _msgSender(); - _transfer(owner, to, value); - return true; - } - - /** - * @dev See {IERC20-allowance}. - */ - function allowance(address owner, address spender) public view virtual returns (uint256) { - return _allowances[owner][spender]; - } - - /** - * @dev See {IERC20-approve}. - * - * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on - * `transferFrom`. This is semantically equivalent to an infinite approval. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function approve(address spender, uint256 value) public virtual returns (bool) { - address owner = _msgSender(); - _approve(owner, spender, value); - return true; - } - - /** - * @dev See {IERC20-transferFrom}. - * - * Emits an {Approval} event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of {ERC20}. - * - * NOTE: Does not update the allowance if the current allowance - * is the maximum `uint256`. - * - * Requirements: - * - * - `from` and `to` cannot be the zero address. - * - `from` must have a balance of at least `value`. - * - the caller must have allowance for ``from``'s tokens of at least - * `value`. - */ - function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { - address spender = _msgSender(); - _spendAllowance(from, spender, value); - _transfer(from, to, value); - return true; - } - - /** - * @dev Moves a `value` amount of tokens from `from` to `to`. - * - * This internal function is equivalent to {transfer}, and can be used to - * e.g. implement automatic token fees, slashing mechanisms, etc. - * - * Emits a {Transfer} event. - * - * NOTE: This function is not virtual, {_update} should be overridden instead. - */ - function _transfer(address from, address to, uint256 value) internal { - if (from == address(0)) { - revert ERC20InvalidSender(address(0)); - } - if (to == address(0)) { - revert ERC20InvalidReceiver(address(0)); - } - _update(from, to, value); - } - - /** - * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` - * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding - * this function. - * - * Emits a {Transfer} event. - */ - function _update(address from, address to, uint256 value) internal virtual { - if (from == address(0)) { - // Overflow check required: The rest of the code assumes that totalSupply never overflows - _totalSupply += value; - } else { - uint256 fromBalance = _balances[from]; - if (fromBalance < value) { - revert ERC20InsufficientBalance(from, fromBalance, value); - } - unchecked { - // Overflow not possible: value <= fromBalance <= totalSupply. - _balances[from] = fromBalance - value; - } - } - - if (to == address(0)) { - unchecked { - // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. - _totalSupply -= value; - } - } else { - unchecked { - // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. - _balances[to] += value; - } - } - - emit Transfer(from, to, value); - } - - /** - * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). - * Relies on the `_update` mechanism - * - * Emits a {Transfer} event with `from` set to the zero address. - * - * NOTE: This function is not virtual, {_update} should be overridden instead. - */ - function _mint(address account, uint256 value) internal { - if (account == address(0)) { - revert ERC20InvalidReceiver(address(0)); - } - _update(address(0), account, value); - } - - /** - * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. - * Relies on the `_update` mechanism. - * - * Emits a {Transfer} event with `to` set to the zero address. - * - * NOTE: This function is not virtual, {_update} should be overridden instead - */ - function _burn(address account, uint256 value) internal { - if (account == address(0)) { - revert ERC20InvalidSender(address(0)); - } - _update(account, address(0), value); - } - - /** - * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. - * - * This internal function is equivalent to `approve`, and can be used to - * e.g. set automatic allowances for certain subsystems, etc. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `owner` cannot be the zero address. - * - `spender` cannot be the zero address. - * - * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. - */ - function _approve(address owner, address spender, uint256 value) internal { - _approve(owner, spender, value, true); - } - - /** - * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. - * - * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by - * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any - * `Approval` event during `transferFrom` operations. - * - * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to - * true using the following override: - * ``` - * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { - * super._approve(owner, spender, value, true); - * } - * ``` - * - * Requirements are the same as {_approve}. - */ - function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { - if (owner == address(0)) { - revert ERC20InvalidApprover(address(0)); - } - if (spender == address(0)) { - revert ERC20InvalidSpender(address(0)); - } - _allowances[owner][spender] = value; - if (emitEvent) { - emit Approval(owner, spender, value); - } - } - - /** - * @dev Updates `owner` s allowance for `spender` based on spent `value`. - * - * Does not update the allowance value in case of infinite allowance. - * Revert if not enough allowance is available. - * - * Does not emit an {Approval} event. - */ - function _spendAllowance(address owner, address spender, uint256 value) internal virtual { - uint256 currentAllowance = allowance(owner, spender); - if (currentAllowance != type(uint256).max) { - if (currentAllowance < value) { - revert ERC20InsufficientAllowance(spender, currentAllowance, value); - } - unchecked { - _approve(owner, spender, currentAllowance - value, false); - } - } - } -} diff --git a/crates/solidity/testing/perf/benches/iai/sources/ERC721.sol b/crates/solidity/testing/perf/benches/iai/sources/ERC721.sol deleted file mode 100644 index 61e678550..000000000 --- a/crates/solidity/testing/perf/benches/iai/sources/ERC721.sol +++ /dev/null @@ -1,484 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol) -// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC721/ERC721.sol - -pragma solidity ^0.8.20; - -import {IERC721} from "./IERC721.sol"; -import {IERC721Receiver} from "./IERC721Receiver.sol"; -import {IERC721Metadata} from "./extensions/IERC721Metadata.sol"; -import {Context} from "../../utils/Context.sol"; -import {Strings} from "../../utils/Strings.sol"; -import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; -import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol"; - -/** - * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including - * the Metadata extension, but not including the Enumerable extension, which is available separately as - * {ERC721Enumerable}. - */ -abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors { - using Strings for uint256; - - // Token name - string private _name; - - // Token symbol - string private _symbol; - - mapping(uint256 tokenId => address) private _owners; - - mapping(address owner => uint256) private _balances; - - mapping(uint256 tokenId => address) private _tokenApprovals; - - mapping(address owner => mapping(address operator => bool)) private _operatorApprovals; - - /** - * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. - */ - constructor(string memory name_, string memory symbol_) { - _name = name_; - _symbol = symbol_; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { - return - interfaceId == type(IERC721).interfaceId || - interfaceId == type(IERC721Metadata).interfaceId || - super.supportsInterface(interfaceId); - } - - /** - * @dev See {IERC721-balanceOf}. - */ - function balanceOf(address owner) public view virtual returns (uint256) { - if (owner == address(0)) { - revert ERC721InvalidOwner(address(0)); - } - return _balances[owner]; - } - - /** - * @dev See {IERC721-ownerOf}. - */ - function ownerOf(uint256 tokenId) public view virtual returns (address) { - return _requireOwned(tokenId); - } - - /** - * @dev See {IERC721Metadata-name}. - */ - function name() public view virtual returns (string memory) { - return _name; - } - - /** - * @dev See {IERC721Metadata-symbol}. - */ - function symbol() public view virtual returns (string memory) { - return _symbol; - } - - /** - * @dev See {IERC721Metadata-tokenURI}. - */ - function tokenURI(uint256 tokenId) public view virtual returns (string memory) { - _requireOwned(tokenId); - - string memory baseURI = _baseURI(); - return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : ""; - } - - /** - * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each - * token will be the concatenation of the `baseURI` and the `tokenId`. Empty - * by default, can be overridden in child contracts. - */ - function _baseURI() internal view virtual returns (string memory) { - return ""; - } - - /** - * @dev See {IERC721-approve}. - */ - function approve(address to, uint256 tokenId) public virtual { - _approve(to, tokenId, _msgSender()); - } - - /** - * @dev See {IERC721-getApproved}. - */ - function getApproved(uint256 tokenId) public view virtual returns (address) { - _requireOwned(tokenId); - - return _getApproved(tokenId); - } - - /** - * @dev See {IERC721-setApprovalForAll}. - */ - function setApprovalForAll(address operator, bool approved) public virtual { - _setApprovalForAll(_msgSender(), operator, approved); - } - - /** - * @dev See {IERC721-isApprovedForAll}. - */ - function isApprovedForAll(address owner, address operator) public view virtual returns (bool) { - return _operatorApprovals[owner][operator]; - } - - /** - * @dev See {IERC721-transferFrom}. - */ - function transferFrom(address from, address to, uint256 tokenId) public virtual { - if (to == address(0)) { - revert ERC721InvalidReceiver(address(0)); - } - // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists - // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. - address previousOwner = _update(to, tokenId, _msgSender()); - if (previousOwner != from) { - revert ERC721IncorrectOwner(from, tokenId, previousOwner); - } - } - - /** - * @dev See {IERC721-safeTransferFrom}. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public { - safeTransferFrom(from, to, tokenId, ""); - } - - /** - * @dev See {IERC721-safeTransferFrom}. - */ - function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual { - transferFrom(from, to, tokenId); - _checkOnERC721Received(from, to, tokenId, data); - } - - /** - * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist - * - * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the - * core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances - * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by - * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`. - */ - function _ownerOf(uint256 tokenId) internal view virtual returns (address) { - return _owners[tokenId]; - } - - /** - * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted. - */ - function _getApproved(uint256 tokenId) internal view virtual returns (address) { - return _tokenApprovals[tokenId]; - } - - /** - * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in - * particular (ignoring whether it is owned by `owner`). - * - * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this - * assumption. - */ - function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) { - return - spender != address(0) && - (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender); - } - - /** - * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner. - * Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets - * the `spender` for the specific `tokenId`. - * - * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this - * assumption. - */ - function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual { - if (!_isAuthorized(owner, spender, tokenId)) { - if (owner == address(0)) { - revert ERC721NonexistentToken(tokenId); - } else { - revert ERC721InsufficientApproval(spender, tokenId); - } - } - } - - /** - * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. - * - * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that - * a uint256 would ever overflow from increments when these increments are bounded to uint128 values. - * - * WARNING: Increasing an account's balance using this function tends to be paired with an override of the - * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership - * remain consistent with one another. - */ - function _increaseBalance(address account, uint128 value) internal virtual { - unchecked { - _balances[account] += value; - } - } - - /** - * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner - * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update. - * - * The `auth` argument is optional. If the value passed is non 0, then this function will check that - * `auth` is either the owner of the token, or approved to operate on the token (by the owner). - * - * Emits a {Transfer} event. - * - * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}. - */ - function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) { - address from = _ownerOf(tokenId); - - // Perform (optional) operator check - if (auth != address(0)) { - _checkAuthorized(from, auth, tokenId); - } - - // Execute the update - if (from != address(0)) { - // Clear approval. No need to re-authorize or emit the Approval event - _approve(address(0), tokenId, address(0), false); - - unchecked { - _balances[from] -= 1; - } - } - - if (to != address(0)) { - unchecked { - _balances[to] += 1; - } - } - - _owners[tokenId] = to; - - emit Transfer(from, to, tokenId); - - return from; - } - - /** - * @dev Mints `tokenId` and transfers it to `to`. - * - * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible - * - * Requirements: - * - * - `tokenId` must not exist. - * - `to` cannot be the zero address. - * - * Emits a {Transfer} event. - */ - function _mint(address to, uint256 tokenId) internal { - if (to == address(0)) { - revert ERC721InvalidReceiver(address(0)); - } - address previousOwner = _update(to, tokenId, address(0)); - if (previousOwner != address(0)) { - revert ERC721InvalidSender(address(0)); - } - } - - /** - * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance. - * - * Requirements: - * - * - `tokenId` must not exist. - * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. - * - * Emits a {Transfer} event. - */ - function _safeMint(address to, uint256 tokenId) internal { - _safeMint(to, tokenId, ""); - } - - /** - * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is - * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. - */ - function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { - _mint(to, tokenId); - _checkOnERC721Received(address(0), to, tokenId, data); - } - - /** - * @dev Destroys `tokenId`. - * The approval is cleared when the token is burned. - * This is an internal function that does not check if the sender is authorized to operate on the token. - * - * Requirements: - * - * - `tokenId` must exist. - * - * Emits a {Transfer} event. - */ - function _burn(uint256 tokenId) internal { - address previousOwner = _update(address(0), tokenId, address(0)); - if (previousOwner == address(0)) { - revert ERC721NonexistentToken(tokenId); - } - } - - /** - * @dev Transfers `tokenId` from `from` to `to`. - * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - `tokenId` token must be owned by `from`. - * - * Emits a {Transfer} event. - */ - function _transfer(address from, address to, uint256 tokenId) internal { - if (to == address(0)) { - revert ERC721InvalidReceiver(address(0)); - } - address previousOwner = _update(to, tokenId, address(0)); - if (previousOwner == address(0)) { - revert ERC721NonexistentToken(tokenId); - } else if (previousOwner != from) { - revert ERC721IncorrectOwner(from, tokenId, previousOwner); - } - } - - /** - * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients - * are aware of the ERC721 standard to prevent tokens from being forever locked. - * - * `data` is additional data, it has no specified format and it is sent in call to `to`. - * - * This internal function is like {safeTransferFrom} in the sense that it invokes - * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g. - * implement alternative mechanisms to perform token transfer, such as signature-based. - * - * Requirements: - * - * - `tokenId` token must exist and be owned by `from`. - * - `to` cannot be the zero address. - * - `from` cannot be the zero address. - * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. - * - * Emits a {Transfer} event. - */ - function _safeTransfer(address from, address to, uint256 tokenId) internal { - _safeTransfer(from, to, tokenId, ""); - } - - /** - * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is - * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. - */ - function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { - _transfer(from, to, tokenId); - _checkOnERC721Received(from, to, tokenId, data); - } - - /** - * @dev Approve `to` to operate on `tokenId` - * - * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is - * either the owner of the token, or approved to operate on all tokens held by this owner. - * - * Emits an {Approval} event. - * - * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. - */ - function _approve(address to, uint256 tokenId, address auth) internal { - _approve(to, tokenId, auth, true); - } - - /** - * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not - * emitted in the context of transfers. - */ - function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual { - // Avoid reading the owner unless necessary - if (emitEvent || auth != address(0)) { - address owner = _requireOwned(tokenId); - - // We do not use _isAuthorized because single-token approvals should not be able to call approve - if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) { - revert ERC721InvalidApprover(auth); - } - - if (emitEvent) { - emit Approval(owner, to, tokenId); - } - } - - _tokenApprovals[tokenId] = to; - } - - /** - * @dev Approve `operator` to operate on all of `owner` tokens - * - * Requirements: - * - operator can't be the address zero. - * - * Emits an {ApprovalForAll} event. - */ - function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { - if (operator == address(0)) { - revert ERC721InvalidOperator(operator); - } - _operatorApprovals[owner][operator] = approved; - emit ApprovalForAll(owner, operator, approved); - } - - /** - * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned). - * Returns the owner. - * - * Overrides to ownership logic should be done to {_ownerOf}. - */ - function _requireOwned(uint256 tokenId) internal view returns (address) { - address owner = _ownerOf(tokenId); - if (owner == address(0)) { - revert ERC721NonexistentToken(tokenId); - } - return owner; - } - - /** - * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the - * recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract. - * - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param data bytes optional data to send along with the call - */ - function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private { - if (to.code.length > 0) { - try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { - if (retval != IERC721Receiver.onERC721Received.selector) { - revert ERC721InvalidReceiver(to); - } - } catch (bytes memory reason) { - if (reason.length == 0) { - revert ERC721InvalidReceiver(to); - } else { - /// @solidity memory-safe-assembly - assembly { - revert(add(32, reason), mload(reason)) - } - } - } - } - } -} diff --git a/crates/solidity/testing/perf/benches/iai/sources/EnumerableMap.sol b/crates/solidity/testing/perf/benches/iai/sources/EnumerableMap.sol deleted file mode 100644 index 1ac10eecf..000000000 --- a/crates/solidity/testing/perf/benches/iai/sources/EnumerableMap.sol +++ /dev/null @@ -1,534 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableMap.sol) -// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/utils/structs/EnumerableMap.sol -// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. - -pragma solidity ^0.8.20; - -import {EnumerableSet} from "./EnumerableSet.sol"; - -/** - * @dev Library for managing an enumerable variant of Solidity's - * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] - * type. - * - * Maps have the following properties: - * - * - Entries are added, removed, and checked for existence in constant time - * (O(1)). - * - Entries are enumerated in O(n). No guarantees are made on the ordering. - * - * ```solidity - * contract Example { - * // Add the library methods - * using EnumerableMap for EnumerableMap.UintToAddressMap; - * - * // Declare a set state variable - * EnumerableMap.UintToAddressMap private myMap; - * } - * ``` - * - * The following map types are supported: - * - * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 - * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 - * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 - * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 - * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure - * unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an - * array of EnumerableMap. - * ==== - */ -library EnumerableMap { - using EnumerableSet for EnumerableSet.Bytes32Set; - - // To implement this library for multiple types with as little code repetition as possible, we write it in - // terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions, - // and user-facing implementations such as `UintToAddressMap` are just wrappers around the underlying Map. - // This means that we can only create new EnumerableMaps for types that fit in bytes32. - - /** - * @dev Query for a nonexistent map key. - */ - error EnumerableMapNonexistentKey(bytes32 key); - - struct Bytes32ToBytes32Map { - // Storage of keys - EnumerableSet.Bytes32Set _keys; - mapping(bytes32 key => bytes32) _values; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) { - map._values[key] = value; - return map._keys.add(key); - } - - /** - * @dev Removes a key-value pair from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { - delete map._values[key]; - return map._keys.remove(key); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { - return map._keys.contains(key); - } - - /** - * @dev Returns the number of key-value pairs in the map. O(1). - */ - function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { - return map._keys.length(); - } - - /** - * @dev Returns the key-value pair stored at position `index` in the map. O(1). - * - * Note that there are no guarantees on the ordering of entries inside the - * array, and it may change when more entries are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { - bytes32 key = map._keys.at(index); - return (key, map._values[key]); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { - bytes32 value = map._values[key]; - if (value == bytes32(0)) { - return (contains(map, key), bytes32(0)); - } else { - return (true, value); - } - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { - bytes32 value = map._values[key]; - if (value == 0 && !contains(map, key)) { - revert EnumerableMapNonexistentKey(key); - } - return value; - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) { - return map._keys.values(); - } - - // UintToUintMap - - struct UintToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) { - return set(map._inner, bytes32(key), bytes32(value)); - } - - /** - * @dev Removes a value from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { - return remove(map._inner, bytes32(key)); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { - return contains(map._inner, bytes32(key)); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(UintToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the map. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (uint256(key), uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(key))); - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(UintToUintMap storage map) internal view returns (uint256[] memory) { - bytes32[] memory store = keys(map._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintToAddressMap - - struct UintToAddressMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { - return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { - return remove(map._inner, bytes32(key)); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { - return contains(map._inner, bytes32(key)); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(UintToAddressMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the map. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (uint256(key), address(uint160(uint256(value)))); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); - return (success, address(uint160(uint256(value)))); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { - return address(uint160(uint256(get(map._inner, bytes32(key))))); - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) { - bytes32[] memory store = keys(map._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // AddressToUintMap - - struct AddressToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) { - return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); - } - - /** - * @dev Removes a value from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(AddressToUintMap storage map, address key) internal returns (bool) { - return remove(map._inner, bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(AddressToUintMap storage map, address key) internal view returns (bool) { - return contains(map._inner, bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(AddressToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the map. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (address(uint160(uint256(key))), uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(AddressToUintMap storage map, address key) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(uint256(uint160(key))))); - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(AddressToUintMap storage map) internal view returns (address[] memory) { - bytes32[] memory store = keys(map._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // Bytes32ToUintMap - - struct Bytes32ToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) { - return set(map._inner, key, bytes32(value)); - } - - /** - * @dev Removes a value from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { - return remove(map._inner, key); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { - return contains(map._inner, key); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(Bytes32ToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the map. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (key, uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, key); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { - return uint256(get(map._inner, key)); - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) { - bytes32[] memory store = keys(map._inner); - bytes32[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} diff --git a/crates/solidity/testing/perf/benches/iai/sources/Governor.sol b/crates/solidity/testing/perf/benches/iai/sources/Governor.sol deleted file mode 100644 index 90950da17..000000000 --- a/crates/solidity/testing/perf/benches/iai/sources/Governor.sol +++ /dev/null @@ -1,851 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (governance/Governor.sol) -// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/governance/Governor.sol - -pragma solidity ^0.8.20; - -import {IERC721Receiver} from "../token/ERC721/IERC721Receiver.sol"; -import {IERC1155Receiver} from "../token/ERC1155/IERC1155Receiver.sol"; -import {EIP712} from "../utils/cryptography/EIP712.sol"; -import {SignatureChecker} from "../utils/cryptography/SignatureChecker.sol"; -import {IERC165, ERC165} from "../utils/introspection/ERC165.sol"; -import {SafeCast} from "../utils/math/SafeCast.sol"; -import {DoubleEndedQueue} from "../utils/structs/DoubleEndedQueue.sol"; -import {Address} from "../utils/Address.sol"; -import {Context} from "../utils/Context.sol"; -import {Nonces} from "../utils/Nonces.sol"; -import {IGovernor, IERC6372} from "./IGovernor.sol"; - -/** - * @dev Core of the governance system, designed to be extended through various modules. - * - * This contract is abstract and requires several functions to be implemented in various modules: - * - * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote} - * - A voting module must implement {_getVotes} - * - Additionally, {votingPeriod} must also be implemented - */ -abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC721Receiver, IERC1155Receiver { - using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque; - - bytes32 public constant BALLOT_TYPEHASH = - keccak256("Ballot(uint256 proposalId,uint8 support,address voter,uint256 nonce)"); - bytes32 public constant EXTENDED_BALLOT_TYPEHASH = - keccak256( - "ExtendedBallot(uint256 proposalId,uint8 support,address voter,uint256 nonce,string reason,bytes params)" - ); - - struct ProposalCore { - address proposer; - uint48 voteStart; - uint32 voteDuration; - bool executed; - bool canceled; - uint48 etaSeconds; - } - - bytes32 private constant ALL_PROPOSAL_STATES_BITMAP = bytes32((2 ** (uint8(type(ProposalState).max) + 1)) - 1); - string private _name; - - mapping(uint256 proposalId => ProposalCore) private _proposals; - - // This queue keeps track of the governor operating on itself. Calls to functions protected by the {onlyGovernance} - // modifier needs to be whitelisted in this queue. Whitelisting is set in {execute}, consumed by the - // {onlyGovernance} modifier and eventually reset after {_executeOperations} completes. This ensures that the - // execution of {onlyGovernance} protected calls can only be achieved through successful proposals. - DoubleEndedQueue.Bytes32Deque private _governanceCall; - - /** - * @dev Restricts a function so it can only be executed through governance proposals. For example, governance - * parameter setters in {GovernorSettings} are protected using this modifier. - * - * The governance executing address may be different from the Governor's own address, for example it could be a - * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these - * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus, - * for example, additional timelock proposers are not able to change governance parameters without going through the - * governance protocol (since v4.6). - */ - modifier onlyGovernance() { - _checkGovernance(); - _; - } - - /** - * @dev Sets the value for {name} and {version} - */ - constructor(string memory name_) EIP712(name_, version()) { - _name = name_; - } - - /** - * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract) - */ - receive() external payable virtual { - if (_executor() != address(this)) { - revert GovernorDisabledDeposit(); - } - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { - return - interfaceId == type(IGovernor).interfaceId || - interfaceId == type(IERC1155Receiver).interfaceId || - super.supportsInterface(interfaceId); - } - - /** - * @dev See {IGovernor-name}. - */ - function name() public view virtual returns (string memory) { - return _name; - } - - /** - * @dev See {IGovernor-version}. - */ - function version() public view virtual returns (string memory) { - return "1"; - } - - /** - * @dev See {IGovernor-hashProposal}. - * - * The proposal id is produced by hashing the ABI encoded `targets` array, the `values` array, the `calldatas` array - * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id - * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in - * advance, before the proposal is submitted. - * - * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the - * same proposal (with same operation and same description) will have the same id if submitted on multiple governors - * across multiple networks. This also means that in order to execute the same operation twice (on the same - * governor) the proposer will have to change the description in order to avoid proposal id conflicts. - */ - function hashProposal( - address[] memory targets, - uint256[] memory values, - bytes[] memory calldatas, - bytes32 descriptionHash - ) public pure virtual returns (uint256) { - return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash))); - } - - /** - * @dev See {IGovernor-state}. - */ - function state(uint256 proposalId) public view virtual returns (ProposalState) { - // We read the struct fields into the stack at once so Solidity emits a single SLOAD - ProposalCore storage proposal = _proposals[proposalId]; - bool proposalExecuted = proposal.executed; - bool proposalCanceled = proposal.canceled; - - if (proposalExecuted) { - return ProposalState.Executed; - } - - if (proposalCanceled) { - return ProposalState.Canceled; - } - - uint256 snapshot = proposalSnapshot(proposalId); - - if (snapshot == 0) { - revert GovernorNonexistentProposal(proposalId); - } - - uint256 currentTimepoint = clock(); - - if (snapshot >= currentTimepoint) { - return ProposalState.Pending; - } - - uint256 deadline = proposalDeadline(proposalId); - - if (deadline >= currentTimepoint) { - return ProposalState.Active; - } else if (!_quorumReached(proposalId) || !_voteSucceeded(proposalId)) { - return ProposalState.Defeated; - } else if (proposalEta(proposalId) == 0) { - return ProposalState.Succeeded; - } else { - return ProposalState.Queued; - } - } - - /** - * @dev See {IGovernor-proposalThreshold}. - */ - function proposalThreshold() public view virtual returns (uint256) { - return 0; - } - - /** - * @dev See {IGovernor-proposalSnapshot}. - */ - function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256) { - return _proposals[proposalId].voteStart; - } - - /** - * @dev See {IGovernor-proposalDeadline}. - */ - function proposalDeadline(uint256 proposalId) public view virtual returns (uint256) { - return _proposals[proposalId].voteStart + _proposals[proposalId].voteDuration; - } - - /** - * @dev See {IGovernor-proposalProposer}. - */ - function proposalProposer(uint256 proposalId) public view virtual returns (address) { - return _proposals[proposalId].proposer; - } - - /** - * @dev See {IGovernor-proposalEta}. - */ - function proposalEta(uint256 proposalId) public view virtual returns (uint256) { - return _proposals[proposalId].etaSeconds; - } - - /** - * @dev See {IGovernor-proposalNeedsQueuing}. - */ - function proposalNeedsQueuing(uint256) public view virtual returns (bool) { - return false; - } - - /** - * @dev Reverts if the `msg.sender` is not the executor. In case the executor is not this contract - * itself, the function reverts if `msg.data` is not whitelisted as a result of an {execute} - * operation. See {onlyGovernance}. - */ - function _checkGovernance() internal virtual { - if (_executor() != _msgSender()) { - revert GovernorOnlyExecutor(_msgSender()); - } - if (_executor() != address(this)) { - bytes32 msgDataHash = keccak256(_msgData()); - // loop until popping the expected operation - throw if deque is empty (operation not authorized) - while (_governanceCall.popFront() != msgDataHash) {} - } - } - - /** - * @dev Amount of votes already cast passes the threshold limit. - */ - function _quorumReached(uint256 proposalId) internal view virtual returns (bool); - - /** - * @dev Is the proposal successful or not. - */ - function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool); - - /** - * @dev Get the voting weight of `account` at a specific `timepoint`, for a vote as described by `params`. - */ - function _getVotes(address account, uint256 timepoint, bytes memory params) internal view virtual returns (uint256); - - /** - * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`. - * - * Note: Support is generic and can represent various things depending on the voting system used. - */ - function _countVote( - uint256 proposalId, - address account, - uint8 support, - uint256 weight, - bytes memory params - ) internal virtual; - - /** - * @dev Default additional encoded parameters used by castVote methods that don't include them - * - * Note: Should be overridden by specific implementations to use an appropriate value, the - * meaning of the additional params, in the context of that implementation - */ - function _defaultParams() internal view virtual returns (bytes memory) { - return ""; - } - - /** - * @dev See {IGovernor-propose}. This function has opt-in frontrunning protection, described in {_isValidDescriptionForProposer}. - */ - function propose( - address[] memory targets, - uint256[] memory values, - bytes[] memory calldatas, - string memory description - ) public virtual returns (uint256) { - address proposer = _msgSender(); - - // check description restriction - if (!_isValidDescriptionForProposer(proposer, description)) { - revert GovernorRestrictedProposer(proposer); - } - - // check proposal threshold - uint256 proposerVotes = getVotes(proposer, clock() - 1); - uint256 votesThreshold = proposalThreshold(); - if (proposerVotes < votesThreshold) { - revert GovernorInsufficientProposerVotes(proposer, proposerVotes, votesThreshold); - } - - return _propose(targets, values, calldatas, description, proposer); - } - - /** - * @dev Internal propose mechanism. Can be overridden to add more logic on proposal creation. - * - * Emits a {IGovernor-ProposalCreated} event. - */ - function _propose( - address[] memory targets, - uint256[] memory values, - bytes[] memory calldatas, - string memory description, - address proposer - ) internal virtual returns (uint256 proposalId) { - proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description))); - - if (targets.length != values.length || targets.length != calldatas.length || targets.length == 0) { - revert GovernorInvalidProposalLength(targets.length, calldatas.length, values.length); - } - if (_proposals[proposalId].voteStart != 0) { - revert GovernorUnexpectedProposalState(proposalId, state(proposalId), bytes32(0)); - } - - uint256 snapshot = clock() + votingDelay(); - uint256 duration = votingPeriod(); - - ProposalCore storage proposal = _proposals[proposalId]; - proposal.proposer = proposer; - proposal.voteStart = SafeCast.toUint48(snapshot); - proposal.voteDuration = SafeCast.toUint32(duration); - - emit ProposalCreated( - proposalId, - proposer, - targets, - values, - new string[](targets.length), - calldatas, - snapshot, - snapshot + duration, - description - ); - - // Using a named return variable to avoid stack too deep errors - } - - /** - * @dev See {IGovernor-queue}. - */ - function queue( - address[] memory targets, - uint256[] memory values, - bytes[] memory calldatas, - bytes32 descriptionHash - ) public virtual returns (uint256) { - uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); - - _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Succeeded)); - - uint48 etaSeconds = _queueOperations(proposalId, targets, values, calldatas, descriptionHash); - - if (etaSeconds != 0) { - _proposals[proposalId].etaSeconds = etaSeconds; - emit ProposalQueued(proposalId, etaSeconds); - } else { - revert GovernorQueueNotImplemented(); - } - - return proposalId; - } - - /** - * @dev Internal queuing mechanism. Can be overridden (without a super call) to modify the way queuing is - * performed (for example adding a vault/timelock). - * - * This is empty by default, and must be overridden to implement queuing. - * - * This function returns a timestamp that describes the expected ETA for execution. If the returned value is 0 - * (which is the default value), the core will consider queueing did not succeed, and the public {queue} function - * will revert. - * - * NOTE: Calling this function directly will NOT check the current state of the proposal, or emit the - * `ProposalQueued` event. Queuing a proposal should be done using {queue}. - */ - function _queueOperations( - uint256 /*proposalId*/, - address[] memory /*targets*/, - uint256[] memory /*values*/, - bytes[] memory /*calldatas*/, - bytes32 /*descriptionHash*/ - ) internal virtual returns (uint48) { - return 0; - } - - /** - * @dev See {IGovernor-execute}. - */ - function execute( - address[] memory targets, - uint256[] memory values, - bytes[] memory calldatas, - bytes32 descriptionHash - ) public payable virtual returns (uint256) { - uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); - - _validateStateBitmap( - proposalId, - _encodeStateBitmap(ProposalState.Succeeded) | _encodeStateBitmap(ProposalState.Queued) - ); - - // mark as executed before calls to avoid reentrancy - _proposals[proposalId].executed = true; - - // before execute: register governance call in queue. - if (_executor() != address(this)) { - for (uint256 i = 0; i < targets.length; ++i) { - if (targets[i] == address(this)) { - _governanceCall.pushBack(keccak256(calldatas[i])); - } - } - } - - _executeOperations(proposalId, targets, values, calldatas, descriptionHash); - - // after execute: cleanup governance call queue. - if (_executor() != address(this) && !_governanceCall.empty()) { - _governanceCall.clear(); - } - - emit ProposalExecuted(proposalId); - - return proposalId; - } - - /** - * @dev Internal execution mechanism. Can be overridden (without a super call) to modify the way execution is - * performed (for example adding a vault/timelock). - * - * NOTE: Calling this function directly will NOT check the current state of the proposal, set the executed flag to - * true or emit the `ProposalExecuted` event. Executing a proposal should be done using {execute} or {_execute}. - */ - function _executeOperations( - uint256 /* proposalId */, - address[] memory targets, - uint256[] memory values, - bytes[] memory calldatas, - bytes32 /*descriptionHash*/ - ) internal virtual { - for (uint256 i = 0; i < targets.length; ++i) { - (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]); - Address.verifyCallResult(success, returndata); - } - } - - /** - * @dev See {IGovernor-cancel}. - */ - function cancel( - address[] memory targets, - uint256[] memory values, - bytes[] memory calldatas, - bytes32 descriptionHash - ) public virtual returns (uint256) { - // The proposalId will be recomputed in the `_cancel` call further down. However we need the value before we - // do the internal call, because we need to check the proposal state BEFORE the internal `_cancel` call - // changes it. The `hashProposal` duplication has a cost that is limited, and that we accept. - uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); - - // public cancel restrictions (on top of existing _cancel restrictions). - _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Pending)); - if (_msgSender() != proposalProposer(proposalId)) { - revert GovernorOnlyProposer(_msgSender()); - } - - return _cancel(targets, values, calldatas, descriptionHash); - } - - /** - * @dev Internal cancel mechanism with minimal restrictions. A proposal can be cancelled in any state other than - * Canceled, Expired, or Executed. Once cancelled a proposal can't be re-submitted. - * - * Emits a {IGovernor-ProposalCanceled} event. - */ - function _cancel( - address[] memory targets, - uint256[] memory values, - bytes[] memory calldatas, - bytes32 descriptionHash - ) internal virtual returns (uint256) { - uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); - - _validateStateBitmap( - proposalId, - ALL_PROPOSAL_STATES_BITMAP ^ - _encodeStateBitmap(ProposalState.Canceled) ^ - _encodeStateBitmap(ProposalState.Expired) ^ - _encodeStateBitmap(ProposalState.Executed) - ); - - _proposals[proposalId].canceled = true; - emit ProposalCanceled(proposalId); - - return proposalId; - } - - /** - * @dev See {IGovernor-getVotes}. - */ - function getVotes(address account, uint256 timepoint) public view virtual returns (uint256) { - return _getVotes(account, timepoint, _defaultParams()); - } - - /** - * @dev See {IGovernor-getVotesWithParams}. - */ - function getVotesWithParams( - address account, - uint256 timepoint, - bytes memory params - ) public view virtual returns (uint256) { - return _getVotes(account, timepoint, params); - } - - /** - * @dev See {IGovernor-castVote}. - */ - function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256) { - address voter = _msgSender(); - return _castVote(proposalId, voter, support, ""); - } - - /** - * @dev See {IGovernor-castVoteWithReason}. - */ - function castVoteWithReason( - uint256 proposalId, - uint8 support, - string calldata reason - ) public virtual returns (uint256) { - address voter = _msgSender(); - return _castVote(proposalId, voter, support, reason); - } - - /** - * @dev See {IGovernor-castVoteWithReasonAndParams}. - */ - function castVoteWithReasonAndParams( - uint256 proposalId, - uint8 support, - string calldata reason, - bytes memory params - ) public virtual returns (uint256) { - address voter = _msgSender(); - return _castVote(proposalId, voter, support, reason, params); - } - - /** - * @dev See {IGovernor-castVoteBySig}. - */ - function castVoteBySig( - uint256 proposalId, - uint8 support, - address voter, - bytes memory signature - ) public virtual returns (uint256) { - bool valid = SignatureChecker.isValidSignatureNow( - voter, - _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support, voter, _useNonce(voter)))), - signature - ); - - if (!valid) { - revert GovernorInvalidSignature(voter); - } - - return _castVote(proposalId, voter, support, ""); - } - - /** - * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}. - */ - function castVoteWithReasonAndParamsBySig( - uint256 proposalId, - uint8 support, - address voter, - string calldata reason, - bytes memory params, - bytes memory signature - ) public virtual returns (uint256) { - bool valid = SignatureChecker.isValidSignatureNow( - voter, - _hashTypedDataV4( - keccak256( - abi.encode( - EXTENDED_BALLOT_TYPEHASH, - proposalId, - support, - voter, - _useNonce(voter), - keccak256(bytes(reason)), - keccak256(params) - ) - ) - ), - signature - ); - - if (!valid) { - revert GovernorInvalidSignature(voter); - } - - return _castVote(proposalId, voter, support, reason, params); - } - - /** - * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve - * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams(). - * - * Emits a {IGovernor-VoteCast} event. - */ - function _castVote( - uint256 proposalId, - address account, - uint8 support, - string memory reason - ) internal virtual returns (uint256) { - return _castVote(proposalId, account, support, reason, _defaultParams()); - } - - /** - * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve - * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. - * - * Emits a {IGovernor-VoteCast} event. - */ - function _castVote( - uint256 proposalId, - address account, - uint8 support, - string memory reason, - bytes memory params - ) internal virtual returns (uint256) { - _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Active)); - - uint256 weight = _getVotes(account, proposalSnapshot(proposalId), params); - _countVote(proposalId, account, support, weight, params); - - if (params.length == 0) { - emit VoteCast(account, proposalId, support, weight, reason); - } else { - emit VoteCastWithParams(account, proposalId, support, weight, reason, params); - } - - return weight; - } - - /** - * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor - * is some contract other than the governor itself, like when using a timelock, this function can be invoked - * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. - * Note that if the executor is simply the governor itself, use of `relay` is redundant. - */ - function relay(address target, uint256 value, bytes calldata data) external payable virtual onlyGovernance { - (bool success, bytes memory returndata) = target.call{value: value}(data); - Address.verifyCallResult(success, returndata); - } - - /** - * @dev Address through which the governor executes action. Will be overloaded by module that execute actions - * through another contract such as a timelock. - */ - function _executor() internal view virtual returns (address) { - return address(this); - } - - /** - * @dev See {IERC721Receiver-onERC721Received}. - * Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock). - */ - function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) { - if (_executor() != address(this)) { - revert GovernorDisabledDeposit(); - } - return this.onERC721Received.selector; - } - - /** - * @dev See {IERC1155Receiver-onERC1155Received}. - * Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock). - */ - function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual returns (bytes4) { - if (_executor() != address(this)) { - revert GovernorDisabledDeposit(); - } - return this.onERC1155Received.selector; - } - - /** - * @dev See {IERC1155Receiver-onERC1155BatchReceived}. - * Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock). - */ - function onERC1155BatchReceived( - address, - address, - uint256[] memory, - uint256[] memory, - bytes memory - ) public virtual returns (bytes4) { - if (_executor() != address(this)) { - revert GovernorDisabledDeposit(); - } - return this.onERC1155BatchReceived.selector; - } - - /** - * @dev Encodes a `ProposalState` into a `bytes32` representation where each bit enabled corresponds to - * the underlying position in the `ProposalState` enum. For example: - * - * 0x000...10000 - * ^^^^^^------ ... - * ^----- Succeeded - * ^---- Defeated - * ^--- Canceled - * ^-- Active - * ^- Pending - */ - function _encodeStateBitmap(ProposalState proposalState) internal pure returns (bytes32) { - return bytes32(1 << uint8(proposalState)); - } - - /** - * @dev Check that the current state of a proposal matches the requirements described by the `allowedStates` bitmap. - * This bitmap should be built using `_encodeStateBitmap`. - * - * If requirements are not met, reverts with a {GovernorUnexpectedProposalState} error. - */ - function _validateStateBitmap(uint256 proposalId, bytes32 allowedStates) private view returns (ProposalState) { - ProposalState currentState = state(proposalId); - if (_encodeStateBitmap(currentState) & allowedStates == bytes32(0)) { - revert GovernorUnexpectedProposalState(proposalId, currentState, allowedStates); - } - return currentState; - } - - /* - * @dev Check if the proposer is authorized to submit a proposal with the given description. - * - * If the proposal description ends with `#proposer=0x???`, where `0x???` is an address written as a hex string - * (case insensitive), then the submission of this proposal will only be authorized to said address. - * - * This is used for frontrunning protection. By adding this pattern at the end of their proposal, one can ensure - * that no other address can submit the same proposal. An attacker would have to either remove or change that part, - * which would result in a different proposal id. - * - * If the description does not match this pattern, it is unrestricted and anyone can submit it. This includes: - * - If the `0x???` part is not a valid hex string. - * - If the `0x???` part is a valid hex string, but does not contain exactly 40 hex digits. - * - If it ends with the expected suffix followed by newlines or other whitespace. - * - If it ends with some other similar suffix, e.g. `#other=abc`. - * - If it does not end with any such suffix. - */ - function _isValidDescriptionForProposer( - address proposer, - string memory description - ) internal view virtual returns (bool) { - uint256 len = bytes(description).length; - - // Length is too short to contain a valid proposer suffix - if (len < 52) { - return true; - } - - // Extract what would be the `#proposer=0x` marker beginning the suffix - bytes12 marker; - assembly { - // - Start of the string contents in memory = description + 32 - // - First character of the marker = len - 52 - // - Length of "#proposer=0x0000000000000000000000000000000000000000" = 52 - // - We read the memory word starting at the first character of the marker: - // - (description + 32) + (len - 52) = description + (len - 20) - // - Note: Solidity will ignore anything past the first 12 bytes - marker := mload(add(description, sub(len, 20))) - } - - // If the marker is not found, there is no proposer suffix to check - if (marker != bytes12("#proposer=0x")) { - return true; - } - - // Parse the 40 characters following the marker as uint160 - uint160 recovered = 0; - for (uint256 i = len - 40; i < len; ++i) { - (bool isHex, uint8 value) = _tryHexToUint(bytes(description)[i]); - // If any of the characters is not a hex digit, ignore the suffix entirely - if (!isHex) { - return true; - } - recovered = (recovered << 4) | value; - } - - return recovered == uint160(proposer); - } - - /** - * @dev Try to parse a character from a string as a hex value. Returns `(true, value)` if the char is in - * `[0-9a-fA-F]` and `(false, 0)` otherwise. Value is guaranteed to be in the range `0 <= value < 16` - */ - function _tryHexToUint(bytes1 char) private pure returns (bool, uint8) { - uint8 c = uint8(char); - unchecked { - // Case 0-9 - if (47 < c && c < 58) { - return (true, c - 48); - } - // Case A-F - else if (64 < c && c < 71) { - return (true, c - 55); - } - // Case a-f - else if (96 < c && c < 103) { - return (true, c - 87); - } - // Else: not a hex char - else { - return (false, 0); - } - } - } - - /** - * @inheritdoc IERC6372 - */ - function clock() public view virtual returns (uint48); - - /** - * @inheritdoc IERC6372 - */ - // solhint-disable-next-line func-name-mixedcase - function CLOCK_MODE() public view virtual returns (string memory); - - /** - * @inheritdoc IGovernor - */ - function votingDelay() public view virtual returns (uint256); - - /** - * @inheritdoc IGovernor - */ - function votingPeriod() public view virtual returns (uint256); - - /** - * @inheritdoc IGovernor - */ - function quorum(uint256 timepoint) public view virtual returns (uint256); -} diff --git a/crates/solidity/testing/perf/benches/iai/sources/SafeCast.sol b/crates/solidity/testing/perf/benches/iai/sources/SafeCast.sol deleted file mode 100644 index 3cf65fd2c..000000000 --- a/crates/solidity/testing/perf/benches/iai/sources/SafeCast.sol +++ /dev/null @@ -1,1154 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) -// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/utils/math/SafeCast.sol -// This file was procedurally generated from scripts/generate/templates/SafeCast.js. - -pragma solidity ^0.8.20; - -/** - * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow - * checks. - * - * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can - * easily result in undesired exploitation or bugs, since developers usually - * assume that overflows raise errors. `SafeCast` restores this intuition by - * reverting the transaction when such an operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeCast { - /** - * @dev Value doesn't fit in an uint of `bits` size. - */ - error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); - - /** - * @dev An int value doesn't fit in an uint of `bits` size. - */ - error SafeCastOverflowedIntToUint(int256 value); - - /** - * @dev Value doesn't fit in an int of `bits` size. - */ - error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); - - /** - * @dev An uint value doesn't fit in an int of `bits` size. - */ - error SafeCastOverflowedUintToInt(uint256 value); - - /** - * @dev Returns the downcasted uint248 from uint256, reverting on - * overflow (when the input is greater than largest uint248). - * - * Counterpart to Solidity's `uint248` operator. - * - * Requirements: - * - * - input must fit into 248 bits - */ - function toUint248(uint256 value) internal pure returns (uint248) { - if (value > type(uint248).max) { - revert SafeCastOverflowedUintDowncast(248, value); - } - return uint248(value); - } - - /** - * @dev Returns the downcasted uint240 from uint256, reverting on - * overflow (when the input is greater than largest uint240). - * - * Counterpart to Solidity's `uint240` operator. - * - * Requirements: - * - * - input must fit into 240 bits - */ - function toUint240(uint256 value) internal pure returns (uint240) { - if (value > type(uint240).max) { - revert SafeCastOverflowedUintDowncast(240, value); - } - return uint240(value); - } - - /** - * @dev Returns the downcasted uint232 from uint256, reverting on - * overflow (when the input is greater than largest uint232). - * - * Counterpart to Solidity's `uint232` operator. - * - * Requirements: - * - * - input must fit into 232 bits - */ - function toUint232(uint256 value) internal pure returns (uint232) { - if (value > type(uint232).max) { - revert SafeCastOverflowedUintDowncast(232, value); - } - return uint232(value); - } - - /** - * @dev Returns the downcasted uint224 from uint256, reverting on - * overflow (when the input is greater than largest uint224). - * - * Counterpart to Solidity's `uint224` operator. - * - * Requirements: - * - * - input must fit into 224 bits - */ - function toUint224(uint256 value) internal pure returns (uint224) { - if (value > type(uint224).max) { - revert SafeCastOverflowedUintDowncast(224, value); - } - return uint224(value); - } - - /** - * @dev Returns the downcasted uint216 from uint256, reverting on - * overflow (when the input is greater than largest uint216). - * - * Counterpart to Solidity's `uint216` operator. - * - * Requirements: - * - * - input must fit into 216 bits - */ - function toUint216(uint256 value) internal pure returns (uint216) { - if (value > type(uint216).max) { - revert SafeCastOverflowedUintDowncast(216, value); - } - return uint216(value); - } - - /** - * @dev Returns the downcasted uint208 from uint256, reverting on - * overflow (when the input is greater than largest uint208). - * - * Counterpart to Solidity's `uint208` operator. - * - * Requirements: - * - * - input must fit into 208 bits - */ - function toUint208(uint256 value) internal pure returns (uint208) { - if (value > type(uint208).max) { - revert SafeCastOverflowedUintDowncast(208, value); - } - return uint208(value); - } - - /** - * @dev Returns the downcasted uint200 from uint256, reverting on - * overflow (when the input is greater than largest uint200). - * - * Counterpart to Solidity's `uint200` operator. - * - * Requirements: - * - * - input must fit into 200 bits - */ - function toUint200(uint256 value) internal pure returns (uint200) { - if (value > type(uint200).max) { - revert SafeCastOverflowedUintDowncast(200, value); - } - return uint200(value); - } - - /** - * @dev Returns the downcasted uint192 from uint256, reverting on - * overflow (when the input is greater than largest uint192). - * - * Counterpart to Solidity's `uint192` operator. - * - * Requirements: - * - * - input must fit into 192 bits - */ - function toUint192(uint256 value) internal pure returns (uint192) { - if (value > type(uint192).max) { - revert SafeCastOverflowedUintDowncast(192, value); - } - return uint192(value); - } - - /** - * @dev Returns the downcasted uint184 from uint256, reverting on - * overflow (when the input is greater than largest uint184). - * - * Counterpart to Solidity's `uint184` operator. - * - * Requirements: - * - * - input must fit into 184 bits - */ - function toUint184(uint256 value) internal pure returns (uint184) { - if (value > type(uint184).max) { - revert SafeCastOverflowedUintDowncast(184, value); - } - return uint184(value); - } - - /** - * @dev Returns the downcasted uint176 from uint256, reverting on - * overflow (when the input is greater than largest uint176). - * - * Counterpart to Solidity's `uint176` operator. - * - * Requirements: - * - * - input must fit into 176 bits - */ - function toUint176(uint256 value) internal pure returns (uint176) { - if (value > type(uint176).max) { - revert SafeCastOverflowedUintDowncast(176, value); - } - return uint176(value); - } - - /** - * @dev Returns the downcasted uint168 from uint256, reverting on - * overflow (when the input is greater than largest uint168). - * - * Counterpart to Solidity's `uint168` operator. - * - * Requirements: - * - * - input must fit into 168 bits - */ - function toUint168(uint256 value) internal pure returns (uint168) { - if (value > type(uint168).max) { - revert SafeCastOverflowedUintDowncast(168, value); - } - return uint168(value); - } - - /** - * @dev Returns the downcasted uint160 from uint256, reverting on - * overflow (when the input is greater than largest uint160). - * - * Counterpart to Solidity's `uint160` operator. - * - * Requirements: - * - * - input must fit into 160 bits - */ - function toUint160(uint256 value) internal pure returns (uint160) { - if (value > type(uint160).max) { - revert SafeCastOverflowedUintDowncast(160, value); - } - return uint160(value); - } - - /** - * @dev Returns the downcasted uint152 from uint256, reverting on - * overflow (when the input is greater than largest uint152). - * - * Counterpart to Solidity's `uint152` operator. - * - * Requirements: - * - * - input must fit into 152 bits - */ - function toUint152(uint256 value) internal pure returns (uint152) { - if (value > type(uint152).max) { - revert SafeCastOverflowedUintDowncast(152, value); - } - return uint152(value); - } - - /** - * @dev Returns the downcasted uint144 from uint256, reverting on - * overflow (when the input is greater than largest uint144). - * - * Counterpart to Solidity's `uint144` operator. - * - * Requirements: - * - * - input must fit into 144 bits - */ - function toUint144(uint256 value) internal pure returns (uint144) { - if (value > type(uint144).max) { - revert SafeCastOverflowedUintDowncast(144, value); - } - return uint144(value); - } - - /** - * @dev Returns the downcasted uint136 from uint256, reverting on - * overflow (when the input is greater than largest uint136). - * - * Counterpart to Solidity's `uint136` operator. - * - * Requirements: - * - * - input must fit into 136 bits - */ - function toUint136(uint256 value) internal pure returns (uint136) { - if (value > type(uint136).max) { - revert SafeCastOverflowedUintDowncast(136, value); - } - return uint136(value); - } - - /** - * @dev Returns the downcasted uint128 from uint256, reverting on - * overflow (when the input is greater than largest uint128). - * - * Counterpart to Solidity's `uint128` operator. - * - * Requirements: - * - * - input must fit into 128 bits - */ - function toUint128(uint256 value) internal pure returns (uint128) { - if (value > type(uint128).max) { - revert SafeCastOverflowedUintDowncast(128, value); - } - return uint128(value); - } - - /** - * @dev Returns the downcasted uint120 from uint256, reverting on - * overflow (when the input is greater than largest uint120). - * - * Counterpart to Solidity's `uint120` operator. - * - * Requirements: - * - * - input must fit into 120 bits - */ - function toUint120(uint256 value) internal pure returns (uint120) { - if (value > type(uint120).max) { - revert SafeCastOverflowedUintDowncast(120, value); - } - return uint120(value); - } - - /** - * @dev Returns the downcasted uint112 from uint256, reverting on - * overflow (when the input is greater than largest uint112). - * - * Counterpart to Solidity's `uint112` operator. - * - * Requirements: - * - * - input must fit into 112 bits - */ - function toUint112(uint256 value) internal pure returns (uint112) { - if (value > type(uint112).max) { - revert SafeCastOverflowedUintDowncast(112, value); - } - return uint112(value); - } - - /** - * @dev Returns the downcasted uint104 from uint256, reverting on - * overflow (when the input is greater than largest uint104). - * - * Counterpart to Solidity's `uint104` operator. - * - * Requirements: - * - * - input must fit into 104 bits - */ - function toUint104(uint256 value) internal pure returns (uint104) { - if (value > type(uint104).max) { - revert SafeCastOverflowedUintDowncast(104, value); - } - return uint104(value); - } - - /** - * @dev Returns the downcasted uint96 from uint256, reverting on - * overflow (when the input is greater than largest uint96). - * - * Counterpart to Solidity's `uint96` operator. - * - * Requirements: - * - * - input must fit into 96 bits - */ - function toUint96(uint256 value) internal pure returns (uint96) { - if (value > type(uint96).max) { - revert SafeCastOverflowedUintDowncast(96, value); - } - return uint96(value); - } - - /** - * @dev Returns the downcasted uint88 from uint256, reverting on - * overflow (when the input is greater than largest uint88). - * - * Counterpart to Solidity's `uint88` operator. - * - * Requirements: - * - * - input must fit into 88 bits - */ - function toUint88(uint256 value) internal pure returns (uint88) { - if (value > type(uint88).max) { - revert SafeCastOverflowedUintDowncast(88, value); - } - return uint88(value); - } - - /** - * @dev Returns the downcasted uint80 from uint256, reverting on - * overflow (when the input is greater than largest uint80). - * - * Counterpart to Solidity's `uint80` operator. - * - * Requirements: - * - * - input must fit into 80 bits - */ - function toUint80(uint256 value) internal pure returns (uint80) { - if (value > type(uint80).max) { - revert SafeCastOverflowedUintDowncast(80, value); - } - return uint80(value); - } - - /** - * @dev Returns the downcasted uint72 from uint256, reverting on - * overflow (when the input is greater than largest uint72). - * - * Counterpart to Solidity's `uint72` operator. - * - * Requirements: - * - * - input must fit into 72 bits - */ - function toUint72(uint256 value) internal pure returns (uint72) { - if (value > type(uint72).max) { - revert SafeCastOverflowedUintDowncast(72, value); - } - return uint72(value); - } - - /** - * @dev Returns the downcasted uint64 from uint256, reverting on - * overflow (when the input is greater than largest uint64). - * - * Counterpart to Solidity's `uint64` operator. - * - * Requirements: - * - * - input must fit into 64 bits - */ - function toUint64(uint256 value) internal pure returns (uint64) { - if (value > type(uint64).max) { - revert SafeCastOverflowedUintDowncast(64, value); - } - return uint64(value); - } - - /** - * @dev Returns the downcasted uint56 from uint256, reverting on - * overflow (when the input is greater than largest uint56). - * - * Counterpart to Solidity's `uint56` operator. - * - * Requirements: - * - * - input must fit into 56 bits - */ - function toUint56(uint256 value) internal pure returns (uint56) { - if (value > type(uint56).max) { - revert SafeCastOverflowedUintDowncast(56, value); - } - return uint56(value); - } - - /** - * @dev Returns the downcasted uint48 from uint256, reverting on - * overflow (when the input is greater than largest uint48). - * - * Counterpart to Solidity's `uint48` operator. - * - * Requirements: - * - * - input must fit into 48 bits - */ - function toUint48(uint256 value) internal pure returns (uint48) { - if (value > type(uint48).max) { - revert SafeCastOverflowedUintDowncast(48, value); - } - return uint48(value); - } - - /** - * @dev Returns the downcasted uint40 from uint256, reverting on - * overflow (when the input is greater than largest uint40). - * - * Counterpart to Solidity's `uint40` operator. - * - * Requirements: - * - * - input must fit into 40 bits - */ - function toUint40(uint256 value) internal pure returns (uint40) { - if (value > type(uint40).max) { - revert SafeCastOverflowedUintDowncast(40, value); - } - return uint40(value); - } - - /** - * @dev Returns the downcasted uint32 from uint256, reverting on - * overflow (when the input is greater than largest uint32). - * - * Counterpart to Solidity's `uint32` operator. - * - * Requirements: - * - * - input must fit into 32 bits - */ - function toUint32(uint256 value) internal pure returns (uint32) { - if (value > type(uint32).max) { - revert SafeCastOverflowedUintDowncast(32, value); - } - return uint32(value); - } - - /** - * @dev Returns the downcasted uint24 from uint256, reverting on - * overflow (when the input is greater than largest uint24). - * - * Counterpart to Solidity's `uint24` operator. - * - * Requirements: - * - * - input must fit into 24 bits - */ - function toUint24(uint256 value) internal pure returns (uint24) { - if (value > type(uint24).max) { - revert SafeCastOverflowedUintDowncast(24, value); - } - return uint24(value); - } - - /** - * @dev Returns the downcasted uint16 from uint256, reverting on - * overflow (when the input is greater than largest uint16). - * - * Counterpart to Solidity's `uint16` operator. - * - * Requirements: - * - * - input must fit into 16 bits - */ - function toUint16(uint256 value) internal pure returns (uint16) { - if (value > type(uint16).max) { - revert SafeCastOverflowedUintDowncast(16, value); - } - return uint16(value); - } - - /** - * @dev Returns the downcasted uint8 from uint256, reverting on - * overflow (when the input is greater than largest uint8). - * - * Counterpart to Solidity's `uint8` operator. - * - * Requirements: - * - * - input must fit into 8 bits - */ - function toUint8(uint256 value) internal pure returns (uint8) { - if (value > type(uint8).max) { - revert SafeCastOverflowedUintDowncast(8, value); - } - return uint8(value); - } - - /** - * @dev Converts a signed int256 into an unsigned uint256. - * - * Requirements: - * - * - input must be greater than or equal to 0. - */ - function toUint256(int256 value) internal pure returns (uint256) { - if (value < 0) { - revert SafeCastOverflowedIntToUint(value); - } - return uint256(value); - } - - /** - * @dev Returns the downcasted int248 from int256, reverting on - * overflow (when the input is less than smallest int248 or - * greater than largest int248). - * - * Counterpart to Solidity's `int248` operator. - * - * Requirements: - * - * - input must fit into 248 bits - */ - function toInt248(int256 value) internal pure returns (int248 downcasted) { - downcasted = int248(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(248, value); - } - } - - /** - * @dev Returns the downcasted int240 from int256, reverting on - * overflow (when the input is less than smallest int240 or - * greater than largest int240). - * - * Counterpart to Solidity's `int240` operator. - * - * Requirements: - * - * - input must fit into 240 bits - */ - function toInt240(int256 value) internal pure returns (int240 downcasted) { - downcasted = int240(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(240, value); - } - } - - /** - * @dev Returns the downcasted int232 from int256, reverting on - * overflow (when the input is less than smallest int232 or - * greater than largest int232). - * - * Counterpart to Solidity's `int232` operator. - * - * Requirements: - * - * - input must fit into 232 bits - */ - function toInt232(int256 value) internal pure returns (int232 downcasted) { - downcasted = int232(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(232, value); - } - } - - /** - * @dev Returns the downcasted int224 from int256, reverting on - * overflow (when the input is less than smallest int224 or - * greater than largest int224). - * - * Counterpart to Solidity's `int224` operator. - * - * Requirements: - * - * - input must fit into 224 bits - */ - function toInt224(int256 value) internal pure returns (int224 downcasted) { - downcasted = int224(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(224, value); - } - } - - /** - * @dev Returns the downcasted int216 from int256, reverting on - * overflow (when the input is less than smallest int216 or - * greater than largest int216). - * - * Counterpart to Solidity's `int216` operator. - * - * Requirements: - * - * - input must fit into 216 bits - */ - function toInt216(int256 value) internal pure returns (int216 downcasted) { - downcasted = int216(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(216, value); - } - } - - /** - * @dev Returns the downcasted int208 from int256, reverting on - * overflow (when the input is less than smallest int208 or - * greater than largest int208). - * - * Counterpart to Solidity's `int208` operator. - * - * Requirements: - * - * - input must fit into 208 bits - */ - function toInt208(int256 value) internal pure returns (int208 downcasted) { - downcasted = int208(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(208, value); - } - } - - /** - * @dev Returns the downcasted int200 from int256, reverting on - * overflow (when the input is less than smallest int200 or - * greater than largest int200). - * - * Counterpart to Solidity's `int200` operator. - * - * Requirements: - * - * - input must fit into 200 bits - */ - function toInt200(int256 value) internal pure returns (int200 downcasted) { - downcasted = int200(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(200, value); - } - } - - /** - * @dev Returns the downcasted int192 from int256, reverting on - * overflow (when the input is less than smallest int192 or - * greater than largest int192). - * - * Counterpart to Solidity's `int192` operator. - * - * Requirements: - * - * - input must fit into 192 bits - */ - function toInt192(int256 value) internal pure returns (int192 downcasted) { - downcasted = int192(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(192, value); - } - } - - /** - * @dev Returns the downcasted int184 from int256, reverting on - * overflow (when the input is less than smallest int184 or - * greater than largest int184). - * - * Counterpart to Solidity's `int184` operator. - * - * Requirements: - * - * - input must fit into 184 bits - */ - function toInt184(int256 value) internal pure returns (int184 downcasted) { - downcasted = int184(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(184, value); - } - } - - /** - * @dev Returns the downcasted int176 from int256, reverting on - * overflow (when the input is less than smallest int176 or - * greater than largest int176). - * - * Counterpart to Solidity's `int176` operator. - * - * Requirements: - * - * - input must fit into 176 bits - */ - function toInt176(int256 value) internal pure returns (int176 downcasted) { - downcasted = int176(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(176, value); - } - } - - /** - * @dev Returns the downcasted int168 from int256, reverting on - * overflow (when the input is less than smallest int168 or - * greater than largest int168). - * - * Counterpart to Solidity's `int168` operator. - * - * Requirements: - * - * - input must fit into 168 bits - */ - function toInt168(int256 value) internal pure returns (int168 downcasted) { - downcasted = int168(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(168, value); - } - } - - /** - * @dev Returns the downcasted int160 from int256, reverting on - * overflow (when the input is less than smallest int160 or - * greater than largest int160). - * - * Counterpart to Solidity's `int160` operator. - * - * Requirements: - * - * - input must fit into 160 bits - */ - function toInt160(int256 value) internal pure returns (int160 downcasted) { - downcasted = int160(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(160, value); - } - } - - /** - * @dev Returns the downcasted int152 from int256, reverting on - * overflow (when the input is less than smallest int152 or - * greater than largest int152). - * - * Counterpart to Solidity's `int152` operator. - * - * Requirements: - * - * - input must fit into 152 bits - */ - function toInt152(int256 value) internal pure returns (int152 downcasted) { - downcasted = int152(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(152, value); - } - } - - /** - * @dev Returns the downcasted int144 from int256, reverting on - * overflow (when the input is less than smallest int144 or - * greater than largest int144). - * - * Counterpart to Solidity's `int144` operator. - * - * Requirements: - * - * - input must fit into 144 bits - */ - function toInt144(int256 value) internal pure returns (int144 downcasted) { - downcasted = int144(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(144, value); - } - } - - /** - * @dev Returns the downcasted int136 from int256, reverting on - * overflow (when the input is less than smallest int136 or - * greater than largest int136). - * - * Counterpart to Solidity's `int136` operator. - * - * Requirements: - * - * - input must fit into 136 bits - */ - function toInt136(int256 value) internal pure returns (int136 downcasted) { - downcasted = int136(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(136, value); - } - } - - /** - * @dev Returns the downcasted int128 from int256, reverting on - * overflow (when the input is less than smallest int128 or - * greater than largest int128). - * - * Counterpart to Solidity's `int128` operator. - * - * Requirements: - * - * - input must fit into 128 bits - */ - function toInt128(int256 value) internal pure returns (int128 downcasted) { - downcasted = int128(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(128, value); - } - } - - /** - * @dev Returns the downcasted int120 from int256, reverting on - * overflow (when the input is less than smallest int120 or - * greater than largest int120). - * - * Counterpart to Solidity's `int120` operator. - * - * Requirements: - * - * - input must fit into 120 bits - */ - function toInt120(int256 value) internal pure returns (int120 downcasted) { - downcasted = int120(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(120, value); - } - } - - /** - * @dev Returns the downcasted int112 from int256, reverting on - * overflow (when the input is less than smallest int112 or - * greater than largest int112). - * - * Counterpart to Solidity's `int112` operator. - * - * Requirements: - * - * - input must fit into 112 bits - */ - function toInt112(int256 value) internal pure returns (int112 downcasted) { - downcasted = int112(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(112, value); - } - } - - /** - * @dev Returns the downcasted int104 from int256, reverting on - * overflow (when the input is less than smallest int104 or - * greater than largest int104). - * - * Counterpart to Solidity's `int104` operator. - * - * Requirements: - * - * - input must fit into 104 bits - */ - function toInt104(int256 value) internal pure returns (int104 downcasted) { - downcasted = int104(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(104, value); - } - } - - /** - * @dev Returns the downcasted int96 from int256, reverting on - * overflow (when the input is less than smallest int96 or - * greater than largest int96). - * - * Counterpart to Solidity's `int96` operator. - * - * Requirements: - * - * - input must fit into 96 bits - */ - function toInt96(int256 value) internal pure returns (int96 downcasted) { - downcasted = int96(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(96, value); - } - } - - /** - * @dev Returns the downcasted int88 from int256, reverting on - * overflow (when the input is less than smallest int88 or - * greater than largest int88). - * - * Counterpart to Solidity's `int88` operator. - * - * Requirements: - * - * - input must fit into 88 bits - */ - function toInt88(int256 value) internal pure returns (int88 downcasted) { - downcasted = int88(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(88, value); - } - } - - /** - * @dev Returns the downcasted int80 from int256, reverting on - * overflow (when the input is less than smallest int80 or - * greater than largest int80). - * - * Counterpart to Solidity's `int80` operator. - * - * Requirements: - * - * - input must fit into 80 bits - */ - function toInt80(int256 value) internal pure returns (int80 downcasted) { - downcasted = int80(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(80, value); - } - } - - /** - * @dev Returns the downcasted int72 from int256, reverting on - * overflow (when the input is less than smallest int72 or - * greater than largest int72). - * - * Counterpart to Solidity's `int72` operator. - * - * Requirements: - * - * - input must fit into 72 bits - */ - function toInt72(int256 value) internal pure returns (int72 downcasted) { - downcasted = int72(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(72, value); - } - } - - /** - * @dev Returns the downcasted int64 from int256, reverting on - * overflow (when the input is less than smallest int64 or - * greater than largest int64). - * - * Counterpart to Solidity's `int64` operator. - * - * Requirements: - * - * - input must fit into 64 bits - */ - function toInt64(int256 value) internal pure returns (int64 downcasted) { - downcasted = int64(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(64, value); - } - } - - /** - * @dev Returns the downcasted int56 from int256, reverting on - * overflow (when the input is less than smallest int56 or - * greater than largest int56). - * - * Counterpart to Solidity's `int56` operator. - * - * Requirements: - * - * - input must fit into 56 bits - */ - function toInt56(int256 value) internal pure returns (int56 downcasted) { - downcasted = int56(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(56, value); - } - } - - /** - * @dev Returns the downcasted int48 from int256, reverting on - * overflow (when the input is less than smallest int48 or - * greater than largest int48). - * - * Counterpart to Solidity's `int48` operator. - * - * Requirements: - * - * - input must fit into 48 bits - */ - function toInt48(int256 value) internal pure returns (int48 downcasted) { - downcasted = int48(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(48, value); - } - } - - /** - * @dev Returns the downcasted int40 from int256, reverting on - * overflow (when the input is less than smallest int40 or - * greater than largest int40). - * - * Counterpart to Solidity's `int40` operator. - * - * Requirements: - * - * - input must fit into 40 bits - */ - function toInt40(int256 value) internal pure returns (int40 downcasted) { - downcasted = int40(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(40, value); - } - } - - /** - * @dev Returns the downcasted int32 from int256, reverting on - * overflow (when the input is less than smallest int32 or - * greater than largest int32). - * - * Counterpart to Solidity's `int32` operator. - * - * Requirements: - * - * - input must fit into 32 bits - */ - function toInt32(int256 value) internal pure returns (int32 downcasted) { - downcasted = int32(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(32, value); - } - } - - /** - * @dev Returns the downcasted int24 from int256, reverting on - * overflow (when the input is less than smallest int24 or - * greater than largest int24). - * - * Counterpart to Solidity's `int24` operator. - * - * Requirements: - * - * - input must fit into 24 bits - */ - function toInt24(int256 value) internal pure returns (int24 downcasted) { - downcasted = int24(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(24, value); - } - } - - /** - * @dev Returns the downcasted int16 from int256, reverting on - * overflow (when the input is less than smallest int16 or - * greater than largest int16). - * - * Counterpart to Solidity's `int16` operator. - * - * Requirements: - * - * - input must fit into 16 bits - */ - function toInt16(int256 value) internal pure returns (int16 downcasted) { - downcasted = int16(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(16, value); - } - } - - /** - * @dev Returns the downcasted int8 from int256, reverting on - * overflow (when the input is less than smallest int8 or - * greater than largest int8). - * - * Counterpart to Solidity's `int8` operator. - * - * Requirements: - * - * - input must fit into 8 bits - */ - function toInt8(int256 value) internal pure returns (int8 downcasted) { - downcasted = int8(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(8, value); - } - } - - /** - * @dev Converts an unsigned uint256 into a signed int256. - * - * Requirements: - * - * - input must be less than or equal to maxInt256. - */ - function toInt256(uint256 value) internal pure returns (int256) { - // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive - if (value > uint256(type(int256).max)) { - revert SafeCastOverflowedUintToInt(value); - } - return int256(value); - } -} diff --git a/crates/solidity/testing/perf/benches/iai/tests/cursor.rs b/crates/solidity/testing/perf/benches/iai/tests/cursor.rs new file mode 100644 index 000000000..b87986aa3 --- /dev/null +++ b/crates/solidity/testing/perf/benches/iai/tests/cursor.rs @@ -0,0 +1,27 @@ +use slang_solidity::kinds::NonterminalKind; +use slang_solidity::text_index::TextIndex; + +use crate::tests::parser::ParsedFile; + +pub fn setup() -> Vec { + let files = super::parser::setup(); + + super::parser::run(files) +} + +pub fn run(files: &[ParsedFile]) { + let mut functions_count = 0; + + for file in files { + let mut cursor = file.tree.cursor_with_offset(TextIndex::ZERO); + + while cursor.go_to_next_nonterminal_with_kind(NonterminalKind::FunctionDefinition) { + functions_count += 1; + } + } + + assert_eq!( + functions_count, 200, + "Failed to fetch all function definitions" + ); +} diff --git a/crates/solidity/testing/perf/benches/iai/tests/definitions.rs b/crates/solidity/testing/perf/benches/iai/tests/definitions.rs new file mode 100644 index 000000000..f883895bd --- /dev/null +++ b/crates/solidity/testing/perf/benches/iai/tests/definitions.rs @@ -0,0 +1,48 @@ +use std::sync::Arc; + +use metaslang_bindings::PathResolver; +use slang_solidity::bindings::{create_with_resolver, Bindings}; +use slang_solidity::text_index::TextIndex; + +use crate::dataset::SOLC_VERSION; +use crate::tests::parser::ParsedFile; + +pub fn setup() -> Vec { + let files = super::parser::setup(); + + super::parser::run(files) +} + +pub fn run(files: &[ParsedFile]) -> Bindings { + let mut definition_count = 0_usize; + let mut bindings = create_with_resolver(SOLC_VERSION, Arc::new(NoOpResolver {})); + + for ParsedFile { + path, + contents: _, + tree, + } in files + { + bindings.add_file( + path.to_str().unwrap(), + tree.cursor_with_offset(TextIndex::ZERO), + ); + definition_count += bindings.all_definitions().count(); + } + + assert!( + // TODO(#1077): finalize the assertion counts once bindings are fully implemented: + definition_count >= 723, + "Only found {definition_count} definitions" + ); + + bindings +} + +struct NoOpResolver; + +impl PathResolver for NoOpResolver { + fn resolve_path(&self, _context_path: &str, path_to_resolve: &str) -> Option { + Some(path_to_resolve.to_string()) + } +} diff --git a/crates/solidity/testing/perf/benches/iai/tests/mod.rs b/crates/solidity/testing/perf/benches/iai/tests/mod.rs new file mode 100644 index 000000000..57805e704 --- /dev/null +++ b/crates/solidity/testing/perf/benches/iai/tests/mod.rs @@ -0,0 +1,5 @@ +pub mod cursor; +pub mod definitions; +pub mod parser; +pub mod query; +pub mod references; diff --git a/crates/solidity/testing/perf/benches/iai/tests/parser.rs b/crates/solidity/testing/perf/benches/iai/tests/parser.rs new file mode 100644 index 000000000..801c85d2f --- /dev/null +++ b/crates/solidity/testing/perf/benches/iai/tests/parser.rs @@ -0,0 +1,43 @@ +use std::path::PathBuf; + +use slang_solidity::cst::Node; +use slang_solidity::language::Language; + +use crate::dataset::{SourceFile, SOLC_VERSION}; + +pub struct ParsedFile { + pub path: PathBuf, + + #[allow(dead_code)] // false-positive. it is used below. + pub contents: String, + + pub tree: Node, +} + +pub fn setup() -> Vec { + SourceFile::load_all() +} + +pub fn run(files: Vec) -> Vec { + let language = Language::new(SOLC_VERSION).unwrap(); + + let mut results = vec![]; + + for SourceFile { path, contents } in files { + let parse_output = language.parse(Language::ROOT_KIND, &contents); + + assert!( + parse_output.is_valid(), + "Found parse errors:\n{0:#?}", + parse_output.errors(), + ); + + results.push(ParsedFile { + path, + contents, + tree: parse_output.tree(), + }); + } + + results +} diff --git a/crates/solidity/testing/perf/benches/iai/tests/query.rs b/crates/solidity/testing/perf/benches/iai/tests/query.rs new file mode 100644 index 000000000..868b2b180 --- /dev/null +++ b/crates/solidity/testing/perf/benches/iai/tests/query.rs @@ -0,0 +1,36 @@ +use slang_solidity::query::Query; +use slang_solidity::text_index::TextIndex; + +use crate::tests::parser::ParsedFile; + +pub fn setup() -> Vec { + let files = super::parser::setup(); + + super::parser::run(files) +} + +pub fn run(files: &[ParsedFile]) { + let mut functions_count = 0; + + let queries = vec![Query::parse( + "[FunctionDefinition + @name name: [_] + ]", + ) + .unwrap()]; + + for file in files { + let cursor = file.tree.cursor_with_offset(TextIndex::ZERO); + + for query_match in cursor.query(queries.clone()) { + assert_eq!(query_match.captures.len(), 1); + + functions_count += 1; + } + } + + assert_eq!( + functions_count, 200, + "Failed to fetch all function definitions" + ); +} diff --git a/crates/solidity/testing/perf/benches/iai/tests/references.rs b/crates/solidity/testing/perf/benches/iai/tests/references.rs new file mode 100644 index 000000000..4e2df5b1d --- /dev/null +++ b/crates/solidity/testing/perf/benches/iai/tests/references.rs @@ -0,0 +1,33 @@ +use slang_solidity::bindings::Bindings; + +pub fn setup() -> Bindings { + let trees = super::definitions::setup(); + + super::definitions::run(&trees) +} + +pub fn run(bindings: &Bindings) { + let mut reference_count = 0_usize; + let mut resolved_references = 0_usize; + + for reference in bindings.all_references() { + reference_count += 1; + + let resolution = reference.jump_to_definition(); + if resolution.is_ok() { + resolved_references += 1; + } + } + + assert!( + // TODO(#1077): finalize the assertion counts once bindings are fully implemented: + reference_count >= 1491, + "Only found {reference_count} references" + ); + + assert!( + // TODO(#1077): finalize the assertion counts once bindings are fully implemented: + resolved_references >= 1170, + "Only resolved {resolved_references} references" + ); +} diff --git a/crates/solidity/testing/perf/package.json b/crates/solidity/testing/perf/package.json new file mode 100644 index 000000000..745c5522b --- /dev/null +++ b/crates/solidity/testing/perf/package.json @@ -0,0 +1,7 @@ +{ + "name": "@slang-private/solidity-testing-perf", + "private": true, + "devDependencies": { + "@openzeppelin/contracts": "5.0.0" + } +} diff --git a/package-lock.json b/package-lock.json index 6777b6dd7..eadea05a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "crates/solidity/outputs/npm/package/platforms/win32-ia32-msvc", "crates/solidity/outputs/npm/package/platforms/win32-x64-msvc", "crates/solidity/outputs/npm/tests", + "crates/solidity/testing/perf", "crates/testlang/outputs/npm/package", "crates/testlang/outputs/npm/tests" ] @@ -153,6 +154,18 @@ "ts-node": "10.9.2" } }, + "crates/solidity/testing/perf": { + "name": "@slang-private/solidity-testing-perf", + "devDependencies": { + "@openzeppelin/contracts": "5.0.0" + } + }, + "crates/solidity/testing/perf/node_modules/@openzeppelin/contracts": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.0.tgz", + "integrity": "sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw==", + "dev": true + }, "crates/testlang/outputs/npm/package": { "name": "@slang-private/slang-testlang", "devDependencies": { @@ -2648,6 +2661,10 @@ "resolved": "crates/solidity/outputs/npm/tests", "link": true }, + "node_modules/@slang-private/solidity-testing-perf": { + "resolved": "crates/solidity/testing/perf", + "link": true + }, "node_modules/@slang-private/testlang-npm-tests": { "resolved": "crates/testlang/outputs/npm/tests", "link": true diff --git a/package.json b/package.json index 7a2fa1b3d..2e120ab96 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "crates/solidity/outputs/npm/package/platforms/win32-ia32-msvc", "crates/solidity/outputs/npm/package/platforms/win32-x64-msvc", "crates/solidity/outputs/npm/tests", + "crates/solidity/testing/perf", "crates/testlang/outputs/npm/package", "crates/testlang/outputs/npm/tests" ]