diff --git a/.github/workflows/sourcify-sweep.yaml b/.github/workflows/sourcify-sweep.yaml new file mode 100644 index 000000000..aa862f5ed --- /dev/null +++ b/.github/workflows/sourcify-sweep.yaml @@ -0,0 +1,205 @@ +name: Sourcify Sweep + +# Runs `solx-dev test sourcify` over the pinned Sourcify corpus with the slang +# build of the commit, one shard per job, and reports the outcome table plus +# the ranked failure census. Runs on every push to main, and on PR pushes while +# the PR carries the `ci:sourcify-sweep` label (adding the label starts a run). +# Report-only: frontend failures never fail the run, only harness breakage does. +# +# The corpus release and both compilers are pinned in solx-dev/sourcify-tests.toml. + +on: + pull_request: + types: [opened, synchronize, reopened, labeled] + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + +concurrency: + # Pushes group by SHA: GitHub keeps one pending run per group, so a + # shared main group would drop queued pushes. + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +defaults: + run: + shell: bash -ex {0} + +env: + SHARD_COUNT: 24 + +jobs: + + label-check: + if: >- + github.event_name != 'pull_request' + || (contains(github.event.pull_request.labels.*.name, 'ci:sourcify-sweep') + && (github.event.action != 'labeled' || github.event.label.name == 'ci:sourcify-sweep') + && !github.event.pull_request.head.repo.fork) + runs-on: ubuntu-24.04 + steps: + - run: 'true' + + cooldown-check: + name: Cargo cooldown check + runs-on: ubuntu-24.04 + needs: label-check + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + persist-credentials: false + - uses: ./.github/actions/cooldown-check + + sweep: + name: Sweep shard ${{ matrix.shard }} + needs: [label-check, cooldown-check] + permissions: + contents: read + packages: read + runs-on: ubuntu-24.04 + container: + image: ghcr.io/nomicfoundation/solx-ci-runner@sha256:cd5a37f2630fdf1898ddb2ca11f8c2ecc4d572c60011fe923b27b1625f92ba15 + # Same host bind-mounts as test.yaml's cargo-checks job so the + # free-disk-space-linux action can reclaim room for the LLVM tree. + volumes: + - /usr/share/dotnet:/mnt/free-disk-space/dotnet + - /usr/local/lib/android:/mnt/free-disk-space/android + - /opt/ghc:/mnt/free-disk-space/ghc + - /usr/local/.ghcup:/mnt/free-disk-space/ghcup + - /opt/hostedtoolcache/CodeQL:/mnt/free-disk-space/codeql + # Warm caches: 12-18 min per shard, build included. A cold LLVM build + # (solx-llvm bump on the PR) adds well over an hour. + timeout-minutes: 180 + env: + CARGO_INCREMENTAL: "0" + SHARD: ${{ matrix.shard }} + strategy: + fail-fast: false + matrix: + # Must stay in sync with SHARD_COUNT above. + shard: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23] + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + submodules: true + persist-credentials: false + + - name: Free disk space (Linux) + uses: ./.github/actions/free-disk-space-linux + + # Standard toolchain configuration (RelWithDebInfo + assertions + MLIR): + # the LLVM cache that cache-warmup.yaml keeps warm on hosted runners. + - name: Build toolchain + uses: ./.github/actions/build-toolchain + + - name: Cache cargo artifacts + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + with: + prefix-key: sourcify-sweep-v1 + cache-on-failure: true + # Every shard builds the same artifacts; one saver is enough. + save-if: ${{ matrix.shard == 0 }} + + - name: Build slang and solx-dev + run: | + ${SFW_PREFIX:-} cargo fetch --locked + ${SFW_PREFIX:-} cargo build --frozen --release --bin slang --bin solx-dev + ./target/release/slang --version + + # The sweep needs only the two binaries; the LLVM tree and the rest of + # the target dir go so the corpus slice and 4 concurrent compiler + # processes have room. + - name: Free disk space (remove build artifacts) + run: | + df -h . + mv target/release/slang target/release/solx-dev "${RUNNER_TEMP}/" + rm -rf solx-llvm target-llvm target + mkdir -p target/release + mv "${RUNNER_TEMP}/slang" "${RUNNER_TEMP}/solx-dev" target/release/ + df -h . + + - name: Run the sweep shard + run: | + ./target/release/solx-dev test sourcify \ + --corpus-dir "${RUNNER_TEMP}/corpus" \ + --output-path "${RUNNER_TEMP}/results-shard-${SHARD}.jsonl" \ + --shard-count "${SHARD_COUNT}" \ + --shard-index "${SHARD}" \ + --threads 4 \ + --memory-limit-mib 6144 + + - name: Upload shard results + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sourcify-sweep-results-shard-${{ matrix.shard }} + path: ${{ runner.temp }}/results-shard-${{ matrix.shard }}.jsonl + if-no-files-found: error + + - name: Upload solx-dev + if: matrix.shard == 0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sourcify-sweep-solx-dev + path: target/release/solx-dev + if-no-files-found: error + + summarize: + name: Summarize + needs: sweep + if: ${{ !cancelled() && needs.sweep.result != 'skipped' }} + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - name: Download solx-dev + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: sourcify-sweep-solx-dev + path: ${{ runner.temp }}/bin + + - name: Download shard results + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: sourcify-sweep-results-shard-* + path: ${{ runner.temp }}/shards + merge-multiple: true + + - name: Combine shards and report + run: | + shards=$(find "${RUNNER_TEMP}/shards" -name 'results-shard-*.jsonl' | wc -l) + if [ "${shards}" -ne "${SHARD_COUNT}" ]; then + echo "Expected ${SHARD_COUNT} shard result files, found ${shards}." >&2 + exit 1 + fi + cat "${RUNNER_TEMP}"/shards/results-shard-*.jsonl > "${RUNNER_TEMP}/results.jsonl" + # Artifacts drop the executable bit. + chmod +x "${RUNNER_TEMP}/bin/solx-dev" + "${RUNNER_TEMP}/bin/solx-dev" test sourcify-report \ + --results-paths "${RUNNER_TEMP}/results.jsonl" \ + --output-path "${RUNNER_TEMP}/report.md" \ + --title "Sourcify sweep (slang vs latest solx release)" + cat "${RUNNER_TEMP}/report.md" >> "${GITHUB_STEP_SUMMARY}" + + - name: Post report comment + if: github.event_name == 'pull_request' + uses: mshick/add-pr-comment@ec328af66588ab8f77cdeb2c264f14aba45bbf59 # v3.12 + with: + message-id: 'sourcify-sweep-report' + message-path: ${{ runner.temp }}/report.md + + - name: Upload combined results + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sourcify-sweep-results + path: | + ${{ runner.temp }}/results.jsonl + ${{ runner.temp }}/report.md diff --git a/Cargo.lock b/Cargo.lock index 61994f960..4e01b6365 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4848,6 +4848,7 @@ dependencies = [ "glob", "hex", "itertools 0.15.0", + "libc", "path-slash", "regex", "sedregex", diff --git a/docs/src/developer-guide/01-testing.md b/docs/src/developer-guide/01-testing.md index b18f5c270..a8890e94e 100644 --- a/docs/src/developer-guide/01-testing.md +++ b/docs/src/developer-guide/01-testing.md @@ -90,6 +90,32 @@ cargo build --release --bin solx-dev The test configurations list projects that are cloned and tested automatically. See [foundry-tests.toml](https://github.com/NomicFoundation/solx/blob/main/solx-dev/foundry-tests.toml) and [hardhat-tests.toml](https://github.com/NomicFoundation/solx/blob/main/solx-dev/hardhat-tests.toml) for the full list of tested projects. +## Sourcify Corpus + +The Sourcify sweep compiles every verified Sourcify contract for solc 0.8.34 and 0.8.36 with `evmVersion` at least `cancun` (119,117 contracts) through `slang --standard-json`, and re-runs each failure with the latest solx release, so a `slang` gap is told apart from input neither compiles: + +```shell +cargo build --release --bin slang --bin solx-dev + +# The 10 committed fixtures +./target/release/solx-dev test sourcify --corpus-path tests/sourcify-sweep/fixtures +./target/release/solx-dev test sourcify-report --results-paths temp-sourcify-reports/results.jsonl + +# One shard of the pinned corpus, as a CI job runs it +./target/release/solx-dev test sourcify --shard-count 24 --shard-index 0 --memory-limit-mib 6144 +``` + +[sourcify-tests.toml](https://github.com/NomicFoundation/solx/blob/main/solx-dev/sourcify-tests.toml) pins the corpus release and names the two compilers. Each contract becomes one standard JSON input with its sources inline, `evmVersion`, `libraries`, `remappings` and `viaIR` passed through verbatim, and bytecode as the only output. Every version pragma is rewritten to `pragma solidity >=<--solidity-version>;`, so both compilers accept the same input. + +| Outcome | Meaning | +|---|---| +| `ok` | No error diagnostics and bytecode for a contract of the target source | +| `slang-fail` | `slang` fails and the latest solx release compiles | +| `both-fail` | Both fail: a corpus artifact or a documented compiler limitation | +| `timeout` | `slang` exceeded `--timeout` | + +The report ranks failures by normalized diagnostic, with example contracts. CI runs the sweep on every push to `main` and on pull requests labelled `ci:sourcify-sweep`, where the report becomes a pull request comment. + ## Test Collection This section describes the format of test files used by **solx-tester**. diff --git a/solx-compiler-downloader/src/lib.rs b/solx-compiler-downloader/src/lib.rs index b7e257886..0a74d1bae 100644 --- a/solx-compiler-downloader/src/lib.rs +++ b/solx-compiler-downloader/src/lib.rs @@ -191,7 +191,7 @@ impl Downloader { /// /// Downloads a file from a URL to a destination path, with resume support and retries. /// - fn download_file(&self, url: &str, destination: impl AsRef) -> anyhow::Result<()> { + pub fn download_file(&self, url: &str, destination: impl AsRef) -> anyhow::Result<()> { std::fs::create_dir_all(destination.as_ref().parent().expect("Always exists"))?; let destination = destination.as_ref(); diff --git a/solx-dev/Cargo.toml b/solx-dev/Cargo.toml index 4594bf52b..f687f9cd9 100644 --- a/solx-dev/Cargo.toml +++ b/solx-dev/Cargo.toml @@ -31,3 +31,6 @@ sedregex = "0.2" solx-compiler-downloader = { path = "../solx-compiler-downloader" } solx-benchmark-converter = { path = "../solx-benchmark-converter" } solx-utils = { path = "../solx-utils" } + +[target.'cfg(unix)'.dependencies] +libc = "0.2" diff --git a/solx-dev/sourcify-tests.toml b/solx-dev/sourcify-tests.toml new file mode 100644 index 000000000..84d89f854 --- /dev/null +++ b/solx-dev/sourcify-tests.toml @@ -0,0 +1,32 @@ +# Sourcify sweep configuration for `solx-dev test sourcify`. +# +# Corpus: +# [corpus] +# url = "https://..." # Release asset unpacking to ./corpus.json + ./contracts/_
.json +# sha256 = "..." # SHA-256 of the release asset +# +# Compilers, as in hardhat-tests.toml: the candidate compiles every contract, +# the reference re-runs the candidate's failures. +# [compilers.] +# name = "slang" # Display name +# path = "./path/to/compiler" # Path to compiler executable +# solidity_version = "0.8.36" # Override --solidity-version for this compiler (optional) +# is_correctness_reference = true/false +# is_correctness_candidate = true/false + +# Every verified Sourcify contract for solc 0.8.34 and 0.8.36 with evmVersion >= cancun. +[corpus] +url = "https://github.com/nebasuke/sourcify-corpora/releases/download/sourcify-corpus-solc-0.8.34-0.8.36-20260920/sourcify-corpus-solc-0.8.34-0.8.36-20260920.tar.xz" +sha256 = "0642e21776808674fb3fc50d352fc666dd7e8d062a322de51d44ab288fd0eb2e" + +[compilers.slang] +name = "slang" +path = "./target/release/slang" +description = "slang built from the current commit" +is_correctness_candidate = true + +[compilers.solx-latest] +name = "solx-latest" +path = "./temp-compilers/solx-latest" +description = "solx downloaded from the latest release" +is_correctness_reference = true diff --git a/solx-dev/src/arguments/test/mod.rs b/solx-dev/src/arguments/test/mod.rs index 3cfe99235..f498aeb99 100644 --- a/solx-dev/src/arguments/test/mod.rs +++ b/solx-dev/src/arguments/test/mod.rs @@ -5,12 +5,15 @@ pub mod foundry; pub mod hardhat; pub mod solx_tester; +pub mod sourcify; use clap::Subcommand; pub use self::foundry::Foundry; pub use self::hardhat::Hardhat; pub use self::solx_tester::SolxTester; +pub use self::sourcify::Sourcify; +pub use self::sourcify::SourcifyReport; /// /// `solx` test arguments. @@ -23,4 +26,8 @@ pub enum Test { Foundry(Foundry), /// Run integration tests with solx-tester. SolxTester(SolxTester), + /// Compile a Sourcify corpus and record the outcomes. + Sourcify(Sourcify), + /// Render the Sourcify sweep report from recorded outcomes. + SourcifyReport(SourcifyReport), } diff --git a/solx-dev/src/arguments/test/sourcify.rs b/solx-dev/src/arguments/test/sourcify.rs new file mode 100644 index 000000000..5578d2c8a --- /dev/null +++ b/solx-dev/src/arguments/test/sourcify.rs @@ -0,0 +1,109 @@ +//! +//! `solx` Sourcify sweep arguments. +//! + +use std::path::PathBuf; + +use clap::Args; + +/// +/// `solx` Sourcify sweep arguments. +/// +#[derive(Args)] +pub struct Sourcify { + // + // Configuration Paths + // + /// Sourcify sweep configuration path. + #[arg( + long, + default_value = "./solx-dev/sourcify-tests.toml", + help_heading = "Configuration Paths" + )] + pub test_config_path: PathBuf, + + /// Compiler downloader configuration path. + #[arg( + long, + default_value = "./solx-compiler-downloader/dev-compilers.json", + help_heading = "Configuration Paths" + )] + pub downloader_config_path: PathBuf, + + // + // Directories + // + /// Directory the pinned corpus is downloaded to and its slice extracted in. + #[arg( + long, + default_value = "./temp-sourcify-corpus", + help_heading = "Directories" + )] + pub corpus_dir: PathBuf, + + /// Local corpus to sweep instead of the pinned one: a corpus root with `contracts/`, or a + /// contracts directory such as `./tests/sourcify-sweep/fixtures`. + #[arg(long, help_heading = "Directories")] + pub corpus_path: Option, + + /// Results path, one JSON line per contract. + #[arg( + long, + default_value = "./temp-sourcify-reports/results.jsonl", + help_heading = "Directories" + )] + pub output_path: PathBuf, + + // + // Test Filtering + // + /// Solidity version every version pragma is rewritten to, as a lower bound. + #[arg(long, default_value = "0.8.34", help_heading = "Test Filtering")] + pub solidity_version: String, + + /// Number of round-robin shards the sorted corpus is split into. + #[arg(long, default_value_t = 1, help_heading = "Test Filtering")] + pub shard_count: usize, + + /// Shard to sweep, in `[0, --shard-count)`. + #[arg(long, default_value_t = 0, help_heading = "Test Filtering")] + pub shard_index: usize, + + /// Stop after this many contracts. + #[arg(long, help_heading = "Test Filtering")] + pub limit: Option, + + // + // Limits + // + /// Number of concurrent compiler processes [default: available parallelism]. + #[arg(long, help_heading = "Limits")] + pub threads: Option, + + /// Per-compilation timeout in seconds. + #[arg(long, default_value_t = 300, help_heading = "Limits")] + pub timeout: u64, + + /// Address-space cap of each compiler process in MiB, so an out-of-memory compilation aborts + /// instead of taking the machine down; 0 for none. + #[arg(long, default_value_t = 0, help_heading = "Limits")] + pub memory_limit_mib: u64, +} + +/// +/// `solx` Sourcify sweep report arguments. +/// +#[derive(Args)] +pub struct SourcifyReport { + /// Results paths written by `test sourcify`, e.g. one per shard. + #[arg(long, num_args = 1.., required = true)] + pub results_paths: Vec, + + /// Markdown report path [default: standard output]. + #[arg(long)] + pub output_path: Option, + + /// Report heading. + #[arg(long, default_value = "Sourcify sweep")] + pub title: String, +} diff --git a/solx-dev/src/lib.rs b/solx-dev/src/lib.rs index 69d4d6dc3..88577501c 100644 --- a/solx-dev/src/lib.rs +++ b/solx-dev/src/lib.rs @@ -25,5 +25,10 @@ pub use self::test::foundry::test as test_foundry; pub use self::test::hardhat::config::Config as HardhatTestConfig; pub use self::test::hardhat::test as test_hardhat; pub use self::test::solx_tester::run as solx_tester; +pub use self::test::sourcify::Limits as SourcifyLimits; +pub use self::test::sourcify::config::Config as SourcifyTestConfig; +pub use self::test::sourcify::corpus::Slice as SourcifySlice; +pub use self::test::sourcify::report::report as report_sourcify; +pub use self::test::sourcify::run as test_sourcify; pub use self::utils::*; pub use self::workflow::Workflow; diff --git a/solx-dev/src/solx_dev/main.rs b/solx-dev/src/solx_dev/main.rs index bd84e162a..b3662f3de 100644 --- a/solx-dev/src/solx_dev/main.rs +++ b/solx-dev/src/solx_dev/main.rs @@ -101,6 +101,47 @@ fn main_inner() -> anyhow::Result<()> { Arguments::Test(TestArguments::SolxTester(arguments)) => { solx_dev::solx_tester(arguments)?; } + Arguments::Test(TestArguments::Sourcify(arguments)) => { + if arguments.shard_count == 0 || arguments.shard_index >= arguments.shard_count { + anyhow::bail!("--shard-index must be in [0, --shard-count)"); + } + + let test_config_path = solx_dev::absolute_path(arguments.test_config_path)?; + let test_config = solx_dev::SourcifyTestConfig::try_from(test_config_path)?; + + let downloader_config_path = solx_dev::absolute_path(arguments.downloader_config_path)?; + let downloader = solx_compiler_downloader::Downloader::default(); + downloader.download(downloader_config_path.as_path())?; + + let threads = match arguments.threads { + Some(threads) => threads, + None => std::thread::available_parallelism()?.get(), + }; + solx_dev::test_sourcify( + test_config, + arguments.corpus_dir, + arguments.corpus_path, + arguments.output_path, + arguments.solidity_version, + solx_dev::SourcifySlice { + shard_count: arguments.shard_count, + shard_index: arguments.shard_index, + limit: arguments.limit, + }, + solx_dev::SourcifyLimits { + threads, + timeout: std::time::Duration::from_secs(arguments.timeout), + memory_limit_mib: arguments.memory_limit_mib, + }, + )?; + } + Arguments::Test(TestArguments::SourcifyReport(arguments)) => { + solx_dev::report_sourcify( + arguments.results_paths, + arguments.output_path, + arguments.title, + )?; + } } Ok(()) diff --git a/solx-dev/src/test/mod.rs b/solx-dev/src/test/mod.rs index 0b636f146..56fc46dac 100644 --- a/solx-dev/src/test/mod.rs +++ b/solx-dev/src/test/mod.rs @@ -7,6 +7,7 @@ use itertools::Itertools; pub mod foundry; pub mod hardhat; pub mod solx_tester; +pub mod sourcify; /// Codegen variants every enabled compiler is tested with. pub(crate) const CODEGENS: [&str; 1] = ["legacy"]; diff --git a/solx-dev/src/test/sourcify/compilation.rs b/solx-dev/src/test/sourcify/compilation.rs new file mode 100644 index 000000000..e406e4d5e --- /dev/null +++ b/solx-dev/src/test/sourcify/compilation.rs @@ -0,0 +1,295 @@ +//! +//! `solx` Sourcify sweep compiler invocation. +//! + +use std::collections::BTreeMap; +use std::io::Read; +use std::io::Write; +use std::path::Path; +use std::process::Command; +use std::process::Stdio; +use std::sync::LazyLock; +use std::time::Duration; +use std::time::Instant; + +use regex::Regex; + +use super::record::Kind; +use super::record::Leg; + +/// The number of trailing standard error characters kept in a record. +const STDERR_TAIL: usize = 2000; + +/// The number of error-severity messages kept in a record. +const MAX_MESSAGES: usize = 5; + +/// The interval at which a running compiler is polled for exit. +const POLL_INTERVAL: Duration = Duration::from_millis(20); + +static SOL_PATH: LazyLock = + LazyLock::new(|| Regex::new(r#"[^\s"'`]+\.sol\b"#).expect("Always valid")); +static HEX_NUMBER: LazyLock = + LazyLock::new(|| Regex::new(r"0x[0-9a-fA-F]+").expect("Always valid")); +static DECIMAL_NUMBER: LazyLock = + LazyLock::new(|| Regex::new(r"\b\d+\b").expect("Always valid")); +static PANIC_WITH_MESSAGE: LazyLock = + LazyLock::new(|| Regex::new(r"panicked at [^\n]+:\n([^\n]*)").expect("Always valid")); +static PANIC: LazyLock = + LazyLock::new(|| Regex::new(r"panicked at [^\n]+").expect("Always valid")); + +/// +/// Compiles a standard JSON input and classifies the result. +/// +/// Errors only on harness breakage: a compiler that cannot be spawned or waited for. +/// +pub fn compile( + compiler: &Path, + input: Vec, + target: &str, + timeout: Duration, + memory_limit_mib: u64, +) -> anyhow::Result { + let mut command = Command::new(compiler); + command.arg("--standard-json"); + command.stdin(Stdio::piped()); + command.stdout(Stdio::piped()); + command.stderr(Stdio::piped()); + if memory_limit_mib > 0 { + limit_address_space(&mut command, memory_limit_mib)?; + } + let mut process = command + .spawn() + .map_err(|error| anyhow::anyhow!("{command:?} process spawning error: {error}"))?; + + let mut stdin = process.stdin.take().expect("Always piped"); + let mut stdout = process.stdout.take().expect("Always piped"); + let mut stderr = process.stderr.take().expect("Always piped"); + // A compiler that exits before reading all input closes the pipe; its output says why. + let writer = std::thread::spawn(move || { + let _ = stdin.write_all(input.as_slice()); + }); + let stdout_reader = std::thread::spawn(move || { + let mut buffer = Vec::new(); + let _ = stdout.read_to_end(&mut buffer); + buffer + }); + let stderr_reader = std::thread::spawn(move || { + let mut buffer = Vec::new(); + let _ = stderr.read_to_end(&mut buffer); + buffer + }); + + let started = Instant::now(); + let status = loop { + if let Some(status) = process + .try_wait() + .map_err(|error| anyhow::anyhow!("{command:?} waiting error: {error}"))? + { + break status; + } + if started.elapsed() > timeout { + let _ = process.kill(); + let _ = process.wait(); + // The readers are left behind: a surviving worker process may still hold the pipes. + return Ok(Leg { + kind: Kind::Timeout, + ..Leg::default() + }); + } + std::thread::sleep(POLL_INTERVAL); + }; + let _ = writer.join(); + let stdout = stdout_reader.join().expect("Never panics"); + let stderr = String::from_utf8_lossy(stderr_reader.join().expect("Never panics").as_slice()) + .into_owned(); + + Ok(classify(status, stdout.as_slice(), stderr.as_str(), target)) +} + +/// +/// Classifies a finished compiler run: ok | error | no-bytecode | panic | abort. +/// +fn classify(status: std::process::ExitStatus, stdout: &[u8], stderr: &str, target: &str) -> Leg { + let exit = exit_code(status); + let stderr_tail = tail(stderr, STDERR_TAIL); + let mut leg = Leg { + exit: Some(exit), + ..Leg::default() + }; + + if exit < 0 { + let last_line = stderr_tail.trim().lines().last().unwrap_or_default(); + leg.kind = Kind::Abort; + leg.signature = Some(format!("signal {}: {}", -exit, signature(last_line))); + leg.stderr = Some(stderr_tail); + return leg; + } + if stderr.contains("panicked at") { + leg.kind = Kind::Panic; + leg.signature = Some(signature(panic_message(stderr).as_str())); + leg.stderr = Some(stderr_tail); + return leg; + } + + let Ok(output) = serde_json::from_slice::(stdout) else { + let message = if stderr_tail.is_empty() { + format!("exit {exit} without standard-JSON output") + } else { + stderr_tail.clone() + }; + leg.kind = Kind::Error; + leg.signature = Some(signature(message.as_str())); + leg.stderr = Some(stderr_tail); + return leg; + }; + + let messages: Vec = output + .get("errors") + .and_then(serde_json::Value::as_array) + .into_iter() + .flatten() + .filter(|error| error.get("severity").and_then(serde_json::Value::as_str) == Some("error")) + .map(|error| { + ["message", "formattedMessage"] + .into_iter() + .filter_map(|key| error.get(key).and_then(serde_json::Value::as_str)) + .find(|message| !message.is_empty()) + .unwrap_or_default() + .to_owned() + }) + .collect(); + if let Some(first) = messages.first() { + leg.kind = Kind::Error; + leg.signature = Some(signature(first.as_str())); + leg.error_count = Some(messages.len()); + leg.messages = messages.into_iter().take(MAX_MESSAGES).collect(); + if !stderr_tail.trim().is_empty() { + leg.stderr = Some(stderr_tail); + } + return leg; + } + + let contracts = output + .get("contracts") + .and_then(serde_json::Value::as_object); + let is_target_compiled = contracts + .and_then(|contracts| contracts.get(target)) + .and_then(serde_json::Value::as_object) + .is_some_and(|file| file.values().any(has_bytecode)); + if !is_target_compiled { + let emitted: BTreeMap> = contracts + .into_iter() + .flatten() + .map(|(path, file)| { + let names = file + .as_object() + .into_iter() + .flatten() + .filter(|(_name, contract)| has_bytecode(contract)) + .map(|(name, _contract)| name.to_owned()) + .collect(); + (path.to_owned(), names) + }) + .collect(); + leg.kind = Kind::NoBytecode; + leg.signature = Some("no errors reported but no bytecode for the target source".to_owned()); + leg.stderr = Some(stderr_tail); + leg.emitted = Some(emitted); + return leg; + } + + leg.kind = Kind::Ok; + leg +} + +/// +/// Collapses a diagnostic into a bucket key: first line, paths and numbers normalized. +/// +pub fn signature(message: &str) -> String { + let line = message.trim().lines().next().unwrap_or(""); + let line = SOL_PATH.replace_all(line, ""); + let line = HEX_NUMBER.replace_all(line.as_ref(), "0x…"); + let line = DECIMAL_NUMBER.replace_all(line.as_ref(), "N"); + line.chars().take(200).collect() +} + +/// +/// The panic message, which is the bucket key; the location stays in the recorded stderr tail. +/// +fn panic_message(stderr: &str) -> String { + if let Some(captures) = PANIC_WITH_MESSAGE.captures(stderr) { + let message = captures.get(1).expect("Always exists").as_str(); + return if message.is_empty() { + "".to_owned() + } else { + message.to_owned() + }; + } + if let Some(found) = PANIC.find(stderr) { + return found.as_str().to_owned(); + } + stderr.trim().lines().last().unwrap_or_default().to_owned() +} + +/// +/// Whether a standard JSON output contract has non-empty bytecode. +/// +fn has_bytecode(contract: &serde_json::Value) -> bool { + contract + .pointer("/evm/bytecode/object") + .and_then(serde_json::Value::as_str) + .is_some_and(|object| !object.is_empty()) +} + +/// +/// The last `count` characters of `text`. +/// +fn tail(text: &str, count: usize) -> String { + let skip = text.chars().count().saturating_sub(count); + text.chars().skip(skip).collect() +} + +/// +/// The exit code, or the negated signal number if the process was killed. +/// +fn exit_code(status: std::process::ExitStatus) -> i32 { + #[cfg(unix)] + if let Some(signal) = std::os::unix::process::ExitStatusExt::signal(&status) { + return -signal; + } + status.code().unwrap_or(-1) +} + +/// +/// Caps the compiler's address space so an out-of-memory compilation aborts deterministically +/// instead of taking the machine down. +/// +#[cfg(unix)] +fn limit_address_space(command: &mut Command, memory_limit_mib: u64) -> anyhow::Result<()> { + use std::os::unix::process::CommandExt; + + let limit = (memory_limit_mib * 1024 * 1024) as libc::rlim_t; + // SAFETY: `setrlimit` is async-signal-safe and touches only the child's own limits. + unsafe { + command.pre_exec(move || { + let rlimit = libc::rlimit { + rlim_cur: limit, + rlim_max: limit, + }; + if libc::setrlimit(libc::RLIMIT_AS, &rlimit) != 0 { + return Err(std::io::Error::last_os_error()); + } + Ok(()) + }); + } + Ok(()) +} + +/// +/// Caps the compiler's address space so an out-of-memory compilation aborts deterministically +/// instead of taking the machine down. +/// +#[cfg(not(unix))] +fn limit_address_space(_command: &mut Command, _memory_limit_mib: u64) -> anyhow::Result<()> { + anyhow::bail!("The compiler memory limit is only supported on Unix") +} diff --git a/solx-dev/src/test/sourcify/config.rs b/solx-dev/src/test/sourcify/config.rs new file mode 100644 index 000000000..92365a087 --- /dev/null +++ b/solx-dev/src/test/sourcify/config.rs @@ -0,0 +1,74 @@ +//! +//! `solx` Sourcify sweep config. +//! + +use std::collections::BTreeMap; +use std::path::PathBuf; + +use crate::test::hardhat::config::compiler::Compiler; + +/// +/// `solx` Sourcify sweep config. +/// +#[derive(Debug, serde::Deserialize)] +pub struct Config { + /// The pinned corpus release. + pub corpus: Corpus, + /// The candidate and reference compilers. + pub compilers: BTreeMap, +} + +/// +/// The pinned corpus release. +/// +#[derive(Debug, serde::Deserialize)] +pub struct Corpus { + /// The `.tar.xz` release asset URL. + pub url: String, + /// The SHA-256 of the release asset. + pub sha256: String, +} + +impl Config { + /// + /// The enabled compiler marked as the correctness candidate. + /// + pub fn candidate(&self) -> anyhow::Result<&Compiler> { + self.compilers + .values() + .find(|compiler| !compiler.disabled && compiler.is_correctness_candidate) + .ok_or_else(|| { + anyhow::anyhow!( + "No candidate compiler specified in the Sourcify sweep configuration" + ) + }) + } + + /// + /// The enabled compiler marked as the correctness reference. + /// + pub fn reference(&self) -> anyhow::Result<&Compiler> { + self.compilers + .values() + .find(|compiler| !compiler.disabled && compiler.is_correctness_reference) + .ok_or_else(|| { + anyhow::anyhow!( + "No reference compiler specified in the Sourcify sweep configuration" + ) + }) + } +} + +impl TryFrom for Config { + type Error = anyhow::Error; + + fn try_from(path: PathBuf) -> Result { + let string = std::fs::read_to_string(path.as_path()).map_err(|error| { + anyhow::anyhow!("Sourcify sweep configuration file {path:?} reading: {error}") + })?; + let config: Self = toml::from_str(string.as_str()).map_err(|error| { + anyhow::anyhow!("Sourcify sweep configuration file {path:?} parsing: {error}") + })?; + Ok(config) + } +} diff --git a/solx-dev/src/test/sourcify/corpus.rs b/solx-dev/src/test/sourcify/corpus.rs new file mode 100644 index 000000000..6ba83af92 --- /dev/null +++ b/solx-dev/src/test/sourcify/corpus.rs @@ -0,0 +1,167 @@ +//! +//! `solx` Sourcify sweep corpus. +//! + +use std::path::Path; +use std::path::PathBuf; +use std::process::Command; + +use super::config::Corpus; + +/// +/// A round-robin slice of the sorted corpus, so CI shards split it evenly. +/// +#[derive(Debug, Clone, Copy)] +pub struct Slice { + /// The number of shards. + pub shard_count: usize, + /// The shard to keep. + pub shard_index: usize, + /// The maximum number of contracts to keep, if any. + pub limit: Option, +} + +impl Slice { + /// + /// Sorts the corpus file names and keeps this slice of them. + /// + pub fn select(&self, mut names: Vec) -> Vec { + names.sort(); + names + .into_iter() + .enumerate() + .filter(|(index, _name)| index % self.shard_count == self.shard_index) + .map(|(_index, name)| name) + .take(self.limit.unwrap_or(usize::MAX)) + .collect() + } +} + +/// +/// Lists the slice of a local corpus directory: either a corpus root with `contracts/` or the +/// contracts directory itself. +/// +pub fn local(directory: &Path, slice: Slice) -> anyhow::Result> { + let contracts_directory = if directory.join("contracts").is_dir() { + directory.join("contracts") + } else { + directory.to_owned() + }; + let names = std::fs::read_dir(contracts_directory.as_path()) + .map_err(|error| { + anyhow::anyhow!("Corpus directory {contracts_directory:?} reading: {error}") + })? + .filter_map(Result::ok) + .map(|entry| entry.file_name().to_string_lossy().into_owned()) + .filter(|name| name.ends_with(".json")) + .collect(); + let names = slice.select(names); + if names.is_empty() { + anyhow::bail!("No corpus records under {contracts_directory:?}"); + } + Ok(names + .into_iter() + .map(|name| contracts_directory.join(name)) + .collect()) +} + +/// +/// Downloads the pinned corpus release into `directory`, verifies it, and extracts only the +/// slice, which is a small part of the full corpus. +/// +pub fn pinned(corpus: &Corpus, directory: &Path, slice: Slice) -> anyhow::Result> { + crate::utils::exists("tar")?; + crate::utils::exists("sha256sum")?; + + let file_name = corpus + .url + .rsplit('/') + .next() + .filter(|name| !name.is_empty()) + .ok_or_else(|| anyhow::anyhow!("Corpus URL `{}` has no file name", corpus.url))?; + let archive = directory.join(file_name); + if archive.exists() { + eprintln!( + "{} corpus {archive:?}. Already exists.", + solx_utils::cargo_status_ok("Skipping"), + ); + } else { + eprintln!( + "{} corpus {} => {archive:?}", + solx_utils::cargo_status_ok("Downloading"), + corpus.url, + ); + solx_compiler_downloader::Downloader::default() + .download_file(corpus.url.as_str(), archive.as_path())?; + } + + let mut sha256sum = Command::new("sha256sum"); + sha256sum.arg(archive.as_path()); + let checksum = output(&mut sha256sum)?; + let checksum = checksum.split_whitespace().next().unwrap_or_default(); + if checksum != corpus.sha256 { + anyhow::bail!( + "Corpus {archive:?} has SHA-256 {checksum}, but the configuration pins {}", + corpus.sha256 + ); + } + + let mut list = Command::new("tar"); + list.arg("-tJf").arg(archive.as_path()); + let names: Vec = output(&mut list)? + .lines() + .filter(|name| name.starts_with("./contracts/") && name.ends_with(".json")) + .map(str::to_owned) + .collect(); + let names = slice.select(names); + if names.is_empty() { + anyhow::bail!("No corpus records in {archive:?}"); + } + + let extracted = directory.join("extracted"); + if extracted.exists() { + std::fs::remove_dir_all(extracted.as_path()) + .map_err(|error| anyhow::anyhow!("Removing {extracted:?}: {error}"))?; + } + std::fs::create_dir_all(extracted.as_path()) + .map_err(|error| anyhow::anyhow!("Creating {extracted:?}: {error}"))?; + let slice_list = directory.join("slice.txt"); + std::fs::write(slice_list.as_path(), names.join("\n") + "\n") + .map_err(|error| anyhow::anyhow!("Writing {slice_list:?}: {error}"))?; + let mut extract = Command::new("tar"); + extract + .arg("-xJf") + .arg(archive.as_path()) + .arg("-C") + .arg(extracted.as_path()) + .arg("-T") + .arg(slice_list.as_path()); + crate::utils::command( + &mut extract, + format!( + "{} {} corpus records", + solx_utils::cargo_status_ok("Extracting"), + names.len() + ) + .as_str(), + )?; + + Ok(names.into_iter().map(|name| extracted.join(name)).collect()) +} + +/// +/// Runs a command and returns its standard output. +/// +fn output(command: &mut Command) -> anyhow::Result { + let output = command + .output() + .map_err(|error| anyhow::anyhow!("{command:?} process spawning error: {error}"))?; + if !output.status.success() { + anyhow::bail!( + "{command:?} subprocess failed: {}", + String::from_utf8_lossy(output.stderr.as_slice()) + ); + } + String::from_utf8(output.stdout) + .map_err(|error| anyhow::anyhow!("{command:?} output is not UTF-8: {error}")) +} diff --git a/solx-dev/src/test/sourcify/mod.rs b/solx-dev/src/test/sourcify/mod.rs new file mode 100644 index 000000000..686e1ffbb --- /dev/null +++ b/solx-dev/src/test/sourcify/mod.rs @@ -0,0 +1,306 @@ +//! +//! `solx` Sourcify sweep: compiles every contract of a Sourcify corpus through the candidate +//! compiler, re-runs its failures with the reference compiler, and records the outcomes. +//! + +pub mod compilation; +pub mod config; +pub mod corpus; +pub mod record; +pub mod report; + +use std::collections::BTreeMap; +use std::io::Write; +use std::path::Path; +use std::path::PathBuf; +use std::sync::LazyLock; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; +use std::time::Duration; +use std::time::Instant; + +use regex::Regex; + +use self::config::Config; +use self::corpus::Slice; +use self::record::Kind; +use self::record::Leg; +use self::record::Outcome; +use self::record::Record; + +/// Settings passed through verbatim: dropping one would turn a real frontend gap into a harness +/// artifact, and the same input must stay valid for the reference compiler. +const PASSTHROUGH_SETTINGS: [&str; 4] = ["evmVersion", "libraries", "remappings", "viaIR"]; + +/// Version-expression characters only, so `pragma solidity` in a comment never swallows code up +/// to the next `;`. +static VERSION_PRAGMA: LazyLock = LazyLock::new(|| { + Regex::new(r"pragma\s+solidity\s+[0-9xX*.^~<>=|\s-]+;").expect("Always valid") +}); + +/// +/// The compiler invocation limits of a sweep. +/// +#[derive(Debug, Clone, Copy)] +pub struct Limits { + /// The number of concurrent compiler processes. + pub threads: usize, + /// The per-compilation timeout. + pub timeout: Duration, + /// The address-space cap of each compiler process in MiB, or 0 for none. + pub memory_limit_mib: u64, +} + +/// +/// Sweeps a slice of the corpus and writes one JSON line per contract to `output_path`, after a +/// first line with both compilers' versions. +/// +/// Compilation failures are results, not errors: only harness breakage fails the sweep. +/// +pub fn run( + config: Config, + corpus_directory: PathBuf, + corpus_path: Option, + output_path: PathBuf, + solidity_version: String, + slice: Slice, + limits: Limits, +) -> anyhow::Result<()> { + let candidate = config.candidate()?; + let reference = config.reference()?; + let candidate_path = crate::utils::absolute_path(candidate.path.as_str())?; + let reference_path = crate::utils::absolute_path(reference.path.as_str())?; + let candidate_pragma = format!( + "pragma solidity >={};", + candidate + .solidity_version + .as_deref() + .unwrap_or(solidity_version.as_str()) + ); + let reference_pragma = format!( + "pragma solidity >={};", + reference + .solidity_version + .as_deref() + .unwrap_or(solidity_version.as_str()) + ); + + let contracts = match corpus_path { + Some(corpus_path) => corpus::local(corpus_path.as_path(), slice)?, + None => corpus::pinned(&config.corpus, corpus_directory.as_path(), slice)?, + }; + + if let Some(parent) = output_path.parent() { + std::fs::create_dir_all(parent) + .map_err(|error| anyhow::anyhow!("Creating {parent:?}: {error}"))?; + } + let mut output = std::fs::File::create(output_path.as_path()) + .map_err(|error| anyhow::anyhow!("Creating {output_path:?}: {error}"))?; + let meta = serde_json::json!({ + "meta": { + "slang": version(candidate_path.as_path())?, + "baseline": version(reference_path.as_path())?, + } + }); + writeln!(output, "{meta}") + .map_err(|error| anyhow::anyhow!("Writing {output_path:?}: {error}"))?; + + eprintln!( + "{} {} contracts with {} threads", + solx_utils::cargo_status_ok("Sweeping"), + contracts.len(), + limits.threads + ); + let started = Instant::now(); + let mut counts = BTreeMap::new(); + let next = AtomicUsize::new(0); + std::thread::scope(|scope| -> anyhow::Result<()> { + let (sender, receiver) = std::sync::mpsc::channel(); + for _ in 0..limits.threads { + let sender = sender.clone(); + let next = &next; + let contracts = contracts.as_slice(); + let candidate = (candidate_path.as_path(), candidate_pragma.as_str()); + let reference = (reference_path.as_path(), reference_pragma.as_str()); + scope.spawn(move || { + while let Some(path) = contracts.get(next.fetch_add(1, Ordering::Relaxed)) { + let record = sweep_one(path.as_path(), candidate, reference, limits); + if sender.send(record).is_err() { + break; + } + } + }); + } + drop(sender); + + for record in receiver { + let record = record?; + writeln!( + output, + "{}", + serde_json::to_string(&record).expect("Always valid") + ) + .map_err(|error| anyhow::anyhow!("Writing {output_path:?}: {error}"))?; + *counts.entry(record.outcome.as_str()).or_insert(0usize) += 1; + let total: usize = counts.values().sum(); + if record.outcome != Outcome::Ok || total.is_multiple_of(100) { + let detail = if record.outcome == Outcome::Ok { + String::new() + } else { + format!( + " [{}] {}", + record.slang.kind.as_str(), + record.slang.signature.as_deref().unwrap_or_default() + ) + }; + eprintln!( + "[{total}/{}] {}: {}{detail}", + contracts.len(), + record.identifier, + record.outcome.as_str() + ); + } + } + Ok(()) + })?; + + eprintln!( + "{} in {}s: {}", + solx_utils::cargo_status_ok("Finished"), + started.elapsed().as_secs(), + counts + .iter() + .map(|(outcome, count)| format!("{outcome}={count}")) + .collect::>() + .join(", ") + ); + Ok(()) +} + +/// +/// Compiles one corpus contract with the candidate, and with the reference if the candidate +/// fails. +/// +fn sweep_one( + path: &Path, + (candidate_path, candidate_pragma): (&Path, &str), + (reference_path, reference_pragma): (&Path, &str), + limits: Limits, +) -> anyhow::Result { + let content = std::fs::read_to_string(path) + .map_err(|error| anyhow::anyhow!("Corpus record {path:?} reading: {error}"))?; + let corpus_record: serde_json::Value = serde_json::from_str(content.as_str()) + .map_err(|error| anyhow::anyhow!("Corpus record {path:?} parsing: {error}"))?; + let target = corpus_record + .get("target") + .and_then(serde_json::Value::as_str) + .ok_or_else(|| anyhow::anyhow!("Corpus record {path:?} has no target"))?; + + let slang = compilation::compile( + candidate_path, + standard_json_input(&corpus_record, candidate_pragma, path)?, + target, + limits.timeout, + limits.memory_limit_mib, + )?; + let (baseline, outcome): (Option, Outcome) = match slang.kind { + Kind::Ok => (None, Outcome::Ok), + Kind::Timeout => (None, Outcome::Timeout), + _ => { + let baseline = compilation::compile( + reference_path, + standard_json_input(&corpus_record, reference_pragma, path)?, + target, + limits.timeout, + limits.memory_limit_mib, + )?; + let outcome = if baseline.kind == Kind::Ok { + Outcome::SlangFail + } else { + Outcome::BothFail + }; + (Some(baseline), outcome) + } + }; + + Ok(Record { + identifier: path + .file_stem() + .expect("Always exists") + .to_string_lossy() + .into_owned(), + chain_id: corpus_record.get("chain_id").cloned().unwrap_or_default(), + target: target.to_owned(), + slang, + baseline, + outcome, + }) +} + +/// +/// The standard JSON input for a corpus record: all sources inline under their original paths, +/// the optimizer at the compiler default, bytecode output only, and every version pragma replaced +/// by `pragma`. +/// +fn standard_json_input( + corpus_record: &serde_json::Value, + pragma: &str, + path: &Path, +) -> anyhow::Result> { + let sources: serde_json::Map = corpus_record + .get("sources") + .and_then(serde_json::Value::as_object) + .ok_or_else(|| anyhow::anyhow!("Corpus record {path:?} has no sources"))? + .iter() + .map(|(source_path, content)| { + let content = content.as_str().unwrap_or_default(); + let content = VERSION_PRAGMA.replace_all(content, regex::NoExpand(pragma)); + ( + source_path.to_owned(), + serde_json::json!({ "content": content }), + ) + }) + .collect(); + let mut settings: serde_json::Map = corpus_record + .get("settings") + .and_then(serde_json::Value::as_object) + .into_iter() + .flatten() + .filter(|(key, value)| { + PASSTHROUGH_SETTINGS.contains(&key.as_str()) + && !value.is_null() + && value.as_array().is_none_or(|array| !array.is_empty()) + && value.as_object().is_none_or(|object| !object.is_empty()) + }) + .map(|(key, value)| (key.to_owned(), value.to_owned())) + .collect(); + settings.insert( + "outputSelection".to_owned(), + serde_json::json!({ "*": { "*": ["evm.bytecode.object", "evm.deployedBytecode.object"] } }), + ); + let input = serde_json::json!({ + "language": "Solidity", + "sources": sources, + "settings": settings, + }); + Ok(serde_json::to_vec(&input).expect("Always valid")) +} + +/// +/// The first line of the compiler's `--version`. +/// +fn version(compiler: &Path) -> anyhow::Result { + let output = std::process::Command::new(compiler) + .arg("--version") + .output() + .map_err(|error| anyhow::anyhow!("{compiler:?} --version: {error}"))?; + if !output.status.success() { + anyhow::bail!("{compiler:?} --version failed with {}", output.status); + } + Ok(String::from_utf8_lossy(output.stdout.as_slice()) + .lines() + .next() + .unwrap_or_default() + .trim() + .to_owned()) +} diff --git a/solx-dev/src/test/sourcify/record.rs b/solx-dev/src/test/sourcify/record.rs new file mode 100644 index 000000000..964cf0500 --- /dev/null +++ b/solx-dev/src/test/sourcify/record.rs @@ -0,0 +1,155 @@ +//! +//! `solx` Sourcify sweep result record. +//! + +use std::collections::BTreeMap; + +/// +/// One corpus contract's sweep result, written as a JSON line. +/// +#[derive(Debug, serde::Serialize, serde::Deserialize)] +pub struct Record { + /// The corpus file stem: `_
`. + #[serde(rename = "id")] + pub identifier: String, + /// The chain the contract is deployed on. + #[serde(default)] + pub chain_id: serde_json::Value, + /// The source path whose contracts must get bytecode. + pub target: String, + /// The candidate compiler leg. + pub slang: Leg, + /// The reference compiler leg, run only when the candidate fails. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub baseline: Option, + /// The overall outcome. + pub outcome: Outcome, +} + +/// +/// The overall outcome of one corpus contract. +/// +#[derive( + Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "kebab-case")] +pub enum Outcome { + /// The candidate compiles. + Ok, + /// The candidate fails and the reference compiles. + SlangFail, + /// The candidate and the reference both fail. + BothFail, + /// The candidate exceeded the per-contract timeout. + Timeout, +} + +impl Outcome { + /// All outcomes in report order. + pub const ALL: [Self; 4] = [Self::Ok, Self::SlangFail, Self::BothFail, Self::Timeout]; + + /// + /// The serialized name. + /// + pub fn as_str(self) -> &'static str { + match self { + Self::Ok => "ok", + Self::SlangFail => "slang-fail", + Self::BothFail => "both-fail", + Self::Timeout => "timeout", + } + } + + /// + /// The meaning shown in the report's outcome table. + /// + pub fn meaning(self) -> &'static str { + match self { + Self::Ok => "compiles: no errors and bytecode for the target source", + Self::SlangFail => "candidate fails, baseline compiles (or no baseline given)", + Self::BothFail => { + "candidate and baseline both fail: corpus artifact or documented compiler limitation" + } + Self::Timeout => "candidate exceeded the per-contract timeout", + } + } +} + +/// +/// One compiler invocation on one corpus contract. +/// +/// Only raw material is recorded; the report buckets it, so the bucketing can be refined and +/// re-rendered over old results. +/// +#[derive(Debug, Default, serde::Serialize, serde::Deserialize)] +pub struct Leg { + /// How the invocation ended. + pub kind: Kind, + /// The exit code, or the negated signal number if the process was killed. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub exit: Option, + /// The first diagnostic with paths and numbers normalized. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub signature: Option, + /// The tail of the standard error. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub stderr: Option, + /// The first error-severity messages. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub messages: Vec, + /// The number of error-severity messages. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub error_count: Option, + /// The contracts with bytecode per source path, recorded when the target got none. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub emitted: Option>>, +} + +/// +/// How one compiler invocation ended. +/// +#[derive( + Debug, + Default, + Clone, + Copy, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + serde::Serialize, + serde::Deserialize, +)] +#[serde(rename_all = "kebab-case")] +pub enum Kind { + /// No error-severity diagnostics and bytecode for the target source. + #[default] + Ok, + /// Error-severity diagnostics, or an exit without standard JSON output. + Error, + /// A clean exit without bytecode for the target source. + NoBytecode, + /// A Rust panic. + Panic, + /// Killed by a signal, e.g. an LLVM fatal error or the memory limit. + Abort, + /// The per-contract timeout was exceeded. + Timeout, +} + +impl Kind { + /// + /// The serialized name. + /// + pub fn as_str(self) -> &'static str { + match self { + Self::Ok => "ok", + Self::Error => "error", + Self::NoBytecode => "no-bytecode", + Self::Panic => "panic", + Self::Abort => "abort", + Self::Timeout => "timeout", + } + } +} diff --git a/solx-dev/src/test/sourcify/report.rs b/solx-dev/src/test/sourcify/report.rs new file mode 100644 index 000000000..47b2668ed --- /dev/null +++ b/solx-dev/src/test/sourcify/report.rs @@ -0,0 +1,341 @@ +//! +//! `solx` Sourcify sweep report. +//! + +use std::collections::BTreeMap; +use std::path::PathBuf; +use std::sync::LazyLock; + +use regex::Regex; + +use super::record::Kind; +use super::record::Leg; +use super::record::Outcome; +use super::record::Record; + +/// The number of failure signatures listed per census. +const TOP_SIGNATURES: usize = 40; + +/// The number of example contracts listed per signature. +const EXAMPLES: usize = 3; + +/// The number of timed-out contracts listed. +const TIMEOUT_EXAMPLES: usize = 20; + +static CRASH_LINE: LazyLock = LazyLock::new(|| { + Regex::new(r"(Assertion `.*?' failed|LLVM ERROR: [^\n]+|fatal error: [^\n]+|Unexpected [^\n]+)") + .expect("Always valid") +}); +static LIBRARY_HASH: LazyLock = + LazyLock::new(|| Regex::new(r"\$[0-9a-f]{64}\$").expect("Always valid")); +static SOL_PATH: LazyLock = + LazyLock::new(|| Regex::new(r#"[^\s"'`]+\.sol\b"#).expect("Always valid")); +static HEX_NUMBER: LazyLock = + LazyLock::new(|| Regex::new(r"0x[0-9a-fA-F]+").expect("Always valid")); +static DECIMAL_NUMBER: LazyLock = + LazyLock::new(|| Regex::new(r"\b\d+\b").expect("Always valid")); +static UNRESOLVED_IMPORT: LazyLock = LazyLock::new(|| { + Regex::new(r"^failed to resolve import (\S+) in (\S+)").expect("Always valid") +}); +static MLIR_ERROR: LazyLock = + LazyLock::new(|| Regex::new(r"error: ([^\n]+)").expect("Always valid")); +static PANIC_LOCATION: LazyLock = + LazyLock::new(|| Regex::new(r"panicked at ([^\n:]+):\d+:\d+").expect("Always valid")); + +/// +/// Renders the markdown report from sweep results: the outcome table and the failure census, +/// which ranks failures by signature with example contracts and so doubles as the frontend's +/// feature-gap backlog. +/// +/// Shard outputs may be passed separately or concatenated. +/// +pub fn report( + results_paths: Vec, + output_path: Option, + title: String, +) -> anyhow::Result<()> { + let mut meta = serde_json::Map::new(); + let mut records = Vec::new(); + for path in results_paths.iter() { + let content = std::fs::read_to_string(path.as_path()) + .map_err(|error| anyhow::anyhow!("Sweep results {path:?} reading: {error}"))?; + for line in content.lines().filter(|line| !line.trim().is_empty()) { + let value: serde_json::Value = serde_json::from_str(line) + .map_err(|error| anyhow::anyhow!("Sweep results {path:?} parsing: {error}"))?; + match value.get("meta").and_then(serde_json::Value::as_object) { + Some(line_meta) => meta.extend(line_meta.clone()), + None => { + records.push(serde_json::from_value::(value).map_err(|error| { + anyhow::anyhow!("Sweep results {path:?} parsing: {error}") + })?) + } + } + } + } + if records.is_empty() { + anyhow::bail!("No sweep results found in {results_paths:?}"); + } + // Shards finish in any order; sorting keeps the tie order of the census stable. + records.sort_by(|left, right| left.identifier.cmp(&right.identifier)); + + let report = render(&meta, records.as_slice(), title.as_str()); + match output_path { + Some(output_path) => std::fs::write(output_path.as_path(), report) + .map_err(|error| anyhow::anyhow!("Writing {output_path:?}: {error}"))?, + None => println!("{report}"), + } + Ok(()) +} + +/// +/// Renders the report markdown. +/// +fn render( + meta: &serde_json::Map, + records: &[Record], + title: &str, +) -> String { + let total = records.len(); + let mut lines = vec![format!("## {title}"), String::new()]; + for name in ["slang", "baseline"] { + if let Some(version) = meta.get(name).and_then(serde_json::Value::as_str) { + lines.push(format!("- {name}: `{version}`")); + } + } + lines.push(format!("- contracts: {total}")); + lines.push(String::new()); + + lines.push("| outcome | count | share | meaning |".to_owned()); + lines.push("|---|---|---|---|".to_owned()); + for outcome in Outcome::ALL { + let count = records + .iter() + .filter(|record| record.outcome == outcome) + .count(); + if count > 0 { + lines.push(format!( + "| {} | {count} | {:.2}% | {} |", + outcome.as_str(), + count as f64 / total as f64 * 100.0, + outcome.meaning() + )); + } + } + lines.push(String::new()); + + let candidate_only: Vec<(&str, &Leg)> = records + .iter() + .filter(|record| record.outcome == Outcome::SlangFail) + .map(|record| (record.identifier.as_str(), &record.slang)) + .collect(); + census( + candidate_only.as_slice(), + "Candidate-only failures", + &mut lines, + ); + // For shared failures the baseline's diagnostic is the one that explains the contract. + let shared: Vec<(&str, &Leg)> = records + .iter() + .filter(|record| record.outcome == Outcome::BothFail) + .filter_map(|record| Some((record.identifier.as_str(), record.baseline.as_ref()?))) + .collect(); + census( + shared.as_slice(), + "Failures shared with the baseline (baseline diagnostics)", + &mut lines, + ); + let timeouts: Vec<&str> = records + .iter() + .filter(|record| record.outcome == Outcome::Timeout) + .map(|record| record.identifier.as_str()) + .collect(); + if !timeouts.is_empty() { + lines.push(format!("### Timeouts ({})", timeouts.len())); + lines.push(String::new()); + lines.push( + timeouts + .iter() + .take(TIMEOUT_EXAMPLES) + .map(|identifier| format!("`{identifier}`")) + .collect::>() + .join(", "), + ); + lines.push(String::new()); + } + + lines.join("\n") +} + +/// +/// Ranks the failures of one leg by kind and signature, with counts and example contracts. +/// +fn census(failures: &[(&str, &Leg)], title: &str, lines: &mut Vec) { + if failures.is_empty() { + return; + } + let mut buckets: BTreeMap<(Kind, String), Vec<&str>> = BTreeMap::new(); + let mut kinds: Vec<(Kind, usize)> = Vec::new(); + for (identifier, leg) in failures.iter() { + let (kind, signature) = refine(leg); + buckets + .entry((kind, signature)) + .or_default() + .push(identifier); + match kinds.iter_mut().find(|(seen, _count)| *seen == kind) { + Some((_kind, count)) => *count += 1, + None => kinds.push((kind, 1)), + } + } + // Stable: equal counts keep first-seen order. + kinds.sort_by(|(_, left), (_, right)| right.cmp(left)); + + lines.push(format!("### {title} ({})", failures.len())); + lines.push(String::new()); + lines.push(format!( + "kinds: {}", + kinds + .iter() + .map(|(kind, count)| format!("`{}` {count}", kind.as_str())) + .collect::>() + .join(", ") + )); + lines.push(String::new()); + lines.push("| count | kind | signature | examples |".to_owned()); + lines.push("|---|---|---|---|".to_owned()); + + let mut ranked: Vec<((Kind, String), Vec<&str>)> = buckets.into_iter().collect(); + ranked.sort_by( + |(left_key, left_identifiers), (right_key, right_identifiers)| { + right_identifiers + .len() + .cmp(&left_identifiers.len()) + .then_with(|| left_key.0.as_str().cmp(right_key.0.as_str())) + .then_with(|| left_key.1.cmp(&right_key.1)) + }, + ); + for ((kind, signature), identifiers) in ranked.iter().take(TOP_SIGNATURES) { + let mut examples = identifiers.clone(); + examples.sort(); + lines.push(format!( + "| {} | {} | {} | {} |", + identifiers.len(), + kind.as_str(), + signature.replace('|', "\\|"), + examples + .iter() + .take(EXAMPLES) + .map(|identifier| format!("`{identifier}`")) + .collect::>() + .join(", ") + )); + } + if ranked.len() > TOP_SIGNATURES { + let rest: usize = ranked + .iter() + .skip(TOP_SIGNATURES) + .map(|(_key, identifiers)| identifiers.len()) + .sum(); + lines.push(format!( + "| {rest} | | *{} further signatures* | |", + ranked.len() - TOP_SIGNATURES + )); + } + lines.push(String::new()); +} + +/// +/// The bucket of one failed leg: sharper than the signature recorded at sweep time, from the +/// recorded diagnostics and stderr tail. +/// +fn refine(leg: &Leg) -> (Kind, String) { + let stderr = leg.stderr.as_deref().unwrap_or_default(); + let recorded = leg.signature.as_deref().unwrap_or_default(); + let signature = match leg.kind { + Kind::Error => { + if let Some(import) = leg + .messages + .iter() + .find(|message| message.starts_with("failed to resolve import")) + { + import_bucket(import.as_str()) + } else { + let first = leg.messages.first().map_or(recorded, String::as_str); + if first.starts_with("Sol pass pipeline failed") { + let detail = MLIR_ERROR.captures(stderr).map_or(first, |captures| { + captures.get(1).expect("Always exists").as_str() + }); + format!("MLIR verifier: {}", normalize(detail)) + } else if first.contains("worker exited without replying") { + let detail = CRASH_LINE + .find(stderr) + .map_or(first, |found| found.as_str()); + format!("worker crash: {}", normalize(detail)) + } else { + normalize(first) + } + } + } + Kind::Panic => { + let location = PANIC_LOCATION + .captures(stderr) + .map(|captures| { + let path: Vec<&str> = captures + .get(1) + .expect("Always exists") + .as_str() + .split('/') + .collect(); + path[path.len().saturating_sub(2)..].join("/") + }) + .unwrap_or_else(|| "?".to_owned()); + format!("{recorded} @ {location}") + } + Kind::Abort => CRASH_LINE + .find(stderr) + .map_or_else(|| recorded.to_owned(), |found| normalize(found.as_str())), + _ => recorded.to_owned(), + }; + (leg.kind, signature) +} + +/// +/// The bucket of an unresolved import, by what kind of path failed to resolve. +/// +fn import_bucket(message: &str) -> String { + let Some(captures) = UNRESOLVED_IMPORT.captures(message) else { + return format!("import resolution: {}", normalize(message)); + }; + let import_path = captures.get(1).expect("Always exists").as_str(); + let importer = captures.get(2).expect("Always exists").as_str(); + if importer.contains("://") || import_path.contains("://") { + "import resolution: URL-style source path".to_owned() + } else if import_path.starts_with('.') { + "import resolution: relative import not found".to_owned() + } else { + "import resolution: non-relative import (remapping or exact source name)".to_owned() + } +} + +/// +/// Collapses a diagnostic into a bucket key: its first two lines with paths, library hashes and +/// numbers replaced. +/// +fn normalize(text: &str) -> String { + let text = text.replace("\\n", "\n"); + let lines: Vec<&str> = text + .lines() + .map(str::trim) + .filter(|line| !line.is_empty()) + .take(2) + .collect(); + let line = if lines.is_empty() { + "".to_owned() + } else { + lines.join(" ") + }; + let line = LIBRARY_HASH.replace_all(line.as_str(), "$$$$"); + let line = SOL_PATH.replace_all(line.as_ref(), ""); + let line = HEX_NUMBER.replace_all(line.as_ref(), "0x…"); + let line = DECIMAL_NUMBER.replace_all(line.as_ref(), "N"); + line.chars().take(160).collect() +} diff --git a/tests/sourcify-sweep/fixtures/contracts/11155111_0x4eeb440d70cc04a6e256d4b2a3c53095574251ee.json b/tests/sourcify-sweep/fixtures/contracts/11155111_0x4eeb440d70cc04a6e256d4b2a3c53095574251ee.json new file mode 100644 index 000000000..078eb4f0d --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/11155111_0x4eeb440d70cc04a6e256d4b2a3c53095574251ee.json @@ -0,0 +1,25 @@ +{ + "chain_id": 11155111, + "name": "0x4eeb440d70cc04a6e256d4b2a3c53095574251ee", + "remappings": ["@openzeppelin/contracts/=@openzeppelin/contracts@5.6.0/"], + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "remappings": ["@openzeppelin/contracts/=@openzeppelin/contracts@5.6.0/"] + }, + "sources": { + "contracts/GymCoin.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport \"https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/access/Ownable.sol\";\nimport \"https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/token/ERC20/ERC20.sol\";\nimport \"https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/utils/ReentrancyGuard.sol\";\n\ncontract GymCoin is ERC20, Ownable, ReentrancyGuard {\n uint256 public buyRate = 0.001 ether;\n uint256 public sellRate = 0.0008 ether;\n\n event GymCoinPurchased(address indexed buyer, uint256 gcAmount, uint256 ethPaid);\n event GymCoinSold(address indexed seller, uint256 gcAmount, uint256 ethReceived);\n event RatesUpdated(uint256 sellRate, uint256 buyRate);\n\n constructor() ERC20(\"Gym Coin\", \"GC\") Ownable(msg.sender) {\n _mint(msg.sender, 1_000_000 * 10 ** decimals());\n }\n\n function buy(uint256 gcAmount) external payable {\n require(gcAmount > 0, \"Amount must be greater than zero\");\n\n uint256 cost = quoteBuyCost(gcAmount);\n require(msg.value == cost, \"Wrong ETH sent\");\n require(balanceOf(owner()) >= gcAmount, \"Owner has no tokens\");\n\n _transfer(owner(), msg.sender, gcAmount);\n\n emit GymCoinPurchased(msg.sender, gcAmount, cost);\n }\n\n function sell(uint256 gcAmount) external nonReentrant {\n require(gcAmount > 0, \"Amount must be greater than zero\");\n require(balanceOf(msg.sender) >= gcAmount, \"Not enough tokens\");\n\n uint256 ethAmount = quoteSellPayout(gcAmount);\n require(address(this).balance >= ethAmount, \"Contract has no ETH\");\n\n _transfer(msg.sender, owner(), gcAmount);\n\n (bool success, ) = payable(msg.sender).call{value: ethAmount}(\"\");\n require(success, \"ETH transfer failed\");\n\n emit GymCoinSold(msg.sender, gcAmount, ethAmount);\n }\n\n function setRates(uint256 newSellRate, uint256 newBuyRate) external onlyOwner {\n require(newSellRate > 0 && newBuyRate > 0, \"Rates must be greater than zero\");\n\n sellRate = newSellRate;\n buyRate = newBuyRate;\n\n emit RatesUpdated(newSellRate, newBuyRate);\n }\n\n function quoteBuyCost(uint256 gcAmount) public view returns (uint256) {\n return (gcAmount * buyRate) / (10 ** decimals());\n }\n\n function quoteSellPayout(uint256 gcAmount) public view returns (uint256) {\n return (gcAmount * sellRate) / (10 ** decimals());\n }\n\n receive() external payable {}\n}\n", + "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/access/Ownable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n", + "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/interfaces/draft-IERC6093.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/draft-IERC6093.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC20InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC20InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `spender`\u2019s `allowance`. Used in transfers.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC20InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n /**\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-721.\n * Used in balance queries.\n * @param owner Address of the current owner of a token.\n */\n error ERC721InvalidOwner(address owner);\n\n /**\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\n * @param tokenId Identifier number of a token.\n */\n error ERC721NonexistentToken(uint256 tokenId);\n\n /**\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param tokenId Identifier number of a token.\n * @param owner Address of the current owner of a token.\n */\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC721InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC721InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`\u2019s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param tokenId Identifier number of a token.\n */\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC721InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n * @param tokenId Identifier number of a token.\n */\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC1155InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC1155InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`\u2019s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param owner Address of the current owner of a token.\n */\n error ERC1155MissingApprovalForAll(address operator, address owner);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC1155InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC1155InvalidOperator(address operator);\n\n /**\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n * Used in batch transfers.\n * @param idsLength Length of the array of token identifiers\n * @param valuesLength Length of the array of token amounts\n */\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n", + "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/token/ERC20/ERC20.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./extensions/IERC20Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {IERC20Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\n mapping(address account => uint256) private _balances;\n\n mapping(address account => mapping(address spender => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * Both values are immutable: they can only be set once during construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return 18;\n }\n\n /// @inheritdoc IERC20\n function totalSupply() public view virtual returns (uint256) {\n return _totalSupply;\n }\n\n /// @inheritdoc IERC20\n function balanceOf(address account) public view virtual returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `value`.\n */\n function transfer(address to, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, value);\n return true;\n }\n\n /// @inheritdoc IERC20\n function allowance(address owner, address spender) public view virtual returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, value);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Skips emitting an {Approval} event indicating an allowance update. This is not\n * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `value`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `value`.\n */\n function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, value);\n _transfer(from, to, value);\n return true;\n }\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _transfer(address from, address to, uint256 value) internal {\n if (from == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n if (to == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(from, to, value);\n }\n\n /**\n * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n * this function.\n *\n * Emits a {Transfer} event.\n */\n function _update(address from, address to, uint256 value) internal virtual {\n if (from == address(0)) {\n // Overflow check required: The rest of the code assumes that totalSupply never overflows\n _totalSupply += value;\n } else {\n uint256 fromBalance = _balances[from];\n if (fromBalance < value) {\n revert ERC20InsufficientBalance(from, fromBalance, value);\n }\n unchecked {\n // Overflow not possible: value <= fromBalance <= totalSupply.\n _balances[from] = fromBalance - value;\n }\n }\n\n if (to == address(0)) {\n unchecked {\n // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n _totalSupply -= value;\n }\n } else {\n unchecked {\n // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n _balances[to] += value;\n }\n }\n\n emit Transfer(from, to, value);\n }\n\n /**\n * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n * Relies on the `_update` mechanism\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _mint(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(address(0), account, value);\n }\n\n /**\n * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n * Relies on the `_update` mechanism.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead\n */\n function _burn(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n _update(account, address(0), value);\n }\n\n /**\n * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n *\n * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n */\n function _approve(address owner, address spender, uint256 value) internal {\n _approve(owner, spender, value, true);\n }\n\n /**\n * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n *\n * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n * `_spendAllowance` during the `transferFrom` operation sets the flag to false. This saves gas by not emitting any\n * `Approval` event during `transferFrom` operations.\n *\n * Anyone who wishes to continue emitting `Approval` events on the `transferFrom` operation can force the flag to\n * true using the following override:\n *\n * ```solidity\n * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n * super._approve(owner, spender, value, true);\n * }\n * ```\n *\n * Requirements are the same as {_approve}.\n */\n function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n if (owner == address(0)) {\n revert ERC20InvalidApprover(address(0));\n }\n if (spender == address(0)) {\n revert ERC20InvalidSpender(address(0));\n }\n _allowances[owner][spender] = value;\n if (emitEvent) {\n emit Approval(owner, spender, value);\n }\n }\n\n /**\n * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\n *\n * Does not update the allowance value in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Does not emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance < type(uint256).max) {\n if (currentAllowance < value) {\n revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n }\n unchecked {\n _approve(owner, spender, currentAllowance - value, false);\n }\n }\n }\n}\n", + "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/token/ERC20/IERC20.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n", + "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/token/ERC20/extensions/IERC20Metadata.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n", + "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/utils/Context.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n", + "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/utils/ReentrancyGuard.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\nimport {StorageSlot} from \"./StorageSlot.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n *\n * IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced\n * by the {ReentrancyGuardTransient} variant in v6.0.\n *\n * @custom:stateless\n */\nabstract contract ReentrancyGuard {\n using StorageSlot for bytes32;\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant NOT_ENTERED = 1;\n uint256 private constant ENTERED = 2;\n\n /**\n * @dev Unauthorized reentrant call.\n */\n error ReentrancyGuardReentrantCall();\n\n constructor() {\n _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n /**\n * @dev A `view` only version of {nonReentrant}. Use to block view functions\n * from being called, preventing reading from inconsistent contract state.\n *\n * CAUTION: This is a \"view\" modifier and does not change the reentrancy\n * status. Use it only on view functions. For payable or non-payable functions,\n * use the standard {nonReentrant} modifier instead.\n */\n modifier nonReentrantView() {\n _nonReentrantBeforeView();\n _;\n }\n\n function _nonReentrantBeforeView() private view {\n if (_reentrancyGuardEntered()) {\n revert ReentrancyGuardReentrantCall();\n }\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be NOT_ENTERED\n _nonReentrantBeforeView();\n\n // Any calls to nonReentrant after this point will fail\n _reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;\n }\n\n function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {\n return REENTRANCY_GUARD_STORAGE;\n }\n}\n", + "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v5.6.1/contracts/utils/StorageSlot.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(newImplementation.code.length > 0);\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct Int256Slot {\n int256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n */\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n}\n" + }, + "target": "contracts/GymCoin.sol", + "version": "0.8.34" +} diff --git a/tests/sourcify-sweep/fixtures/contracts/11155111_0xc374f3ad6f715e912dbbc5cba1a2789b9836d5cc.json b/tests/sourcify-sweep/fixtures/contracts/11155111_0xc374f3ad6f715e912dbbc5cba1a2789b9836d5cc.json new file mode 100644 index 000000000..fcc9b6206 --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/11155111_0xc374f3ad6f715e912dbbc5cba1a2789b9836d5cc.json @@ -0,0 +1,165 @@ +{ + "chain_id": 11155111, + "name": "0xc374f3ad6f715e912dbbc5cba1a2789b9836d5cc", + "remappings": [ + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@chainlink/contracts/=npm/@chainlink/contracts@1.5.0/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@prb/math/=npm/@prb/math@4.1.1/" + ], + "settings": { + "libraries": {}, + "optimizer": { + "enabled": true, + "runs": 200 + }, + "remappings": [ + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@chainlink/contracts/=npm/@chainlink/contracts@1.5.0/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.6.1/", + "project/:@prb/math/=npm/@prb/math@4.1.1/" + ] + }, + "sources": { + "npm/@chainlink/contracts@1.5.0/src/v0.8/shared/interfaces/AggregatorV3Interface.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// solhint-disable-next-line interface-starts-with-i\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n function getRoundData(\n uint80 _roundId\n ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n function latestRoundData()\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n}\n", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/access/OwnableUpgradeable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n struct OwnableStorage {\n address _owner;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n assembly {\n $.slot := OwnableStorageLocation\n }\n }\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n function __Ownable_init(address initialOwner) internal onlyInitializing {\n __Ownable_init_unchained(initialOwner);\n }\n\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n OwnableStorage storage $ = _getOwnableStorage();\n return $._owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n OwnableStorage storage $ = _getOwnableStorage();\n address oldOwner = $._owner;\n $._owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/proxy/utils/Initializable.sol": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/proxy/utils/UUPSUpgradeable.sol": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.22;\n\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\";\n", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/utils/ContextUpgradeable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/utils/PausableUpgradeable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Pausable\n struct PausableStorage {\n bool _paused;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Pausable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;\n\n function _getPausableStorage() private pure returns (PausableStorage storage $) {\n assembly {\n $.slot := PausableStorageLocation\n }\n }\n\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n /**\n * @dev The operation failed because the contract is paused.\n */\n error EnforcedPause();\n\n /**\n * @dev The operation failed because the contract is not paused.\n */\n error ExpectedPause();\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n function __Pausable_init() internal onlyInitializing {\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n PausableStorage storage $ = _getPausableStorage();\n return $._paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n if (paused()) {\n revert EnforcedPause();\n }\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n if (!paused()) {\n revert ExpectedPause();\n }\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n PausableStorage storage $ = _getPausableStorage();\n $._paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n PausableStorage storage $ = _getPausableStorage();\n $._paused = false;\n emit Unpaused(_msgSender());\n }\n}\n", + "npm/@openzeppelin/contracts-upgradeable@5.6.1/utils/introspection/ERC165Upgradeable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165 {\n function __ERC165_init() internal onlyInitializing {\n }\n\n function __ERC165_init_unchained() internal onlyInitializing {\n }\n /// @inheritdoc IERC165\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/interfaces/IERC1363.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n /*\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n * 0xb0202a11 ===\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n */\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferAndCall(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @param data Additional data with no specified format, sent in call to `to`.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param from The address which you want to send tokens from.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param from The address which you want to send tokens from.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @param data Additional data with no specified format, sent in call to `to`.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n * @param spender The address which will spend the funds.\n * @param value The amount of tokens to be spent.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function approveAndCall(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n * @param spender The address which will spend the funds.\n * @param value The amount of tokens to be spent.\n * @param data Additional data with no specified format, sent in call to `spender`.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n", + "npm/@openzeppelin/contracts@5.6.1/interfaces/IERC165.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n", + "npm/@openzeppelin/contracts@5.6.1/interfaces/IERC1967.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1967.sol)\n\npragma solidity >=0.4.11;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n", + "npm/@openzeppelin/contracts@5.6.1/interfaces/IERC20.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n", + "npm/@openzeppelin/contracts@5.6.1/interfaces/draft-IERC1822.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n", + "npm/@openzeppelin/contracts@5.6.1/proxy/ERC1967/ERC1967Utils.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (proxy/ERC1967/ERC1967Utils.sol)\n\npragma solidity ^0.8.21;\n\nimport {IBeacon} from \"../beacon/IBeacon.sol\";\nimport {IERC1967} from \"../../interfaces/IERC1967.sol\";\nimport {Address} from \"../../utils/Address.sol\";\nimport {StorageSlot} from \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This library provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\n */\nlibrary ERC1967Utils {\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1.\n */\n // solhint-disable-next-line private-vars-leading-underscore\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev The `implementation` of the proxy is invalid.\n */\n error ERC1967InvalidImplementation(address implementation);\n\n /**\n * @dev The `admin` of the proxy is invalid.\n */\n error ERC1967InvalidAdmin(address admin);\n\n /**\n * @dev The `beacon` of the proxy is invalid.\n */\n error ERC1967InvalidBeacon(address beacon);\n\n /**\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\n */\n error ERC1967NonPayable();\n\n /**\n * @dev Returns the current implementation address.\n */\n function getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the ERC-1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n if (newImplementation.code.length == 0) {\n revert ERC1967InvalidImplementation(newImplementation);\n }\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n * to avoid stuck value in the contract.\n *\n * Emits an {IERC1967-Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\n _setImplementation(newImplementation);\n emit IERC1967.Upgraded(newImplementation);\n\n if (data.length > 0) {\n Address.functionDelegateCall(newImplementation, data);\n } else {\n _checkNonPayable();\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1.\n */\n // solhint-disable-next-line private-vars-leading-underscore\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\n * the https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the ERC-1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n if (newAdmin == address(0)) {\n revert ERC1967InvalidAdmin(address(0));\n }\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {IERC1967-AdminChanged} event.\n */\n function changeAdmin(address newAdmin) internal {\n emit IERC1967.AdminChanged(getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is the keccak-256 hash of \"eip1967.proxy.beacon\" subtracted by 1.\n */\n // solhint-disable-next-line private-vars-leading-underscore\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the ERC-1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n if (newBeacon.code.length == 0) {\n revert ERC1967InvalidBeacon(newBeacon);\n }\n\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\n\n address beaconImplementation = IBeacon(newBeacon).implementation();\n if (beaconImplementation.code.length == 0) {\n revert ERC1967InvalidImplementation(beaconImplementation);\n }\n }\n\n /**\n * @dev Change the beacon and trigger a setup call if data is nonempty.\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n * to avoid stuck value in the contract.\n *\n * Emits an {IERC1967-BeaconUpgraded} event.\n *\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\n * efficiency.\n */\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\n _setBeacon(newBeacon);\n emit IERC1967.BeaconUpgraded(newBeacon);\n\n if (data.length > 0) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n } else {\n _checkNonPayable();\n }\n }\n\n /**\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\n * if an upgrade doesn't perform an initialization call.\n */\n function _checkNonPayable() private {\n if (msg.value > 0) {\n revert ERC1967NonPayable();\n }\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/proxy/beacon/IBeacon.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (proxy/beacon/IBeacon.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {UpgradeableBeacon} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n", + "npm/@openzeppelin/contracts@5.6.1/proxy/utils/Initializable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reinitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\n *\n * NOTE: Consider following the ERC-7201 formula to derive storage locations.\n */\n function _initializableStorageSlot() internal pure virtual returns (bytes32) {\n return INITIALIZABLE_STORAGE;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n bytes32 slot = _initializableStorageSlot();\n assembly {\n $.slot := slot\n }\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/proxy/utils/UUPSUpgradeable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.22;\n\nimport {IERC1822Proxiable} from \"../../interfaces/draft-IERC1822.sol\";\nimport {ERC1967Utils} from \"../ERC1967/ERC1967Utils.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * @custom:stateless\n */\nabstract contract UUPSUpgradeable is IERC1822Proxiable {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address private immutable __self = address(this);\n\n /**\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\n * If the getter returns `\"5.0.0\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\n * during an upgrade.\n */\n string public constant UPGRADE_INTERFACE_VERSION = \"5.0.0\";\n\n /**\n * @dev The call is from an unauthorized context.\n */\n error UUPSUnauthorizedCallContext();\n\n /**\n * @dev The storage `slot` is unsupported as a UUID.\n */\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n _checkProxy();\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n _checkNotDelegated();\n _;\n }\n\n /**\n * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view notDelegated returns (bytes32) {\n return ERC1967Utils.IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data);\n }\n\n /**\n * @dev Reverts if the execution is not performed via delegatecall or the execution\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\n */\n function _checkProxy() internal view virtual {\n if (\n address(this) == __self || // Must be called through delegatecall\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\n ) {\n revert UUPSUnauthorizedCallContext();\n }\n }\n\n /**\n * @dev Reverts if the execution is performed via delegatecall.\n * See {notDelegated}.\n */\n function _checkNotDelegated() internal view virtual {\n if (address(this) != __self) {\n // Must not be called through delegatecall\n revert UUPSUnauthorizedCallContext();\n }\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\n *\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\n * is expected to be the implementation slot in ERC-1967.\n *\n * Emits an {IERC1967-Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\n revert UUPSUnsupportedProxiableUUID(slot);\n }\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\n } catch {\n // The implementation is not UUPS\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\n }\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/token/ERC20/IERC20.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n", + "npm/@openzeppelin/contracts@5.6.1/token/ERC20/extensions/IERC20Metadata.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n", + "npm/@openzeppelin/contracts@5.6.1/token/ERC20/utils/SafeERC20.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n if (!_safeTransfer(token, to, value, true)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n if (!_safeTransferFrom(token, from, to, value, true)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n */\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n return _safeTransfer(token, to, value, false);\n }\n\n /**\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n */\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n return _safeTransferFrom(token, from, to, value, false);\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n *\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n *\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance < requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n *\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n * set here.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n if (!_safeApprove(token, spender, value, false)) {\n if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));\n if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n * code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when\n * targeting contracts.\n *\n * Reverts if the returned value is other than `true`.\n */\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n if (to.code.length == 0) {\n safeTransfer(token, to, value);\n } else if (!token.transferAndCall(to, value, data)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n * has no code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when\n * targeting contracts.\n *\n * Reverts if the returned value is other than `true`.\n */\n function transferFromAndCallRelaxed(\n IERC1363 token,\n address from,\n address to,\n uint256 value,\n bytes memory data\n ) internal {\n if (to.code.length == 0) {\n safeTransferFrom(token, from, to, value);\n } else if (!token.transferFromAndCall(from, to, value, data)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n * targeting contracts.\n *\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n * Oppositely, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n * once without retrying, and relies on the returned value to be true.\n *\n * Reverts if the returned value is other than `true`.\n */\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n if (to.code.length == 0) {\n forceApprove(token, to, value);\n } else if (!token.approveAndCall(to, value, data)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the\n * return value is optional (but if data is returned, it must not be false).\n *\n * @param token The token targeted by the call.\n * @param to The recipient of the tokens\n * @param value The amount of token to transfer\n * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n */\n function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {\n bytes4 selector = IERC20.transfer.selector;\n\n assembly (\"memory-safe\") {\n let fmp := mload(0x40)\n mstore(0x00, selector)\n mstore(0x04, and(to, shr(96, not(0))))\n mstore(0x24, value)\n success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n // if call success and return is true, all is good.\n // otherwise (not success or return is not true), we need to perform further checks\n if iszero(and(success, eq(mload(0x00), 1))) {\n // if the call was a failure and bubble is enabled, bubble the error\n if and(iszero(success), bubble) {\n returndatacopy(fmp, 0x00, returndatasize())\n revert(fmp, returndatasize())\n }\n // if the return value is not true, then the call is only successful if:\n // - the token address has code\n // - the returndata is empty\n success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n }\n mstore(0x40, fmp)\n }\n }\n\n /**\n * @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return\n * value: the return value is optional (but if data is returned, it must not be false).\n *\n * @param token The token targeted by the call.\n * @param from The sender of the tokens\n * @param to The recipient of the tokens\n * @param value The amount of token to transfer\n * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n */\n function _safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value,\n bool bubble\n ) private returns (bool success) {\n bytes4 selector = IERC20.transferFrom.selector;\n\n assembly (\"memory-safe\") {\n let fmp := mload(0x40)\n mstore(0x00, selector)\n mstore(0x04, and(from, shr(96, not(0))))\n mstore(0x24, and(to, shr(96, not(0))))\n mstore(0x44, value)\n success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)\n // if call success and return is true, all is good.\n // otherwise (not success or return is not true), we need to perform further checks\n if iszero(and(success, eq(mload(0x00), 1))) {\n // if the call was a failure and bubble is enabled, bubble the error\n if and(iszero(success), bubble) {\n returndatacopy(fmp, 0x00, returndatasize())\n revert(fmp, returndatasize())\n }\n // if the return value is not true, then the call is only successful if:\n // - the token address has code\n // - the returndata is empty\n success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n }\n mstore(0x40, fmp)\n mstore(0x60, 0)\n }\n }\n\n /**\n * @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:\n * the return value is optional (but if data is returned, it must not be false).\n *\n * @param token The token targeted by the call.\n * @param spender The spender of the tokens\n * @param value The amount of token to transfer\n * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n */\n function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {\n bytes4 selector = IERC20.approve.selector;\n\n assembly (\"memory-safe\") {\n let fmp := mload(0x40)\n mstore(0x00, selector)\n mstore(0x04, and(spender, shr(96, not(0))))\n mstore(0x24, value)\n success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n // if call success and return is true, all is good.\n // otherwise (not success or return is not true), we need to perform further checks\n if iszero(and(success, eq(mload(0x00), 1))) {\n // if the call was a failure and bubble is enabled, bubble the error\n if and(iszero(success), bubble) {\n returndatacopy(fmp, 0x00, returndatasize())\n revert(fmp, returndatasize())\n }\n // if the return value is not true, then the call is only successful if:\n // - the token address has code\n // - the returndata is empty\n success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n }\n mstore(0x40, fmp)\n }\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/Address.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\nimport {Errors} from \"./Errors.sol\";\nimport {LowLevelCall} from \"./LowLevelCall.sol\";\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance < amount) {\n revert Errors.InsufficientBalance(address(this).balance, amount);\n }\n if (LowLevelCall.callNoReturn(recipient, amount, \"\")) {\n // call successful, nothing to do\n return;\n } else if (LowLevelCall.returnDataSize() > 0) {\n LowLevelCall.bubbleRevert();\n } else {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {Errors.FailedCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance < value) {\n revert Errors.InsufficientBalance(address(this).balance, value);\n }\n bool success = LowLevelCall.callNoReturn(target, value, data);\n if (success && (LowLevelCall.returnDataSize() > 0 || target.code.length > 0)) {\n return LowLevelCall.returnData();\n } else if (success) {\n revert AddressEmptyCode(target);\n } else if (LowLevelCall.returnDataSize() > 0) {\n LowLevelCall.bubbleRevert();\n } else {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n bool success = LowLevelCall.staticcallNoReturn(target, data);\n if (success && (LowLevelCall.returnDataSize() > 0 || target.code.length > 0)) {\n return LowLevelCall.returnData();\n } else if (success) {\n revert AddressEmptyCode(target);\n } else if (LowLevelCall.returnDataSize() > 0) {\n LowLevelCall.bubbleRevert();\n } else {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n bool success = LowLevelCall.delegatecallNoReturn(target, data);\n if (success && (LowLevelCall.returnDataSize() > 0 || target.code.length > 0)) {\n return LowLevelCall.returnData();\n } else if (success) {\n revert AddressEmptyCode(target);\n } else if (LowLevelCall.returnDataSize() > 0) {\n LowLevelCall.bubbleRevert();\n } else {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\n * of an unsuccessful call.\n *\n * NOTE: This function is DEPRECATED and may be removed in the next major release.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (success && (returndata.length > 0 || target.code.length > 0)) {\n return returndata;\n } else if (success) {\n revert AddressEmptyCode(target);\n } else if (returndata.length > 0) {\n LowLevelCall.bubbleRevert(returndata);\n } else {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {Errors.FailedCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else if (returndata.length > 0) {\n LowLevelCall.bubbleRevert(returndata);\n } else {\n revert Errors.FailedCall();\n }\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/Errors.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of common custom errors used in multiple contracts\n *\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\n * It is recommended to avoid relying on the error API for critical functionality.\n *\n * _Available since v5.1._\n */\nlibrary Errors {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error InsufficientBalance(uint256 balance, uint256 needed);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedCall();\n\n /**\n * @dev The deployment failed.\n */\n error FailedDeployment();\n\n /**\n * @dev A necessary precompile is missing.\n */\n error MissingPrecompile(address);\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/LowLevelCall.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/LowLevelCall.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library of low level call functions that implement different calling strategies to deal with the return data.\n *\n * WARNING: Using this library requires an advanced understanding of Solidity and how the EVM works. It is recommended\n * to use the {Address} library instead.\n */\nlibrary LowLevelCall {\n /// @dev Performs a Solidity function call using a low level `call` and ignoring the return data.\n function callNoReturn(address target, bytes memory data) internal returns (bool success) {\n return callNoReturn(target, 0, data);\n }\n\n /// @dev Same as {callNoReturn-address-bytes}, but allows specifying the value to be sent in the call.\n function callNoReturn(address target, uint256 value, bytes memory data) internal returns (bool success) {\n assembly (\"memory-safe\") {\n success := call(gas(), target, value, add(data, 0x20), mload(data), 0x00, 0x00)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `call` and returns the first 64 bytes of the result\n /// in the scratch space of memory. Useful for functions that return a tuple with two single-word values.\n ///\n /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated\n /// and this function doesn't zero it out.\n function callReturn64Bytes(\n address target,\n bytes memory data\n ) internal returns (bool success, bytes32 result1, bytes32 result2) {\n return callReturn64Bytes(target, 0, data);\n }\n\n /// @dev Same as {callReturn64Bytes-address-bytes}, but allows specifying the value to be sent in the call.\n function callReturn64Bytes(\n address target,\n uint256 value,\n bytes memory data\n ) internal returns (bool success, bytes32 result1, bytes32 result2) {\n assembly (\"memory-safe\") {\n success := call(gas(), target, value, add(data, 0x20), mload(data), 0x00, 0x40)\n result1 := mload(0x00)\n result2 := mload(0x20)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `staticcall` and ignoring the return data.\n function staticcallNoReturn(address target, bytes memory data) internal view returns (bool success) {\n assembly (\"memory-safe\") {\n success := staticcall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x00)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `staticcall` and returns the first 64 bytes of the result\n /// in the scratch space of memory. Useful for functions that return a tuple with two single-word values.\n ///\n /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated\n /// and this function doesn't zero it out.\n function staticcallReturn64Bytes(\n address target,\n bytes memory data\n ) internal view returns (bool success, bytes32 result1, bytes32 result2) {\n assembly (\"memory-safe\") {\n success := staticcall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x40)\n result1 := mload(0x00)\n result2 := mload(0x20)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `delegatecall` and ignoring the return data.\n function delegatecallNoReturn(address target, bytes memory data) internal returns (bool success) {\n assembly (\"memory-safe\") {\n success := delegatecall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x00)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `delegatecall` and returns the first 64 bytes of the result\n /// in the scratch space of memory. Useful for functions that return a tuple with two single-word values.\n ///\n /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated\n /// and this function doesn't zero it out.\n function delegatecallReturn64Bytes(\n address target,\n bytes memory data\n ) internal returns (bool success, bytes32 result1, bytes32 result2) {\n assembly (\"memory-safe\") {\n success := delegatecall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x40)\n result1 := mload(0x00)\n result2 := mload(0x20)\n }\n }\n\n /// @dev Returns the size of the return data buffer.\n function returnDataSize() internal pure returns (uint256 size) {\n assembly (\"memory-safe\") {\n size := returndatasize()\n }\n }\n\n /// @dev Returns a buffer containing the return data from the last call.\n function returnData() internal pure returns (bytes memory result) {\n assembly (\"memory-safe\") {\n result := mload(0x40)\n mstore(result, returndatasize())\n returndatacopy(add(result, 0x20), 0x00, returndatasize())\n mstore(0x40, add(result, add(0x20, returndatasize())))\n }\n }\n\n /// @dev Revert with the return data from the last call.\n function bubbleRevert() internal pure {\n assembly (\"memory-safe\") {\n let fmp := mload(0x40)\n returndatacopy(fmp, 0x00, returndatasize())\n revert(fmp, returndatasize())\n }\n }\n\n function bubbleRevert(bytes memory returndata) internal pure {\n assembly (\"memory-safe\") {\n revert(add(returndata, 0x20), mload(returndata))\n }\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/Panic.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n * using Panic for uint256;\n *\n * // Use any of the declared internal constants\n * function foo() { Panic.GENERIC.panic(); }\n *\n * // Alternatively\n * function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n /// @dev generic / unspecified error\n uint256 internal constant GENERIC = 0x00;\n /// @dev used by the assert() builtin\n uint256 internal constant ASSERT = 0x01;\n /// @dev arithmetic underflow or overflow\n uint256 internal constant UNDER_OVERFLOW = 0x11;\n /// @dev division or modulo by zero\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\n /// @dev enum conversion error\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n /// @dev invalid encoding in storage\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n /// @dev empty array pop\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n /// @dev array out of bounds access\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n /// @dev resource error (too large allocation or too large array)\n uint256 internal constant RESOURCE_ERROR = 0x41;\n /// @dev calling invalid internal function\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n /// @dev Reverts with a panic code. Recommended to use with\n /// the internal constants with predefined codes.\n function panic(uint256 code) internal pure {\n assembly (\"memory-safe\") {\n mstore(0x00, 0x4e487b71)\n mstore(0x20, code)\n revert(0x1c, 0x24)\n }\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/ReentrancyGuardTransient.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuardTransient.sol)\n\npragma solidity ^0.8.24;\n\nimport {TransientSlot} from \"./TransientSlot.sol\";\n\n/**\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\n *\n * NOTE: This variant only works on networks where EIP-1153 is available.\n *\n * _Available since v5.1._\n *\n * @custom:stateless\n */\nabstract contract ReentrancyGuardTransient {\n using TransientSlot for *;\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n /**\n * @dev Unauthorized reentrant call.\n */\n error ReentrancyGuardReentrantCall();\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n /**\n * @dev A `view` only version of {nonReentrant}. Use to block view functions\n * from being called, preventing reading from inconsistent contract state.\n *\n * CAUTION: This is a \"view\" modifier and does not change the reentrancy\n * status. Use it only on view functions. For payable or non-payable functions,\n * use the standard {nonReentrant} modifier instead.\n */\n modifier nonReentrantView() {\n _nonReentrantBeforeView();\n _;\n }\n\n function _nonReentrantBeforeView() private view {\n if (_reentrancyGuardEntered()) {\n revert ReentrancyGuardReentrantCall();\n }\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, REENTRANCY_GUARD_STORAGE.asBoolean().tload() will be false\n _nonReentrantBeforeView();\n\n // Any calls to nonReentrant after this point will fail\n _reentrancyGuardStorageSlot().asBoolean().tstore(true);\n }\n\n function _nonReentrantAfter() private {\n _reentrancyGuardStorageSlot().asBoolean().tstore(false);\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _reentrancyGuardStorageSlot().asBoolean().tload();\n }\n\n function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {\n return REENTRANCY_GUARD_STORAGE;\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/StorageSlot.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(newImplementation.code.length > 0);\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct Int256Slot {\n int256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n */\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/TransientSlot.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/TransientSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\n\npragma solidity ^0.8.24;\n\n/**\n * @dev Library for reading and writing value-types to specific transient storage slots.\n *\n * Transient slots are often used to store temporary values that are removed after the current transaction.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * * Example reading and writing values using transient storage:\n * ```solidity\n * contract Lock {\n * using TransientSlot for *;\n *\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\n *\n * modifier locked() {\n * require(!_LOCK_SLOT.asBoolean().tload());\n *\n * _LOCK_SLOT.asBoolean().tstore(true);\n * _;\n * _LOCK_SLOT.asBoolean().tstore(false);\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary TransientSlot {\n /**\n * @dev UDVT that represents a slot holding an address.\n */\n type AddressSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a AddressSlot.\n */\n function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\n return AddressSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represents a slot holding a bool.\n */\n type BooleanSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a BooleanSlot.\n */\n function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\n return BooleanSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represents a slot holding a bytes32.\n */\n type Bytes32Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Bytes32Slot.\n */\n function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\n return Bytes32Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represents a slot holding a uint256.\n */\n type Uint256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Uint256Slot.\n */\n function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\n return Uint256Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represents a slot holding a int256.\n */\n type Int256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Int256Slot.\n */\n function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\n return Int256Slot.wrap(slot);\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(AddressSlot slot) internal view returns (address value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(AddressSlot slot, address value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(BooleanSlot slot) internal view returns (bool value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(BooleanSlot slot, bool value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Bytes32Slot slot, bytes32 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Uint256Slot slot) internal view returns (uint256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Uint256Slot slot, uint256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Int256Slot slot) internal view returns (int256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Int256Slot slot, int256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/introspection/IERC165.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/math/Math.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Floor, // Toward negative infinity\n Ceil, // Toward positive infinity\n Trunc, // Toward zero\n Expand // Away from zero\n }\n\n /**\n * @dev Return the 512-bit addition of two uint256.\n *\n * The result is stored in two 256 variables such that sum = high * 2\u00b2\u2075\u2076 + low.\n */\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n assembly (\"memory-safe\") {\n low := add(a, b)\n high := lt(low, a)\n }\n }\n\n /**\n * @dev Return the 512-bit multiplication of two uint256.\n *\n * The result is stored in two 256 variables such that product = high * 2\u00b2\u2075\u2076 + low.\n */\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\u00b2\u2075\u2076 and mod 2\u00b2\u2075\u2076 - 1, then use\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = high * 2\u00b2\u2075\u2076 + low.\n assembly (\"memory-safe\") {\n let mm := mulmod(a, b, not(0))\n low := mul(a, b)\n high := sub(sub(mm, low), lt(mm, low))\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a + b;\n success = c >= a;\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a - b;\n success = c <= a;\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a * b;\n assembly (\"memory-safe\") {\n // Only true when the multiplication doesn't overflow\n // (c / a == b) || (a == 0)\n success := or(eq(div(c, a), b), iszero(a))\n }\n // equivalent to: success ? c : 0\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n success = b > 0;\n assembly (\"memory-safe\") {\n // The `DIV` opcode returns zero when the denominator is 0.\n result := div(a, b)\n }\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n success = b > 0;\n assembly (\"memory-safe\") {\n // The `MOD` opcode returns zero when the denominator is 0.\n result := mod(a, b)\n }\n }\n }\n\n /**\n * @dev Unsigned saturating addition, bounds to `2\u00b2\u2075\u2076 - 1` instead of overflowing.\n */\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n (bool success, uint256 result) = tryAdd(a, b);\n return ternary(success, result, type(uint256).max);\n }\n\n /**\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n */\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n (, uint256 result) = trySub(a, b);\n return result;\n }\n\n /**\n * @dev Unsigned saturating multiplication, bounds to `2\u00b2\u2075\u2076 - 1` instead of overflowing.\n */\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n (bool success, uint256 result) = tryMul(a, b);\n return ternary(success, result, type(uint256).max);\n }\n\n /**\n * @dev Branchless ternary evaluation for `condition ? a : b`. Gas costs are constant.\n *\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n * However, the compiler may optimize Solidity ternary operations (i.e. `condition ? a : b`) to only compute\n * one branch when needed, making this function more expensive.\n */\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n unchecked {\n // branchless ternary works because:\n // b ^ (a ^ b) == a\n // b ^ 0 == b\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\n }\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return ternary(a > b, a, b);\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return ternary(a < b, a, b);\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n unchecked {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds towards infinity instead\n * of rounding towards zero.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n if (b == 0) {\n // Guarantee the same behavior as in a regular Solidity division.\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n\n // The following calculation ensures accurate ceiling division without overflow.\n // Since a is non-zero, (a - 1) / b will not overflow.\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n // but the largest value we can obtain is type(uint256).max - 1, which happens\n // when a = type(uint256).max and b = 1.\n unchecked {\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n }\n }\n\n /**\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n * denominator == 0.\n *\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n * Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n (uint256 high, uint256 low) = mul512(x, y);\n\n // Handle non-overflow cases, 256 by 256 division.\n if (high == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return low / denominator;\n }\n\n // Make sure the result is less than 2\u00b2\u2075\u2076. Also prevents denominator == 0.\n if (denominator <= high) {\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n }\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [high low].\n uint256 remainder;\n assembly (\"memory-safe\") {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n high := sub(high, gt(remainder, low))\n low := sub(low, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n uint256 twos = denominator & (0 - denominator);\n assembly (\"memory-safe\") {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [high low] by twos.\n low := div(low, twos)\n\n // Flip twos such that it is 2\u00b2\u2075\u2076 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from high into low.\n low |= high * twos;\n\n // Invert denominator mod 2\u00b2\u2075\u2076. Now that denominator is an odd number, it has an inverse modulo 2\u00b2\u2075\u2076 such\n // that denominator * inv \u2261 1 mod 2\u00b2\u2075\u2076. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv \u2261 1 mod 2\u2074.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n // works in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2\u2078\n inverse *= 2 - denominator * inverse; // inverse mod 2\u00b9\u2076\n inverse *= 2 - denominator * inverse; // inverse mod 2\u00b3\u00b2\n inverse *= 2 - denominator * inverse; // inverse mod 2\u2076\u2074\n inverse *= 2 - denominator * inverse; // inverse mod 2\u00b9\u00b2\u2078\n inverse *= 2 - denominator * inverse; // inverse mod 2\u00b2\u2075\u2076\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2\u00b2\u2075\u2076. Since the preconditions guarantee that the outcome is\n // less than 2\u00b2\u2075\u2076, this is the final result. We don't need to compute the high bits of the result and high\n // is no longer required.\n result = low * inverse;\n return result;\n }\n }\n\n /**\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n }\n\n /**\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n */\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n unchecked {\n (uint256 high, uint256 low) = mul512(x, y);\n if (high >= 1 << n) {\n Panic.panic(Panic.UNDER_OVERFLOW);\n }\n return (high << (256 - n)) | (low >> n);\n }\n }\n\n /**\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n */\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n }\n\n /**\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n *\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n *\n * If the input value is not inversible, 0 is returned.\n *\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n */\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n unchecked {\n if (n == 0) return 0;\n\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n // ax + ny = 1\n // ax = 1 + (-y)n\n // ax \u2261 1 (mod n) # x is the inverse of a modulo n\n\n // If the remainder is 0 the gcd is n right away.\n uint256 remainder = a % n;\n uint256 gcd = n;\n\n // Therefore the initial coefficients are:\n // ax + ny = gcd(a, n) = n\n // 0a + 1n = n\n int256 x = 0;\n int256 y = 1;\n\n while (remainder != 0) {\n uint256 quotient = gcd / remainder;\n\n (gcd, remainder) = (\n // The old remainder is the next gcd to try.\n remainder,\n // Compute the next remainder.\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n // where gcd is at most n (capped to type(uint256).max)\n gcd - remainder * quotient\n );\n\n (x, y) = (\n // Increment the coefficient of a.\n y,\n // Decrement the coefficient of n.\n // Can overflow, but the result is casted to uint256 so that the\n // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n x - y * int256(quotient)\n );\n }\n\n if (gcd != 1) return 0; // No inverse exists.\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n }\n }\n\n /**\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n *\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n * prime, then `a**(p-1) \u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \u2261 1 mod p`, which means that\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n *\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n */\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n unchecked {\n return Math.modExp(a, p - 2, p);\n }\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n *\n * Requirements:\n * - modulus can't be zero\n * - underlying staticcall to precompile must succeed\n *\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n * interpreted as 0.\n */\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n (bool success, uint256 result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n * to operate modulo 0 or if the underlying precompile reverted.\n *\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n * of a revert, but the result may be incorrectly interpreted as 0.\n */\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n if (m == 0) return (false, 0);\n assembly (\"memory-safe\") {\n let ptr := mload(0x40)\n // | Offset | Content | Content (Hex) |\n // |-----------|------------|--------------------------------------------------------------------|\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n mstore(ptr, 0x20)\n mstore(add(ptr, 0x20), 0x20)\n mstore(add(ptr, 0x40), 0x20)\n mstore(add(ptr, 0x60), b)\n mstore(add(ptr, 0x80), e)\n mstore(add(ptr, 0xa0), m)\n\n // Given the result < m, it's guaranteed to fit in 32 bytes,\n // so we can use the memory scratch space located at offset 0.\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n result := mload(0x00)\n }\n }\n\n /**\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\n */\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n (bool success, bytes memory result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n */\n function tryModExp(\n bytes memory b,\n bytes memory e,\n bytes memory m\n ) internal view returns (bool success, bytes memory result) {\n if (_zeroBytes(m)) return (false, new bytes(0));\n\n uint256 mLen = m.length;\n\n // Encode call args in result and move the free memory pointer\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n assembly (\"memory-safe\") {\n let dataPtr := add(result, 0x20)\n // Write result on top of args to avoid allocating extra memory.\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n // Overwrite the length.\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n mstore(result, mLen)\n // Set the memory pointer after the returned data.\n mstore(0x40, add(dataPtr, mLen))\n }\n }\n\n /**\n * @dev Returns whether the provided byte array is zero.\n */\n function _zeroBytes(bytes memory buffer) private pure returns (bool) {\n uint256 chunk;\n for (uint256 i = 0; i < buffer.length; i += 0x20) {\n // See _unsafeReadBytesOffset from utils/Bytes.sol\n assembly (\"memory-safe\") {\n chunk := mload(add(add(buffer, 0x20), i))\n }\n if (chunk >> (8 * saturatingSub(i + 0x20, buffer.length)) != 0) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n * towards zero.\n *\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n * using integer operations.\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n unchecked {\n // Take care of easy edge cases when a == 0 or a == 1\n if (a <= 1) {\n return a;\n }\n\n // In this function, we use Newton's method to get a root of `f(x) := x\u00b2 - a`. It involves building a\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n // the current value as `\u03b5_n = | x_n - sqrt(a) |`.\n //\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n // of the target. (i.e. `2**(e-1) \u2264 sqrt(a) < 2**e`). We know that `e \u2264 128` because `(2\u00b9\u00b2\u2078)\u00b2 = 2\u00b2\u2075\u2076` is\n // bigger than any uint256.\n //\n // By noticing that\n // `2**(e-1) \u2264 sqrt(a) < 2**e \u2192 (2**(e-1))\u00b2 \u2264 a < (2**e)\u00b2 \u2192 2**(2*e-2) \u2264 a < 2**(2*e)`\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n // to the msb function.\n uint256 aa = a;\n uint256 xn = 1;\n\n if (aa >= (1 << 128)) {\n aa >>= 128;\n xn <<= 64;\n }\n if (aa >= (1 << 64)) {\n aa >>= 64;\n xn <<= 32;\n }\n if (aa >= (1 << 32)) {\n aa >>= 32;\n xn <<= 16;\n }\n if (aa >= (1 << 16)) {\n aa >>= 16;\n xn <<= 8;\n }\n if (aa >= (1 << 8)) {\n aa >>= 8;\n xn <<= 4;\n }\n if (aa >= (1 << 4)) {\n aa >>= 4;\n xn <<= 2;\n }\n if (aa >= (1 << 2)) {\n xn <<= 1;\n }\n\n // We now have x_n such that `x_n = 2**(e-1) \u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \u03b5_n \u2264 2**(e-1).\n //\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \u03b5_n \u2264 2**(e-2).\n // This is going to be our x_0 (and \u03b5_0)\n xn = (3 * xn) >> 1; // \u03b5_0 := | x_0 - sqrt(a) | \u2264 2**(e-2)\n\n // From here, Newton's method give us:\n // x_{n+1} = (x_n + a / x_n) / 2\n //\n // One should note that:\n // x_{n+1}\u00b2 - a = ((x_n + a / x_n) / 2)\u00b2 - a\n // = ((x_n\u00b2 + a) / (2 * x_n))\u00b2 - a\n // = (x_n\u2074 + 2 * a * x_n\u00b2 + a\u00b2) / (4 * x_n\u00b2) - a\n // = (x_n\u2074 + 2 * a * x_n\u00b2 + a\u00b2 - 4 * a * x_n\u00b2) / (4 * x_n\u00b2)\n // = (x_n\u2074 - 2 * a * x_n\u00b2 + a\u00b2) / (4 * x_n\u00b2)\n // = (x_n\u00b2 - a)\u00b2 / (2 * x_n)\u00b2\n // = ((x_n\u00b2 - a) / (2 * x_n))\u00b2\n // \u2265 0\n // Which proves that for all n \u2265 1, sqrt(a) \u2264 x_n\n //\n // This gives us the proof of quadratic convergence of the sequence:\n // \u03b5_{n+1} = | x_{n+1} - sqrt(a) |\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\n // = | (x_n\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n // = | (x_n - sqrt(a))\u00b2 / (2 * x_n) |\n // = | \u03b5_n\u00b2 / (2 * x_n) |\n // = \u03b5_n\u00b2 / | (2 * x_n) |\n //\n // For the first iteration, we have a special case where x_0 is known:\n // \u03b5_1 = \u03b5_0\u00b2 / | (2 * x_0) |\n // \u2264 (2**(e-2))\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\n // \u2264 2**(2*e-4) / (3 * 2**(e-1))\n // \u2264 2**(e-3) / 3\n // \u2264 2**(e-3-log2(3))\n // \u2264 2**(e-4.5)\n //\n // For the following iterations, we use the fact that, 2**(e-1) \u2264 sqrt(a) \u2264 x_n:\n // \u03b5_{n+1} = \u03b5_n\u00b2 / | (2 * x_n) |\n // \u2264 (2**(e-k))\u00b2 / (2 * 2**(e-1))\n // \u2264 2**(2*e-2*k) / 2**e\n // \u2264 2**(e-2*k)\n xn = (xn + a / xn) >> 1; // \u03b5_1 := | x_1 - sqrt(a) | \u2264 2**(e-4.5) -- special case, see above\n xn = (xn + a / xn) >> 1; // \u03b5_2 := | x_2 - sqrt(a) | \u2264 2**(e-9) -- general case with k = 4.5\n xn = (xn + a / xn) >> 1; // \u03b5_3 := | x_3 - sqrt(a) | \u2264 2**(e-18) -- general case with k = 9\n xn = (xn + a / xn) >> 1; // \u03b5_4 := | x_4 - sqrt(a) | \u2264 2**(e-36) -- general case with k = 18\n xn = (xn + a / xn) >> 1; // \u03b5_5 := | x_5 - sqrt(a) | \u2264 2**(e-72) -- general case with k = 36\n xn = (xn + a / xn) >> 1; // \u03b5_6 := | x_6 - sqrt(a) | \u2264 2**(e-144) -- general case with k = 72\n\n // Because e \u2264 128 (as discussed during the first estimation phase), we know have reached a precision\n // \u03b5_6 \u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n // sqrt(a) or sqrt(a) + 1.\n return xn - SafeCast.toUint(xn > a / xn);\n }\n }\n\n /**\n * @dev Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n }\n }\n\n /**\n * @dev Return the log in base 2 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n */\n function log2(uint256 x) internal pure returns (uint256 r) {\n // If value has upper 128 bits set, log2 result is at least 128\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n // If upper 64 bits of 128-bit half set, add 64 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n // If upper 32 bits of 64-bit half set, add 32 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n // If upper 16 bits of 32-bit half set, add 16 to result\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n // If upper 8 bits of 16-bit half set, add 8 to result\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n // If upper 4 bits of 8-bit half set, add 4 to result\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n // Shifts value right by the current result and use it as an index into this lookup table:\n //\n // | x (4 bits) | index | table[index] = MSB position |\n // |------------|---------|-----------------------------|\n // | 0000 | 0 | table[0] = 0 |\n // | 0001 | 1 | table[1] = 0 |\n // | 0010 | 2 | table[2] = 1 |\n // | 0011 | 3 | table[3] = 1 |\n // | 0100 | 4 | table[4] = 2 |\n // | 0101 | 5 | table[5] = 2 |\n // | 0110 | 6 | table[6] = 2 |\n // | 0111 | 7 | table[7] = 2 |\n // | 1000 | 8 | table[8] = 3 |\n // | 1001 | 9 | table[9] = 3 |\n // | 1010 | 10 | table[10] = 3 |\n // | 1011 | 11 | table[11] = 3 |\n // | 1100 | 12 | table[12] = 3 |\n // | 1101 | 13 | table[13] = 3 |\n // | 1110 | 14 | table[14] = 3 |\n // | 1111 | 15 | table[15] = 3 |\n //\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the first 16 bytes (most significant half).\n assembly (\"memory-safe\") {\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n }\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n }\n }\n\n /**\n * @dev Return the log in base 10 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n }\n }\n\n /**\n * @dev Return the log in base 256 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 x) internal pure returns (uint256 r) {\n // If value has upper 128 bits set, log2 result is at least 128\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n // If upper 64 bits of 128-bit half set, add 64 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n // If upper 32 bits of 64-bit half set, add 32 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n // If upper 16 bits of 32-bit half set, add 16 to result\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n }\n }\n\n /**\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n */\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n return uint8(rounding) % 2 == 1;\n }\n\n /**\n * @dev Counts the number of leading zero bits in a uint256.\n */\n function clz(uint256 x) internal pure returns (uint256) {\n return ternary(x == 0, 256, 255 - log2(x));\n }\n}\n", + "npm/@openzeppelin/contracts@5.6.1/utils/math/SafeCast.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n /**\n * @dev Value doesn't fit in a uint of `bits` size.\n */\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n /**\n * @dev An int value doesn't fit in a uint of `bits` size.\n */\n error SafeCastOverflowedIntToUint(int256 value);\n\n /**\n * @dev Value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n /**\n * @dev A uint value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedUintToInt(uint256 value);\n\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n if (value > type(uint248).max) {\n revert SafeCastOverflowedUintDowncast(248, value);\n }\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n if (value > type(uint240).max) {\n revert SafeCastOverflowedUintDowncast(240, value);\n }\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n if (value > type(uint232).max) {\n revert SafeCastOverflowedUintDowncast(232, value);\n }\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n if (value > type(uint224).max) {\n revert SafeCastOverflowedUintDowncast(224, value);\n }\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n if (value > type(uint216).max) {\n revert SafeCastOverflowedUintDowncast(216, value);\n }\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n if (value > type(uint208).max) {\n revert SafeCastOverflowedUintDowncast(208, value);\n }\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n if (value > type(uint200).max) {\n revert SafeCastOverflowedUintDowncast(200, value);\n }\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n if (value > type(uint192).max) {\n revert SafeCastOverflowedUintDowncast(192, value);\n }\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n if (value > type(uint184).max) {\n revert SafeCastOverflowedUintDowncast(184, value);\n }\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n if (value > type(uint176).max) {\n revert SafeCastOverflowedUintDowncast(176, value);\n }\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n if (value > type(uint168).max) {\n revert SafeCastOverflowedUintDowncast(168, value);\n }\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n if (value > type(uint160).max) {\n revert SafeCastOverflowedUintDowncast(160, value);\n }\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n if (value > type(uint152).max) {\n revert SafeCastOverflowedUintDowncast(152, value);\n }\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n if (value > type(uint144).max) {\n revert SafeCastOverflowedUintDowncast(144, value);\n }\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n if (value > type(uint136).max) {\n revert SafeCastOverflowedUintDowncast(136, value);\n }\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n if (value > type(uint128).max) {\n revert SafeCastOverflowedUintDowncast(128, value);\n }\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n if (value > type(uint120).max) {\n revert SafeCastOverflowedUintDowncast(120, value);\n }\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n if (value > type(uint112).max) {\n revert SafeCastOverflowedUintDowncast(112, value);\n }\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n if (value > type(uint104).max) {\n revert SafeCastOverflowedUintDowncast(104, value);\n }\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n if (value > type(uint96).max) {\n revert SafeCastOverflowedUintDowncast(96, value);\n }\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n if (value > type(uint88).max) {\n revert SafeCastOverflowedUintDowncast(88, value);\n }\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n if (value > type(uint80).max) {\n revert SafeCastOverflowedUintDowncast(80, value);\n }\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n if (value > type(uint72).max) {\n revert SafeCastOverflowedUintDowncast(72, value);\n }\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n if (value > type(uint64).max) {\n revert SafeCastOverflowedUintDowncast(64, value);\n }\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n if (value > type(uint56).max) {\n revert SafeCastOverflowedUintDowncast(56, value);\n }\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n if (value > type(uint48).max) {\n revert SafeCastOverflowedUintDowncast(48, value);\n }\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n if (value > type(uint40).max) {\n revert SafeCastOverflowedUintDowncast(40, value);\n }\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n if (value > type(uint32).max) {\n revert SafeCastOverflowedUintDowncast(32, value);\n }\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n if (value > type(uint24).max) {\n revert SafeCastOverflowedUintDowncast(24, value);\n }\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n if (value > type(uint16).max) {\n revert SafeCastOverflowedUintDowncast(16, value);\n }\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n if (value > type(uint8).max) {\n revert SafeCastOverflowedUintDowncast(8, value);\n }\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n if (value < 0) {\n revert SafeCastOverflowedIntToUint(value);\n }\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(248, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(240, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(232, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(224, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(216, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(208, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(200, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(192, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(184, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(176, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(168, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(160, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(152, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(144, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(136, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(128, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(120, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(112, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(104, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(96, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(88, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(80, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(72, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(64, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(56, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(48, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(40, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(32, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(24, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(16, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(8, value);\n }\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n if (value > uint256(type(int256).max)) {\n revert SafeCastOverflowedUintToInt(value);\n }\n return int256(value);\n }\n\n /**\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n */\n function toUint(bool b) internal pure returns (uint256 u) {\n assembly (\"memory-safe\") {\n u := iszero(iszero(b))\n }\n }\n}\n", + "npm/@prb/math@4.1.1/src/Common.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\n// Common.sol\n//\n// Common mathematical functions used in both SD59x18 and UD60x18. Note that these global functions do not\n// always operate with SD59x18 and UD60x18 numbers.\n\n/*//////////////////////////////////////////////////////////////////////////\n CUSTOM ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when the resultant value in {mulDiv} overflows uint256.\nerror PRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator);\n\n/// @notice Thrown when the resultant value in {mulDiv18} overflows uint256.\nerror PRBMath_MulDiv18_Overflow(uint256 x, uint256 y);\n\n/// @notice Thrown when one of the inputs passed to {mulDivSigned} is `type(int256).min`.\nerror PRBMath_MulDivSigned_InputTooSmall();\n\n/// @notice Thrown when the resultant value in {mulDivSigned} overflows int256.\nerror PRBMath_MulDivSigned_Overflow(int256 x, int256 y);\n\n/*//////////////////////////////////////////////////////////////////////////\n CONSTANTS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @dev The maximum value a uint128 number can have.\nuint128 constant MAX_UINT128 = type(uint128).max;\n\n/// @dev The maximum value a uint40 number can have.\nuint40 constant MAX_UINT40 = type(uint40).max;\n\n/// @dev The maximum value a uint64 number can have.\nuint64 constant MAX_UINT64 = type(uint64).max;\n\n/// @dev The unit number, which is the decimal precision of the fixed-point types.\nuint256 constant UNIT = 1e18;\n\n/// @dev The unit number inverted mod 2^256.\nuint256 constant UNIT_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\n\n/// @dev The largest power of two that divides the decimal value of `UNIT`. The logarithm of this value is the least significant\n/// bit in the binary representation of `UNIT`.\nuint256 constant UNIT_LPOTD = 262144;\n\n/*//////////////////////////////////////////////////////////////////////////\n FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Calculates the binary exponent of x using the binary fraction method.\n/// @dev Has to use 192.64-bit fixed-point numbers. See https://ethereum.stackexchange.com/a/96594/24693.\n/// @param x The exponent as an unsigned 192.64-bit fixed-point number.\n/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp2(uint256 x) pure returns (uint256 result) {\n unchecked {\n // Start from 0.5 in the 192.64-bit fixed-point format.\n result = 0x800000000000000000000000000000000000000000000000;\n\n // The following logic multiplies the result by $\\sqrt{2^{-i}}$ when the bit at position i is 1. Key points:\n //\n // 1. Intermediate results will not overflow, as the starting point is 2^191 and all magic factors are under 2^65.\n // 2. The rationale for organizing the if statements into groups of 8 is gas savings. If the result of performing\n // a bitwise AND operation between x and any value in the array [0x80; 0x40; 0x20; 0x10; 0x08; 0x04; 0x02; 0x01] is 1,\n // we know that `x & 0xFF` is also 1.\n if (x & 0xFF00000000000000 > 0) {\n if (x & 0x8000000000000000 > 0) {\n result = (result * 0x16A09E667F3BCC909) >> 64;\n }\n if (x & 0x4000000000000000 > 0) {\n result = (result * 0x1306FE0A31B7152DF) >> 64;\n }\n if (x & 0x2000000000000000 > 0) {\n result = (result * 0x1172B83C7D517ADCE) >> 64;\n }\n if (x & 0x1000000000000000 > 0) {\n result = (result * 0x10B5586CF9890F62A) >> 64;\n }\n if (x & 0x800000000000000 > 0) {\n result = (result * 0x1059B0D31585743AE) >> 64;\n }\n if (x & 0x400000000000000 > 0) {\n result = (result * 0x102C9A3E778060EE7) >> 64;\n }\n if (x & 0x200000000000000 > 0) {\n result = (result * 0x10163DA9FB33356D8) >> 64;\n }\n if (x & 0x100000000000000 > 0) {\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\n }\n }\n\n if (x & 0xFF000000000000 > 0) {\n if (x & 0x80000000000000 > 0) {\n result = (result * 0x10058C86DA1C09EA2) >> 64;\n }\n if (x & 0x40000000000000 > 0) {\n result = (result * 0x1002C605E2E8CEC50) >> 64;\n }\n if (x & 0x20000000000000 > 0) {\n result = (result * 0x100162F3904051FA1) >> 64;\n }\n if (x & 0x10000000000000 > 0) {\n result = (result * 0x1000B175EFFDC76BA) >> 64;\n }\n if (x & 0x8000000000000 > 0) {\n result = (result * 0x100058BA01FB9F96D) >> 64;\n }\n if (x & 0x4000000000000 > 0) {\n result = (result * 0x10002C5CC37DA9492) >> 64;\n }\n if (x & 0x2000000000000 > 0) {\n result = (result * 0x1000162E525EE0547) >> 64;\n }\n if (x & 0x1000000000000 > 0) {\n result = (result * 0x10000B17255775C04) >> 64;\n }\n }\n\n if (x & 0xFF0000000000 > 0) {\n if (x & 0x800000000000 > 0) {\n result = (result * 0x1000058B91B5BC9AE) >> 64;\n }\n if (x & 0x400000000000 > 0) {\n result = (result * 0x100002C5C89D5EC6D) >> 64;\n }\n if (x & 0x200000000000 > 0) {\n result = (result * 0x10000162E43F4F831) >> 64;\n }\n if (x & 0x100000000000 > 0) {\n result = (result * 0x100000B1721BCFC9A) >> 64;\n }\n if (x & 0x80000000000 > 0) {\n result = (result * 0x10000058B90CF1E6E) >> 64;\n }\n if (x & 0x40000000000 > 0) {\n result = (result * 0x1000002C5C863B73F) >> 64;\n }\n if (x & 0x20000000000 > 0) {\n result = (result * 0x100000162E430E5A2) >> 64;\n }\n if (x & 0x10000000000 > 0) {\n result = (result * 0x1000000B172183551) >> 64;\n }\n }\n\n if (x & 0xFF00000000 > 0) {\n if (x & 0x8000000000 > 0) {\n result = (result * 0x100000058B90C0B49) >> 64;\n }\n if (x & 0x4000000000 > 0) {\n result = (result * 0x10000002C5C8601CC) >> 64;\n }\n if (x & 0x2000000000 > 0) {\n result = (result * 0x1000000162E42FFF0) >> 64;\n }\n if (x & 0x1000000000 > 0) {\n result = (result * 0x10000000B17217FBB) >> 64;\n }\n if (x & 0x800000000 > 0) {\n result = (result * 0x1000000058B90BFCE) >> 64;\n }\n if (x & 0x400000000 > 0) {\n result = (result * 0x100000002C5C85FE3) >> 64;\n }\n if (x & 0x200000000 > 0) {\n result = (result * 0x10000000162E42FF1) >> 64;\n }\n if (x & 0x100000000 > 0) {\n result = (result * 0x100000000B17217F8) >> 64;\n }\n }\n\n if (x & 0xFF000000 > 0) {\n if (x & 0x80000000 > 0) {\n result = (result * 0x10000000058B90BFC) >> 64;\n }\n if (x & 0x40000000 > 0) {\n result = (result * 0x1000000002C5C85FE) >> 64;\n }\n if (x & 0x20000000 > 0) {\n result = (result * 0x100000000162E42FF) >> 64;\n }\n if (x & 0x10000000 > 0) {\n result = (result * 0x1000000000B17217F) >> 64;\n }\n if (x & 0x8000000 > 0) {\n result = (result * 0x100000000058B90C0) >> 64;\n }\n if (x & 0x4000000 > 0) {\n result = (result * 0x10000000002C5C860) >> 64;\n }\n if (x & 0x2000000 > 0) {\n result = (result * 0x1000000000162E430) >> 64;\n }\n if (x & 0x1000000 > 0) {\n result = (result * 0x10000000000B17218) >> 64;\n }\n }\n\n if (x & 0xFF0000 > 0) {\n if (x & 0x800000 > 0) {\n result = (result * 0x1000000000058B90C) >> 64;\n }\n if (x & 0x400000 > 0) {\n result = (result * 0x100000000002C5C86) >> 64;\n }\n if (x & 0x200000 > 0) {\n result = (result * 0x10000000000162E43) >> 64;\n }\n if (x & 0x100000 > 0) {\n result = (result * 0x100000000000B1721) >> 64;\n }\n if (x & 0x80000 > 0) {\n result = (result * 0x10000000000058B91) >> 64;\n }\n if (x & 0x40000 > 0) {\n result = (result * 0x1000000000002C5C8) >> 64;\n }\n if (x & 0x20000 > 0) {\n result = (result * 0x100000000000162E4) >> 64;\n }\n if (x & 0x10000 > 0) {\n result = (result * 0x1000000000000B172) >> 64;\n }\n }\n\n if (x & 0xFF00 > 0) {\n if (x & 0x8000 > 0) {\n result = (result * 0x100000000000058B9) >> 64;\n }\n if (x & 0x4000 > 0) {\n result = (result * 0x10000000000002C5D) >> 64;\n }\n if (x & 0x2000 > 0) {\n result = (result * 0x1000000000000162E) >> 64;\n }\n if (x & 0x1000 > 0) {\n result = (result * 0x10000000000000B17) >> 64;\n }\n if (x & 0x800 > 0) {\n result = (result * 0x1000000000000058C) >> 64;\n }\n if (x & 0x400 > 0) {\n result = (result * 0x100000000000002C6) >> 64;\n }\n if (x & 0x200 > 0) {\n result = (result * 0x10000000000000163) >> 64;\n }\n if (x & 0x100 > 0) {\n result = (result * 0x100000000000000B1) >> 64;\n }\n }\n\n if (x & 0xFF > 0) {\n if (x & 0x80 > 0) {\n result = (result * 0x10000000000000059) >> 64;\n }\n if (x & 0x40 > 0) {\n result = (result * 0x1000000000000002C) >> 64;\n }\n if (x & 0x20 > 0) {\n result = (result * 0x10000000000000016) >> 64;\n }\n if (x & 0x10 > 0) {\n result = (result * 0x1000000000000000B) >> 64;\n }\n if (x & 0x8 > 0) {\n result = (result * 0x10000000000000006) >> 64;\n }\n if (x & 0x4 > 0) {\n result = (result * 0x10000000000000003) >> 64;\n }\n if (x & 0x2 > 0) {\n result = (result * 0x10000000000000001) >> 64;\n }\n if (x & 0x1 > 0) {\n result = (result * 0x10000000000000001) >> 64;\n }\n }\n\n // In the code snippet below, two operations are executed simultaneously:\n //\n // 1. The result is multiplied by $(2^n + 1)$, where $2^n$ represents the integer part, and the additional 1\n // accounts for the initial guess of 0.5. This is achieved by subtracting from 191 instead of 192.\n // 2. The result is then converted to an unsigned 60.18-decimal fixed-point format.\n //\n // The underlying logic is based on the relationship $2^{191-ip} = 2^{ip} / 2^{191}$, where $ip$ denotes the\n // integer part, $2^n$.\n result *= UNIT;\n result >>= (191 - (x >> 64));\n }\n}\n\n/// @notice Finds the zero-based index of the first 1 in the binary representation of x.\n///\n/// @dev See the note on \"msb\" in this Wikipedia article: https://en.wikipedia.org/wiki/Find_first_set\n///\n/// The implementation satisfies these properties:\n///\n/// $$\n/// \\begin{cases}\n/// x = 0 \\implies \\text{msb}(x) = 0 \\\\\n/// x > 0 \\implies x \\gg \\text{msb}(x) = 1\n/// \\end{cases}\n/// $$\n///\n/// Each step below is equivalent to this high-level code:\n///\n/// ```solidity\n/// if (x >= 2 ** 128) {\n/// x >>= 128;\n/// result += 128;\n/// }\n/// ```\n///\n/// Where 128 is replaced with each respective power of two factor. The Yul instructions used below are:\n///\n/// - \"gt\" is \"greater than\"\n/// - \"or\" is the OR bitwise operator\n/// - \"shl\" is \"shift left\"\n/// - \"shr\" is \"shift right\"\n///\n/// See the full high-level implementation here:\n/// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948\n///\n/// @param x The uint256 number for which to find the index of the most significant bit.\n/// @return result The index of the most significant bit as a uint256.\n/// @custom:smtchecker abstract-function-nondet\nfunction msb(uint256 x) pure returns (uint256 result) {\n // 2^128\n assembly (\"memory-safe\") {\n let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n x := shr(factor, x)\n result := or(result, factor)\n }\n // 2^64\n assembly (\"memory-safe\") {\n let factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n x := shr(factor, x)\n result := or(result, factor)\n }\n // 2^32\n assembly (\"memory-safe\") {\n let factor := shl(5, gt(x, 0xFFFFFFFF))\n x := shr(factor, x)\n result := or(result, factor)\n }\n // 2^16\n assembly (\"memory-safe\") {\n let factor := shl(4, gt(x, 0xFFFF))\n x := shr(factor, x)\n result := or(result, factor)\n }\n // 2^8\n assembly (\"memory-safe\") {\n let factor := shl(3, gt(x, 0xFF))\n x := shr(factor, x)\n result := or(result, factor)\n }\n // 2^4\n assembly (\"memory-safe\") {\n let factor := shl(2, gt(x, 0xF))\n x := shr(factor, x)\n result := or(result, factor)\n }\n // 2^2\n assembly (\"memory-safe\") {\n let factor := shl(1, gt(x, 0x3))\n x := shr(factor, x)\n result := or(result, factor)\n }\n // 2^1\n // No need to shift x any more.\n assembly (\"memory-safe\") {\n let factor := gt(x, 0x1)\n result := or(result, factor)\n }\n}\n\n/// @notice Calculates x*y\u00f7denominator with 512-bit precision.\n///\n/// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\n///\n/// Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - The denominator must not be zero.\n/// - The result must fit in uint256.\n///\n/// @param x The multiplicand as a uint256.\n/// @param y The multiplier as a uint256.\n/// @param denominator The divisor as a uint256.\n/// @return result The result as a uint256.\n/// @custom:smtchecker abstract-function-nondet\nfunction mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 result) {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512-bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly (\"memory-safe\") {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n unchecked {\n return prod0 / denominator;\n }\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n if (prod1 >= denominator) {\n revert PRBMath_MulDiv_Overflow(x, y, denominator);\n }\n\n ////////////////////////////////////////////////////////////////////////////\n // 512 by 256 division\n ////////////////////////////////////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly (\"memory-safe\") {\n // Compute remainder using the mulmod Yul instruction.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512-bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n unchecked {\n // Calculate the largest power of two divisor of the denominator using the unary operator ~. This operation cannot overflow\n // because the denominator cannot be zero at this point in the function execution. The result is always >= 1.\n // For more detail, see https://cs.stackexchange.com/q/138556/92363.\n uint256 lpotdod = denominator & (~denominator + 1);\n uint256 flippedLpotdod;\n\n assembly (\"memory-safe\") {\n // Factor powers of two out of denominator.\n denominator := div(denominator, lpotdod)\n\n // Divide [prod1 prod0] by lpotdod.\n prod0 := div(prod0, lpotdod)\n\n // Get the flipped value `2^256 / lpotdod`. If the `lpotdod` is zero, the flipped value is one.\n // `sub(0, lpotdod)` produces the two's complement version of `lpotdod`, which is equivalent to flipping all the bits.\n // However, `div` interprets this value as an unsigned value: https://ethereum.stackexchange.com/q/147168/24693\n flippedLpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * flippedLpotdod;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n }\n}\n\n/// @notice Calculates x*y\u00f71e18 with 512-bit precision.\n///\n/// @dev A variant of {mulDiv} with constant folding, i.e. in which the denominator is hard coded to 1e18.\n///\n/// Notes:\n/// - The body is purposely left uncommented; to understand how this works, see the documentation in {mulDiv}.\n/// - The result is rounded toward zero.\n/// - We take as an axiom that the result cannot be `MAX_UINT256` when x and y solve the following system of equations:\n///\n/// $$\n/// \\begin{cases}\n/// x * y = {MAX\\_UINT256} * {UNIT} \\\\\n/// (x * y) \\% {UNIT} \\geq \\frac{UNIT}{2}\n/// \\end{cases}\n/// $$\n///\n/// Requirements:\n/// - Refer to the requirements in {mulDiv}.\n/// - The result must fit in uint256.\n///\n/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\n/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\n/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n/// @custom:smtchecker abstract-function-nondet\nfunction mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) {\n uint256 prod0;\n uint256 prod1;\n assembly (\"memory-safe\") {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n if (prod1 == 0) {\n unchecked {\n return prod0 / UNIT;\n }\n }\n\n if (prod1 >= UNIT) {\n revert PRBMath_MulDiv18_Overflow(x, y);\n }\n\n uint256 remainder;\n assembly (\"memory-safe\") {\n remainder := mulmod(x, y, UNIT)\n result := mul(\n or(\n div(sub(prod0, remainder), UNIT_LPOTD),\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1))\n ),\n UNIT_INVERSE\n )\n }\n}\n\n/// @notice Calculates x*y\u00f7denominator with 512-bit precision.\n///\n/// @dev This is an extension of {mulDiv} for signed numbers, which works by computing the signs and the absolute values separately.\n///\n/// Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - Refer to the requirements in {mulDiv}.\n/// - None of the inputs can be `type(int256).min`.\n/// - The result must fit in int256.\n///\n/// @param x The multiplicand as an int256.\n/// @param y The multiplier as an int256.\n/// @param denominator The divisor as an int256.\n/// @return result The result as an int256.\n/// @custom:smtchecker abstract-function-nondet\nfunction mulDivSigned(int256 x, int256 y, int256 denominator) pure returns (int256 result) {\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\n revert PRBMath_MulDivSigned_InputTooSmall();\n }\n\n // Get hold of the absolute values of x, y and the denominator.\n uint256 xAbs;\n uint256 yAbs;\n uint256 dAbs;\n unchecked {\n xAbs = x < 0 ? uint256(-x) : uint256(x);\n yAbs = y < 0 ? uint256(-y) : uint256(y);\n dAbs = denominator < 0 ? uint256(-denominator) : uint256(denominator);\n }\n\n // Compute the absolute value of x*y\u00f7denominator. The result must fit in int256.\n uint256 resultAbs = mulDiv(xAbs, yAbs, dAbs);\n if (resultAbs > uint256(type(int256).max)) {\n revert PRBMath_MulDivSigned_Overflow(x, y);\n }\n\n // Get the signs of x, y and the denominator.\n uint256 sx;\n uint256 sy;\n uint256 sd;\n assembly (\"memory-safe\") {\n // \"sgt\" is the \"signed greater than\" assembly instruction and \"sub(0,1)\" is -1 in two's complement.\n sx := sgt(x, sub(0, 1))\n sy := sgt(y, sub(0, 1))\n sd := sgt(denominator, sub(0, 1))\n }\n\n // XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs.\n // If there are, the result should be negative. Otherwise, it should be positive.\n unchecked {\n result = sx ^ sy ^ sd == 0 ? -int256(resultAbs) : int256(resultAbs);\n }\n}\n\n/// @notice Calculates the square root of x using the Babylonian method.\n///\n/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n///\n/// The implementation satisfies these properties:\n///\n/// $$\n/// \\begin{cases}\n/// \\lfloor\\sqrt{x}\\rfloor \\leq \\sqrt{x} < \\lfloor\\sqrt{x}\\rfloor + 1 \\\\[0.5em]\n/// \\lfloor\\sqrt{x}\\rfloor^2 \\leq x < (\\lfloor\\sqrt{x}\\rfloor + 1)^2\n/// \\end{cases}\n/// $$\n///\n/// Notes:\n/// - If x is not a perfect square, the result is rounded down.\n/// - Credits to OpenZeppelin for the explanations in comments below.\n///\n/// @param x The uint256 number for which to calculate the square root.\n/// @return result The result as a uint256.\n/// @custom:smtchecker abstract-function-nondet\nfunction sqrt(uint256 x) pure returns (uint256 result) {\n if (x == 0) {\n return 0;\n }\n\n // For our first guess, we calculate the biggest power of 2 which is smaller than the square root of x.\n //\n // We know that the \"msb\" (most significant bit) of x is a power of 2 such that we have:\n //\n // $$\n // msb(x) <= x <= 2*msb(x)\n // $$\n //\n // We write $msb(x)$ as $2^k$, and we get:\n //\n // $$\n // k = log_2(x)\n // $$\n //\n // Thus, we can write the initial inequality as:\n //\n // $$\n // 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\\\\n // sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\\\\n // 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1}\n // $$\n //\n // Consequently, $2^{log_2(x) / 2}$ is a good first approximation of sqrt(x) with at least one correct bit.\n uint256 xAux = uint256(x);\n result = 1;\n if (xAux >= 2 ** 128) {\n xAux >>= 128;\n result <<= 64;\n }\n if (xAux >= 2 ** 64) {\n xAux >>= 64;\n result <<= 32;\n }\n if (xAux >= 2 ** 32) {\n xAux >>= 32;\n result <<= 16;\n }\n if (xAux >= 2 ** 16) {\n xAux >>= 16;\n result <<= 8;\n }\n if (xAux >= 2 ** 8) {\n xAux >>= 8;\n result <<= 4;\n }\n if (xAux >= 2 ** 4) {\n xAux >>= 4;\n result <<= 2;\n }\n if (xAux >= 2 ** 2) {\n result <<= 1;\n }\n\n // At this point, `result` is an estimation with at least one bit of precision. We know the true value has at\n // most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision\n // doubles at every iteration). We thus need at most 7 iterations to turn our partial result with one bit of\n // precision into the expected uint128 result.\n unchecked {\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n\n // If x is not a perfect square, round the result toward zero.\n uint256 roundedResult = x / result;\n if (result >= roundedResult) {\n result = roundedResult;\n }\n }\n}\n", + "npm/@prb/math@4.1.1/src/UD60x18.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\n/*\n\n\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\n\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255a\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255d\u2588\u2588\u2551 \u2588\u2588\u2551\n\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\n\u2588\u2588\u2554\u2550\u2550\u2550\u255d \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u255a\u2588\u2588\u2554\u255d\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\n\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u2588\u2588\u2551 \u255a\u2550\u255d \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\n\u255a\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u255d\n\n\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557\n\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255d \u2588\u2588\u2554\u2550\u2588\u2588\u2588\u2588\u2557\u255a\u2588\u2588\u2557\u2588\u2588\u2554\u255d\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\n\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2551 \u255a\u2588\u2588\u2588\u2554\u255d \u255a\u2588\u2588\u2551\u255a\u2588\u2588\u2588\u2588\u2588\u2554\u255d\n\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2554\u255d\u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\n\u255a\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u255a\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u255a\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u2588\u2588\u2554\u255d \u2588\u2588\u2557 \u2588\u2588\u2551\u255a\u2588\u2588\u2588\u2588\u2588\u2554\u255d\n \u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u255d\n\n*/\n\nimport \"./ud60x18/Casting.sol\";\nimport \"./ud60x18/Constants.sol\";\nimport \"./ud60x18/Conversions.sol\";\nimport \"./ud60x18/Errors.sol\";\nimport \"./ud60x18/Helpers.sol\";\nimport \"./ud60x18/Math.sol\";\nimport \"./ud60x18/ValueType.sol\";\n", + "npm/@prb/math@4.1.1/src/sd1x18/Casting.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as CastingErrors;\nimport { SD59x18 } from \"../sd59x18/ValueType.sol\";\nimport { UD60x18 } from \"../ud60x18/ValueType.sol\";\nimport { SD1x18 } from \"./ValueType.sol\";\n\n/// @notice Casts an SD1x18 number into SD59x18.\n/// @dev There is no overflow check because SD1x18 \u2286 SD59x18.\nfunction intoSD59x18(SD1x18 x) pure returns (SD59x18 result) {\n result = SD59x18.wrap(int256(SD1x18.unwrap(x)));\n}\n\n/// @notice Casts an SD1x18 number into UD60x18.\n/// @dev Requirements:\n/// - x \u2265 0\nfunction intoUD60x18(SD1x18 x) pure returns (UD60x18 result) {\n int64 xInt = SD1x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD1x18_ToUD60x18_Underflow(x);\n }\n result = UD60x18.wrap(uint64(xInt));\n}\n\n/// @notice Casts an SD1x18 number into uint128.\n/// @dev Requirements:\n/// - x \u2265 0\nfunction intoUint128(SD1x18 x) pure returns (uint128 result) {\n int64 xInt = SD1x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD1x18_ToUint128_Underflow(x);\n }\n result = uint128(uint64(xInt));\n}\n\n/// @notice Casts an SD1x18 number into uint256.\n/// @dev Requirements:\n/// - x \u2265 0\nfunction intoUint256(SD1x18 x) pure returns (uint256 result) {\n int64 xInt = SD1x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD1x18_ToUint256_Underflow(x);\n }\n result = uint256(uint64(xInt));\n}\n\n/// @notice Casts an SD1x18 number into uint40.\n/// @dev Requirements:\n/// - x \u2265 0\n/// - x \u2264 MAX_UINT40\nfunction intoUint40(SD1x18 x) pure returns (uint40 result) {\n int64 xInt = SD1x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD1x18_ToUint40_Underflow(x);\n }\n if (xInt > int64(uint64(Common.MAX_UINT40))) {\n revert CastingErrors.PRBMath_SD1x18_ToUint40_Overflow(x);\n }\n result = uint40(uint64(xInt));\n}\n\n/// @notice Alias for {wrap}.\nfunction sd1x18(int64 x) pure returns (SD1x18 result) {\n result = SD1x18.wrap(x);\n}\n\n/// @notice Unwraps an SD1x18 number into int64.\nfunction unwrap(SD1x18 x) pure returns (int64 result) {\n result = SD1x18.unwrap(x);\n}\n\n/// @notice Wraps an int64 number into SD1x18.\nfunction wrap(int64 x) pure returns (SD1x18 result) {\n result = SD1x18.wrap(x);\n}\n", + "npm/@prb/math@4.1.1/src/sd1x18/Constants.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD1x18 } from \"./ValueType.sol\";\n\n/// @dev Euler's number as an SD1x18 number.\nSD1x18 constant E = SD1x18.wrap(2_718281828459045235);\n\n/// @dev The maximum value an SD1x18 number can have.\nint64 constant uMAX_SD1x18 = 9_223372036854775807;\nSD1x18 constant MAX_SD1x18 = SD1x18.wrap(uMAX_SD1x18);\n\n/// @dev The minimum value an SD1x18 number can have.\nint64 constant uMIN_SD1x18 = -9_223372036854775808;\nSD1x18 constant MIN_SD1x18 = SD1x18.wrap(uMIN_SD1x18);\n\n/// @dev PI as an SD1x18 number.\nSD1x18 constant PI = SD1x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of SD1x18.\nSD1x18 constant UNIT = SD1x18.wrap(1e18);\nint64 constant uUNIT = 1e18;\n", + "npm/@prb/math@4.1.1/src/sd1x18/Errors.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD1x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in UD60x18.\nerror PRBMath_SD1x18_ToUD60x18_Underflow(SD1x18 x);\n\n/// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in uint128.\nerror PRBMath_SD1x18_ToUint128_Underflow(SD1x18 x);\n\n/// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in uint256.\nerror PRBMath_SD1x18_ToUint256_Underflow(SD1x18 x);\n\n/// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in uint40.\nerror PRBMath_SD1x18_ToUint40_Overflow(SD1x18 x);\n\n/// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in uint40.\nerror PRBMath_SD1x18_ToUint40_Underflow(SD1x18 x);\n", + "npm/@prb/math@4.1.1/src/sd1x18/ValueType.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\n\n/// @notice The signed 1.18-decimal fixed-point number representation, which can have up to 1 digit and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity\n/// type int64. This is useful when end users want to use int64 to save gas, e.g. with tight variable packing in contract\n/// storage.\ntype SD1x18 is int64;\n\n/*//////////////////////////////////////////////////////////////////////////\n CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n Casting.intoSD59x18,\n Casting.intoUD60x18,\n Casting.intoUint128,\n Casting.intoUint256,\n Casting.intoUint40,\n Casting.unwrap\n} for SD1x18 global;\n", + "npm/@prb/math@4.1.1/src/sd21x18/Casting.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as CastingErrors;\nimport { SD59x18 } from \"../sd59x18/ValueType.sol\";\nimport { UD60x18 } from \"../ud60x18/ValueType.sol\";\nimport { SD21x18 } from \"./ValueType.sol\";\n\n/// @notice Casts an SD21x18 number into SD59x18.\n/// @dev There is no overflow check because SD21x18 \u2286 SD59x18.\nfunction intoSD59x18(SD21x18 x) pure returns (SD59x18 result) {\n result = SD59x18.wrap(int256(SD21x18.unwrap(x)));\n}\n\n/// @notice Casts an SD21x18 number into UD60x18.\n/// @dev Requirements:\n/// - x \u2265 0\nfunction intoUD60x18(SD21x18 x) pure returns (UD60x18 result) {\n int128 xInt = SD21x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD21x18_ToUD60x18_Underflow(x);\n }\n result = UD60x18.wrap(uint128(xInt));\n}\n\n/// @notice Casts an SD21x18 number into uint128.\n/// @dev Requirements:\n/// - x \u2265 0\nfunction intoUint128(SD21x18 x) pure returns (uint128 result) {\n int128 xInt = SD21x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD21x18_ToUint128_Underflow(x);\n }\n result = uint128(xInt);\n}\n\n/// @notice Casts an SD21x18 number into uint256.\n/// @dev Requirements:\n/// - x \u2265 0\nfunction intoUint256(SD21x18 x) pure returns (uint256 result) {\n int128 xInt = SD21x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD21x18_ToUint256_Underflow(x);\n }\n result = uint256(uint128(xInt));\n}\n\n/// @notice Casts an SD21x18 number into uint40.\n/// @dev Requirements:\n/// - x \u2265 0\n/// - x \u2264 MAX_UINT40\nfunction intoUint40(SD21x18 x) pure returns (uint40 result) {\n int128 xInt = SD21x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD21x18_ToUint40_Underflow(x);\n }\n if (xInt > int128(uint128(Common.MAX_UINT40))) {\n revert CastingErrors.PRBMath_SD21x18_ToUint40_Overflow(x);\n }\n result = uint40(uint128(xInt));\n}\n\n/// @notice Alias for {wrap}.\nfunction sd21x18(int128 x) pure returns (SD21x18 result) {\n result = SD21x18.wrap(x);\n}\n\n/// @notice Unwraps an SD21x18 number into int128.\nfunction unwrap(SD21x18 x) pure returns (int128 result) {\n result = SD21x18.unwrap(x);\n}\n\n/// @notice Wraps an int128 number into SD21x18.\nfunction wrap(int128 x) pure returns (SD21x18 result) {\n result = SD21x18.wrap(x);\n}\n", + "npm/@prb/math@4.1.1/src/sd21x18/Constants.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD21x18 } from \"./ValueType.sol\";\n\n/// @dev Euler's number as an SD21x18 number.\nSD21x18 constant E = SD21x18.wrap(2_718281828459045235);\n\n/// @dev The maximum value an SD21x18 number can have.\nint128 constant uMAX_SD21x18 = 170141183460469231731_687303715884105727;\nSD21x18 constant MAX_SD21x18 = SD21x18.wrap(uMAX_SD21x18);\n\n/// @dev The minimum value an SD21x18 number can have.\nint128 constant uMIN_SD21x18 = -170141183460469231731_687303715884105728;\nSD21x18 constant MIN_SD21x18 = SD21x18.wrap(uMIN_SD21x18);\n\n/// @dev PI as an SD21x18 number.\nSD21x18 constant PI = SD21x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of SD21x18.\nSD21x18 constant UNIT = SD21x18.wrap(1e18);\nint128 constant uUNIT = 1e18;\n", + "npm/@prb/math@4.1.1/src/sd21x18/Errors.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD21x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in uint128.\nerror PRBMath_SD21x18_ToUint128_Underflow(SD21x18 x);\n\n/// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in UD60x18.\nerror PRBMath_SD21x18_ToUD60x18_Underflow(SD21x18 x);\n\n/// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in uint256.\nerror PRBMath_SD21x18_ToUint256_Underflow(SD21x18 x);\n\n/// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in uint40.\nerror PRBMath_SD21x18_ToUint40_Overflow(SD21x18 x);\n\n/// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in uint40.\nerror PRBMath_SD21x18_ToUint40_Underflow(SD21x18 x);\n", + "npm/@prb/math@4.1.1/src/sd21x18/ValueType.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\n\n/// @notice The signed 21.18-decimal fixed-point number representation, which can have up to 21 digits and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity\n/// type int128. This is useful when end users want to use int128 to save gas, e.g. with tight variable packing in contract\n/// storage.\ntype SD21x18 is int128;\n\n/*//////////////////////////////////////////////////////////////////////////\n CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n Casting.intoSD59x18,\n Casting.intoUD60x18,\n Casting.intoUint128,\n Casting.intoUint256,\n Casting.intoUint40,\n Casting.unwrap\n} for SD21x18 global;\n", + "npm/@prb/math@4.1.1/src/sd59x18/Casting.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Errors.sol\" as CastingErrors;\nimport { MAX_UINT128, MAX_UINT40 } from \"../Common.sol\";\nimport { uMAX_SD1x18, uMIN_SD1x18 } from \"../sd1x18/Constants.sol\";\nimport { SD1x18 } from \"../sd1x18/ValueType.sol\";\nimport { uMAX_SD21x18, uMIN_SD21x18 } from \"../sd21x18/Constants.sol\";\nimport { SD21x18 } from \"../sd21x18/ValueType.sol\";\nimport { uMAX_UD2x18 } from \"../ud2x18/Constants.sol\";\nimport { UD2x18 } from \"../ud2x18/ValueType.sol\";\nimport { uMAX_UD21x18 } from \"../ud21x18/Constants.sol\";\nimport { UD21x18 } from \"../ud21x18/ValueType.sol\";\nimport { UD60x18 } from \"../ud60x18/ValueType.sol\";\nimport { SD59x18 } from \"./ValueType.sol\";\n\n/// @notice Casts an SD59x18 number into int256.\n/// @dev This is basically a functional alias for {unwrap}.\nfunction intoInt256(SD59x18 x) pure returns (int256 result) {\n result = SD59x18.unwrap(x);\n}\n\n/// @notice Casts an SD59x18 number into SD1x18.\n/// @dev Requirements:\n/// - x \u2265 uMIN_SD1x18\n/// - x \u2264 uMAX_SD1x18\nfunction intoSD1x18(SD59x18 x) pure returns (SD1x18 result) {\n int256 xInt = SD59x18.unwrap(x);\n if (xInt < uMIN_SD1x18) {\n revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Underflow(x);\n }\n if (xInt > uMAX_SD1x18) {\n revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Overflow(x);\n }\n result = SD1x18.wrap(int64(xInt));\n}\n\n/// @notice Casts an SD59x18 number into SD21x18.\n/// @dev Requirements:\n/// - x \u2265 uMIN_SD21x18\n/// - x \u2264 uMAX_SD21x18\nfunction intoSD21x18(SD59x18 x) pure returns (SD21x18 result) {\n int256 xInt = SD59x18.unwrap(x);\n if (xInt < uMIN_SD21x18) {\n revert CastingErrors.PRBMath_SD59x18_IntoSD21x18_Underflow(x);\n }\n if (xInt > uMAX_SD21x18) {\n revert CastingErrors.PRBMath_SD59x18_IntoSD21x18_Overflow(x);\n }\n result = SD21x18.wrap(int128(xInt));\n}\n\n/// @notice Casts an SD59x18 number into UD2x18.\n/// @dev Requirements:\n/// - x \u2265 0\n/// - x \u2264 uMAX_UD2x18\nfunction intoUD2x18(SD59x18 x) pure returns (UD2x18 result) {\n int256 xInt = SD59x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Underflow(x);\n }\n if (xInt > int256(uint256(uMAX_UD2x18))) {\n revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Overflow(x);\n }\n result = UD2x18.wrap(uint64(uint256(xInt)));\n}\n\n/// @notice Casts an SD59x18 number into UD21x18.\n/// @dev Requirements:\n/// - x \u2265 0\n/// - x \u2264 uMAX_UD21x18\nfunction intoUD21x18(SD59x18 x) pure returns (UD21x18 result) {\n int256 xInt = SD59x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD59x18_IntoUD21x18_Underflow(x);\n }\n if (xInt > int256(uint256(uMAX_UD21x18))) {\n revert CastingErrors.PRBMath_SD59x18_IntoUD21x18_Overflow(x);\n }\n result = UD21x18.wrap(uint128(uint256(xInt)));\n}\n\n/// @notice Casts an SD59x18 number into UD60x18.\n/// @dev Requirements:\n/// - x \u2265 0\nfunction intoUD60x18(SD59x18 x) pure returns (UD60x18 result) {\n int256 xInt = SD59x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD59x18_IntoUD60x18_Underflow(x);\n }\n result = UD60x18.wrap(uint256(xInt));\n}\n\n/// @notice Casts an SD59x18 number into uint256.\n/// @dev Requirements:\n/// - x \u2265 0\nfunction intoUint256(SD59x18 x) pure returns (uint256 result) {\n int256 xInt = SD59x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD59x18_IntoUint256_Underflow(x);\n }\n result = uint256(xInt);\n}\n\n/// @notice Casts an SD59x18 number into uint128.\n/// @dev Requirements:\n/// - x \u2265 0\n/// - x \u2264 uMAX_UINT128\nfunction intoUint128(SD59x18 x) pure returns (uint128 result) {\n int256 xInt = SD59x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD59x18_IntoUint128_Underflow(x);\n }\n if (xInt > int256(uint256(MAX_UINT128))) {\n revert CastingErrors.PRBMath_SD59x18_IntoUint128_Overflow(x);\n }\n result = uint128(uint256(xInt));\n}\n\n/// @notice Casts an SD59x18 number into uint40.\n/// @dev Requirements:\n/// - x \u2265 0\n/// - x \u2264 MAX_UINT40\nfunction intoUint40(SD59x18 x) pure returns (uint40 result) {\n int256 xInt = SD59x18.unwrap(x);\n if (xInt < 0) {\n revert CastingErrors.PRBMath_SD59x18_IntoUint40_Underflow(x);\n }\n if (xInt > int256(uint256(MAX_UINT40))) {\n revert CastingErrors.PRBMath_SD59x18_IntoUint40_Overflow(x);\n }\n result = uint40(uint256(xInt));\n}\n\n/// @notice Alias for {wrap}.\nfunction sd(int256 x) pure returns (SD59x18 result) {\n result = SD59x18.wrap(x);\n}\n\n/// @notice Alias for {wrap}.\nfunction sd59x18(int256 x) pure returns (SD59x18 result) {\n result = SD59x18.wrap(x);\n}\n\n/// @notice Unwraps an SD59x18 number into int256.\nfunction unwrap(SD59x18 x) pure returns (int256 result) {\n result = SD59x18.unwrap(x);\n}\n\n/// @notice Wraps an int256 number into SD59x18.\nfunction wrap(int256 x) pure returns (SD59x18 result) {\n result = SD59x18.wrap(x);\n}\n", + "npm/@prb/math@4.1.1/src/sd59x18/Constants.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD59x18 } from \"./ValueType.sol\";\n\n// NOTICE: the \"u\" prefix stands for \"unwrapped\".\n\n/// @dev Euler's number as an SD59x18 number.\nSD59x18 constant E = SD59x18.wrap(2_718281828459045235);\n\n/// @dev The maximum input permitted in {exp}.\nint256 constant uEXP_MAX_INPUT = 133_084258667509499440;\nSD59x18 constant EXP_MAX_INPUT = SD59x18.wrap(uEXP_MAX_INPUT);\n\n/// @dev Any value less than this returns 0 in {exp}.\nint256 constant uEXP_MIN_THRESHOLD = -41_446531673892822322;\nSD59x18 constant EXP_MIN_THRESHOLD = SD59x18.wrap(uEXP_MIN_THRESHOLD);\n\n/// @dev The maximum input permitted in {exp2}.\nint256 constant uEXP2_MAX_INPUT = 192e18 - 1;\nSD59x18 constant EXP2_MAX_INPUT = SD59x18.wrap(uEXP2_MAX_INPUT);\n\n/// @dev Any value less than this returns 0 in {exp2}.\nint256 constant uEXP2_MIN_THRESHOLD = -59_794705707972522261;\nSD59x18 constant EXP2_MIN_THRESHOLD = SD59x18.wrap(uEXP2_MIN_THRESHOLD);\n\n/// @dev Half the UNIT number.\nint256 constant uHALF_UNIT = 0.5e18;\nSD59x18 constant HALF_UNIT = SD59x18.wrap(uHALF_UNIT);\n\n/// @dev $log_2(10)$ as an SD59x18 number.\nint256 constant uLOG2_10 = 3_321928094887362347;\nSD59x18 constant LOG2_10 = SD59x18.wrap(uLOG2_10);\n\n/// @dev $log_2(e)$ as an SD59x18 number.\nint256 constant uLOG2_E = 1_442695040888963407;\nSD59x18 constant LOG2_E = SD59x18.wrap(uLOG2_E);\n\n/// @dev The maximum value an SD59x18 number can have.\nint256 constant uMAX_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_792003956564819967;\nSD59x18 constant MAX_SD59x18 = SD59x18.wrap(uMAX_SD59x18);\n\n/// @dev The maximum whole value an SD59x18 number can have.\nint256 constant uMAX_WHOLE_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_000000000000000000;\nSD59x18 constant MAX_WHOLE_SD59x18 = SD59x18.wrap(uMAX_WHOLE_SD59x18);\n\n/// @dev The minimum value an SD59x18 number can have.\nint256 constant uMIN_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_792003956564819968;\nSD59x18 constant MIN_SD59x18 = SD59x18.wrap(uMIN_SD59x18);\n\n/// @dev The minimum whole value an SD59x18 number can have.\nint256 constant uMIN_WHOLE_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_000000000000000000;\nSD59x18 constant MIN_WHOLE_SD59x18 = SD59x18.wrap(uMIN_WHOLE_SD59x18);\n\n/// @dev PI as an SD59x18 number.\nSD59x18 constant PI = SD59x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of SD59x18.\nint256 constant uUNIT = 1e18;\nSD59x18 constant UNIT = SD59x18.wrap(1e18);\n\n/// @dev The unit number squared.\nint256 constant uUNIT_SQUARED = 1e36;\nSD59x18 constant UNIT_SQUARED = SD59x18.wrap(uUNIT_SQUARED);\n\n/// @dev Zero as an SD59x18 number.\nSD59x18 constant ZERO = SD59x18.wrap(0);\n", + "npm/@prb/math@4.1.1/src/sd59x18/Errors.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD59x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when taking the absolute value of `MIN_SD59x18`.\nerror PRBMath_SD59x18_Abs_MinSD59x18();\n\n/// @notice Thrown when ceiling a number overflows SD59x18.\nerror PRBMath_SD59x18_Ceil_Overflow(SD59x18 x);\n\n/// @notice Thrown when converting a basic integer to the fixed-point format overflows SD59x18.\nerror PRBMath_SD59x18_Convert_Overflow(int256 x);\n\n/// @notice Thrown when converting a basic integer to the fixed-point format underflows SD59x18.\nerror PRBMath_SD59x18_Convert_Underflow(int256 x);\n\n/// @notice Thrown when dividing two numbers and one of them is `MIN_SD59x18`.\nerror PRBMath_SD59x18_Div_InputTooSmall();\n\n/// @notice Thrown when dividing two numbers and one of the intermediary unsigned results overflows SD59x18.\nerror PRBMath_SD59x18_Div_Overflow(SD59x18 x, SD59x18 y);\n\n/// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441.\nerror PRBMath_SD59x18_Exp_InputTooBig(SD59x18 x);\n\n/// @notice Thrown when taking the binary exponent of a base greater than 192e18.\nerror PRBMath_SD59x18_Exp2_InputTooBig(SD59x18 x);\n\n/// @notice Thrown when flooring a number underflows SD59x18.\nerror PRBMath_SD59x18_Floor_Underflow(SD59x18 x);\n\n/// @notice Thrown when taking the geometric mean of two numbers and their product is negative.\nerror PRBMath_SD59x18_Gm_NegativeProduct(SD59x18 x, SD59x18 y);\n\n/// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows SD59x18.\nerror PRBMath_SD59x18_Gm_Overflow(SD59x18 x, SD59x18 y);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in SD1x18.\nerror PRBMath_SD59x18_IntoSD1x18_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in SD1x18.\nerror PRBMath_SD59x18_IntoSD1x18_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in SD21x18.\nerror PRBMath_SD59x18_IntoSD21x18_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in SD21x18.\nerror PRBMath_SD59x18_IntoSD21x18_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD2x18.\nerror PRBMath_SD59x18_IntoUD2x18_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD2x18.\nerror PRBMath_SD59x18_IntoUD2x18_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD21x18.\nerror PRBMath_SD59x18_IntoUD21x18_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD21x18.\nerror PRBMath_SD59x18_IntoUD21x18_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD60x18.\nerror PRBMath_SD59x18_IntoUD60x18_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint128.\nerror PRBMath_SD59x18_IntoUint128_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint128.\nerror PRBMath_SD59x18_IntoUint128_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint256.\nerror PRBMath_SD59x18_IntoUint256_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint40.\nerror PRBMath_SD59x18_IntoUint40_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint40.\nerror PRBMath_SD59x18_IntoUint40_Underflow(SD59x18 x);\n\n/// @notice Thrown when taking the logarithm of a number less than or equal to zero.\nerror PRBMath_SD59x18_Log_InputTooSmall(SD59x18 x);\n\n/// @notice Thrown when multiplying two numbers and one of the inputs is `MIN_SD59x18`.\nerror PRBMath_SD59x18_Mul_InputTooSmall();\n\n/// @notice Thrown when multiplying two numbers and the intermediary absolute result overflows SD59x18.\nerror PRBMath_SD59x18_Mul_Overflow(SD59x18 x, SD59x18 y);\n\n/// @notice Thrown when raising a number to a power and the intermediary absolute result overflows SD59x18.\nerror PRBMath_SD59x18_Powu_Overflow(SD59x18 x, uint256 y);\n\n/// @notice Thrown when taking the square root of a negative number.\nerror PRBMath_SD59x18_Sqrt_NegativeInput(SD59x18 x);\n\n/// @notice Thrown when calculating the square root overflows SD59x18.\nerror PRBMath_SD59x18_Sqrt_Overflow(SD59x18 x);\n", + "npm/@prb/math@4.1.1/src/sd59x18/Helpers.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { wrap } from \"./Casting.sol\";\nimport { SD59x18 } from \"./ValueType.sol\";\n\n/// @notice Implements the checked addition operation (+) in the SD59x18 type.\nfunction add(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n return wrap(x.unwrap() + y.unwrap());\n}\n\n/// @notice Implements the AND (&) bitwise operation in the SD59x18 type.\nfunction and(SD59x18 x, int256 bits) pure returns (SD59x18 result) {\n return wrap(x.unwrap() & bits);\n}\n\n/// @notice Implements the AND (&) bitwise operation in the SD59x18 type.\nfunction and2(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n return wrap(x.unwrap() & y.unwrap());\n}\n\n/// @notice Implements the equal (=) operation in the SD59x18 type.\nfunction eq(SD59x18 x, SD59x18 y) pure returns (bool result) {\n result = x.unwrap() == y.unwrap();\n}\n\n/// @notice Implements the greater than operation (>) in the SD59x18 type.\nfunction gt(SD59x18 x, SD59x18 y) pure returns (bool result) {\n result = x.unwrap() > y.unwrap();\n}\n\n/// @notice Implements the greater than or equal to operation (>=) in the SD59x18 type.\nfunction gte(SD59x18 x, SD59x18 y) pure returns (bool result) {\n result = x.unwrap() >= y.unwrap();\n}\n\n/// @notice Implements a zero comparison check function in the SD59x18 type.\nfunction isZero(SD59x18 x) pure returns (bool result) {\n result = x.unwrap() == 0;\n}\n\n/// @notice Implements the left shift operation (<<) in the SD59x18 type.\nfunction lshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) {\n result = wrap(x.unwrap() << bits);\n}\n\n/// @notice Implements the lower than operation (<) in the SD59x18 type.\nfunction lt(SD59x18 x, SD59x18 y) pure returns (bool result) {\n result = x.unwrap() < y.unwrap();\n}\n\n/// @notice Implements the lower than or equal to operation (<=) in the SD59x18 type.\nfunction lte(SD59x18 x, SD59x18 y) pure returns (bool result) {\n result = x.unwrap() <= y.unwrap();\n}\n\n/// @notice Implements the unchecked modulo operation (%) in the SD59x18 type.\nfunction mod(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n result = wrap(x.unwrap() % y.unwrap());\n}\n\n/// @notice Implements the not equal operation (!=) in the SD59x18 type.\nfunction neq(SD59x18 x, SD59x18 y) pure returns (bool result) {\n result = x.unwrap() != y.unwrap();\n}\n\n/// @notice Implements the NOT (~) bitwise operation in the SD59x18 type.\nfunction not(SD59x18 x) pure returns (SD59x18 result) {\n result = wrap(~x.unwrap());\n}\n\n/// @notice Implements the OR (|) bitwise operation in the SD59x18 type.\nfunction or(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n result = wrap(x.unwrap() | y.unwrap());\n}\n\n/// @notice Implements the right shift operation (>>) in the SD59x18 type.\nfunction rshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) {\n result = wrap(x.unwrap() >> bits);\n}\n\n/// @notice Implements the checked subtraction operation (-) in the SD59x18 type.\nfunction sub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n result = wrap(x.unwrap() - y.unwrap());\n}\n\n/// @notice Implements the checked unary minus operation (-) in the SD59x18 type.\nfunction unary(SD59x18 x) pure returns (SD59x18 result) {\n result = wrap(-x.unwrap());\n}\n\n/// @notice Implements the unchecked addition operation (+) in the SD59x18 type.\nfunction uncheckedAdd(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n unchecked {\n result = wrap(x.unwrap() + y.unwrap());\n }\n}\n\n/// @notice Implements the unchecked subtraction operation (-) in the SD59x18 type.\nfunction uncheckedSub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n unchecked {\n result = wrap(x.unwrap() - y.unwrap());\n }\n}\n\n/// @notice Implements the unchecked unary minus operation (-) in the SD59x18 type.\nfunction uncheckedUnary(SD59x18 x) pure returns (SD59x18 result) {\n unchecked {\n result = wrap(-x.unwrap());\n }\n}\n\n/// @notice Implements the XOR (^) bitwise operation in the SD59x18 type.\nfunction xor(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n result = wrap(x.unwrap() ^ y.unwrap());\n}\n", + "npm/@prb/math@4.1.1/src/sd59x18/Math.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as Errors;\nimport {\n uEXP_MAX_INPUT,\n uEXP2_MAX_INPUT,\n uEXP_MIN_THRESHOLD,\n uEXP2_MIN_THRESHOLD,\n uHALF_UNIT,\n uLOG2_10,\n uLOG2_E,\n uMAX_SD59x18,\n uMAX_WHOLE_SD59x18,\n uMIN_SD59x18,\n uMIN_WHOLE_SD59x18,\n UNIT,\n uUNIT,\n uUNIT_SQUARED,\n ZERO\n} from \"./Constants.sol\";\nimport { wrap } from \"./Helpers.sol\";\nimport { SD59x18 } from \"./ValueType.sol\";\n\n/// @notice Calculates the absolute value of x.\n///\n/// @dev Requirements:\n/// - x > MIN_SD59x18.\n///\n/// @param x The SD59x18 number for which to calculate the absolute value.\n/// @return result The absolute value of x as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction abs(SD59x18 x) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n if (xInt == uMIN_SD59x18) {\n revert Errors.PRBMath_SD59x18_Abs_MinSD59x18();\n }\n result = xInt < 0 ? wrap(-xInt) : x;\n}\n\n/// @notice Calculates the arithmetic average of x and y.\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// @param x The first operand as an SD59x18 number.\n/// @param y The second operand as an SD59x18 number.\n/// @return result The arithmetic average as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction avg(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n int256 yInt = y.unwrap();\n\n unchecked {\n // This operation is equivalent to `x / 2 + y / 2`, and it can never overflow.\n int256 sum = (xInt >> 1) + (yInt >> 1);\n\n if (sum < 0) {\n // If at least one of x and y is odd, add 1 to the result, because shifting negative numbers to the right\n // rounds toward negative infinity. The right part is equivalent to `sum + (x % 2 == 1 || y % 2 == 1)`.\n assembly (\"memory-safe\") {\n result := add(sum, and(or(xInt, yInt), 1))\n }\n } else {\n // Add 1 if both x and y are odd to account for the double 0.5 remainder truncated after shifting.\n result = wrap(sum + (xInt & yInt & 1));\n }\n }\n}\n\n/// @notice Yields the smallest whole number greater than or equal to x.\n///\n/// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts.\n/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n///\n/// Requirements:\n/// - x \u2264 MAX_WHOLE_SD59x18\n///\n/// @param x The SD59x18 number to ceil.\n/// @return result The smallest whole number greater than or equal to x, as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction ceil(SD59x18 x) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n if (xInt > uMAX_WHOLE_SD59x18) {\n revert Errors.PRBMath_SD59x18_Ceil_Overflow(x);\n }\n\n int256 remainder = xInt % uUNIT;\n if (remainder == 0) {\n result = x;\n } else {\n unchecked {\n // Solidity uses C fmod style, which returns a modulus with the same sign as x.\n int256 resultInt = xInt - remainder;\n if (xInt > 0) {\n resultInt += uUNIT;\n }\n result = wrap(resultInt);\n }\n }\n}\n\n/// @notice Divides two SD59x18 numbers, returning a new SD59x18 number.\n///\n/// @dev This is an extension of {Common.mulDiv} for signed numbers, which works by computing the signs and the absolute\n/// values separately.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv}.\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - Refer to the requirements in {Common.mulDiv}.\n/// - None of the inputs can be `MIN_SD59x18`.\n/// - The denominator must not be zero.\n/// - The result must fit in SD59x18.\n///\n/// @param x The numerator as an SD59x18 number.\n/// @param y The denominator as an SD59x18 number.\n/// @return result The quotient as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction div(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n int256 yInt = y.unwrap();\n if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {\n revert Errors.PRBMath_SD59x18_Div_InputTooSmall();\n }\n\n // Get hold of the absolute values of x and y.\n uint256 xAbs;\n uint256 yAbs;\n unchecked {\n xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt);\n yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt);\n }\n\n // Compute the absolute value (x*UNIT\u00f7y). The resulting value must fit in SD59x18.\n uint256 resultAbs = Common.mulDiv(xAbs, uint256(uUNIT), yAbs);\n if (resultAbs > uint256(uMAX_SD59x18)) {\n revert Errors.PRBMath_SD59x18_Div_Overflow(x, y);\n }\n\n // Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for\n // negative, 0 for positive or zero).\n bool sameSign = (xInt ^ yInt) > -1;\n\n // If the inputs have the same sign, the result should be positive. Otherwise, it should be negative.\n unchecked {\n result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));\n }\n}\n\n/// @notice Calculates the natural exponent of x using the following formula:\n///\n/// $$\n/// e^x = 2^{x * log_2{e}}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {exp2}.\n///\n/// Requirements:\n/// - Refer to the requirements in {exp2}.\n/// - x < 133_084258667509499441.\n///\n/// @param x The exponent as an SD59x18 number.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp(SD59x18 x) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n\n // Any input less than the threshold returns zero.\n // This check also prevents an overflow for very small numbers.\n if (xInt < uEXP_MIN_THRESHOLD) {\n return ZERO;\n }\n\n // This check prevents values greater than 192e18 from being passed to {exp2}.\n if (xInt > uEXP_MAX_INPUT) {\n revert Errors.PRBMath_SD59x18_Exp_InputTooBig(x);\n }\n\n unchecked {\n // Inline the fixed-point multiplication to save gas.\n int256 doubleUnitProduct = xInt * uLOG2_E;\n result = exp2(wrap(doubleUnitProduct / uUNIT));\n }\n}\n\n/// @notice Calculates the binary exponent of x using the binary fraction method using the following formula:\n///\n/// $$\n/// 2^{-x} = \\frac{1}{2^x}\n/// $$\n///\n/// @dev See https://ethereum.stackexchange.com/q/79903/24693.\n///\n/// Notes:\n/// - If x < -59_794705707972522261, the result is zero.\n///\n/// Requirements:\n/// - x < 192e18.\n/// - The result must fit in SD59x18.\n///\n/// @param x The exponent as an SD59x18 number.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp2(SD59x18 x) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n if (xInt < 0) {\n // The inverse of any number less than the threshold is truncated to zero.\n if (xInt < uEXP2_MIN_THRESHOLD) {\n return ZERO;\n }\n\n unchecked {\n // Inline the fixed-point inversion to save gas.\n result = wrap(uUNIT_SQUARED / exp2(wrap(-xInt)).unwrap());\n }\n } else {\n // Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format.\n if (xInt > uEXP2_MAX_INPUT) {\n revert Errors.PRBMath_SD59x18_Exp2_InputTooBig(x);\n }\n\n unchecked {\n // Convert x to the 192.64-bit fixed-point format.\n uint256 x_192x64 = uint256((xInt << 64) / uUNIT);\n\n // It is safe to cast the result to int256 due to the checks above.\n result = wrap(int256(Common.exp2(x_192x64)));\n }\n }\n}\n\n/// @notice Yields the greatest whole number less than or equal to x.\n///\n/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional\n/// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n///\n/// Requirements:\n/// - x \u2265 MIN_WHOLE_SD59x18\n///\n/// @param x The SD59x18 number to floor.\n/// @return result The greatest whole number less than or equal to x, as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction floor(SD59x18 x) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n if (xInt < uMIN_WHOLE_SD59x18) {\n revert Errors.PRBMath_SD59x18_Floor_Underflow(x);\n }\n\n int256 remainder = xInt % uUNIT;\n if (remainder == 0) {\n result = x;\n } else {\n unchecked {\n // Solidity uses C fmod style, which returns a modulus with the same sign as x.\n int256 resultInt = xInt - remainder;\n if (xInt < 0) {\n resultInt -= uUNIT;\n }\n result = wrap(resultInt);\n }\n }\n}\n\n/// @notice Yields the excess beyond the floor of x for positive numbers and the part of the number to the right.\n/// of the radix point for negative numbers.\n/// @dev Based on the odd function definition. https://en.wikipedia.org/wiki/Fractional_part\n/// @param x The SD59x18 number to get the fractional part of.\n/// @return result The fractional part of x as an SD59x18 number.\nfunction frac(SD59x18 x) pure returns (SD59x18 result) {\n result = wrap(x.unwrap() % uUNIT);\n}\n\n/// @notice Calculates the geometric mean of x and y, i.e. $\\sqrt{x * y}$.\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x * y must fit in SD59x18.\n/// - x * y must not be negative, since complex numbers are not supported.\n///\n/// @param x The first operand as an SD59x18 number.\n/// @param y The second operand as an SD59x18 number.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction gm(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n int256 yInt = y.unwrap();\n if (xInt == 0 || yInt == 0) {\n return ZERO;\n }\n\n unchecked {\n // Equivalent to `xy / x != y`. Checking for overflow this way is faster than letting Solidity do it.\n int256 xyInt = xInt * yInt;\n if (xyInt / xInt != yInt) {\n revert Errors.PRBMath_SD59x18_Gm_Overflow(x, y);\n }\n\n // The product must not be negative, since complex numbers are not supported.\n if (xyInt < 0) {\n revert Errors.PRBMath_SD59x18_Gm_NegativeProduct(x, y);\n }\n\n // We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT`\n // during multiplication. See the comments in {Common.sqrt}.\n uint256 resultUint = Common.sqrt(uint256(xyInt));\n result = wrap(int256(resultUint));\n }\n}\n\n/// @notice Calculates the inverse of x.\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x must not be zero.\n///\n/// @param x The SD59x18 number for which to calculate the inverse.\n/// @return result The inverse as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction inv(SD59x18 x) pure returns (SD59x18 result) {\n result = wrap(uUNIT_SQUARED / x.unwrap());\n}\n\n/// @notice Calculates the natural logarithm of x using the following formula:\n///\n/// $$\n/// ln{x} = log_2{x} / log_2{e}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2}.\n/// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`.\n///\n/// Requirements:\n/// - Refer to the requirements in {log2}.\n///\n/// @param x The SD59x18 number for which to calculate the natural logarithm.\n/// @return result The natural logarithm as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction ln(SD59x18 x) pure returns (SD59x18 result) {\n // Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that\n // {log2} can return is ~195_205294292027477728.\n result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E);\n}\n\n/// @notice Calculates the common logarithm of x using the following formula:\n///\n/// $$\n/// log_{10}{x} = log_2{x} / log_2{10}\n/// $$\n///\n/// However, if x is an exact power of ten, a hard coded value is returned.\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2}.\n///\n/// Requirements:\n/// - Refer to the requirements in {log2}.\n///\n/// @param x The SD59x18 number for which to calculate the common logarithm.\n/// @return result The common logarithm as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction log10(SD59x18 x) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n if (xInt < 0) {\n revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x);\n }\n\n // Note that the `mul` in this block is the standard multiplication operation, not {SD59x18.mul}.\n // prettier-ignore\n assembly (\"memory-safe\") {\n switch x\n case 1 { result := mul(uUNIT, sub(0, 18)) }\n case 10 { result := mul(uUNIT, sub(1, 18)) }\n case 100 { result := mul(uUNIT, sub(2, 18)) }\n case 1000 { result := mul(uUNIT, sub(3, 18)) }\n case 10000 { result := mul(uUNIT, sub(4, 18)) }\n case 100000 { result := mul(uUNIT, sub(5, 18)) }\n case 1000000 { result := mul(uUNIT, sub(6, 18)) }\n case 10000000 { result := mul(uUNIT, sub(7, 18)) }\n case 100000000 { result := mul(uUNIT, sub(8, 18)) }\n case 1000000000 { result := mul(uUNIT, sub(9, 18)) }\n case 10000000000 { result := mul(uUNIT, sub(10, 18)) }\n case 100000000000 { result := mul(uUNIT, sub(11, 18)) }\n case 1000000000000 { result := mul(uUNIT, sub(12, 18)) }\n case 10000000000000 { result := mul(uUNIT, sub(13, 18)) }\n case 100000000000000 { result := mul(uUNIT, sub(14, 18)) }\n case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) }\n case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) }\n case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) }\n case 1000000000000000000 { result := 0 }\n case 10000000000000000000 { result := uUNIT }\n case 100000000000000000000 { result := mul(uUNIT, 2) }\n case 1000000000000000000000 { result := mul(uUNIT, 3) }\n case 10000000000000000000000 { result := mul(uUNIT, 4) }\n case 100000000000000000000000 { result := mul(uUNIT, 5) }\n case 1000000000000000000000000 { result := mul(uUNIT, 6) }\n case 10000000000000000000000000 { result := mul(uUNIT, 7) }\n case 100000000000000000000000000 { result := mul(uUNIT, 8) }\n case 1000000000000000000000000000 { result := mul(uUNIT, 9) }\n case 10000000000000000000000000000 { result := mul(uUNIT, 10) }\n case 100000000000000000000000000000 { result := mul(uUNIT, 11) }\n case 1000000000000000000000000000000 { result := mul(uUNIT, 12) }\n case 10000000000000000000000000000000 { result := mul(uUNIT, 13) }\n case 100000000000000000000000000000000 { result := mul(uUNIT, 14) }\n case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) }\n case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) }\n case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) }\n case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) }\n case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) }\n case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) }\n case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) }\n case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) }\n case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) }\n case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) }\n case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) }\n case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) }\n case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) }\n case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) }\n case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) }\n case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) }\n case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) }\n case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) }\n case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) }\n case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) }\n case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) }\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) }\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) }\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) }\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) }\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) }\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) }\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) }\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) }\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) }\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) }\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) }\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) }\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) }\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) }\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) }\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) }\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) }\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) }\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) }\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) }\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) }\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) }\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) }\n default { result := uMAX_SD59x18 }\n }\n\n if (result.unwrap() == uMAX_SD59x18) {\n unchecked {\n // Inline the fixed-point division to save gas.\n result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10);\n }\n }\n}\n\n/// @notice Calculates the binary logarithm of x using the iterative approximation algorithm:\n///\n/// $$\n/// log_2{x} = n + log_2{y}, \\text{ where } y = x*2^{-n}, \\ y \\in [1, 2)\n/// $$\n///\n/// For $0 \\leq x \\lt 1$, the input is inverted:\n///\n/// $$\n/// log_2{x} = -log_2{\\frac{1}{x}}\n/// $$\n///\n/// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation.\n///\n/// Notes:\n/// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal.\n///\n/// Requirements:\n/// - x > 0\n///\n/// @param x The SD59x18 number for which to calculate the binary logarithm.\n/// @return result The binary logarithm as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction log2(SD59x18 x) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n if (xInt <= 0) {\n revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x);\n }\n\n unchecked {\n int256 sign;\n if (xInt >= uUNIT) {\n sign = 1;\n } else {\n sign = -1;\n // Inline the fixed-point inversion to save gas.\n xInt = uUNIT_SQUARED / xInt;\n }\n\n // Calculate the integer part of the logarithm.\n uint256 n = Common.msb(uint256(xInt / uUNIT));\n\n // This is the integer part of the logarithm as an SD59x18 number. The operation can't overflow\n // because n is at most 255, `UNIT` is 1e18, and the sign is either 1 or -1.\n int256 resultInt = int256(n) * uUNIT;\n\n // Calculate $y = x * 2^{-n}$.\n int256 y = xInt >> n;\n\n // If y is the unit number, the fractional part is zero.\n if (y == uUNIT) {\n return wrap(resultInt * sign);\n }\n\n // Calculate the fractional part via the iterative approximation.\n // The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient.\n int256 doubleUnit = 2e18;\n for (int256 delta = uHALF_UNIT; delta > 0; delta >>= 1) {\n y = (y * y) / uUNIT;\n\n // Is y^2 >= 2e18 and so in the range [2e18, 4e18)?\n if (y >= doubleUnit) {\n // Add the 2^{-m} factor to the logarithm.\n resultInt = resultInt + delta;\n\n // Halve y, which corresponds to z/2 in the Wikipedia article.\n y >>= 1;\n }\n }\n resultInt *= sign;\n result = wrap(resultInt);\n }\n}\n\n/// @notice Multiplies two SD59x18 numbers together, returning a new SD59x18 number.\n///\n/// @dev Notes:\n/// - Refer to the notes in {Common.mulDiv18}.\n///\n/// Requirements:\n/// - Refer to the requirements in {Common.mulDiv18}.\n/// - None of the inputs can be `MIN_SD59x18`.\n/// - The result must fit in SD59x18.\n///\n/// @param x The multiplicand as an SD59x18 number.\n/// @param y The multiplier as an SD59x18 number.\n/// @return result The product as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction mul(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n int256 yInt = y.unwrap();\n if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {\n revert Errors.PRBMath_SD59x18_Mul_InputTooSmall();\n }\n\n // Get hold of the absolute values of x and y.\n uint256 xAbs;\n uint256 yAbs;\n unchecked {\n xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt);\n yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt);\n }\n\n // Compute the absolute value (x*y\u00f7UNIT). The resulting value must fit in SD59x18.\n uint256 resultAbs = Common.mulDiv18(xAbs, yAbs);\n if (resultAbs > uint256(uMAX_SD59x18)) {\n revert Errors.PRBMath_SD59x18_Mul_Overflow(x, y);\n }\n\n // Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for\n // negative, 0 for positive or zero).\n bool sameSign = (xInt ^ yInt) > -1;\n\n // If the inputs have the same sign, the result should be positive. Otherwise, it should be negative.\n unchecked {\n result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));\n }\n}\n\n/// @notice Raises x to the power of y using the following formula:\n///\n/// $$\n/// x^y = 2^{log_2{x} * y}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {exp2}, {log2}, and {mul}.\n/// - Returns `UNIT` for 0^0.\n///\n/// Requirements:\n/// - Refer to the requirements in {exp2}, {log2}, and {mul}.\n///\n/// @param x The base as an SD59x18 number.\n/// @param y Exponent to raise x to, as an SD59x18 number\n/// @return result x raised to power y, as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction pow(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n int256 yInt = y.unwrap();\n\n // If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero.\n if (xInt == 0) {\n return yInt == 0 ? UNIT : ZERO;\n }\n // If x is `UNIT`, the result is always `UNIT`.\n else if (xInt == uUNIT) {\n return UNIT;\n }\n\n // If y is zero, the result is always `UNIT`.\n if (yInt == 0) {\n return UNIT;\n }\n // If y is `UNIT`, the result is always x.\n else if (yInt == uUNIT) {\n return x;\n }\n\n // Calculate the result using the formula.\n result = exp2(mul(log2(x), y));\n}\n\n/// @notice Raises x (an SD59x18 number) to the power y (an unsigned basic integer) using the well-known\n/// algorithm \"exponentiation by squaring\".\n///\n/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv18}.\n/// - Returns `UNIT` for 0^0.\n///\n/// Requirements:\n/// - Refer to the requirements in {abs} and {Common.mulDiv18}.\n/// - The result must fit in SD59x18.\n///\n/// @param x The base as an SD59x18 number.\n/// @param y The exponent as a uint256.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction powu(SD59x18 x, uint256 y) pure returns (SD59x18 result) {\n uint256 xAbs = uint256(abs(x).unwrap());\n\n // Calculate the first iteration of the loop in advance.\n uint256 resultAbs = y & 1 > 0 ? xAbs : uint256(uUNIT);\n\n // Equivalent to `for(y /= 2; y > 0; y /= 2)`.\n uint256 yAux = y;\n for (yAux >>= 1; yAux > 0; yAux >>= 1) {\n xAbs = Common.mulDiv18(xAbs, xAbs);\n\n // Equivalent to `y % 2 == 1`.\n if (yAux & 1 > 0) {\n resultAbs = Common.mulDiv18(resultAbs, xAbs);\n }\n }\n\n // The result must fit in SD59x18.\n if (resultAbs > uint256(uMAX_SD59x18)) {\n revert Errors.PRBMath_SD59x18_Powu_Overflow(x, y);\n }\n\n unchecked {\n // Is the base negative and the exponent odd? If yes, the result should be negative.\n int256 resultInt = int256(resultAbs);\n bool isNegative = x.unwrap() < 0 && y & 1 == 1;\n if (isNegative) {\n resultInt = -resultInt;\n }\n result = wrap(resultInt);\n }\n}\n\n/// @notice Calculates the square root of x using the Babylonian method.\n///\n/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n///\n/// Notes:\n/// - Only the positive root is returned.\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x \u2265 0, since complex numbers are not supported.\n/// - x \u2264 MAX_SD59x18 / UNIT\n///\n/// @param x The SD59x18 number for which to calculate the square root.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction sqrt(SD59x18 x) pure returns (SD59x18 result) {\n int256 xInt = x.unwrap();\n if (xInt < 0) {\n revert Errors.PRBMath_SD59x18_Sqrt_NegativeInput(x);\n }\n if (xInt > uMAX_SD59x18 / uUNIT) {\n revert Errors.PRBMath_SD59x18_Sqrt_Overflow(x);\n }\n\n unchecked {\n // Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two SD59x18 numbers.\n // In this case, the two numbers are both the square root.\n uint256 resultUint = Common.sqrt(uint256(xInt * uUNIT));\n result = wrap(int256(resultUint));\n }\n}\n", + "npm/@prb/math@4.1.1/src/sd59x18/ValueType.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\nimport \"./Helpers.sol\" as Helpers;\nimport \"./Math.sol\" as Math;\n\n/// @notice The signed 59.18-decimal fixed-point number representation, which can have up to 59 digits and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity\n/// type int256.\ntype SD59x18 is int256;\n\n/*//////////////////////////////////////////////////////////////////////////\n CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n Casting.intoInt256,\n Casting.intoSD1x18,\n Casting.intoSD21x18,\n Casting.intoUD2x18,\n Casting.intoUD21x18,\n Casting.intoUD60x18,\n Casting.intoUint256,\n Casting.intoUint128,\n Casting.intoUint40,\n Casting.unwrap\n} for SD59x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n MATHEMATICAL FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n Math.abs,\n Math.avg,\n Math.ceil,\n Math.div,\n Math.exp,\n Math.exp2,\n Math.floor,\n Math.frac,\n Math.gm,\n Math.inv,\n Math.log10,\n Math.log2,\n Math.ln,\n Math.mul,\n Math.pow,\n Math.powu,\n Math.sqrt\n} for SD59x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n HELPER FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n Helpers.add,\n Helpers.and,\n Helpers.eq,\n Helpers.gt,\n Helpers.gte,\n Helpers.isZero,\n Helpers.lshift,\n Helpers.lt,\n Helpers.lte,\n Helpers.mod,\n Helpers.neq,\n Helpers.not,\n Helpers.or,\n Helpers.rshift,\n Helpers.sub,\n Helpers.uncheckedAdd,\n Helpers.uncheckedSub,\n Helpers.uncheckedUnary,\n Helpers.xor\n} for SD59x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n OPERATORS\n//////////////////////////////////////////////////////////////////////////*/\n\n// The global \"using for\" directive makes it possible to use these operators on the SD59x18 type.\nusing {\n Helpers.add as +,\n Helpers.and2 as &,\n Math.div as /,\n Helpers.eq as ==,\n Helpers.gt as >,\n Helpers.gte as >=,\n Helpers.lt as <,\n Helpers.lte as <=,\n Helpers.mod as %,\n Math.mul as *,\n Helpers.neq as !=,\n Helpers.not as ~,\n Helpers.or as |,\n Helpers.sub as -,\n Helpers.unary as -,\n Helpers.xor as ^\n} for SD59x18 global;\n", + "npm/@prb/math@4.1.1/src/ud21x18/Casting.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as Errors;\nimport { SD59x18 } from \"../sd59x18/ValueType.sol\";\nimport { UD60x18 } from \"../ud60x18/ValueType.sol\";\nimport { UD21x18 } from \"./ValueType.sol\";\n\n/// @notice Casts a UD21x18 number into SD59x18.\n/// @dev There is no overflow check because UD21x18 \u2286 SD59x18.\nfunction intoSD59x18(UD21x18 x) pure returns (SD59x18 result) {\n result = SD59x18.wrap(int256(uint256(UD21x18.unwrap(x))));\n}\n\n/// @notice Casts a UD21x18 number into UD60x18.\n/// @dev There is no overflow check because UD21x18 \u2286 UD60x18.\nfunction intoUD60x18(UD21x18 x) pure returns (UD60x18 result) {\n result = UD60x18.wrap(UD21x18.unwrap(x));\n}\n\n/// @notice Casts a UD21x18 number into uint128.\n/// @dev This is basically an alias for {unwrap}.\nfunction intoUint128(UD21x18 x) pure returns (uint128 result) {\n result = UD21x18.unwrap(x);\n}\n\n/// @notice Casts a UD21x18 number into uint256.\n/// @dev There is no overflow check because UD21x18 \u2286 uint256.\nfunction intoUint256(UD21x18 x) pure returns (uint256 result) {\n result = uint256(UD21x18.unwrap(x));\n}\n\n/// @notice Casts a UD21x18 number into uint40.\n/// @dev Requirements:\n/// - x \u2264 MAX_UINT40\nfunction intoUint40(UD21x18 x) pure returns (uint40 result) {\n uint128 xUint = UD21x18.unwrap(x);\n if (xUint > uint128(Common.MAX_UINT40)) {\n revert Errors.PRBMath_UD21x18_IntoUint40_Overflow(x);\n }\n result = uint40(xUint);\n}\n\n/// @notice Alias for {wrap}.\nfunction ud21x18(uint128 x) pure returns (UD21x18 result) {\n result = UD21x18.wrap(x);\n}\n\n/// @notice Unwrap a UD21x18 number into uint128.\nfunction unwrap(UD21x18 x) pure returns (uint128 result) {\n result = UD21x18.unwrap(x);\n}\n\n/// @notice Wraps a uint128 number into UD21x18.\nfunction wrap(uint128 x) pure returns (UD21x18 result) {\n result = UD21x18.wrap(x);\n}\n", + "npm/@prb/math@4.1.1/src/ud21x18/Constants.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD21x18 } from \"./ValueType.sol\";\n\n/// @dev Euler's number as a UD21x18 number.\nUD21x18 constant E = UD21x18.wrap(2_718281828459045235);\n\n/// @dev The maximum value a UD21x18 number can have.\nuint128 constant uMAX_UD21x18 = 340282366920938463463_374607431768211455;\nUD21x18 constant MAX_UD21x18 = UD21x18.wrap(uMAX_UD21x18);\n\n/// @dev PI as a UD21x18 number.\nUD21x18 constant PI = UD21x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of UD21x18.\nuint256 constant uUNIT = 1e18;\nUD21x18 constant UNIT = UD21x18.wrap(1e18);\n", + "npm/@prb/math@4.1.1/src/ud21x18/Errors.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD21x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when trying to cast a UD21x18 number that doesn't fit in uint40.\nerror PRBMath_UD21x18_IntoUint40_Overflow(UD21x18 x);\n", + "npm/@prb/math@4.1.1/src/ud21x18/ValueType.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\n\n/// @notice The unsigned 21.18-decimal fixed-point number representation, which can have up to 21 digits and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity\n/// type uint128. This is useful when end users want to use uint128 to save gas, e.g. with tight variable packing in contract\n/// storage.\ntype UD21x18 is uint128;\n\n/*//////////////////////////////////////////////////////////////////////////\n CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n Casting.intoSD59x18,\n Casting.intoUD60x18,\n Casting.intoUint128,\n Casting.intoUint256,\n Casting.intoUint40,\n Casting.unwrap\n} for UD21x18 global;\n", + "npm/@prb/math@4.1.1/src/ud2x18/Casting.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as Errors;\nimport { SD59x18 } from \"../sd59x18/ValueType.sol\";\nimport { UD60x18 } from \"../ud60x18/ValueType.sol\";\nimport { UD2x18 } from \"./ValueType.sol\";\n\n/// @notice Casts a UD2x18 number into SD59x18.\n/// @dev There is no overflow check because UD2x18 \u2286 SD59x18.\nfunction intoSD59x18(UD2x18 x) pure returns (SD59x18 result) {\n result = SD59x18.wrap(int256(uint256(UD2x18.unwrap(x))));\n}\n\n/// @notice Casts a UD2x18 number into UD60x18.\n/// @dev There is no overflow check because UD2x18 \u2286 UD60x18.\nfunction intoUD60x18(UD2x18 x) pure returns (UD60x18 result) {\n result = UD60x18.wrap(UD2x18.unwrap(x));\n}\n\n/// @notice Casts a UD2x18 number into uint128.\n/// @dev There is no overflow check because UD2x18 \u2286 uint128.\nfunction intoUint128(UD2x18 x) pure returns (uint128 result) {\n result = uint128(UD2x18.unwrap(x));\n}\n\n/// @notice Casts a UD2x18 number into uint256.\n/// @dev There is no overflow check because UD2x18 \u2286 uint256.\nfunction intoUint256(UD2x18 x) pure returns (uint256 result) {\n result = uint256(UD2x18.unwrap(x));\n}\n\n/// @notice Casts a UD2x18 number into uint40.\n/// @dev Requirements:\n/// - x \u2264 MAX_UINT40\nfunction intoUint40(UD2x18 x) pure returns (uint40 result) {\n uint64 xUint = UD2x18.unwrap(x);\n if (xUint > uint64(Common.MAX_UINT40)) {\n revert Errors.PRBMath_UD2x18_IntoUint40_Overflow(x);\n }\n result = uint40(xUint);\n}\n\n/// @notice Alias for {wrap}.\nfunction ud2x18(uint64 x) pure returns (UD2x18 result) {\n result = UD2x18.wrap(x);\n}\n\n/// @notice Unwrap a UD2x18 number into uint64.\nfunction unwrap(UD2x18 x) pure returns (uint64 result) {\n result = UD2x18.unwrap(x);\n}\n\n/// @notice Wraps a uint64 number into UD2x18.\nfunction wrap(uint64 x) pure returns (UD2x18 result) {\n result = UD2x18.wrap(x);\n}\n", + "npm/@prb/math@4.1.1/src/ud2x18/Constants.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD2x18 } from \"./ValueType.sol\";\n\n/// @dev Euler's number as a UD2x18 number.\nUD2x18 constant E = UD2x18.wrap(2_718281828459045235);\n\n/// @dev The maximum value a UD2x18 number can have.\nuint64 constant uMAX_UD2x18 = 18_446744073709551615;\nUD2x18 constant MAX_UD2x18 = UD2x18.wrap(uMAX_UD2x18);\n\n/// @dev PI as a UD2x18 number.\nUD2x18 constant PI = UD2x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of UD2x18.\nUD2x18 constant UNIT = UD2x18.wrap(1e18);\nuint64 constant uUNIT = 1e18;\n", + "npm/@prb/math@4.1.1/src/ud2x18/Errors.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD2x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when trying to cast a UD2x18 number that doesn't fit in uint40.\nerror PRBMath_UD2x18_IntoUint40_Overflow(UD2x18 x);\n", + "npm/@prb/math@4.1.1/src/ud2x18/ValueType.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\n\n/// @notice The unsigned 2.18-decimal fixed-point number representation, which can have up to 2 digits and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity\n/// type uint64. This is useful when end users want to use uint64 to save gas, e.g. with tight variable packing in contract\n/// storage.\ntype UD2x18 is uint64;\n\n/*//////////////////////////////////////////////////////////////////////////\n CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n Casting.intoSD59x18,\n Casting.intoUD60x18,\n Casting.intoUint128,\n Casting.intoUint256,\n Casting.intoUint40,\n Casting.unwrap\n} for UD2x18 global;\n", + "npm/@prb/math@4.1.1/src/ud60x18/Casting.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Errors.sol\" as CastingErrors;\nimport { MAX_UINT128, MAX_UINT40 } from \"../Common.sol\";\nimport { uMAX_SD1x18 } from \"../sd1x18/Constants.sol\";\nimport { SD1x18 } from \"../sd1x18/ValueType.sol\";\nimport { uMAX_SD21x18 } from \"../sd21x18/Constants.sol\";\nimport { SD21x18 } from \"../sd21x18/ValueType.sol\";\nimport { uMAX_SD59x18 } from \"../sd59x18/Constants.sol\";\nimport { SD59x18 } from \"../sd59x18/ValueType.sol\";\nimport { uMAX_UD2x18 } from \"../ud2x18/Constants.sol\";\nimport { uMAX_UD21x18 } from \"../ud21x18/Constants.sol\";\nimport { UD2x18 } from \"../ud2x18/ValueType.sol\";\nimport { UD21x18 } from \"../ud21x18/ValueType.sol\";\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/// @notice Casts a UD60x18 number into SD1x18.\n/// @dev Requirements:\n/// - x \u2264 uMAX_SD1x18\nfunction intoSD1x18(UD60x18 x) pure returns (SD1x18 result) {\n uint256 xUint = UD60x18.unwrap(x);\n if (xUint > uint256(int256(uMAX_SD1x18))) {\n revert CastingErrors.PRBMath_UD60x18_IntoSD1x18_Overflow(x);\n }\n result = SD1x18.wrap(int64(uint64(xUint)));\n}\n\n/// @notice Casts a UD60x18 number into SD21x18.\n/// @dev Requirements:\n/// - x \u2264 uMAX_SD21x18\nfunction intoSD21x18(UD60x18 x) pure returns (SD21x18 result) {\n uint256 xUint = UD60x18.unwrap(x);\n if (xUint > uint256(int256(uMAX_SD21x18))) {\n revert CastingErrors.PRBMath_UD60x18_IntoSD21x18_Overflow(x);\n }\n result = SD21x18.wrap(int128(uint128(xUint)));\n}\n\n/// @notice Casts a UD60x18 number into UD2x18.\n/// @dev Requirements:\n/// - x \u2264 uMAX_UD2x18\nfunction intoUD2x18(UD60x18 x) pure returns (UD2x18 result) {\n uint256 xUint = UD60x18.unwrap(x);\n if (xUint > uMAX_UD2x18) {\n revert CastingErrors.PRBMath_UD60x18_IntoUD2x18_Overflow(x);\n }\n result = UD2x18.wrap(uint64(xUint));\n}\n\n/// @notice Casts a UD60x18 number into UD21x18.\n/// @dev Requirements:\n/// - x \u2264 uMAX_UD21x18\nfunction intoUD21x18(UD60x18 x) pure returns (UD21x18 result) {\n uint256 xUint = UD60x18.unwrap(x);\n if (xUint > uMAX_UD21x18) {\n revert CastingErrors.PRBMath_UD60x18_IntoUD21x18_Overflow(x);\n }\n result = UD21x18.wrap(uint128(xUint));\n}\n\n/// @notice Casts a UD60x18 number into SD59x18.\n/// @dev Requirements:\n/// - x \u2264 uMAX_SD59x18\nfunction intoSD59x18(UD60x18 x) pure returns (SD59x18 result) {\n uint256 xUint = UD60x18.unwrap(x);\n if (xUint > uint256(uMAX_SD59x18)) {\n revert CastingErrors.PRBMath_UD60x18_IntoSD59x18_Overflow(x);\n }\n result = SD59x18.wrap(int256(xUint));\n}\n\n/// @notice Casts a UD60x18 number into uint128.\n/// @dev This is basically an alias for {unwrap}.\nfunction intoUint256(UD60x18 x) pure returns (uint256 result) {\n result = UD60x18.unwrap(x);\n}\n\n/// @notice Casts a UD60x18 number into uint128.\n/// @dev Requirements:\n/// - x \u2264 MAX_UINT128\nfunction intoUint128(UD60x18 x) pure returns (uint128 result) {\n uint256 xUint = UD60x18.unwrap(x);\n if (xUint > MAX_UINT128) {\n revert CastingErrors.PRBMath_UD60x18_IntoUint128_Overflow(x);\n }\n result = uint128(xUint);\n}\n\n/// @notice Casts a UD60x18 number into uint40.\n/// @dev Requirements:\n/// - x \u2264 MAX_UINT40\nfunction intoUint40(UD60x18 x) pure returns (uint40 result) {\n uint256 xUint = UD60x18.unwrap(x);\n if (xUint > MAX_UINT40) {\n revert CastingErrors.PRBMath_UD60x18_IntoUint40_Overflow(x);\n }\n result = uint40(xUint);\n}\n\n/// @notice Alias for {wrap}.\nfunction ud(uint256 x) pure returns (UD60x18 result) {\n result = UD60x18.wrap(x);\n}\n\n/// @notice Alias for {wrap}.\nfunction ud60x18(uint256 x) pure returns (UD60x18 result) {\n result = UD60x18.wrap(x);\n}\n\n/// @notice Unwraps a UD60x18 number into uint256.\nfunction unwrap(UD60x18 x) pure returns (uint256 result) {\n result = UD60x18.unwrap(x);\n}\n\n/// @notice Wraps a uint256 number into the UD60x18 value type.\nfunction wrap(uint256 x) pure returns (UD60x18 result) {\n result = UD60x18.wrap(x);\n}\n", + "npm/@prb/math@4.1.1/src/ud60x18/Constants.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD60x18 } from \"./ValueType.sol\";\n\n// NOTICE: the \"u\" prefix stands for \"unwrapped\".\n\n/// @dev Euler's number as a UD60x18 number.\nUD60x18 constant E = UD60x18.wrap(2_718281828459045235);\n\n/// @dev The maximum input permitted in {exp}.\nuint256 constant uEXP_MAX_INPUT = 133_084258667509499440;\nUD60x18 constant EXP_MAX_INPUT = UD60x18.wrap(uEXP_MAX_INPUT);\n\n/// @dev The maximum input permitted in {exp2}.\nuint256 constant uEXP2_MAX_INPUT = 192e18 - 1;\nUD60x18 constant EXP2_MAX_INPUT = UD60x18.wrap(uEXP2_MAX_INPUT);\n\n/// @dev Half the UNIT number.\nuint256 constant uHALF_UNIT = 0.5e18;\nUD60x18 constant HALF_UNIT = UD60x18.wrap(uHALF_UNIT);\n\n/// @dev $log_2(10)$ as a UD60x18 number.\nuint256 constant uLOG2_10 = 3_321928094887362347;\nUD60x18 constant LOG2_10 = UD60x18.wrap(uLOG2_10);\n\n/// @dev $log_2(e)$ as a UD60x18 number.\nuint256 constant uLOG2_E = 1_442695040888963407;\nUD60x18 constant LOG2_E = UD60x18.wrap(uLOG2_E);\n\n/// @dev The maximum value a UD60x18 number can have.\nuint256 constant uMAX_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\nUD60x18 constant MAX_UD60x18 = UD60x18.wrap(uMAX_UD60x18);\n\n/// @dev The maximum whole value a UD60x18 number can have.\nuint256 constant uMAX_WHOLE_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\nUD60x18 constant MAX_WHOLE_UD60x18 = UD60x18.wrap(uMAX_WHOLE_UD60x18);\n\n/// @dev PI as a UD60x18 number.\nUD60x18 constant PI = UD60x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of UD60x18.\nuint256 constant uUNIT = 1e18;\nUD60x18 constant UNIT = UD60x18.wrap(uUNIT);\n\n/// @dev The unit number squared.\nuint256 constant uUNIT_SQUARED = 1e36;\nUD60x18 constant UNIT_SQUARED = UD60x18.wrap(uUNIT_SQUARED);\n\n/// @dev Zero as a UD60x18 number.\nUD60x18 constant ZERO = UD60x18.wrap(0);\n", + "npm/@prb/math@4.1.1/src/ud60x18/Conversions.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { uMAX_UD60x18, uUNIT } from \"./Constants.sol\";\nimport { PRBMath_UD60x18_Convert_Overflow } from \"./Errors.sol\";\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/// @notice Converts a UD60x18 number to a simple integer by dividing it by `UNIT`.\n/// @dev The result is rounded toward zero.\n/// @param x The UD60x18 number to convert.\n/// @return result The same number in basic integer form.\nfunction convert(UD60x18 x) pure returns (uint256 result) {\n result = UD60x18.unwrap(x) / uUNIT;\n}\n\n/// @notice Converts a simple integer to UD60x18 by multiplying it by `UNIT`.\n///\n/// @dev Requirements:\n/// - x \u2264 MAX_UD60x18 / UNIT\n///\n/// @param x The basic integer to convert.\n/// @return result The same number converted to UD60x18.\nfunction convert(uint256 x) pure returns (UD60x18 result) {\n if (x > uMAX_UD60x18 / uUNIT) {\n revert PRBMath_UD60x18_Convert_Overflow(x);\n }\n unchecked {\n result = UD60x18.wrap(x * uUNIT);\n }\n}\n", + "npm/@prb/math@4.1.1/src/ud60x18/Errors.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when ceiling a number overflows UD60x18.\nerror PRBMath_UD60x18_Ceil_Overflow(UD60x18 x);\n\n/// @notice Thrown when converting a basic integer to the fixed-point format overflows UD60x18.\nerror PRBMath_UD60x18_Convert_Overflow(uint256 x);\n\n/// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441.\nerror PRBMath_UD60x18_Exp_InputTooBig(UD60x18 x);\n\n/// @notice Thrown when taking the binary exponent of a base greater than 192e18.\nerror PRBMath_UD60x18_Exp2_InputTooBig(UD60x18 x);\n\n/// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows UD60x18.\nerror PRBMath_UD60x18_Gm_Overflow(UD60x18 x, UD60x18 y);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18.\nerror PRBMath_UD60x18_IntoSD1x18_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD21x18.\nerror PRBMath_UD60x18_IntoSD21x18_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD59x18.\nerror PRBMath_UD60x18_IntoSD59x18_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18.\nerror PRBMath_UD60x18_IntoUD2x18_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD21x18.\nerror PRBMath_UD60x18_IntoUD21x18_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128.\nerror PRBMath_UD60x18_IntoUint128_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40.\nerror PRBMath_UD60x18_IntoUint40_Overflow(UD60x18 x);\n\n/// @notice Thrown when taking the logarithm of a number less than UNIT.\nerror PRBMath_UD60x18_Log_InputTooSmall(UD60x18 x);\n\n/// @notice Thrown when calculating the square root overflows UD60x18.\nerror PRBMath_UD60x18_Sqrt_Overflow(UD60x18 x);\n", + "npm/@prb/math@4.1.1/src/ud60x18/Helpers.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { wrap } from \"./Casting.sol\";\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/// @notice Implements the checked addition operation (+) in the UD60x18 type.\nfunction add(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n result = wrap(x.unwrap() + y.unwrap());\n}\n\n/// @notice Implements the AND (&) bitwise operation in the UD60x18 type.\nfunction and(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {\n result = wrap(x.unwrap() & bits);\n}\n\n/// @notice Implements the AND (&) bitwise operation in the UD60x18 type.\nfunction and2(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n result = wrap(x.unwrap() & y.unwrap());\n}\n\n/// @notice Implements the equal operation (==) in the UD60x18 type.\nfunction eq(UD60x18 x, UD60x18 y) pure returns (bool result) {\n result = x.unwrap() == y.unwrap();\n}\n\n/// @notice Implements the greater than operation (>) in the UD60x18 type.\nfunction gt(UD60x18 x, UD60x18 y) pure returns (bool result) {\n result = x.unwrap() > y.unwrap();\n}\n\n/// @notice Implements the greater than or equal to operation (>=) in the UD60x18 type.\nfunction gte(UD60x18 x, UD60x18 y) pure returns (bool result) {\n result = x.unwrap() >= y.unwrap();\n}\n\n/// @notice Implements a zero comparison check function in the UD60x18 type.\nfunction isZero(UD60x18 x) pure returns (bool result) {\n // This wouldn't work if x could be negative.\n result = x.unwrap() == 0;\n}\n\n/// @notice Implements the left shift operation (<<) in the UD60x18 type.\nfunction lshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {\n result = wrap(x.unwrap() << bits);\n}\n\n/// @notice Implements the lower than operation (<) in the UD60x18 type.\nfunction lt(UD60x18 x, UD60x18 y) pure returns (bool result) {\n result = x.unwrap() < y.unwrap();\n}\n\n/// @notice Implements the lower than or equal to operation (<=) in the UD60x18 type.\nfunction lte(UD60x18 x, UD60x18 y) pure returns (bool result) {\n result = x.unwrap() <= y.unwrap();\n}\n\n/// @notice Implements the checked modulo operation (%) in the UD60x18 type.\nfunction mod(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n result = wrap(x.unwrap() % y.unwrap());\n}\n\n/// @notice Implements the not equal operation (!=) in the UD60x18 type.\nfunction neq(UD60x18 x, UD60x18 y) pure returns (bool result) {\n result = x.unwrap() != y.unwrap();\n}\n\n/// @notice Implements the NOT (~) bitwise operation in the UD60x18 type.\nfunction not(UD60x18 x) pure returns (UD60x18 result) {\n result = wrap(~x.unwrap());\n}\n\n/// @notice Implements the OR (|) bitwise operation in the UD60x18 type.\nfunction or(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n result = wrap(x.unwrap() | y.unwrap());\n}\n\n/// @notice Implements the right shift operation (>>) in the UD60x18 type.\nfunction rshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {\n result = wrap(x.unwrap() >> bits);\n}\n\n/// @notice Implements the checked subtraction operation (-) in the UD60x18 type.\nfunction sub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n result = wrap(x.unwrap() - y.unwrap());\n}\n\n/// @notice Implements the unchecked addition operation (+) in the UD60x18 type.\nfunction uncheckedAdd(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n unchecked {\n result = wrap(x.unwrap() + y.unwrap());\n }\n}\n\n/// @notice Implements the unchecked subtraction operation (-) in the UD60x18 type.\nfunction uncheckedSub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n unchecked {\n result = wrap(x.unwrap() - y.unwrap());\n }\n}\n\n/// @notice Implements the XOR (^) bitwise operation in the UD60x18 type.\nfunction xor(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n result = wrap(x.unwrap() ^ y.unwrap());\n}\n", + "npm/@prb/math@4.1.1/src/ud60x18/Math.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as Errors;\nimport { wrap } from \"./Casting.sol\";\nimport {\n uEXP_MAX_INPUT,\n uEXP2_MAX_INPUT,\n uHALF_UNIT,\n uLOG2_10,\n uLOG2_E,\n uMAX_UD60x18,\n uMAX_WHOLE_UD60x18,\n UNIT,\n uUNIT,\n uUNIT_SQUARED,\n ZERO\n} from \"./Constants.sol\";\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/*//////////////////////////////////////////////////////////////////////////\n MATHEMATICAL FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Calculates the arithmetic average of x and y using the following formula:\n///\n/// $$\n/// avg(x, y) = (x & y) + ((xUint ^ yUint) / 2)\n/// $$\n///\n/// In English, this is what this formula does:\n///\n/// 1. AND x and y.\n/// 2. Calculate half of XOR x and y.\n/// 3. Add the two results together.\n///\n/// This technique is known as SWAR, which stands for \"SIMD within a register\". You can read more about it here:\n/// https://devblogs.microsoft.com/oldnewthing/20220207-00/?p=106223\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// @param x The first operand as a UD60x18 number.\n/// @param y The second operand as a UD60x18 number.\n/// @return result The arithmetic average as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction avg(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n uint256 xUint = x.unwrap();\n uint256 yUint = y.unwrap();\n unchecked {\n result = wrap((xUint & yUint) + ((xUint ^ yUint) >> 1));\n }\n}\n\n/// @notice Yields the smallest whole number greater than or equal to x.\n///\n/// @dev This is optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional\n/// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n///\n/// Requirements:\n/// - x \u2264 MAX_WHOLE_UD60x18\n///\n/// @param x The UD60x18 number to ceil.\n/// @return result The smallest whole number greater than or equal to x, as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction ceil(UD60x18 x) pure returns (UD60x18 result) {\n uint256 xUint = x.unwrap();\n if (xUint > uMAX_WHOLE_UD60x18) {\n revert Errors.PRBMath_UD60x18_Ceil_Overflow(x);\n }\n\n assembly (\"memory-safe\") {\n // Equivalent to `x % UNIT`.\n let remainder := mod(x, uUNIT)\n\n // Equivalent to `UNIT - remainder`.\n let delta := sub(uUNIT, remainder)\n\n // Equivalent to `x + remainder > 0 ? delta : 0`.\n result := add(x, mul(delta, gt(remainder, 0)))\n }\n}\n\n/// @notice Divides two UD60x18 numbers, returning a new UD60x18 number.\n///\n/// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv}.\n///\n/// Requirements:\n/// - Refer to the requirements in {Common.mulDiv}.\n///\n/// @param x The numerator as a UD60x18 number.\n/// @param y The denominator as a UD60x18 number.\n/// @return result The quotient as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction div(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n result = wrap(Common.mulDiv(x.unwrap(), uUNIT, y.unwrap()));\n}\n\n/// @notice Calculates the natural exponent of x using the following formula:\n///\n/// $$\n/// e^x = 2^{x * log_2{e}}\n/// $$\n///\n/// @dev Requirements:\n/// - x \u2264 133_084258667509499440\n///\n/// @param x The exponent as a UD60x18 number.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp(UD60x18 x) pure returns (UD60x18 result) {\n uint256 xUint = x.unwrap();\n\n // This check prevents values greater than 192e18 from being passed to {exp2}.\n if (xUint > uEXP_MAX_INPUT) {\n revert Errors.PRBMath_UD60x18_Exp_InputTooBig(x);\n }\n\n unchecked {\n // Inline the fixed-point multiplication to save gas.\n uint256 doubleUnitProduct = xUint * uLOG2_E;\n result = exp2(wrap(doubleUnitProduct / uUNIT));\n }\n}\n\n/// @notice Calculates the binary exponent of x using the binary fraction method.\n///\n/// @dev See https://ethereum.stackexchange.com/q/79903/24693\n///\n/// Requirements:\n/// - x < 192e18\n/// - The result must fit in UD60x18.\n///\n/// @param x The exponent as a UD60x18 number.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp2(UD60x18 x) pure returns (UD60x18 result) {\n uint256 xUint = x.unwrap();\n\n // Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format.\n if (xUint > uEXP2_MAX_INPUT) {\n revert Errors.PRBMath_UD60x18_Exp2_InputTooBig(x);\n }\n\n // Convert x to the 192.64-bit fixed-point format.\n uint256 x_192x64 = (xUint << 64) / uUNIT;\n\n // Pass x to the {Common.exp2} function, which uses the 192.64-bit fixed-point number representation.\n result = wrap(Common.exp2(x_192x64));\n}\n\n/// @notice Yields the greatest whole number less than or equal to x.\n/// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts.\n/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n/// @param x The UD60x18 number to floor.\n/// @return result The greatest whole number less than or equal to x, as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction floor(UD60x18 x) pure returns (UD60x18 result) {\n assembly (\"memory-safe\") {\n // Equivalent to `x % UNIT`.\n let remainder := mod(x, uUNIT)\n\n // Equivalent to `x - remainder > 0 ? remainder : 0)`.\n result := sub(x, mul(remainder, gt(remainder, 0)))\n }\n}\n\n/// @notice Yields the excess beyond the floor of x using the odd function definition.\n/// @dev See https://en.wikipedia.org/wiki/Fractional_part.\n/// @param x The UD60x18 number to get the fractional part of.\n/// @return result The fractional part of x as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction frac(UD60x18 x) pure returns (UD60x18 result) {\n assembly (\"memory-safe\") {\n result := mod(x, uUNIT)\n }\n}\n\n/// @notice Calculates the geometric mean of x and y, i.e. $\\sqrt{x * y}$, rounding down.\n///\n/// @dev Requirements:\n/// - x * y must fit in UD60x18.\n///\n/// @param x The first operand as a UD60x18 number.\n/// @param y The second operand as a UD60x18 number.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction gm(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n uint256 xUint = x.unwrap();\n uint256 yUint = y.unwrap();\n if (xUint == 0 || yUint == 0) {\n return ZERO;\n }\n\n unchecked {\n // Checking for overflow this way is faster than letting Solidity do it.\n uint256 xyUint = xUint * yUint;\n if (xyUint / xUint != yUint) {\n revert Errors.PRBMath_UD60x18_Gm_Overflow(x, y);\n }\n\n // We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT`\n // during multiplication. See the comments in {Common.sqrt}.\n result = wrap(Common.sqrt(xyUint));\n }\n}\n\n/// @notice Calculates the inverse of x.\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x must not be zero.\n///\n/// @param x The UD60x18 number for which to calculate the inverse.\n/// @return result The inverse as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction inv(UD60x18 x) pure returns (UD60x18 result) {\n unchecked {\n result = wrap(uUNIT_SQUARED / x.unwrap());\n }\n}\n\n/// @notice Calculates the natural logarithm of x using the following formula:\n///\n/// $$\n/// ln{x} = log_2{x} / log_2{e}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2}.\n/// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`.\n///\n/// Requirements:\n/// - Refer to the requirements in {log2}.\n///\n/// @param x The UD60x18 number for which to calculate the natural logarithm.\n/// @return result The natural logarithm as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction ln(UD60x18 x) pure returns (UD60x18 result) {\n unchecked {\n // Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that\n // {log2} can return is ~196_205294292027477728.\n result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E);\n }\n}\n\n/// @notice Calculates the common logarithm of x using the following formula:\n///\n/// $$\n/// log_{10}{x} = log_2{x} / log_2{10}\n/// $$\n///\n/// However, if x is an exact power of ten, a hard coded value is returned.\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2}.\n///\n/// Requirements:\n/// - Refer to the requirements in {log2}.\n///\n/// @param x The UD60x18 number for which to calculate the common logarithm.\n/// @return result The common logarithm as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction log10(UD60x18 x) pure returns (UD60x18 result) {\n uint256 xUint = x.unwrap();\n if (xUint < uUNIT) {\n revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x);\n }\n\n // Note that the `mul` in this assembly block is the standard multiplication operation, not {UD60x18.mul}.\n // prettier-ignore\n assembly (\"memory-safe\") {\n switch x\n case 1 { result := mul(uUNIT, sub(0, 18)) }\n case 10 { result := mul(uUNIT, sub(1, 18)) }\n case 100 { result := mul(uUNIT, sub(2, 18)) }\n case 1000 { result := mul(uUNIT, sub(3, 18)) }\n case 10000 { result := mul(uUNIT, sub(4, 18)) }\n case 100000 { result := mul(uUNIT, sub(5, 18)) }\n case 1000000 { result := mul(uUNIT, sub(6, 18)) }\n case 10000000 { result := mul(uUNIT, sub(7, 18)) }\n case 100000000 { result := mul(uUNIT, sub(8, 18)) }\n case 1000000000 { result := mul(uUNIT, sub(9, 18)) }\n case 10000000000 { result := mul(uUNIT, sub(10, 18)) }\n case 100000000000 { result := mul(uUNIT, sub(11, 18)) }\n case 1000000000000 { result := mul(uUNIT, sub(12, 18)) }\n case 10000000000000 { result := mul(uUNIT, sub(13, 18)) }\n case 100000000000000 { result := mul(uUNIT, sub(14, 18)) }\n case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) }\n case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) }\n case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) }\n case 1000000000000000000 { result := 0 }\n case 10000000000000000000 { result := uUNIT }\n case 100000000000000000000 { result := mul(uUNIT, 2) }\n case 1000000000000000000000 { result := mul(uUNIT, 3) }\n case 10000000000000000000000 { result := mul(uUNIT, 4) }\n case 100000000000000000000000 { result := mul(uUNIT, 5) }\n case 1000000000000000000000000 { result := mul(uUNIT, 6) }\n case 10000000000000000000000000 { result := mul(uUNIT, 7) }\n case 100000000000000000000000000 { result := mul(uUNIT, 8) }\n case 1000000000000000000000000000 { result := mul(uUNIT, 9) }\n case 10000000000000000000000000000 { result := mul(uUNIT, 10) }\n case 100000000000000000000000000000 { result := mul(uUNIT, 11) }\n case 1000000000000000000000000000000 { result := mul(uUNIT, 12) }\n case 10000000000000000000000000000000 { result := mul(uUNIT, 13) }\n case 100000000000000000000000000000000 { result := mul(uUNIT, 14) }\n case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) }\n case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) }\n case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) }\n case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) }\n case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) }\n case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) }\n case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) }\n case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) }\n case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) }\n case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) }\n case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) }\n case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) }\n case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) }\n case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) }\n case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) }\n case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) }\n case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) }\n case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) }\n case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) }\n case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) }\n case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) }\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) }\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) }\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) }\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) }\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) }\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) }\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) }\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) }\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) }\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) }\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) }\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) }\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) }\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) }\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) }\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) }\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) }\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) }\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) }\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) }\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) }\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) }\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) }\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 59) }\n default { result := uMAX_UD60x18 }\n }\n\n if (result.unwrap() == uMAX_UD60x18) {\n unchecked {\n // Inline the fixed-point division to save gas.\n result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10);\n }\n }\n}\n\n/// @notice Calculates the binary logarithm of x using the iterative approximation algorithm:\n///\n/// $$\n/// log_2{x} = n + log_2{y}, \\text{ where } y = x*2^{-n}, \\ y \\in [1, 2)\n/// $$\n///\n/// For $0 \\leq x \\lt 1$, the input is inverted:\n///\n/// $$\n/// log_2{x} = -log_2{\\frac{1}{x}}\n/// $$\n///\n/// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\n///\n/// Notes:\n/// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal.\n///\n/// Requirements:\n/// - x \u2265 UNIT\n///\n/// @param x The UD60x18 number for which to calculate the binary logarithm.\n/// @return result The binary logarithm as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction log2(UD60x18 x) pure returns (UD60x18 result) {\n uint256 xUint = x.unwrap();\n\n if (xUint < uUNIT) {\n revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x);\n }\n\n unchecked {\n // Calculate the integer part of the logarithm.\n uint256 n = Common.msb(xUint / uUNIT);\n\n // This is the integer part of the logarithm as a UD60x18 number. The operation can't overflow because\n // n is at most 255 and UNIT is 1e18.\n uint256 resultUint = n * uUNIT;\n\n // Calculate $y = x * 2^{-n}$.\n uint256 y = xUint >> n;\n\n // If y is the unit number, the fractional part is zero.\n if (y == uUNIT) {\n return wrap(resultUint);\n }\n\n // Calculate the fractional part via the iterative approximation.\n // The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient.\n uint256 doubleUnit = 2e18;\n for (uint256 delta = uHALF_UNIT; delta > 0; delta >>= 1) {\n y = (y * y) / uUNIT;\n\n // Is y^2 >= 2e18 and so in the range [2e18, 4e18)?\n if (y >= doubleUnit) {\n // Add the 2^{-m} factor to the logarithm.\n resultUint += delta;\n\n // Halve y, which corresponds to z/2 in the Wikipedia article.\n y >>= 1;\n }\n }\n result = wrap(resultUint);\n }\n}\n\n/// @notice Multiplies two UD60x18 numbers together, returning a new UD60x18 number.\n///\n/// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv}.\n///\n/// Requirements:\n/// - Refer to the requirements in {Common.mulDiv}.\n///\n/// @dev See the documentation in {Common.mulDiv18}.\n/// @param x The multiplicand as a UD60x18 number.\n/// @param y The multiplier as a UD60x18 number.\n/// @return result The product as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction mul(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n result = wrap(Common.mulDiv18(x.unwrap(), y.unwrap()));\n}\n\n/// @notice Raises x to the power of y.\n///\n/// For $1 \\leq x \\leq \\infty$, the following standard formula is used:\n///\n/// $$\n/// x^y = 2^{log_2{x} * y}\n/// $$\n///\n/// For $0 \\leq x \\lt 1$, since the unsigned {log2} is undefined, an equivalent formula is used:\n///\n/// $$\n/// i = \\frac{1}{x}\n/// w = 2^{log_2{i} * y}\n/// x^y = \\frac{1}{w}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2} and {mul}.\n/// - Returns `UNIT` for 0^0.\n/// - It may not perform well with very small values of x. Consider using SD59x18 as an alternative.\n///\n/// Requirements:\n/// - Refer to the requirements in {exp2}, {log2}, and {mul}.\n///\n/// @param x The base as a UD60x18 number.\n/// @param y The exponent as a UD60x18 number.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction pow(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n uint256 xUint = x.unwrap();\n uint256 yUint = y.unwrap();\n\n // If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero.\n if (xUint == 0) {\n return yUint == 0 ? UNIT : ZERO;\n }\n // If x is `UNIT`, the result is always `UNIT`.\n else if (xUint == uUNIT) {\n return UNIT;\n }\n\n // If y is zero, the result is always `UNIT`.\n if (yUint == 0) {\n return UNIT;\n }\n // If y is `UNIT`, the result is always x.\n else if (yUint == uUNIT) {\n return x;\n }\n\n // If x is > UNIT, use the standard formula.\n if (xUint > uUNIT) {\n result = exp2(mul(log2(x), y));\n }\n // Conversely, if x < UNIT, use the equivalent formula.\n else {\n UD60x18 i = wrap(uUNIT_SQUARED / xUint);\n UD60x18 w = exp2(mul(log2(i), y));\n result = wrap(uUNIT_SQUARED / w.unwrap());\n }\n}\n\n/// @notice Raises x (a UD60x18 number) to the power y (an unsigned basic integer) using the well-known\n/// algorithm \"exponentiation by squaring\".\n///\n/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv18}.\n/// - Returns `UNIT` for 0^0.\n///\n/// Requirements:\n/// - The result must fit in UD60x18.\n///\n/// @param x The base as a UD60x18 number.\n/// @param y The exponent as a uint256.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction powu(UD60x18 x, uint256 y) pure returns (UD60x18 result) {\n // Calculate the first iteration of the loop in advance.\n uint256 xUint = x.unwrap();\n uint256 resultUint = y & 1 > 0 ? xUint : uUNIT;\n\n // Equivalent to `for(y /= 2; y > 0; y /= 2)`.\n for (y >>= 1; y > 0; y >>= 1) {\n xUint = Common.mulDiv18(xUint, xUint);\n\n // Equivalent to `y % 2 == 1`.\n if (y & 1 > 0) {\n resultUint = Common.mulDiv18(resultUint, xUint);\n }\n }\n result = wrap(resultUint);\n}\n\n/// @notice Calculates the square root of x using the Babylonian method.\n///\n/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n///\n/// Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x \u2264 MAX_UD60x18 / UNIT\n///\n/// @param x The UD60x18 number for which to calculate the square root.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction sqrt(UD60x18 x) pure returns (UD60x18 result) {\n uint256 xUint = x.unwrap();\n\n unchecked {\n if (xUint > uMAX_UD60x18 / uUNIT) {\n revert Errors.PRBMath_UD60x18_Sqrt_Overflow(x);\n }\n // Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two UD60x18 numbers.\n // In this case, the two numbers are both the square root.\n result = wrap(Common.sqrt(xUint * uUNIT));\n }\n}\n", + "npm/@prb/math@4.1.1/src/ud60x18/ValueType.sol": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\nimport \"./Helpers.sol\" as Helpers;\nimport \"./Math.sol\" as Math;\n\n/// @notice The unsigned 60.18-decimal fixed-point number representation, which can have up to 60 digits and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the Solidity type uint256.\n/// @dev The value type is defined here so it can be imported in all other files.\ntype UD60x18 is uint256;\n\n/*//////////////////////////////////////////////////////////////////////////\n CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n Casting.intoSD1x18,\n Casting.intoSD21x18,\n Casting.intoSD59x18,\n Casting.intoUD2x18,\n Casting.intoUD21x18,\n Casting.intoUint128,\n Casting.intoUint256,\n Casting.intoUint40,\n Casting.unwrap\n} for UD60x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n MATHEMATICAL FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\n// The global \"using for\" directive makes the functions in this library callable on the UD60x18 type.\nusing {\n Math.avg,\n Math.ceil,\n Math.div,\n Math.exp,\n Math.exp2,\n Math.floor,\n Math.frac,\n Math.gm,\n Math.inv,\n Math.ln,\n Math.log10,\n Math.log2,\n Math.mul,\n Math.pow,\n Math.powu,\n Math.sqrt\n} for UD60x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n HELPER FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\n// The global \"using for\" directive makes the functions in this library callable on the UD60x18 type.\nusing {\n Helpers.add,\n Helpers.and,\n Helpers.eq,\n Helpers.gt,\n Helpers.gte,\n Helpers.isZero,\n Helpers.lshift,\n Helpers.lt,\n Helpers.lte,\n Helpers.mod,\n Helpers.neq,\n Helpers.not,\n Helpers.or,\n Helpers.rshift,\n Helpers.sub,\n Helpers.uncheckedAdd,\n Helpers.uncheckedSub,\n Helpers.xor\n} for UD60x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n OPERATORS\n//////////////////////////////////////////////////////////////////////////*/\n\n// The global \"using for\" directive makes it possible to use these operators on the UD60x18 type.\nusing {\n Helpers.add as +,\n Helpers.and2 as &,\n Math.div as /,\n Helpers.eq as ==,\n Helpers.gt as >,\n Helpers.gte as >=,\n Helpers.lt as <,\n Helpers.lte as <=,\n Helpers.or as |,\n Helpers.mod as %,\n Math.mul as *,\n Helpers.neq as !=,\n Helpers.not as ~,\n Helpers.sub as -,\n Helpers.xor as ^\n} for UD60x18 global;\n", + "project/contracts/ERC7540Upgradeable.sol": "// SPDX-License-Identifier: BUSL-1.1\n// Compatible with OpenZeppelin Contracts ^5.0.0\npragma solidity ^0.8.27;\n\nimport {IERC165} from \"@openzeppelin/contracts/interfaces/IERC165.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {ContextUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\nimport {ERC165Upgradeable} from \"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol\";\nimport {IERC7540Deposit, IERC7540Redeem, IERC7540Operator} from \"./interfaces/IERC7540.sol\";\nimport {IShare} from \"./interfaces/IShare.sol\";\nimport {ERC7575Upgradeable} from \"./ERC7575Upgradeable.sol\";\n\n/**\n * @dev Implementation of the ERC-7540 \"Asynchronous ERC-4626 Tokenized Vaults\" as defined in\n * https://eips.ethereum.org/EIPS/eip-7540[ERC-7540].\n */\nabstract contract ERC7540Upgradeable is\n Initializable,\n ContextUpgradeable,\n ERC165Upgradeable,\n ERC7575Upgradeable,\n IERC7540Deposit,\n IERC7540Redeem,\n IERC7540Operator\n{\n using Math for uint256;\n\n struct Claimable {\n uint256 assets;\n uint256 shares;\n }\n\n /// @custom:storage-location erc7201:sivo.storage.ERC7540\n struct ERC7540Storage {\n mapping(address controller => mapping(address operator => bool)) _isOperator;\n mapping(address => uint256) _pendingDeposit;\n uint256 _totalPendingDeposit;\n mapping(address => Claimable) _claimableDeposit;\n Claimable _totalClaimableDeposit;\n mapping(address => uint256) _pendingRedeem;\n uint256 _totalPendingRedeem;\n mapping(address => Claimable) _claimableRedeem;\n Claimable _totalClaimableRedeem;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"sivo.storage.ERC7540\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant ERC7540StorageLocation =\n 0xf5d2f41a999c1144bf8aecf5f175bd2b2374bdc6361a14b1c4bce35d5759aa00;\n\n function _getERC7540Storage()\n private\n pure\n returns (ERC7540Storage storage $)\n {\n assembly {\n $.slot := ERC7540StorageLocation\n }\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(\n bytes4 interfaceId\n )\n public\n view\n virtual\n override(ERC165Upgradeable, ERC7575Upgradeable)\n returns (bool)\n {\n return\n interfaceId == type(IERC7540Deposit).interfaceId ||\n interfaceId == type(IERC7540Redeem).interfaceId ||\n interfaceId == type(IERC7540Operator).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n function isOperator(\n address controller,\n address operator\n ) external view returns (bool status) {\n ERC7540Storage storage $ = _getERC7540Storage();\n return $._isOperator[controller][operator];\n }\n\n function setOperator(\n address operator,\n bool approved\n ) external returns (bool success) {\n ERC7540Storage storage $ = _getERC7540Storage();\n $._isOperator[_msgSender()][operator] = approved;\n emit OperatorSet(_msgSender(), operator, approved);\n return true;\n }\n\n modifier onlyOperator(address subject) {\n _checkOperator(subject);\n _;\n }\n\n function _checkOperator(address subject) internal view virtual {\n if (subject == _msgSender()) return;\n ERC7540Storage storage $ = _getERC7540Storage();\n if ($._isOperator[subject][_msgSender()]) return;\n revert ERC7540UnauthorizedSender(_msgSender(), subject);\n }\n\n function requestDeposit(\n uint256 assets,\n address controller,\n address owner\n ) external onlyOperator(owner) returns (uint256 requestId) {\n requestId = 0;\n ERC7540Storage storage $ = _getERC7540Storage();\n SafeERC20.safeTransferFrom(_asset(), owner, address(this), assets);\n $._pendingDeposit[controller] += assets;\n $._totalPendingDeposit += assets;\n emit DepositRequest(controller, owner, requestId, _msgSender(), assets);\n }\n\n function cancelDeposit(\n uint256 assets,\n address receiver,\n address controller\n ) external onlyOperator(controller) {\n ERC7540Storage storage $ = _getERC7540Storage();\n $._pendingDeposit[controller] -= assets;\n $._totalPendingDeposit -= assets;\n SafeERC20.safeTransfer(_asset(), receiver, assets);\n emit DepositCancel(controller, receiver, _msgSender(), assets);\n }\n\n function pendingDepositRequest(\n uint256 requestId,\n address controller\n ) external view returns (uint256 assets) {\n if (requestId != 0) return 0;\n ERC7540Storage storage $ = _getERC7540Storage();\n return $._pendingDeposit[controller];\n }\n\n function _claimableDeposit(\n uint256 assets,\n address controller\n ) internal returns (uint256 shares) {\n ERC7540Storage storage $ = _getERC7540Storage();\n $._pendingDeposit[controller] -= assets;\n $._totalPendingDeposit -= assets;\n shares = previewDeposit(assets);\n _share().mint(address(this), shares, assets);\n $._claimableDeposit[controller].assets += assets;\n $._totalClaimableDeposit.assets += assets;\n $._claimableDeposit[controller].shares += shares;\n $._totalClaimableDeposit.shares += shares;\n emit DepositClaimable(controller, assets, shares);\n }\n\n function claimableDepositRequest(\n uint256 requestId,\n address controller\n ) external view returns (uint256 assets) {\n if (requestId != 0) return 0;\n ERC7540Storage storage $ = _getERC7540Storage();\n return $._claimableDeposit[controller].assets;\n }\n\n function deposit(\n uint256 assets,\n address receiver,\n address controller\n ) external onlyOperator(controller) returns (uint256 shares) {\n ERC7540Storage storage $ = _getERC7540Storage();\n Claimable storage $$ = $._claimableDeposit[controller];\n shares = $$.shares.mulDiv(assets, $$.assets);\n $$.assets -= assets;\n $._totalClaimableDeposit.assets -= assets;\n $$.shares -= shares;\n $._totalClaimableDeposit.shares -= shares;\n _share().transfer(receiver, shares);\n emit Deposit(controller, receiver, assets, shares);\n }\n\n function mint(\n uint256 shares,\n address receiver,\n address controller\n ) external onlyOperator(controller) returns (uint256 assets) {\n ERC7540Storage storage $ = _getERC7540Storage();\n Claimable storage $$ = $._claimableDeposit[controller];\n assets = $$.assets.mulDiv(shares, $$.shares);\n $$.shares -= shares;\n $._totalClaimableDeposit.shares -= shares;\n $$.assets -= assets;\n $._totalClaimableDeposit.assets -= assets;\n _share().transfer(receiver, shares);\n emit Deposit(controller, receiver, assets, shares);\n }\n\n function requestRedeem(\n uint256 shares,\n address controller,\n address owner\n ) external onlyOperator(owner) returns (uint256 requestId) {\n requestId = 0;\n ERC7540Storage storage $ = _getERC7540Storage();\n _share().transferFrom(owner, address(this), shares);\n $._pendingRedeem[controller] += shares;\n $._totalPendingRedeem += shares;\n emit RedeemRequest(controller, owner, requestId, _msgSender(), shares);\n }\n\n function cancelRedeem(\n uint256 shares,\n address receiver,\n address controller\n ) external onlyOperator(controller) {\n ERC7540Storage storage $ = _getERC7540Storage();\n $._pendingRedeem[controller] -= shares;\n $._totalPendingRedeem -= shares;\n _share().transfer(receiver, shares);\n emit RedeemCancel(controller, receiver, _msgSender(), shares);\n }\n\n function pendingRedeemRequest(\n uint256 requestId,\n address controller\n ) external view returns (uint256 shares) {\n if (requestId != 0) return 0;\n ERC7540Storage storage $ = _getERC7540Storage();\n return $._pendingRedeem[controller];\n }\n\n function _claimableRedeem(\n uint256 shares,\n address controller\n ) internal returns (uint256 assets) {\n ERC7540Storage storage $ = _getERC7540Storage();\n $._pendingRedeem[controller] -= shares;\n $._totalPendingRedeem -= shares;\n assets = previewRedeem(shares);\n _share().burn(address(this), shares, assets);\n $._claimableRedeem[controller].assets += assets;\n $._totalClaimableRedeem.assets += assets;\n $._claimableRedeem[controller].shares += shares;\n $._totalClaimableRedeem.shares += shares;\n emit RedeemClaimable(controller, assets, shares);\n }\n\n function claimableRedeemRequest(\n uint256 requestId,\n address controller\n ) external view returns (uint256 shares) {\n if (requestId != 0) return 0;\n ERC7540Storage storage $ = _getERC7540Storage();\n return $._claimableRedeem[controller].shares;\n }\n\n function withdraw(\n uint256 assets,\n address receiver,\n address controller\n )\n public\n virtual\n override\n onlyOperator(controller)\n returns (uint256 shares)\n {\n ERC7540Storage storage $ = _getERC7540Storage();\n Claimable storage $$ = $._claimableRedeem[controller];\n if ($$.assets == 0) return super.withdraw(assets, receiver, controller);\n shares = $$.shares.mulDiv(assets, $$.assets);\n $$.assets -= assets;\n $._totalClaimableRedeem.assets -= assets;\n $$.shares -= shares;\n $._totalClaimableRedeem.shares -= shares;\n SafeERC20.safeTransfer(_asset(), receiver, assets);\n emit Withdraw(_msgSender(), receiver, controller, assets, shares);\n }\n\n function redeem(\n uint256 shares,\n address receiver,\n address controller\n )\n public\n virtual\n override\n onlyOperator(controller)\n returns (uint256 assets)\n {\n ERC7540Storage storage $ = _getERC7540Storage();\n Claimable storage $$ = $._claimableRedeem[controller];\n if ($$.shares == 0) return super.redeem(shares, receiver, controller);\n assets = $$.assets.mulDiv(shares, $$.shares);\n $$.shares -= shares;\n $._totalClaimableRedeem.shares -= shares;\n $$.assets -= assets;\n $._totalClaimableRedeem.assets -= assets;\n SafeERC20.safeTransfer(_asset(), receiver, assets);\n emit Withdraw(_msgSender(), receiver, controller, assets, shares);\n }\n}\n", + "project/contracts/ERC7575Store.sol": "// SPDX-License-Identifier: BUSL-1.1\n// Compatible with OpenZeppelin Contracts ^5.0.0\npragma solidity ^0.8.27;\n\nimport {IERC20Metadata as IERC20} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\n/// @custom:security-contact security@sivo.com\ncontract ERC7575Store is Initializable {\n error ERC7575AssetDecimalsExceedsShareDecimals(\n uint8 assetDecimals,\n uint8 shareDecimals\n );\n\n /// @custom:storage-location erc7201:sivo.storage.ERC7575\n struct ERC7575Storage {\n address _share;\n address _asset;\n uint8 _assetDecimals;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"sivo.storage.ERC7575\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant ERC7575StorageLocation =\n 0xded009ad9b938d1a1baff1d97e239efee9c206ea56ae29f5a0cade6f16ce7500;\n\n function _getERC7575Storage()\n internal\n pure\n returns (ERC7575Storage storage $)\n {\n assembly {\n $.slot := ERC7575StorageLocation\n }\n }\n\n /**\n * @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC-20 or ERC-777).\n */\n function __ERC7575_init(\n address asset_,\n address share_\n ) internal onlyInitializing {\n __ERC7575_init_unchained(asset_, share_);\n }\n\n function __ERC7575_init_unchained(\n address asset_,\n address share_\n ) internal onlyInitializing {\n ERC7575Storage storage $ = _getERC7575Storage();\n $._asset = asset_;\n $._share = share_;\n (bool success, uint8 assetDecimals) = _tryGetAssetDecimals(\n IERC20(asset_)\n );\n $._assetDecimals = success ? assetDecimals : 18;\n if ($._assetDecimals > IERC20(share_).decimals()) {\n revert ERC7575AssetDecimalsExceedsShareDecimals(\n $._assetDecimals,\n IERC20(share_).decimals()\n );\n }\n }\n\n /**\n * @dev Attempts to fetch the asset decimals. A return value of false indicates that the attempt failed in some way.\n */\n function _tryGetAssetDecimals(\n IERC20 asset_\n ) private view returns (bool ok, uint8 assetDecimals) {\n (bool success, bytes memory encodedDecimals) = address(asset_)\n .staticcall(abi.encodeCall(IERC20.decimals, ()));\n if (success && encodedDecimals.length >= 32) {\n uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256));\n if (returnedDecimals <= type(uint8).max) {\n return (true, uint8(returnedDecimals));\n }\n }\n return (false, 0);\n }\n}\n", + "project/contracts/ERC7575Upgradeable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/extensions/ERC7575.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"@openzeppelin/contracts/interfaces/IERC165.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {ContextUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\nimport {ERC165Upgradeable} from \"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol\";\nimport {IERC7575} from \"./interfaces/IERC7575.sol\";\nimport {IShare} from \"./interfaces/IShare.sol\";\nimport {ERC7575Store} from \"./ERC7575Store.sol\";\n\n/**\n * @dev Implementation of the ERC-7575 \"Multi-Asset Tokenized Vault Standard\" as defined in\n * https://eips.ethereum.org/EIPS/eip-7575[ERC-7575].\n * @dev From @openzeppelin/contracts-upgradeable/ERC4626Upgradeable.sol, minus ERC-20\n */\nabstract contract ERC7575Upgradeable is\n ContextUpgradeable,\n ERC165Upgradeable,\n ERC7575Store,\n IERC7575\n{\n using Math for uint256;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(\n bytes4 interfaceId\n ) public view virtual override(ERC165Upgradeable, IERC165) returns (bool) {\n return\n interfaceId == type(IERC7575).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n function _share() internal view virtual returns (IShare) {\n ERC7575Storage storage $ = _getERC7575Storage();\n return IShare($._share);\n }\n\n function _asset() internal view virtual returns (IERC20) {\n ERC7575Storage storage $ = _getERC7575Storage();\n return IERC20($._asset);\n }\n\n /** @dev See {IERC7575-share}. */\n function share() public view virtual returns (address) {\n ERC7575Storage storage $ = _getERC7575Storage();\n return address($._share);\n }\n\n /** @dev See {IERC7575-asset}. */\n function asset() public view virtual returns (address) {\n ERC7575Storage storage $ = _getERC7575Storage();\n return address($._asset);\n }\n\n /** @dev See {IERC7575-totalAssets}. */\n function totalAssets() public view virtual returns (uint256) {\n IShare share_ = _share();\n return share_.assetTotalDeployed() + share_.assetTotalIdle();\n }\n\n /** @dev See {IERC7575-convertToShares}. */\n function convertToShares(\n uint256 assets\n ) public view virtual returns (uint256) {\n return _convertToShares(assets, Math.Rounding.Floor);\n }\n\n /** @dev See {IERC7575-convertToAssets}. */\n function convertToAssets(\n uint256 shares\n ) public view virtual returns (uint256) {\n return _convertToAssets(shares, Math.Rounding.Floor);\n }\n\n /** @dev See {IERC7575-maxDeposit}. */\n function maxDeposit(address) public view virtual returns (uint256) {\n return type(uint256).max;\n }\n\n /** @dev See {IERC7575-maxMint}. */\n function maxMint(address) public view virtual returns (uint256) {\n return type(uint256).max;\n }\n\n /** @dev See {IERC7575-maxWithdraw}. */\n function maxWithdraw(address owner) public view virtual returns (uint256) {\n return _convertToAssets(_share().balanceOf(owner), Math.Rounding.Floor);\n }\n\n /** @dev See {IERC7575-maxRedeem}. */\n function maxRedeem(address owner) public view virtual returns (uint256) {\n return _share().balanceOf(owner);\n }\n\n /** @dev See {IERC7575-previewDeposit}. */\n function previewDeposit(\n uint256 assets\n ) public view virtual returns (uint256) {\n return _convertToShares(assets, Math.Rounding.Floor);\n }\n\n /** @dev See {IERC7575-previewMint}. */\n function previewMint(uint256 shares) public view virtual returns (uint256) {\n return _convertToAssets(shares, Math.Rounding.Ceil);\n }\n\n /** @dev See {IERC7575-previewWithdraw}. */\n function previewWithdraw(\n uint256 assets\n ) public view virtual returns (uint256) {\n return _convertToShares(assets, Math.Rounding.Ceil);\n }\n\n /** @dev See {IERC7575-previewRedeem}. */\n function previewRedeem(\n uint256 shares\n ) public view virtual returns (uint256) {\n return _convertToAssets(shares, Math.Rounding.Floor);\n }\n\n /** @dev See {IERC7575-deposit}. */\n function deposit(\n uint256 assets,\n address receiver\n ) public virtual returns (uint256) {\n uint256 maxAssets = maxDeposit(receiver);\n if (assets > maxAssets) {\n revert ERC7575ExceededMaxDeposit(receiver, assets, maxAssets);\n }\n\n uint256 shares = previewDeposit(assets);\n _deposit(_msgSender(), receiver, assets, shares);\n\n return shares;\n }\n\n /** @dev See {IERC7575-mint}. */\n function mint(\n uint256 shares,\n address receiver\n ) public virtual returns (uint256) {\n uint256 maxShares = maxMint(receiver);\n if (shares > maxShares) {\n revert ERC7575ExceededMaxMint(receiver, shares, maxShares);\n }\n\n uint256 assets = previewMint(shares);\n _deposit(_msgSender(), receiver, assets, shares);\n\n return assets;\n }\n\n /** @dev See {IERC7575-withdraw}. */\n function withdraw(\n uint256 assets,\n address receiver,\n address owner\n ) public virtual returns (uint256) {\n uint256 maxAssets = maxWithdraw(owner);\n if (assets > maxAssets) {\n revert ERC7575ExceededMaxWithdraw(owner, assets, maxAssets);\n }\n\n uint256 shares = previewWithdraw(assets);\n _withdraw(_msgSender(), receiver, owner, assets, shares);\n\n return shares;\n }\n\n /** @dev See {IERC7575-redeem}. */\n function redeem(\n uint256 shares,\n address receiver,\n address owner\n ) public virtual returns (uint256) {\n uint256 maxShares = maxRedeem(owner);\n if (shares > maxShares) {\n revert ERC7575ExceededMaxRedeem(owner, shares, maxShares);\n }\n\n uint256 assets = previewRedeem(shares);\n _withdraw(_msgSender(), receiver, owner, assets, shares);\n\n return assets;\n }\n\n /**\n * @dev Internal conversion function (from assets to shares) with support for rounding direction.\n */\n function _convertToShares(\n uint256 assets,\n Math.Rounding rounding\n ) internal view virtual returns (uint256) {\n return\n assets.mulDiv(\n _share().totalSupply() + 10 ** _decimalsOffset(),\n totalAssets() + 1,\n rounding\n );\n }\n\n /**\n * @dev Internal conversion function (from shares to assets) with support for rounding direction.\n */\n function _convertToAssets(\n uint256 shares,\n Math.Rounding rounding\n ) internal view virtual returns (uint256) {\n return\n shares.mulDiv(\n totalAssets() + 1,\n _share().totalSupply() + 10 ** _decimalsOffset(),\n rounding\n );\n }\n\n /**\n * @dev Deposit/mint common workflow.\n */\n function _deposit(\n address caller,\n address receiver,\n uint256 assets,\n uint256 shares\n ) internal virtual {\n // If asset() is ERC-777, `transferFrom` can trigger a reentrancy BEFORE the transfer happens through the\n // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer,\n // calls the vault, which is assumed not malicious.\n //\n // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the\n // assets are transferred and before the shares are minted, which is a valid state.\n // slither-disable-next-line reentrancy-no-eth\n SafeERC20.safeTransferFrom(_asset(), caller, address(this), assets);\n _share().mint(receiver, shares, assets);\n\n emit Deposit(caller, receiver, assets, shares);\n }\n\n /**\n * @dev Withdraw/redeem common workflow.\n */\n function _withdraw(\n address caller,\n address receiver,\n address owner,\n uint256 assets,\n uint256 shares\n ) internal virtual {\n IShare share_ = _share();\n if (caller != owner) {\n share_.spendAllowance(owner, caller, shares);\n }\n\n // If asset() is ERC-777, `transfer` can trigger a reentrancy AFTER the transfer happens through the\n // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer,\n // calls the vault, which is assumed not malicious.\n //\n // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the\n // shares are burned and after the assets are transferred, which is a valid state.\n share_.burn(owner, shares, assets);\n SafeERC20.safeTransfer(_asset(), receiver, assets);\n\n emit Withdraw(caller, receiver, owner, assets, shares);\n }\n\n function _decimalsOffset() internal view virtual returns (uint8) {\n ERC7575Storage storage $ = _getERC7575Storage();\n return IShare($._share).decimals() - $._assetDecimals;\n }\n}\n", + "project/contracts/Helper.sol": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.24;\nimport {UD60x18, exp as exp_} from \"@prb/math/src/UD60x18.sol\";\n\nlibrary Helper {\n uint64 internal constant Precision = 1e18;\n uint64 internal constant SecondsPerYear = 31_536_000; // 365 * 24 * 60 * 60\n uint64 internal constant FactorScale = 1e18;\n\n function exp(uint x_) internal pure returns (uint) {\n UD60x18 x = UD60x18.wrap(x_);\n UD60x18 result = exp_(x);\n return UD60x18.unwrap(result);\n }\n}\n", + "project/contracts/Vault.sol": "// SPDX-License-Identifier: BUSL-1.1\n// Compatible with OpenZeppelin Contracts ^5.0.0\npragma solidity ^0.8.27;\n\nimport {AggregatorV3Interface} from \"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol\";\nimport {IERC20Metadata as IERC20} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport {ReentrancyGuardTransient} from \"@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {ERC7540Upgradeable} from \"./ERC7540Upgradeable.sol\";\nimport {ERC7575Upgradeable} from \"./ERC7575Upgradeable.sol\";\nimport {Helper} from \"./Helper.sol\";\nimport {IERC7575} from \"./interfaces/IERC7575.sol\";\nimport {IShare} from \"./interfaces/IShare.sol\";\nimport {IVault} from \"./interfaces/IVault.sol\";\nimport {VaultOptions} from \"./VaultOptions.sol\";\n\n/// @title Vault Contract\n/// @notice This contract manages the tokenization of receivables. As receivables become available the can be purchased with a stablecoin like USDC, USDT, EURC, etc. The contract is [ERC-4626](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) compliant. The `asset()` function returns the asset contract address. The contract also handles redemption of receivable tokens (a.k.a. sTokens depending on the asset: sivoUSDC, sivoUSDT, sEURC, etc.). Pricing increases dynamically based on the amount of receivables that are sold.\n/// @notice Deployed contract addresses:\n/// | Chain Type | Name | ID | Contract Address |\n/// | ------------ | ---------- | -------- | ---------------- |\n/// | Mainnet | Base | 8453 | [0x63001191a63B9458D3Eafe7Ad704042B1Ae9C60B](https://basescan.org/token/0x63001191a63B9458D3Eafe7Ad704042B1Ae9C60B) |\n/// | Testnet | Base Sepolia | 84532 | [0xc8Bc7A069493fFb1953a6bf17B26c670CCEC54b6](https://sepolia.basescan.org/token/0xc8Bc7A069493fFb1953a6bf17B26c670CCEC54b6) |\n/// @custom:security-contact security@sivo.com\ncontract Vault is\n Initializable,\n ERC7540Upgradeable,\n IVault,\n OwnableUpgradeable,\n PausableUpgradeable,\n ReentrancyGuardTransient,\n UUPSUpgradeable,\n VaultOptions\n{\n error VaultPriceOutOfRange(int256 price, int256 priceMin, int256 priceMax);\n error VaultOracleStale(uint256 updatedAt, uint256 maxStaleness);\n error VaultInvalidPriceRange(int256 priceMin, int256 priceMax);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n function initialize(Options memory options) public initializer {\n __ERC7575_init(options.asset, options.share);\n __Ownable_init(options.owner);\n __VaultOptions_init(\n options.oracle,\n options.price_min,\n options.price_max,\n options.max_staleness\n );\n }\n\n function _requireNotPaused() internal view virtual override {\n super._requireNotPaused();\n _requirePriceInRange();\n }\n\n function _requirePriceInRange() internal view {\n VaultOptionsStorage storage $ = _getVaultOptionsStorage();\n address oracle = $._oracle;\n if (oracle == address(0)) return;\n (, int256 price, , uint256 updatedAt, ) = AggregatorV3Interface(oracle)\n .latestRoundData();\n uint256 maxStaleness_ = $._maxStaleness;\n if (maxStaleness_ > 0 && block.timestamp - updatedAt > maxStaleness_) {\n revert VaultOracleStale(updatedAt, maxStaleness_);\n }\n if (price < $._priceMin || price > $._priceMax) {\n revert VaultPriceOutOfRange(price, $._priceMin, $._priceMax);\n }\n }\n\n /// @notice Updates the Chainlink oracle address and staleness duration\n /// @dev Can only be called by the contract owner\n /// @dev Set maxStaleness_ to 0 to disable staleness check\n /// @param oracle_ The new Chainlink oracle address\n /// @param maxStaleness_ The new maximum staleness in seconds\n function setOracle(\n address oracle_,\n uint256 maxStaleness_\n ) external onlyOwner {\n VaultOptionsStorage storage $ = _getVaultOptionsStorage();\n $._oracle = oracle_;\n $._maxStaleness = maxStaleness_;\n }\n\n /// @notice Updates the acceptable price range\n /// @dev Can only be called by the contract owner\n /// @param priceMin_ The new minimum acceptable price\n /// @param priceMax_ The new maximum acceptable price\n function setPriceRange(\n int256 priceMin_,\n int256 priceMax_\n ) external onlyOwner {\n if (priceMin_ > priceMax_) {\n revert VaultInvalidPriceRange(priceMin_, priceMax_);\n }\n VaultOptionsStorage storage $ = _getVaultOptionsStorage();\n $._priceMin = priceMin_;\n $._priceMax = priceMax_;\n }\n\n function _authorizeUpgrade(\n address newImplementation\n ) internal override onlyOwner {}\n\n /// @notice Pauses the contract, preventing deposits and withdrawals\n /// @dev Can only be called by the contract owner\n /// @dev When paused, the deposit and withdraw functions will revert\n function pause() external onlyOwner {\n _pause();\n }\n\n /// @notice Unpauses the contract, allowing deposits and withdrawals\n /// @dev Can only be called by the contract owner\n /// @dev Re-enables deposit and withdraw functionality after a pause\n function unpause() external onlyOwner {\n _unpause();\n }\n\n function _assetTotalInVault() internal view returns (uint) {\n return IERC20(asset()).balanceOf(address(this));\n }\n\n function _shareTotalInVault() internal view returns (uint) {\n return convertToShares(_assetTotalInVault());\n }\n\n /// @inheritdoc IERC7575\n function maxDeposit(\n address\n ) public view override(ERC7575Upgradeable, IERC7575) returns (uint256) {\n uint assetTotalDeployed_ = _share().assetTotalDeployed();\n uint assetTotalIdle_ = _share().assetTotalIdle();\n uint assetTotal_ = assetTotalDeployed_ + assetTotalIdle_;\n if (assetTotal_ == 0) return type(uint).max;\n uint minDeployedFactor = Helper.FactorScale - _share().maxIdleFactor();\n if (minDeployedFactor == 0) return type(uint).max;\n uint maxTotalAssets = Math.mulDiv(\n assetTotalDeployed_,\n Helper.FactorScale,\n minDeployedFactor\n );\n return assetTotal_ > maxTotalAssets ? 0 : maxTotalAssets - assetTotal_;\n }\n\n /// @inheritdoc IERC7575\n function maxMint(\n address receiver\n ) public view override(ERC7575Upgradeable, IERC7575) returns (uint256) {\n return convertToShares(maxDeposit(receiver));\n }\n\n /// @inheritdoc IERC7575\n function deposit(\n uint256 assets,\n address receiver\n )\n public\n override(ERC7575Upgradeable, IERC7575)\n nonReentrant\n whenNotPaused\n returns (uint256)\n {\n _share().accrue();\n if (assets == type(uint).max) assets = maxDeposit(receiver);\n return super.deposit(assets, receiver);\n }\n\n /// @inheritdoc IERC7575\n function mint(\n uint256 shares,\n address receiver\n )\n public\n override(ERC7575Upgradeable, IERC7575)\n nonReentrant\n whenNotPaused\n returns (uint256)\n {\n _share().accrue();\n if (shares == type(uint).max) shares = maxMint(receiver);\n return super.mint(shares, receiver);\n }\n\n /// @inheritdoc IERC7575\n function withdraw(\n uint256 assets,\n address receiver,\n address owner\n )\n public\n override(ERC7540Upgradeable, IERC7575)\n nonReentrant\n whenNotPaused\n returns (uint256)\n {\n _share().accrue();\n if (assets == type(uint).max)\n assets = Math.min(maxWithdraw(owner), _assetTotalInVault());\n return super.withdraw(assets, receiver, owner);\n }\n\n /// @inheritdoc IERC7575\n function redeem(\n uint256 shares,\n address receiver,\n address owner\n )\n public\n override(ERC7540Upgradeable, IERC7575)\n nonReentrant\n whenNotPaused\n returns (uint256)\n {\n _share().accrue();\n if (shares == type(uint).max)\n shares = Math.min(maxRedeem(owner), _shareTotalInVault());\n return super.redeem(shares, receiver, owner);\n }\n\n /// @notice Deploys assets from vault to RWA\n /// @dev Can only be called by the contract owner\n /// @dev Transfers assets from contract to owner and increases the assetTotalInRwa\n /// @dev Emits a ShareDeployAsset event after the transfer is complete\n /// @param assets Assets to transfer, or max uint to transfer all available\n /// @param data Additional data associated with deployment\n /// @return The amount of assets transferred\n /// @custom:error ShareDeployAsset Thrown if trying to transfer more than available\n function deploy(\n uint assets,\n bytes calldata data\n ) external nonReentrant onlyOwner returns (uint) {\n _share().accrue();\n assets = _share().deploy(assets, data);\n address to = _msgSender();\n SafeERC20.safeTransfer(_asset(), to, assets);\n emit VaultDeployAsset(to, assets, data);\n return assets;\n }\n\n /// @notice Recalls assets from RWA\n /// @dev Can only be called by the contract owner\n /// @dev Transfers assets from rwa to vault and decreases the assetTotalInRwa\n /// @dev Emits a TransferFromRwa event after the transfer is complete\n /// @param assets Assets to transfer, or max uint to transfer all available\n /// @param data Additional data associated with recall\n /// @return The amount of assets transferred\n /// @custom:error ShareInsufficientDeployedAssets Thrown if trying to settle more than the total sold amount\n function recall(\n uint assets,\n bytes calldata data\n ) external nonReentrant onlyOwner returns (uint) {\n _share().accrue();\n address from = _msgSender();\n assets = _share().recall(assets, data);\n SafeERC20.safeTransferFrom(_asset(), from, address(this), assets);\n emit VaultRecallAsset(from, assets, data);\n return assets;\n }\n\n function claimableDeposit(\n uint256 assets,\n address controller\n ) external nonReentrant onlyOwner returns (uint256 shares) {\n _share().accrue();\n return _claimableDeposit(assets, controller);\n }\n\n function claimableRedeem(\n uint256 shares,\n address controller\n ) external nonReentrant onlyOwner returns (uint256 assets) {\n _share().accrue();\n return _claimableRedeem(shares, controller);\n }\n}\n", + "project/contracts/VaultOptions.sol": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.27;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\ncontract VaultOptions is Initializable {\n struct Options {\n address owner;\n address asset;\n address share;\n address oracle;\n int256 price_min;\n int256 price_max;\n uint256 max_staleness;\n }\n\n /// @custom:storage-location erc7201:sivo.storage.VaultOptions\n struct VaultOptionsStorage {\n address _oracle;\n int256 _priceMin;\n int256 _priceMax;\n uint256 _maxStaleness;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"sivo.storage.VaultOptions\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant VaultOptionsStorageLocation =\n 0x91248f89b7431c31d2d93628b59d1cf32b96e520f520bd67fdf5d426af02eb00;\n\n function _getVaultOptionsStorage()\n internal\n pure\n returns (VaultOptionsStorage storage $)\n {\n assembly {\n $.slot := VaultOptionsStorageLocation\n }\n }\n\n /// @notice Returns the Chainlink oracle address used for price validation\n function oracle() public view returns (address) {\n return _getVaultOptionsStorage()._oracle;\n }\n\n /// @notice Returns the minimum acceptable oracle price\n function priceMin() public view returns (int256) {\n return _getVaultOptionsStorage()._priceMin;\n }\n\n /// @notice Returns the maximum acceptable oracle price\n function priceMax() public view returns (int256) {\n return _getVaultOptionsStorage()._priceMax;\n }\n\n /// @notice Returns the maximum allowed staleness for oracle data (in seconds)\n /// @dev 0 means no staleness check is enforced\n function maxStaleness() public view returns (uint256) {\n return _getVaultOptionsStorage()._maxStaleness;\n }\n\n function __VaultOptions_init(\n address oracle_,\n int256 priceMin_,\n int256 priceMax_,\n uint256 maxStaleness_\n ) internal onlyInitializing {\n __VaultOptions_init_unchained(\n oracle_,\n priceMin_,\n priceMax_,\n maxStaleness_\n );\n }\n\n function __VaultOptions_init_unchained(\n address oracle_,\n int256 priceMin_,\n int256 priceMax_,\n uint256 maxStaleness_\n ) internal onlyInitializing {\n VaultOptionsStorage storage $ = _getVaultOptionsStorage();\n $._oracle = oracle_;\n $._priceMin = priceMin_;\n $._priceMax = priceMax_;\n $._maxStaleness = maxStaleness_;\n }\n}\n", + "project/contracts/interfaces/IERC7540.sol": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.27;\n\n/**\n * @title IERC7540Operator - Operator Management Interface\n * @notice Interface for managing operator permissions for ERC-7540 compatible vaults\n * @dev Allows controllers to designate operators who can act on their behalf\n */\ninterface IERC7540Operator {\n event OperatorSet(\n address indexed controller,\n address indexed operator,\n bool approved\n );\n\n /**\n * @dev Returns true if `operator` is approved to manage requests on behalf of `controller`\n *\n * - MUST NOT revert.\n *\n * @param controller The address that controls the operator permissions\n * @param operator The address to check if it has operator permissions\n * @return status Boolean indicating if operator is approved for controller\n */\n function isOperator(\n address controller,\n address operator\n ) external view returns (bool status);\n\n /**\n * @dev Grant or revoke operator permissions for msg.sender (the controller)\n *\n * - MUST emit the OperatorSet event.\n * - MUST return true on success.\n *\n * @param operator The address to grant or revoke permissions for\n * @param approved Boolean indicating whether to grant (true) or revoke (false) permissions\n * @return success Must be true on success\n */\n function setOperator(\n address operator,\n bool approved\n ) external returns (bool success);\n}\n\n/**\n * @title IERC7540Deposit - Asynchronous Deposit Interface\n * @notice Interface for handling asynchronous deposits in ERC-7540 compatible vaults\n * @dev Provides methods for requesting and claiming deposits\n */\ninterface IERC7540Deposit {\n event DepositRequest(\n address indexed controller,\n address indexed owner,\n uint256 indexed requestId,\n address sender,\n uint256 assets\n );\n\n event DepositCancel(\n address indexed controller,\n address indexed receiver,\n address sender,\n uint256 assets\n );\n\n event DepositClaimable(\n address indexed controller,\n uint256 assets,\n uint256 shares\n );\n\n error ERC7540UnauthorizedSender(address sender, address subject);\n\n /**\n * @dev Initiate an asynchronous deposit request, locking assets and returning a requestId\n *\n * - MUST emit the DepositRequest event.\n * - MUST lock the assets until they can be claimed.\n * - MUST return a unique requestId that can be used to track and claim the deposit.\n *\n * @param assets The amount of assets to deposit\n * @param controller The address that will control this deposit\n * @param owner The address that owns the assets to be deposited\n * @return requestId An identifier for this deposit request. Always returns 0 which makes requests fungible.\n */\n function requestDeposit(\n uint256 assets,\n address controller,\n address owner\n ) external returns (uint256 requestId);\n\n /**\n * @dev Returns the amount of assets pending deposit for a controller under a specific requestId\n *\n * - MUST NOT revert if the requestId exists.\n * - MUST return 0 if the requestId does not exist or if the assets are no longer pending.\n *\n * @param requestId The unique identifier for the deposit request\n * @param controller The address controlling this deposit request\n * @return assets The amount of assets pending deposit\n */\n function pendingDepositRequest(\n uint256 requestId,\n address controller\n ) external view returns (uint256 assets);\n\n /**\n * @dev Returns the amount of assets claimable for deposit by a controller under a specific requestId\n *\n * - MUST NOT revert if the requestId exists.\n * - MUST return 0 if the requestId does not exist or if the assets are not yet claimable.\n *\n * @param requestId The unique identifier for the deposit request\n * @param controller The address controlling this deposit request\n * @return assets The amount of assets claimable for deposit\n */\n function claimableDepositRequest(\n uint256 requestId,\n address controller\n ) external view returns (uint256 assets);\n\n /**\n * @dev Claims deposited assets similar to ERC-4626 deposit, but with controller parameter\n *\n * - MUST emit the Deposit event.\n * - MUST convert the claimed assets to shares and transfer them to receiver.\n * - MUST revert if assets cannot be claimed.\n *\n * @param assets The amount of assets to claim\n * @param receiver The address that will receive the shares\n * @param controller The address controlling this deposit\n * @return shares The amount of shares minted to receiver\n */\n function deposit(\n uint256 assets,\n address receiver,\n address controller\n ) external returns (uint256 shares);\n\n /**\n * @dev Claims deposited assets via ERC-4626 mint semantics, with controller parameter\n *\n * - MUST emit the Deposit event.\n * - MUST mint the specified shares to receiver.\n * - MUST revert if shares cannot be minted.\n *\n * @param shares The amount of shares to mint\n * @param receiver The address that will receive the shares\n * @param controller The address controlling this mint operation\n * @return assets The amount of assets used to mint the shares\n */\n function mint(\n uint256 shares,\n address receiver,\n address controller\n ) external returns (uint256 assets);\n}\n\n/**\n * @title IERC7540Redeem - Asynchronous Redemption Interface\n * @notice Interface for handling asynchronous redemptions in ERC-7540 compatible vaults\n * @dev Provides methods for requesting and tracking redemptions\n * @dev Semantics for redeem and withdraw functions: if the controller has claimable redemptions\n * it follows async (ERC-7540) semantics and consumes claimable redemptions with pricing that was\n * locked when the request transitioned to claimable.\n * Otherwise it follows sync (ERC-4626) semantics that consume shares.\n */\ninterface IERC7540Redeem {\n event RedeemRequest(\n address indexed controller,\n address indexed owner,\n uint256 indexed requestId,\n address sender,\n uint256 shares\n );\n\n event RedeemCancel(\n address indexed controller,\n address indexed receiver,\n address sender,\n uint256 shares\n );\n\n event RedeemClaimable(\n address indexed controller,\n uint256 assets,\n uint256 shares\n );\n\n /**\n * @dev Initiate an asynchronous redemption request, locking shares and returning a requestId\n *\n * - MUST emit the RedeemRequest event.\n * - MUST lock the shares until they can be redeemed.\n * - MUST return a unique requestId that can be used to track the redemption.\n *\n * @param shares The amount of shares to redeem\n * @param controller The address that will control this redemption\n * @param owner The address that owns the shares being redeemed\n * @return requestId A unique identifier for this redemption request. Always returns 0 which makes requests fungible.\n */\n function requestRedeem(\n uint256 shares,\n address controller,\n address owner\n ) external returns (uint256 requestId);\n\n /**\n * @dev Returns the amount of shares pending redemption for a controller under a specific requestId\n *\n * - MUST NOT revert if the requestId exists.\n * - MUST return 0 if the requestId does not exist or if the shares are no longer pending.\n *\n * @param requestId The unique identifier for the redemption request\n * @param controller The address controlling this redemption request\n * @return shares The amount of shares pending redemption\n */\n function pendingRedeemRequest(\n uint256 requestId,\n address controller\n ) external view returns (uint256 shares);\n\n /**\n * @dev Returns the amount of shares claimable for redemption by a controller under a specific requestId\n *\n * - MUST NOT revert if the requestId exists.\n * - MUST return 0 if the requestId does not exist or if the shares are not yet claimable.\n *\n * @param requestId The unique identifier for the redemption request\n * @param controller The address controlling this redemption request\n * @return shares The amount of shares claimable for redemption\n */\n function claimableRedeemRequest(\n uint256 requestId,\n address controller\n ) external view returns (uint256 shares);\n}\n", + "project/contracts/interfaces/IERC7575.sol": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.27;\n\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/// @title IERC7575 - Multi-Asset ERC-4626 Vaults Interface\n/// @notice Extended ERC-4626 Interface enabling Multi-Asset Vaults\n/// @dev According to ERC-7575 specification: https://eips.ethereum.org/EIPS/eip-7575\n/// @dev All ERC-7575 Vaults MUST implement ERC-4626 excluding the ERC-20 methods and events\n/// @dev From @openzeppelin/contracts/interfaces/IERC4626.sol, minus ERC-20\ninterface IERC7575 is IERC165 {\n event Deposit(\n address indexed sender,\n address indexed owner,\n uint256 assets,\n uint256 shares\n );\n\n event Withdraw(\n address indexed sender,\n address indexed receiver,\n address indexed owner,\n uint256 assets,\n uint256 shares\n );\n\n /**\n * @dev Attempted to deposit more assets than the max amount for `receiver`.\n */\n error ERC7575ExceededMaxDeposit(\n address receiver,\n uint256 assets,\n uint256 max\n );\n\n /**\n * @dev Attempted to mint more shares than the max amount for `receiver`.\n */\n error ERC7575ExceededMaxMint(address receiver, uint256 shares, uint256 max);\n\n /**\n * @dev Attempted to withdraw more assets than the max amount for `receiver`.\n */\n error ERC7575ExceededMaxWithdraw(\n address owner,\n uint256 assets,\n uint256 max\n );\n\n /**\n * @dev Attempted to redeem more shares than the max amount for `receiver`.\n */\n error ERC7575ExceededMaxRedeem(address owner, uint256 shares, uint256 max);\n\n /// @notice The address of the underlying share received on deposit into the Vault\n /// @dev MUST return an address of an ERC-20 share representation of the Vault\n /// @dev share MAY return the address of the Vault itself (i.e., share == address(this))\n /// @dev If share != address(this):\n /// - entry functions MUST increase the share balance of the receiver: share.balanceOf(receiver) += shares\n /// - exit functions MUST decrease the share balance of the owner: share.balanceOf(owner) -= shares\n /// @dev MUST NOT revert\n /// @return shareTokenAddress The address of the share token\n function share() external view returns (address shareTokenAddress);\n\n /**\n * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n *\n * - MUST be an ERC-20 token contract.\n * - MUST NOT revert.\n */\n function asset() external view returns (address assetTokenAddress);\n\n /**\n * @dev Returns the total amount of the underlying asset that is \u201cmanaged\u201d by Vault.\n *\n * - SHOULD include any compounding that occurs from yield.\n * - MUST be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT revert.\n */\n function totalAssets() external view returns (uint256 totalManagedAssets);\n\n /**\n * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n * scenario where all the conditions are met.\n *\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT show any variations depending on the caller.\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n * - MUST NOT revert.\n *\n * NOTE: This calculation MAY NOT reflect the \u201cper-user\u201d price-per-share, and instead should reflect the\n * \u201caverage-user\u2019s\u201d price-per-share, meaning what the average user should expect to see when exchanging to and\n * from.\n */\n function convertToShares(\n uint256 assets\n ) external view returns (uint256 shares);\n\n /**\n * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n * scenario where all the conditions are met.\n *\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT show any variations depending on the caller.\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n * - MUST NOT revert.\n *\n * NOTE: This calculation MAY NOT reflect the \u201cper-user\u201d price-per-share, and instead should reflect the\n * \u201caverage-user\u2019s\u201d price-per-share, meaning what the average user should expect to see when exchanging to and\n * from.\n */\n function convertToAssets(\n uint256 shares\n ) external view returns (uint256 assets);\n\n /**\n * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n * through a deposit call.\n *\n * - MUST return a limited value if receiver is subject to some deposit limit.\n * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n * - MUST NOT revert.\n */\n function maxDeposit(\n address receiver\n ) external view returns (uint256 maxAssets);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n * current on-chain conditions.\n *\n * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n * in the same transaction.\n * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n * deposit would be accepted, regardless if the user has enough tokens approved, etc.\n * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n */\n function previewDeposit(\n uint256 assets\n ) external view returns (uint256 shares);\n\n /**\n * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n *\n * - MUST emit the Deposit event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n * deposit execution, and are accounted for during deposit.\n * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n * approving enough underlying tokens to the Vault contract, etc).\n *\n * NOTE: most implementations will require pre-approval of the Vault with the Vault\u2019s underlying asset token.\n */\n function deposit(\n uint256 assets,\n address receiver\n ) external returns (uint256 shares);\n\n /**\n * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n * - MUST return a limited value if receiver is subject to some mint limit.\n * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n * - MUST NOT revert.\n */\n function maxMint(\n address receiver\n ) external view returns (uint256 maxShares);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n * current on-chain conditions.\n *\n * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n * same transaction.\n * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n * would be accepted, regardless if the user has enough tokens approved, etc.\n * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by minting.\n */\n function previewMint(uint256 shares) external view returns (uint256 assets);\n\n /**\n * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n *\n * - MUST emit the Deposit event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n * execution, and are accounted for during mint.\n * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n * approving enough underlying tokens to the Vault contract, etc).\n *\n * NOTE: most implementations will require pre-approval of the Vault with the Vault\u2019s underlying asset token.\n */\n function mint(\n uint256 shares,\n address receiver\n ) external returns (uint256 assets);\n\n /**\n * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n * Vault, through a withdraw call.\n *\n * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n * - MUST NOT revert.\n */\n function maxWithdraw(\n address owner\n ) external view returns (uint256 maxAssets);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n * given current on-chain conditions.\n *\n * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n * called\n * in the same transaction.\n * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n * the withdrawal would be accepted, regardless if the user has enough shares, etc.\n * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n */\n function previewWithdraw(\n uint256 assets\n ) external view returns (uint256 shares);\n\n /**\n * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n *\n * - MUST emit the Withdraw event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n * withdraw execution, and are accounted for during withdraw.\n * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n * not having enough shares, etc).\n *\n * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n * Those methods should be performed separately.\n */\n function withdraw(\n uint256 assets,\n address receiver,\n address owner\n ) external returns (uint256 shares);\n\n /**\n * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n * through a redeem call.\n *\n * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n * - MUST NOT revert.\n */\n function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,\n * given current on-chain conditions.\n *\n * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n * same transaction.\n * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n * redemption would be accepted, regardless if the user has enough shares, etc.\n * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n */\n function previewRedeem(\n uint256 shares\n ) external view returns (uint256 assets);\n\n /**\n * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n *\n * - MUST emit the Withdraw event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n * redeem execution, and are accounted for during redeem.\n * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n * not having enough shares, etc).\n *\n * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n * Those methods should be performed separately.\n */\n function redeem(\n uint256 shares,\n address receiver,\n address owner\n ) external returns (uint256 assets);\n}\n", + "project/contracts/interfaces/IShare.sol": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.24;\n\nimport {IERC20Metadata as IERC20} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\n/// @title IShare\n/// @notice This interface defines the functions and events of the Share contract, which manages the tokenization of receivables. As receivables become available the can be purchased with a stablecoin like USDC, USDT, EURC, etc. The contract is [ERC-4626](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) compliant. The `asset()` function returns the asset contract address. The contract also handles redemption of receivable tokens (a.k.a. sTokens depending on the asset: sivoUSDC, sivoUSDT, sEURC, etc.). Pricing increases dynamically based on the amount of receivables that are sold.\n/// | Chain Type | Name | ID | Market | Currency | Contract Address |\n/// | ---------- | ---- | -- | ------ | ------ | ---------------- |\n/// | Mainnet | Base | 8453 | US | USD | [0x7e6C74cFFC9B179BFd6C69C79682920Bf7611eF3](https://basescan.org/contract/0x7e6C74cFFC9B179BFd6C69C79682920Bf7611eF3) |\n/// | Testnet | Base Sepolia | 84532 | US | USD | [0x47BA8e2832Fce402aa21BD64E72824F062e91AE3](https://sepolia.basescan.org/contract/0x47BA8e2832Fce402aa21BD64E72824F062e91AE3) |\ninterface IShare is IERC20 {\n /// @notice Emitted when the discount rate parameters are updated\n /// @param discountRateBase The new base discount rate (per second)\n /// @param discountRateSlope The new discount rate slope (per second)\n event DiscountChange(uint discountRateBase, uint discountRateSlope);\n\n /// @notice Emitted when the idle factor parameters are updated\n /// @param minIdleFactor The new minimum idle factor\n /// @param maxIdleFactor The new maximum idle factor\n event IdleFactorChange(uint minIdleFactor, uint maxIdleFactor);\n\n /// @notice Emitted when the vault status is updated\n /// @param vault The vault address\n /// @param isVault The new vault status\n event UpdateVault(address vault, bool isVault);\n\n /// @notice Emitted when discount accrual is processed\n /// @param timeElapsed The time elapsed since the last accrual (in seconds)\n /// @param assetTotalDeployedStart The total assets deployed at the start of the accrual period\n /// @param assetTotalDeployedEnd The total assets deployed at the end of the accrual period\n /// @param assetTotalIdle The total assets idle during the accrual period\n /// @param totalSupply The total supply of shares\n event Accrue(\n uint timeElapsed,\n uint assetTotalDeployedStart,\n uint assetTotalDeployedEnd,\n uint assetTotalIdle,\n uint totalSupply\n );\n\n /// @notice Emitted when assets are deployed to RWAs\n /// @param vault The address of the vault that deployed the assets\n /// @param assets The amount of assets transferred\n /// @param data Additional data associated with deployment\n event ShareDeployAsset(address indexed vault, uint assets, bytes data);\n\n /// @notice Emitted when assets are recalled from RWAs\n /// @param vault The address of the vault that recalled the assets\n /// @param assets The amount of assets transferred\n /// @param data Additional data associated with recall\n event ShareRecallAsset(address indexed vault, uint assets, bytes data);\n\n /// @notice Error thrown when the timestamp exceeds the maximum value that can be stored\n /// @param timestamp The timestamp that caused the error\n error TimestampTooLarge(uint timestamp);\n\n /// @notice Error thrown when the caller is not a vault\n error ShareUnauthorizedVault();\n\n /// @notice Error thrown when there are insufficient idle assets\n /// @param assets The amount of assets that caused the error\n /// @param max The maximum amount of assets that can be deployed\n error ShareInsufficientIdleAssets(uint assets, uint max);\n\n /// @notice Error thrown when there are insufficient deployed assets\n /// @param assets The amount of assets that caused the error\n /// @param max The maximum amount of assets that can be deployed\n error ShareInsufficientDeployedAssets(uint assets, uint max);\n\n /// @notice Error thrown when the accrual is out of date\n /// @param timeElapsed The time elapsed since the last accrual\n error AccrualOutOfDate(uint timeElapsed);\n\n /// @notice The slope component of the discount rate (per second)\n /// @dev Adjusted by dividing annual rate by SECONDS_PER_YEAR\n function discountRateSlope() external view returns (uint64);\n\n /// @notice The base component of the discount rate (per second)\n /// @dev Adjusted by dividing annual rate by SECONDS_PER_YEAR\n function discountRateBase() external view returns (uint64);\n\n /// @notice The minimum idle factor, representing the minimum percent of total assets that must remain idle\n /// @dev Scaled by FactorScale (1e18)\n function minIdleFactor() external view returns (uint64);\n\n /// @notice The maximum idle factor, representing the maximum percent of total assets that should remain idle\n /// @dev Scaled by FactorScale (1e18)\n function maxIdleFactor() external view returns (uint64);\n\n /// @notice The timestamp of the last accrual calculation\n /// @dev Stored as uint40 to save gas, can represent timestamps until year 36812\n function lastAccrualTime() external view returns (uint40);\n\n /// @notice Returns the total assets deployed\n /// @dev Calculated by applying discount accrual since last update\n function assetTotalDeployed() external view returns (uint);\n\n /// @notice Returns the total assets idle\n /// @dev Includes idle assets across all vaults\n function assetTotalIdle() external view returns (uint);\n\n /// @notice Calculates the accrual rate of deployed assets based on utilization\n /// @dev The accrual rate is used to determine how share value increases over time\n /// @param utilization_ The current utilization factor (ratio of assets in share to deployed assets)\n /// @return The calculated accrual rate including base rate plus slope component\n function accrueRate(uint utilization_) external view returns (uint);\n\n /// @notice Simulates an accrual at the current block, given current on-chain conditions\n /// @dev Uses the time elapsed since last accrual and calculates accrual\n /// @return timeElapsed The time elapsed since last accrual in seconds\n /// @return assetTotalDeployedStart The total assets deployed at the start of the accrual period\n /// @return assetTotalDeployedEnd The total assets deployed at the end of the accrual period\n /// @return assetTotalIdle The total assets idle during the accrual period\n function previewAccrue() external view returns (uint, uint, uint, uint);\n\n /// @notice Performs an accrual at the current block, given current on-chain conditions\n /// @dev Can only be called by the vaults. Should be called by vaults before converting between assets and shares.\n function accrue() external;\n\n /// @notice Mints shares to the specified address\n /// @dev Can only be called by linked vaults\n /// @param to The address to mint shares to\n /// @param shares The total shares to mint\n /// @param assets The total assets added to the vault\n function mint(address to, uint256 shares, uint256 assets) external;\n\n /// @notice Burns shares from the specified owner\n /// @dev Can only be called by linked vaults\n /// @param owner The owner of the shares to burn\n /// @param shares The total shares to burn\n /// @param assets The total assets removed from the vault\n function burn(address owner, uint256 shares, uint256 assets) external;\n\n /// @notice Spends the allowance of shares from the owner to the spender\n /// @dev Can only be called by linked vaults\n /// @param owner The owner of the shares\n /// @param spender The spender of the shares\n /// @param shares The total shares to spend\n function spendAllowance(\n address owner,\n address spender,\n uint256 shares\n ) external;\n\n /// @notice Deploys assets from vault to RWA\n /// @dev Can only be called by the contract owner\n /// @dev Transfers assets from contract to owner and increases the assetTotalInRwa\n /// @dev Emits a TransferToRwa event after the transfer is complete\n /// @param assets Assets to transfer, or max uint to transfer all available\n /// @param data Additional data associated with deployment\n /// @return The amount of assets transferred\n /// @custom:error ShareInsufficientIdleAssets Thrown if trying to transfer more than available\n function deploy(uint256 assets, bytes calldata data) external returns (uint256);\n\n /// @notice Recalls assets from RWA\n /// @dev Can only be called by the contract owner\n /// @dev Transfers assets from rwa to vault and decreases the assetTotalInRwa\n /// @dev Emits a TransferFromRwa event after the transfer is complete\n /// @param assets Assets to transfer, or max uint to transfer all available\n /// @param data Additional data associated with recall\n /// @return The amount of assets transferred\n /// @custom:error ShareInsufficientDeployedAssets Thrown if trying to settle more than the total sold amount\n function recall(uint256 assets, bytes calldata data) external returns (uint256);\n}\n", + "project/contracts/interfaces/IVault.sol": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.24;\n\nimport {IERC7575} from \"./IERC7575.sol\";\nimport {IERC7540Deposit, IERC7540Redeem, IERC7540Operator} from \"./IERC7540.sol\";\n\n/// @title IVault\n/// @notice This interface defines the functions and events of the Vault contract, which manages the tokenization of receivables. As receivables become available the can be purchased with a stablecoin like USDC, USDT, EURC, etc. The contract is [ERC-4626](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) compliant. The `asset()` function returns the asset contract address. The contract also handles redemption of receivable tokens (a.k.a. sTokens depending on the asset: sivoUSDC, sivoUSDT, sEURC, etc.). Pricing increases dynamically based on the amount of receivables that are sold.\n/// | Chain Type | Name | ID | Market | Asset | Contract Address |\n/// | ---------- | ---- | -- | ------ |------ | ---------------- |\n/// | Mainnet | Base | 8453 | US | [USDC](https://basescan.org/token/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913) | [0x7e6C74cFFC9B179BFd6C69C79682920Bf7611eF3](https://basescan.org/address/0x7e6C74cFFC9B179BFd6C69C79682920Bf7611eF3) |\n/// | Testnet | Base Sepolia | 84532 | US | [USDC](https://sepolia.basescan.org/token/0x036CbD53842c5426634e7929541eC2318f3dCF7e) | [0x47BA8e2832Fce402aa21BD64E72824F062e91AE3](https://sepolia.basescan.org/address/0x47BA8e2832Fce402aa21BD64E72824F062e91AE3) |\ninterface IVault is\n IERC7575,\n IERC7540Deposit,\n IERC7540Redeem,\n IERC7540Operator\n{\n /// @notice Emitted when assets are deployed to RWAs\n /// @param to The address of the receiver of the assets\n /// @param assets The amount of assets transferred\n /// @param data Additional data associated with deployment\n event VaultDeployAsset(address indexed to, uint assets, bytes data);\n\n /// @notice Emitted when assets are recalled from RWAs\n /// @param from The address of the sender of the assets\n /// @param assets The amount of assets transferred\n /// @param data Additional data associated with recall\n event VaultRecallAsset(address indexed from, uint assets, bytes data);\n}\n" + }, + "target": "project/contracts/Vault.sol", + "version": "0.8.34" +} diff --git a/tests/sourcify-sweep/fixtures/contracts/11155111_0xdd8eda562280aac3a4d0d377d4961646f3bb5dc2.json b/tests/sourcify-sweep/fixtures/contracts/11155111_0xdd8eda562280aac3a4d0d377d4961646f3bb5dc2.json new file mode 100644 index 000000000..9c628d66a --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/11155111_0xdd8eda562280aac3a4d0d377d4961646f3bb5dc2.json @@ -0,0 +1,23 @@ +{ + "chain_id": 11155111, + "name": "0xdd8eda562280aac3a4d0d377d4961646f3bb5dc2", + "remappings": ["@openzeppelin/contracts/=@openzeppelin/contracts@5.7.0/"], + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "remappings": ["@openzeppelin/contracts/=@openzeppelin/contracts@5.7.0/"] + }, + "sources": { + "@openzeppelin/contracts@5.7.0/access/Ownable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n", + "@openzeppelin/contracts@5.7.0/token/ERC20/IERC20.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n", + "@openzeppelin/contracts@5.7.0/utils/Context.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n", + "@openzeppelin/contracts@5.7.0/utils/Pausable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n bool private _paused;\n\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n /**\n * @dev The operation failed because the contract is paused.\n */\n error EnforcedPause();\n\n /**\n * @dev The operation failed because the contract is not paused.\n */\n error ExpectedPause();\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n if (paused()) {\n revert EnforcedPause();\n }\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n if (!paused()) {\n revert ExpectedPause();\n }\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n", + "@openzeppelin/contracts@5.7.0/utils/ReentrancyGuard.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\nimport {StorageSlot} from \"./StorageSlot.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n *\n * IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced\n * by the {ReentrancyGuardTransient} variant in v6.0.\n *\n * @custom:stateless\n */\nabstract contract ReentrancyGuard {\n using StorageSlot for bytes32;\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant NOT_ENTERED = 1;\n uint256 private constant ENTERED = 2;\n\n /**\n * @dev Unauthorized reentrant call.\n */\n error ReentrancyGuardReentrantCall();\n\n constructor() {\n _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n /**\n * @dev A `view` only version of {nonReentrant}. Use to block view functions\n * from being called, preventing reading from inconsistent contract state.\n *\n * CAUTION: This is a \"view\" modifier and does not change the reentrancy\n * status. Use it only on view functions. For payable or non-payable functions,\n * use the standard {nonReentrant} modifier instead.\n */\n modifier nonReentrantView() {\n _nonReentrantBeforeView();\n _;\n }\n\n function _nonReentrantBeforeView() private view {\n if (_reentrancyGuardEntered()) {\n revert ReentrancyGuardReentrantCall();\n }\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be NOT_ENTERED\n _nonReentrantBeforeView();\n\n // Any calls to nonReentrant after this point will fail\n _reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;\n }\n\n function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {\n return REENTRANCY_GUARD_STORAGE;\n }\n}\n", + "@openzeppelin/contracts@5.7.0/utils/StorageSlot.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(newImplementation.code.length > 0);\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct Int256Slot {\n int256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n */\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n}\n", + "KawnixStaking.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.20;\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\r\nimport \"@openzeppelin/contracts/utils/Pausable.sol\";\r\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\r\n\r\ncontract KawnixStaking is ReentrancyGuard, Pausable, Ownable {\r\n IERC20 public immutable kawToken;\r\n\r\n // Staking thresholds in USD (1e18 scale)\r\n uint256 public proUsdRequirement = 2000 * 1e18;\r\n uint256 public eliteUsdRequirement = 10000 * 1e18;\r\n\r\n struct Stake {\r\n uint256 amountKAW;\r\n uint256 usdValueAtStake;\r\n uint256 startTime;\r\n uint256 unlockTime;\r\n uint8 tier; // 0: Standard, 1: PRO, 2: ELITE\r\n bool active;\r\n }\r\n\r\n mapping(address => Stake) public stakes;\r\n\r\n event Staked(address indexed user, uint256 amount, uint8 tier, uint256 unlockTime);\r\n event Unstaked(address indexed user, uint256 amount);\r\n event EmergencyUnstaked(address indexed user, uint256 amount);\r\n\r\n constructor(address _kawToken, address initialOwner) Ownable(initialOwner) {\r\n require(_kawToken != address(0), \"Invalid token address\");\r\n kawToken = IERC20(_kawToken);\r\n }\r\n\r\n /**\r\n * @notice Stakes KAW tokens to gain PRO (1) or ELITE (2) status\r\n * @param kawAmount Total KAW tokens transferred (in 1e18 units)\r\n * @param targetTier 1 for PRO, 2 for ELITE\r\n * @param currentKawUsdPrice Current price of 1 KAW in USD (scaled by 1e18)\r\n */\r\n function stake(uint256 kawAmount, uint8 targetTier, uint256 currentKawUsdPrice) \r\n external \r\n nonReentrant \r\n whenNotPaused \r\n {\r\n require(targetTier == 1 || targetTier == 2, \"Invalid target tier\");\r\n require(!stakes[msg.sender].active, \"Active stake already exists\");\r\n require(currentKawUsdPrice > 0, \"Invalid price\");\r\n\r\n // Calculate USD equivalent value of tokens provided\r\n uint256 usdValue = (kawAmount * currentKawUsdPrice) / 1e18;\r\n uint256 requiredUsd = (targetTier == 1) ? proUsdRequirement : eliteUsdRequirement;\r\n \r\n require(usdValue >= requiredUsd, \"Insufficient USD value for tier\");\r\n\r\n uint256 duration = (targetTier == 1) ? 30 days : 90 days;\r\n\r\n // Pull tokens from user to staking contract\r\n require(kawToken.transferFrom(msg.sender, address(this), kawAmount), \"Token transfer failed\");\r\n\r\n stakes[msg.sender] = Stake({\r\n amountKAW: kawAmount,\r\n usdValueAtStake: usdValue,\r\n startTime: block.timestamp,\r\n unlockTime: block.timestamp + duration,\r\n tier: targetTier,\r\n active: true\r\n });\r\n\r\n emit Staked(msg.sender, kawAmount, targetTier, block.timestamp + duration);\r\n }\r\n\r\n /**\r\n * @notice Unstakes KAW tokens after lock duration has passed\r\n */\r\n function unstake() external nonReentrant {\r\n Stake storage userStake = stakes[msg.sender];\r\n require(userStake.active, \"No active stake found\");\r\n require(block.timestamp >= userStake.unlockTime, \"Stake duration locked\");\r\n\r\n uint256 amountToReturn = userStake.amountKAW;\r\n \r\n // Reset stake state before token transfer (Security Best Practice)\r\n userStake.active = false;\r\n userStake.tier = 0;\r\n\r\n require(kawToken.transfer(msg.sender, amountToReturn), \"Token refund failed\");\r\n\r\n emit Unstaked(msg.sender, amountToReturn);\r\n }\r\n\r\n /**\r\n * @notice Returns current active tier of user\r\n */\r\n function getCurrentTier(address user) external view returns (uint8) {\r\n Stake memory userStake = stakes[user];\r\n if (!userStake.active || block.timestamp < userStake.unlockTime) {\r\n return userStake.active ? userStake.tier : 0;\r\n }\r\n // Returns 0 (Standard) if stake lock period has expired\r\n return 0;\r\n }\r\n\r\n function pause() external onlyOwner {\r\n _pause();\r\n }\r\n\r\n function unpause() external onlyOwner {\r\n _unpause();\r\n }\r\n}" + }, + "target": "KawnixStaking.sol", + "version": "0.8.34" +} diff --git a/tests/sourcify-sweep/fixtures/contracts/1_0x00019038843f98d160f568c1f001c8f7c2558e11.json b/tests/sourcify-sweep/fixtures/contracts/1_0x00019038843f98d160f568c1f001c8f7c2558e11.json new file mode 100644 index 000000000..d8c5e4653 --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/1_0x00019038843f98d160f568c1f001c8f7c2558e11.json @@ -0,0 +1,53 @@ +{ + "chain_id": 1, + "name": "0x00019038843f98d160f568c1f001c8f7c2558e11", + "remappings": [], + "settings": { + "evmVersion": "cancun", + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true + }, + "sources": { + "@uniswap/v4-core/src/interfaces/IExtsload.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @notice Interface for functions to access any storage slot in a contract\ninterface IExtsload {\n /// @notice Called by external contracts to access granular pool state\n /// @param slot Key of slot to sload\n /// @return value The value of the slot as bytes32\n function extsload(bytes32 slot) external view returns (bytes32 value);\n\n /// @notice Called by external contracts to access granular pool state\n /// @param startSlot Key of slot to start sloading from\n /// @param nSlots Number of slots to load into return value\n /// @return values List of loaded values.\n function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory values);\n\n /// @notice Called by external contracts to access sparse pool state\n /// @param slots List of slots to SLOAD from.\n /// @return values List of loaded values.\n function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory values);\n}\n", + "@uniswap/v4-core/src/interfaces/IExttload.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\n/// @notice Interface for functions to access any transient storage slot in a contract\ninterface IExttload {\n /// @notice Called by external contracts to access transient storage of the contract\n /// @param slot Key of slot to tload\n /// @return value The value of the slot as bytes32\n function exttload(bytes32 slot) external view returns (bytes32 value);\n\n /// @notice Called by external contracts to access sparse transient pool state\n /// @param slots List of slots to tload\n /// @return values List of loaded values\n function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory values);\n}\n", + "@uniswap/v4-core/src/interfaces/IHooks.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {PoolKey} from \"../types/PoolKey.sol\";\nimport {BalanceDelta} from \"../types/BalanceDelta.sol\";\nimport {ModifyLiquidityParams, SwapParams} from \"../types/PoolOperation.sol\";\nimport {BeforeSwapDelta} from \"../types/BeforeSwapDelta.sol\";\n\n/// @notice V4 decides whether to invoke specific hooks by inspecting the least significant bits\n/// of the address that the hooks contract is deployed to.\n/// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400\n/// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used.\n/// See the Hooks library for the full spec.\n/// @dev Should only be callable by the v4 PoolManager.\ninterface IHooks {\n /// @notice The hook called before the state of a pool is initialized\n /// @param sender The initial msg.sender for the initialize call\n /// @param key The key for the pool being initialized\n /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96\n /// @return bytes4 The function selector for the hook\n function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96) external returns (bytes4);\n\n /// @notice The hook called after the state of a pool is initialized\n /// @param sender The initial msg.sender for the initialize call\n /// @param key The key for the pool being initialized\n /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96\n /// @param tick The current tick after the state of a pool is initialized\n /// @return bytes4 The function selector for the hook\n function afterInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, int24 tick)\n external\n returns (bytes4);\n\n /// @notice The hook called before liquidity is added\n /// @param sender The initial msg.sender for the add liquidity call\n /// @param key The key for the pool\n /// @param params The parameters for adding liquidity\n /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook\n /// @return bytes4 The function selector for the hook\n function beforeAddLiquidity(\n address sender,\n PoolKey calldata key,\n ModifyLiquidityParams calldata params,\n bytes calldata hookData\n ) external returns (bytes4);\n\n /// @notice The hook called after liquidity is added\n /// @param sender The initial msg.sender for the add liquidity call\n /// @param key The key for the pool\n /// @param params The parameters for adding liquidity\n /// @param delta The caller's balance delta after adding liquidity; the sum of principal delta, fees accrued, and hook delta\n /// @param feesAccrued The fees accrued since the last time fees were collected from this position\n /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook\n /// @return bytes4 The function selector for the hook\n /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency\n function afterAddLiquidity(\n address sender,\n PoolKey calldata key,\n ModifyLiquidityParams calldata params,\n BalanceDelta delta,\n BalanceDelta feesAccrued,\n bytes calldata hookData\n ) external returns (bytes4, BalanceDelta);\n\n /// @notice The hook called before liquidity is removed\n /// @param sender The initial msg.sender for the remove liquidity call\n /// @param key The key for the pool\n /// @param params The parameters for removing liquidity\n /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook\n /// @return bytes4 The function selector for the hook\n function beforeRemoveLiquidity(\n address sender,\n PoolKey calldata key,\n ModifyLiquidityParams calldata params,\n bytes calldata hookData\n ) external returns (bytes4);\n\n /// @notice The hook called after liquidity is removed\n /// @param sender The initial msg.sender for the remove liquidity call\n /// @param key The key for the pool\n /// @param params The parameters for removing liquidity\n /// @param delta The caller's balance delta after removing liquidity; the sum of principal delta, fees accrued, and hook delta\n /// @param feesAccrued The fees accrued since the last time fees were collected from this position\n /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook\n /// @return bytes4 The function selector for the hook\n /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency\n function afterRemoveLiquidity(\n address sender,\n PoolKey calldata key,\n ModifyLiquidityParams calldata params,\n BalanceDelta delta,\n BalanceDelta feesAccrued,\n bytes calldata hookData\n ) external returns (bytes4, BalanceDelta);\n\n /// @notice The hook called before a swap\n /// @param sender The initial msg.sender for the swap call\n /// @param key The key for the pool\n /// @param params The parameters for the swap\n /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook\n /// @return bytes4 The function selector for the hook\n /// @return BeforeSwapDelta The hook's delta in specified and unspecified currencies. Positive: the hook is owed/took currency, negative: the hook owes/sent currency\n /// @return uint24 Optionally override the lp fee, only used if three conditions are met: 1. the Pool has a dynamic fee, 2. the value's 2nd highest bit is set (23rd bit, 0x400000), and 3. the value is less than or equal to the maximum fee (1 million)\n function beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata hookData)\n external\n returns (bytes4, BeforeSwapDelta, uint24);\n\n /// @notice The hook called after a swap\n /// @param sender The initial msg.sender for the swap call\n /// @param key The key for the pool\n /// @param params The parameters for the swap\n /// @param delta The amount owed to the caller (positive) or owed to the pool (negative)\n /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook\n /// @return bytes4 The function selector for the hook\n /// @return int128 The hook's delta in unspecified currency. Positive: the hook is owed/took currency, negative: the hook owes/sent currency\n function afterSwap(\n address sender,\n PoolKey calldata key,\n SwapParams calldata params,\n BalanceDelta delta,\n bytes calldata hookData\n ) external returns (bytes4, int128);\n\n /// @notice The hook called before donate\n /// @param sender The initial msg.sender for the donate call\n /// @param key The key for the pool\n /// @param amount0 The amount of token0 being donated\n /// @param amount1 The amount of token1 being donated\n /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook\n /// @return bytes4 The function selector for the hook\n function beforeDonate(\n address sender,\n PoolKey calldata key,\n uint256 amount0,\n uint256 amount1,\n bytes calldata hookData\n ) external returns (bytes4);\n\n /// @notice The hook called after donate\n /// @param sender The initial msg.sender for the donate call\n /// @param key The key for the pool\n /// @param amount0 The amount of token0 being donated\n /// @param amount1 The amount of token1 being donated\n /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook\n /// @return bytes4 The function selector for the hook\n function afterDonate(\n address sender,\n PoolKey calldata key,\n uint256 amount0,\n uint256 amount1,\n bytes calldata hookData\n ) external returns (bytes4);\n}\n", + "@uniswap/v4-core/src/interfaces/IPoolManager.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {Currency} from \"../types/Currency.sol\";\nimport {PoolKey} from \"../types/PoolKey.sol\";\nimport {IHooks} from \"./IHooks.sol\";\nimport {IERC6909Claims} from \"./external/IERC6909Claims.sol\";\nimport {IProtocolFees} from \"./IProtocolFees.sol\";\nimport {BalanceDelta} from \"../types/BalanceDelta.sol\";\nimport {PoolId} from \"../types/PoolId.sol\";\nimport {IExtsload} from \"./IExtsload.sol\";\nimport {IExttload} from \"./IExttload.sol\";\nimport {ModifyLiquidityParams, SwapParams} from \"../types/PoolOperation.sol\";\n\n/// @notice Interface for the PoolManager\ninterface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload, IExttload {\n /// @notice Thrown when a currency is not netted out after the contract is unlocked\n error CurrencyNotSettled();\n\n /// @notice Thrown when trying to interact with a non-initialized pool\n error PoolNotInitialized();\n\n /// @notice Thrown when unlock is called, but the contract is already unlocked\n error AlreadyUnlocked();\n\n /// @notice Thrown when a function is called that requires the contract to be unlocked, but it is not\n error ManagerLocked();\n\n /// @notice Pools are limited to type(int16).max tickSpacing in #initialize, to prevent overflow\n error TickSpacingTooLarge(int24 tickSpacing);\n\n /// @notice Pools must have a positive non-zero tickSpacing passed to #initialize\n error TickSpacingTooSmall(int24 tickSpacing);\n\n /// @notice PoolKey must have currencies where address(currency0) < address(currency1)\n error CurrenciesOutOfOrderOrEqual(address currency0, address currency1);\n\n /// @notice Thrown when a call to updateDynamicLPFee is made by an address that is not the hook,\n /// or on a pool that does not have a dynamic swap fee.\n error UnauthorizedDynamicLPFeeUpdate();\n\n /// @notice Thrown when trying to swap amount of 0\n error SwapAmountCannotBeZero();\n\n ///@notice Thrown when native currency is passed to a non native settlement\n error NonzeroNativeValue();\n\n /// @notice Thrown when `clear` is called with an amount that is not exactly equal to the open currency delta.\n error MustClearExactPositiveDelta();\n\n /// @notice Emitted when a new pool is initialized\n /// @param id The abi encoded hash of the pool key struct for the new pool\n /// @param currency0 The first currency of the pool by address sort order\n /// @param currency1 The second currency of the pool by address sort order\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n /// @param tickSpacing The minimum number of ticks between initialized ticks\n /// @param hooks The hooks contract address for the pool, or address(0) if none\n /// @param sqrtPriceX96 The price of the pool on initialization\n /// @param tick The initial tick of the pool corresponding to the initialized price\n event Initialize(\n PoolId indexed id,\n Currency indexed currency0,\n Currency indexed currency1,\n uint24 fee,\n int24 tickSpacing,\n IHooks hooks,\n uint160 sqrtPriceX96,\n int24 tick\n );\n\n /// @notice Emitted when a liquidity position is modified\n /// @param id The abi encoded hash of the pool key struct for the pool that was modified\n /// @param sender The address that modified the pool\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param liquidityDelta The amount of liquidity that was added or removed\n /// @param salt The extra data to make positions unique\n event ModifyLiquidity(\n PoolId indexed id, address indexed sender, int24 tickLower, int24 tickUpper, int256 liquidityDelta, bytes32 salt\n );\n\n /// @notice Emitted for swaps between currency0 and currency1\n /// @param id The abi encoded hash of the pool key struct for the pool that was modified\n /// @param sender The address that initiated the swap call, and that received the callback\n /// @param amount0 The delta of the currency0 balance of the pool\n /// @param amount1 The delta of the currency1 balance of the pool\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\n /// @param liquidity The liquidity of the pool after the swap\n /// @param tick The log base 1.0001 of the price of the pool after the swap\n /// @param fee The swap fee in hundredths of a bip\n event Swap(\n PoolId indexed id,\n address indexed sender,\n int128 amount0,\n int128 amount1,\n uint160 sqrtPriceX96,\n uint128 liquidity,\n int24 tick,\n uint24 fee\n );\n\n /// @notice Emitted for donations\n /// @param id The abi encoded hash of the pool key struct for the pool that was donated to\n /// @param sender The address that initiated the donate call\n /// @param amount0 The amount donated in currency0\n /// @param amount1 The amount donated in currency1\n event Donate(PoolId indexed id, address indexed sender, uint256 amount0, uint256 amount1);\n\n /// @notice All interactions on the contract that account deltas require unlocking. A caller that calls `unlock` must implement\n /// `IUnlockCallback(msg.sender).unlockCallback(data)`, where they interact with the remaining functions on this contract.\n /// @dev The only functions callable without an unlocking are `initialize` and `updateDynamicLPFee`\n /// @param data Any data to pass to the callback, via `IUnlockCallback(msg.sender).unlockCallback(data)`\n /// @return The data returned by the call to `IUnlockCallback(msg.sender).unlockCallback(data)`\n function unlock(bytes calldata data) external returns (bytes memory);\n\n /// @notice Initialize the state for a given pool ID\n /// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee\n /// @param key The pool key for the pool to initialize\n /// @param sqrtPriceX96 The initial square root price\n /// @return tick The initial tick of the pool\n function initialize(PoolKey memory key, uint160 sqrtPriceX96) external returns (int24 tick);\n\n /// @notice Modify the liquidity for the given pool\n /// @dev Poke by calling with a zero liquidityDelta\n /// @param key The pool to modify liquidity in\n /// @param params The parameters for modifying the liquidity\n /// @param hookData The data to pass through to the add/removeLiquidity hooks\n /// @return callerDelta The balance delta of the caller of modifyLiquidity. This is the total of both principal, fee deltas, and hook deltas if applicable\n /// @return feesAccrued The balance delta of the fees generated in the liquidity range. Returned for informational purposes\n /// @dev Note that feesAccrued can be artificially inflated by a malicious actor and integrators should be careful using the value\n /// For pools with a single liquidity position, actors can donate to themselves to inflate feeGrowthGlobal (and consequently feesAccrued)\n /// atomically donating and collecting fees in the same unlockCallback may make the inflated value more extreme\n function modifyLiquidity(PoolKey memory key, ModifyLiquidityParams memory params, bytes calldata hookData)\n external\n returns (BalanceDelta callerDelta, BalanceDelta feesAccrued);\n\n /// @notice Swap against the given pool\n /// @param key The pool to swap in\n /// @param params The parameters for swapping\n /// @param hookData The data to pass through to the swap hooks\n /// @return swapDelta The balance delta of the address swapping\n /// @dev Swapping on low liquidity pools may cause unexpected swap amounts when liquidity available is less than amountSpecified.\n /// Additionally note that if interacting with hooks that have the BEFORE_SWAP_RETURNS_DELTA_FLAG or AFTER_SWAP_RETURNS_DELTA_FLAG\n /// the hook may alter the swap input/output. Integrators should perform checks on the returned swapDelta.\n function swap(PoolKey memory key, SwapParams memory params, bytes calldata hookData)\n external\n returns (BalanceDelta swapDelta);\n\n /// @notice Donate the given currency amounts to the in-range liquidity providers of a pool\n /// @dev Calls to donate can be frontrun adding just-in-time liquidity, with the aim of receiving a portion donated funds.\n /// Donors should keep this in mind when designing donation mechanisms.\n /// @dev This function donates to in-range LPs at slot0.tick. In certain edge-cases of the swap algorithm, the `sqrtPrice` of\n /// a pool can be at the lower boundary of tick `n`, but the `slot0.tick` of the pool is already `n - 1`. In this case a call to\n /// `donate` would donate to tick `n - 1` (slot0.tick) not tick `n` (getTickAtSqrtPrice(slot0.sqrtPriceX96)).\n /// Read the comments in `Pool.swap()` for more information about this.\n /// @param key The key of the pool to donate to\n /// @param amount0 The amount of currency0 to donate\n /// @param amount1 The amount of currency1 to donate\n /// @param hookData The data to pass through to the donate hooks\n /// @return BalanceDelta The delta of the caller after the donate\n function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData)\n external\n returns (BalanceDelta);\n\n /// @notice Writes the current ERC20 balance of the specified currency to transient storage\n /// This is used to checkpoint balances for the manager and derive deltas for the caller.\n /// @dev This MUST be called before any ERC20 tokens are sent into the contract, but can be skipped\n /// for native tokens because the amount to settle is determined by the sent value.\n /// However, if an ERC20 token has been synced and not settled, and the caller instead wants to settle\n /// native funds, this function can be called with the native currency to then be able to settle the native currency\n function sync(Currency currency) external;\n\n /// @notice Called by the user to net out some value owed to the user\n /// @dev Will revert if the requested amount is not available, consider using `mint` instead\n /// @dev Can also be used as a mechanism for free flash loans\n /// @param currency The currency to withdraw from the pool manager\n /// @param to The address to withdraw to\n /// @param amount The amount of currency to withdraw\n function take(Currency currency, address to, uint256 amount) external;\n\n /// @notice Called by the user to pay what is owed\n /// @return paid The amount of currency settled\n function settle() external payable returns (uint256 paid);\n\n /// @notice Called by the user to pay on behalf of another address\n /// @param recipient The address to credit for the payment\n /// @return paid The amount of currency settled\n function settleFor(address recipient) external payable returns (uint256 paid);\n\n /// @notice WARNING - Any currency that is cleared, will be non-retrievable, and locked in the contract permanently.\n /// A call to clear will zero out a positive balance WITHOUT a corresponding transfer.\n /// @dev This could be used to clear a balance that is considered dust.\n /// Additionally, the amount must be the exact positive balance. This is to enforce that the caller is aware of the amount being cleared.\n function clear(Currency currency, uint256 amount) external;\n\n /// @notice Called by the user to move value into ERC6909 balance\n /// @param to The address to mint the tokens to\n /// @param id The currency address to mint to ERC6909s, as a uint256\n /// @param amount The amount of currency to mint\n /// @dev The id is converted to a uint160 to correspond to a currency address\n /// If the upper 12 bytes are not 0, they will be 0-ed out\n function mint(address to, uint256 id, uint256 amount) external;\n\n /// @notice Called by the user to move value from ERC6909 balance\n /// @param from The address to burn the tokens from\n /// @param id The currency address to burn from ERC6909s, as a uint256\n /// @param amount The amount of currency to burn\n /// @dev The id is converted to a uint160 to correspond to a currency address\n /// If the upper 12 bytes are not 0, they will be 0-ed out\n function burn(address from, uint256 id, uint256 amount) external;\n\n /// @notice Updates the pools lp fees for the a pool that has enabled dynamic lp fees.\n /// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee\n /// @param key The key of the pool to update dynamic LP fees for\n /// @param newDynamicLPFee The new dynamic pool LP fee\n function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external;\n}\n", + "@uniswap/v4-core/src/interfaces/IProtocolFees.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Currency} from \"../types/Currency.sol\";\nimport {PoolId} from \"../types/PoolId.sol\";\nimport {PoolKey} from \"../types/PoolKey.sol\";\n\n/// @notice Interface for all protocol-fee related functions in the pool manager\ninterface IProtocolFees {\n /// @notice Thrown when protocol fee is set too high\n error ProtocolFeeTooLarge(uint24 fee);\n\n /// @notice Thrown when collectProtocolFees or setProtocolFee is not called by the controller.\n error InvalidCaller();\n\n /// @notice Thrown when collectProtocolFees is attempted on a token that is synced.\n error ProtocolFeeCurrencySynced();\n\n /// @notice Emitted when the protocol fee controller address is updated in setProtocolFeeController.\n event ProtocolFeeControllerUpdated(address indexed protocolFeeController);\n\n /// @notice Emitted when the protocol fee is updated for a pool.\n event ProtocolFeeUpdated(PoolId indexed id, uint24 protocolFee);\n\n /// @notice Given a currency address, returns the protocol fees accrued in that currency\n /// @param currency The currency to check\n /// @return amount The amount of protocol fees accrued in the currency\n function protocolFeesAccrued(Currency currency) external view returns (uint256 amount);\n\n /// @notice Sets the protocol fee for the given pool\n /// @param key The key of the pool to set a protocol fee for\n /// @param newProtocolFee The fee to set\n function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external;\n\n /// @notice Sets the protocol fee controller\n /// @param controller The new protocol fee controller\n function setProtocolFeeController(address controller) external;\n\n /// @notice Collects the protocol fees for a given recipient and currency, returning the amount collected\n /// @dev This will revert if the contract is unlocked\n /// @param recipient The address to receive the protocol fees\n /// @param currency The currency to withdraw\n /// @param amount The amount of currency to withdraw\n /// @return amountCollected The amount of currency successfully withdrawn\n function collectProtocolFees(address recipient, Currency currency, uint256 amount)\n external\n returns (uint256 amountCollected);\n\n /// @notice Returns the current protocol fee controller address\n /// @return address The current protocol fee controller address\n function protocolFeeController() external view returns (address);\n}\n", + "@uniswap/v4-core/src/interfaces/external/IERC20Minimal.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Minimal ERC20 interface for Uniswap\n/// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3\ninterface IERC20Minimal {\n /// @notice Returns an account's balance in the token\n /// @param account The account for which to look up the number of tokens it has, i.e. its balance\n /// @return The number of tokens held by the account\n function balanceOf(address account) external view returns (uint256);\n\n /// @notice Transfers the amount of token from the `msg.sender` to the recipient\n /// @param recipient The account that will receive the amount transferred\n /// @param amount The number of tokens to send from the sender to the recipient\n /// @return Returns true for a successful transfer, false for an unsuccessful transfer\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /// @notice Returns the current allowance given to a spender by an owner\n /// @param owner The account of the token owner\n /// @param spender The account of the token spender\n /// @return The current allowance granted by `owner` to `spender`\n function allowance(address owner, address spender) external view returns (uint256);\n\n /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount`\n /// @param spender The account which will be allowed to spend a given amount of the owners tokens\n /// @param amount The amount of tokens allowed to be used by `spender`\n /// @return Returns true for a successful approval, false for unsuccessful\n function approve(address spender, uint256 amount) external returns (bool);\n\n /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender`\n /// @param sender The account from which the transfer will be initiated\n /// @param recipient The recipient of the transfer\n /// @param amount The amount of the transfer\n /// @return Returns true for a successful transfer, false for unsuccessful\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`.\n /// @param from The account from which the tokens were sent, i.e. the balance decreased\n /// @param to The account to which the tokens were sent, i.e. the balance increased\n /// @param value The amount of tokens that were transferred\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes.\n /// @param owner The account that approved spending of its tokens\n /// @param spender The account for which the spending allowance was modified\n /// @param value The new allowance from the owner to the spender\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n", + "@uniswap/v4-core/src/interfaces/external/IERC6909Claims.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @notice Interface for claims over a contract balance, wrapped as a ERC6909\ninterface IERC6909Claims {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event OperatorSet(address indexed owner, address indexed operator, bool approved);\n\n event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);\n\n event Transfer(address caller, address indexed from, address indexed to, uint256 indexed id, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n FUNCTIONS\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Owner balance of an id.\n /// @param owner The address of the owner.\n /// @param id The id of the token.\n /// @return amount The balance of the token.\n function balanceOf(address owner, uint256 id) external view returns (uint256 amount);\n\n /// @notice Spender allowance of an id.\n /// @param owner The address of the owner.\n /// @param spender The address of the spender.\n /// @param id The id of the token.\n /// @return amount The allowance of the token.\n function allowance(address owner, address spender, uint256 id) external view returns (uint256 amount);\n\n /// @notice Checks if a spender is approved by an owner as an operator\n /// @param owner The address of the owner.\n /// @param spender The address of the spender.\n /// @return approved The approval status.\n function isOperator(address owner, address spender) external view returns (bool approved);\n\n /// @notice Transfers an amount of an id from the caller to a receiver.\n /// @param receiver The address of the receiver.\n /// @param id The id of the token.\n /// @param amount The amount of the token.\n /// @return bool True, always, unless the function reverts\n function transfer(address receiver, uint256 id, uint256 amount) external returns (bool);\n\n /// @notice Transfers an amount of an id from a sender to a receiver.\n /// @param sender The address of the sender.\n /// @param receiver The address of the receiver.\n /// @param id The id of the token.\n /// @param amount The amount of the token.\n /// @return bool True, always, unless the function reverts\n function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool);\n\n /// @notice Approves an amount of an id to a spender.\n /// @param spender The address of the spender.\n /// @param id The id of the token.\n /// @param amount The amount of the token.\n /// @return bool True, always\n function approve(address spender, uint256 id, uint256 amount) external returns (bool);\n\n /// @notice Sets or removes an operator for the caller.\n /// @param operator The address of the operator.\n /// @param approved The approval status.\n /// @return bool True, always\n function setOperator(address operator, bool approved) external returns (bool);\n}\n", + "@uniswap/v4-core/src/libraries/BitMath.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title BitMath\n/// @dev This library provides functionality for computing bit properties of an unsigned integer\n/// @author Solady (https://github.com/Vectorized/solady/blob/8200a70e8dc2a77ecb074fc2e99a2a0d36547522/src/utils/LibBit.sol)\nlibrary BitMath {\n /// @notice Returns the index of the most significant bit of the number,\n /// where the least significant bit is at index 0 and the most significant bit is at index 255\n /// @param x the value for which to compute the most significant bit, must be greater than 0\n /// @return r the index of the most significant bit\n function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {\n require(x > 0);\n\n assembly (\"memory-safe\") {\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffff, shr(r, x))))\n r := or(r, shl(3, lt(0xff, shr(r, x))))\n // forgefmt: disable-next-item\n r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),\n 0x0706060506020500060203020504000106050205030304010505030400000000))\n }\n }\n\n /// @notice Returns the index of the least significant bit of the number,\n /// where the least significant bit is at index 0 and the most significant bit is at index 255\n /// @param x the value for which to compute the least significant bit, must be greater than 0\n /// @return r the index of the least significant bit\n function leastSignificantBit(uint256 x) internal pure returns (uint8 r) {\n require(x > 0);\n\n assembly (\"memory-safe\") {\n // Isolate the least significant bit.\n x := and(x, sub(0, x))\n // For the upper 3 bits of the result, use a De Bruijn-like lookup.\n // Credit to adhusson: https://blog.adhusson.com/cheap-find-first-set-evm/\n // forgefmt: disable-next-item\n r := shl(5, shr(252, shl(shl(2, shr(250, mul(x,\n 0xb6db6db6ddddddddd34d34d349249249210842108c6318c639ce739cffffffff))),\n 0x8040405543005266443200005020610674053026020000107506200176117077)))\n // For the lower 5 bits of the result, use a De Bruijn lookup.\n // forgefmt: disable-next-item\n r := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f),\n 0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))\n }\n }\n}\n", + "@uniswap/v4-core/src/libraries/CustomRevert.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Library for reverting with custom errors efficiently\n/// @notice Contains functions for reverting with custom errors with different argument types efficiently\n/// @dev To use this library, declare `using CustomRevert for bytes4;` and replace `revert CustomError()` with\n/// `CustomError.selector.revertWith()`\n/// @dev The functions may tamper with the free memory pointer but it is fine since the call context is exited immediately\nlibrary CustomRevert {\n /// @dev ERC-7751 error for wrapping bubbled up reverts\n error WrappedError(address target, bytes4 selector, bytes reason, bytes details);\n\n /// @dev Reverts with the selector of a custom error in the scratch space\n function revertWith(bytes4 selector) internal pure {\n assembly (\"memory-safe\") {\n mstore(0, selector)\n revert(0, 0x04)\n }\n }\n\n /// @dev Reverts with a custom error with an address argument in the scratch space\n function revertWith(bytes4 selector, address addr) internal pure {\n assembly (\"memory-safe\") {\n mstore(0, selector)\n mstore(0x04, and(addr, 0xffffffffffffffffffffffffffffffffffffffff))\n revert(0, 0x24)\n }\n }\n\n /// @dev Reverts with a custom error with an int24 argument in the scratch space\n function revertWith(bytes4 selector, int24 value) internal pure {\n assembly (\"memory-safe\") {\n mstore(0, selector)\n mstore(0x04, signextend(2, value))\n revert(0, 0x24)\n }\n }\n\n /// @dev Reverts with a custom error with a uint160 argument in the scratch space\n function revertWith(bytes4 selector, uint160 value) internal pure {\n assembly (\"memory-safe\") {\n mstore(0, selector)\n mstore(0x04, and(value, 0xffffffffffffffffffffffffffffffffffffffff))\n revert(0, 0x24)\n }\n }\n\n /// @dev Reverts with a custom error with two int24 arguments\n function revertWith(bytes4 selector, int24 value1, int24 value2) internal pure {\n assembly (\"memory-safe\") {\n let fmp := mload(0x40)\n mstore(fmp, selector)\n mstore(add(fmp, 0x04), signextend(2, value1))\n mstore(add(fmp, 0x24), signextend(2, value2))\n revert(fmp, 0x44)\n }\n }\n\n /// @dev Reverts with a custom error with two uint160 arguments\n function revertWith(bytes4 selector, uint160 value1, uint160 value2) internal pure {\n assembly (\"memory-safe\") {\n let fmp := mload(0x40)\n mstore(fmp, selector)\n mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff))\n revert(fmp, 0x44)\n }\n }\n\n /// @dev Reverts with a custom error with two address arguments\n function revertWith(bytes4 selector, address value1, address value2) internal pure {\n assembly (\"memory-safe\") {\n let fmp := mload(0x40)\n mstore(fmp, selector)\n mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff))\n revert(fmp, 0x44)\n }\n }\n\n /// @notice bubble up the revert message returned by a call and revert with a wrapped ERC-7751 error\n /// @dev this method can be vulnerable to revert data bombs\n function bubbleUpAndRevertWith(\n address revertingContract,\n bytes4 revertingFunctionSelector,\n bytes4 additionalContext\n ) internal pure {\n bytes4 wrappedErrorSelector = WrappedError.selector;\n assembly (\"memory-safe\") {\n // Ensure the size of the revert data is a multiple of 32 bytes\n let encodedDataSize := mul(div(add(returndatasize(), 31), 32), 32)\n\n let fmp := mload(0x40)\n\n // Encode wrapped error selector, address, function selector, offset, additional context, size, revert reason\n mstore(fmp, wrappedErrorSelector)\n mstore(add(fmp, 0x04), and(revertingContract, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(\n add(fmp, 0x24),\n and(revertingFunctionSelector, 0xffffffff00000000000000000000000000000000000000000000000000000000)\n )\n // offset revert reason\n mstore(add(fmp, 0x44), 0x80)\n // offset additional context\n mstore(add(fmp, 0x64), add(0xa0, encodedDataSize))\n // size revert reason\n mstore(add(fmp, 0x84), returndatasize())\n // revert reason\n returndatacopy(add(fmp, 0xa4), 0, returndatasize())\n // size additional context\n mstore(add(fmp, add(0xa4, encodedDataSize)), 0x04)\n // additional context\n mstore(\n add(fmp, add(0xc4, encodedDataSize)),\n and(additionalContext, 0xffffffff00000000000000000000000000000000000000000000000000000000)\n )\n revert(fmp, add(0xe4, encodedDataSize))\n }\n }\n}\n", + "@uniswap/v4-core/src/libraries/FixedPoint96.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title FixedPoint96\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\n/// @dev Used in SqrtPriceMath.sol\nlibrary FixedPoint96 {\n uint8 internal constant RESOLUTION = 96;\n uint256 internal constant Q96 = 0x1000000000000000000000000;\n}\n", + "@uniswap/v4-core/src/libraries/FullMath.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Contains 512-bit math functions\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\n/// @dev Handles \"phantom overflow\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\nlibrary FullMath {\n /// @notice Calculates floor(a\u00d7b\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n /// @param a The multiplicand\n /// @param b The multiplier\n /// @param denominator The divisor\n /// @return result The 256-bit result\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\n function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = a * b\n // Compute the product mod 2**256 and mod 2**256 - 1\n // then use the Chinese Remainder Theorem to reconstruct\n // the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2**256 + prod0\n uint256 prod0 = a * b; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly (\"memory-safe\") {\n let mm := mulmod(a, b, not(0))\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Make sure the result is less than 2**256.\n // Also prevents denominator == 0\n require(denominator > prod1);\n\n // Handle non-overflow cases, 256 by 256 division\n if (prod1 == 0) {\n assembly (\"memory-safe\") {\n result := div(prod0, denominator)\n }\n return result;\n }\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0]\n // Compute remainder using mulmod\n uint256 remainder;\n assembly (\"memory-safe\") {\n remainder := mulmod(a, b, denominator)\n }\n // Subtract 256 bit number from 512 bit number\n assembly (\"memory-safe\") {\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator\n // Compute largest power of two divisor of denominator.\n // Always >= 1.\n uint256 twos = (0 - denominator) & denominator;\n // Divide denominator by power of two\n assembly (\"memory-safe\") {\n denominator := div(denominator, twos)\n }\n\n // Divide [prod1 prod0] by the factors of two\n assembly (\"memory-safe\") {\n prod0 := div(prod0, twos)\n }\n // Shift in bits from prod1 into prod0. For this we need\n // to flip `twos` such that it is 2**256 / twos.\n // If twos is zero, then it becomes one\n assembly (\"memory-safe\") {\n twos := add(div(sub(0, twos), twos), 1)\n }\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2**256\n // Now that denominator is an odd number, it has an inverse\n // modulo 2**256 such that denominator * inv = 1 mod 2**256.\n // Compute the inverse by starting with a seed that is correct\n // correct for four bits. That is, denominator * inv = 1 mod 2**4\n uint256 inv = (3 * denominator) ^ 2;\n // Now use Newton-Raphson iteration to improve the precision.\n // Thanks to Hensel's lifting lemma, this also works in modular\n // arithmetic, doubling the correct bits in each step.\n inv *= 2 - denominator * inv; // inverse mod 2**8\n inv *= 2 - denominator * inv; // inverse mod 2**16\n inv *= 2 - denominator * inv; // inverse mod 2**32\n inv *= 2 - denominator * inv; // inverse mod 2**64\n inv *= 2 - denominator * inv; // inverse mod 2**128\n inv *= 2 - denominator * inv; // inverse mod 2**256\n\n // Because the division is now exact we can divide by multiplying\n // with the modular inverse of denominator. This will give us the\n // correct result modulo 2**256. Since the preconditions guarantee\n // that the outcome is less than 2**256, this is the final result.\n // We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inv;\n return result;\n }\n }\n\n /// @notice Calculates ceil(a\u00d7b\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n /// @param a The multiplicand\n /// @param b The multiplier\n /// @param denominator The divisor\n /// @return result The 256-bit result\n function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n result = mulDiv(a, b, denominator);\n if (mulmod(a, b, denominator) != 0) {\n require(++result > 0);\n }\n }\n }\n}\n", + "@uniswap/v4-core/src/libraries/SafeCast.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {CustomRevert} from \"./CustomRevert.sol\";\n\n/// @title Safe casting methods\n/// @notice Contains methods for safely casting between types\nlibrary SafeCast {\n using CustomRevert for bytes4;\n\n error SafeCastOverflow();\n\n /// @notice Cast a uint256 to a uint160, revert on overflow\n /// @param x The uint256 to be downcasted\n /// @return y The downcasted integer, now type uint160\n function toUint160(uint256 x) internal pure returns (uint160 y) {\n y = uint160(x);\n if (y != x) SafeCastOverflow.selector.revertWith();\n }\n\n /// @notice Cast a uint256 to a uint128, revert on overflow\n /// @param x The uint256 to be downcasted\n /// @return y The downcasted integer, now type uint128\n function toUint128(uint256 x) internal pure returns (uint128 y) {\n y = uint128(x);\n if (x != y) SafeCastOverflow.selector.revertWith();\n }\n\n /// @notice Cast a int128 to a uint128, revert on overflow or underflow\n /// @param x The int128 to be casted\n /// @return y The casted integer, now type uint128\n function toUint128(int128 x) internal pure returns (uint128 y) {\n if (x < 0) SafeCastOverflow.selector.revertWith();\n y = uint128(x);\n }\n\n /// @notice Cast a int256 to a int128, revert on overflow or underflow\n /// @param x The int256 to be downcasted\n /// @return y The downcasted integer, now type int128\n function toInt128(int256 x) internal pure returns (int128 y) {\n y = int128(x);\n if (y != x) SafeCastOverflow.selector.revertWith();\n }\n\n /// @notice Cast a uint256 to a int256, revert on overflow\n /// @param x The uint256 to be casted\n /// @return y The casted integer, now type int256\n function toInt256(uint256 x) internal pure returns (int256 y) {\n y = int256(x);\n if (y < 0) SafeCastOverflow.selector.revertWith();\n }\n\n /// @notice Cast a uint256 to a int128, revert on overflow\n /// @param x The uint256 to be downcasted\n /// @return The downcasted integer, now type int128\n function toInt128(uint256 x) internal pure returns (int128) {\n if (x >= 1 << 127) SafeCastOverflow.selector.revertWith();\n return int128(int256(x));\n }\n}\n", + "@uniswap/v4-core/src/libraries/TickMath.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {BitMath} from \"./BitMath.sol\";\nimport {CustomRevert} from \"./CustomRevert.sol\";\n\n/// @title Math library for computing sqrt prices from ticks and vice versa\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\n/// prices between 2**-128 and 2**128\nlibrary TickMath {\n using CustomRevert for bytes4;\n\n /// @notice Thrown when the tick passed to #getSqrtPriceAtTick is not between MIN_TICK and MAX_TICK\n error InvalidTick(int24 tick);\n /// @notice Thrown when the price passed to #getTickAtSqrtPrice does not correspond to a price between MIN_TICK and MAX_TICK\n error InvalidSqrtPrice(uint160 sqrtPriceX96);\n\n /// @dev The minimum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**-128\n /// @dev If ever MIN_TICK and MAX_TICK are not centered around 0, the absTick logic in getSqrtPriceAtTick cannot be used\n int24 internal constant MIN_TICK = -887272;\n /// @dev The maximum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**128\n /// @dev If ever MIN_TICK and MAX_TICK are not centered around 0, the absTick logic in getSqrtPriceAtTick cannot be used\n int24 internal constant MAX_TICK = 887272;\n\n /// @dev The minimum tick spacing value drawn from the range of type int16 that is greater than 0, i.e. min from the range [1, 32767]\n int24 internal constant MIN_TICK_SPACING = 1;\n /// @dev The maximum tick spacing value drawn from the range of type int16, i.e. max from the range [1, 32767]\n int24 internal constant MAX_TICK_SPACING = type(int16).max;\n\n /// @dev The minimum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MIN_TICK)\n uint160 internal constant MIN_SQRT_PRICE = 4295128739;\n /// @dev The maximum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MAX_TICK)\n uint160 internal constant MAX_SQRT_PRICE = 1461446703485210103287273052203988822378723970342;\n /// @dev A threshold used for optimized bounds check, equals `MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1`\n uint160 internal constant MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE =\n 1461446703485210103287273052203988822378723970342 - 4295128739 - 1;\n\n /// @notice Given a tickSpacing, compute the maximum usable tick\n function maxUsableTick(int24 tickSpacing) internal pure returns (int24) {\n unchecked {\n return (MAX_TICK / tickSpacing) * tickSpacing;\n }\n }\n\n /// @notice Given a tickSpacing, compute the minimum usable tick\n function minUsableTick(int24 tickSpacing) internal pure returns (int24) {\n unchecked {\n return (MIN_TICK / tickSpacing) * tickSpacing;\n }\n }\n\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\n /// @dev Throws if |tick| > max tick\n /// @param tick The input tick for the above formula\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the price of the two assets (currency1/currency0)\n /// at the given tick\n function getSqrtPriceAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\n unchecked {\n uint256 absTick;\n assembly (\"memory-safe\") {\n tick := signextend(2, tick)\n // mask = 0 if tick >= 0 else -1 (all 1s)\n let mask := sar(255, tick)\n // if tick >= 0, |tick| = tick = 0 ^ tick\n // if tick < 0, |tick| = ~~|tick| = ~(-|tick| - 1) = ~(tick - 1) = (-1) ^ (tick - 1)\n // either way, |tick| = mask ^ (tick + mask)\n absTick := xor(mask, add(mask, tick))\n }\n\n if (absTick > uint256(int256(MAX_TICK))) InvalidTick.selector.revertWith(tick);\n\n // The tick is decomposed into bits, and for each bit with index i that is set, the product of 1/sqrt(1.0001^(2^i))\n // is calculated (using Q128.128). The constants used for this calculation are rounded to the nearest integer\n\n // Equivalent to:\n // price = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\n // or price = int(2**128 / sqrt(1.0001)) if (absTick & 0x1) else 1 << 128\n uint256 price;\n assembly (\"memory-safe\") {\n price := xor(shl(128, 1), mul(xor(shl(128, 1), 0xfffcb933bd6fad37aa2d162d1a594001), and(absTick, 0x1)))\n }\n if (absTick & 0x2 != 0) price = (price * 0xfff97272373d413259a46990580e213a) >> 128;\n if (absTick & 0x4 != 0) price = (price * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\n if (absTick & 0x8 != 0) price = (price * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\n if (absTick & 0x10 != 0) price = (price * 0xffcb9843d60f6159c9db58835c926644) >> 128;\n if (absTick & 0x20 != 0) price = (price * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\n if (absTick & 0x40 != 0) price = (price * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\n if (absTick & 0x80 != 0) price = (price * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\n if (absTick & 0x100 != 0) price = (price * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\n if (absTick & 0x200 != 0) price = (price * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\n if (absTick & 0x400 != 0) price = (price * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\n if (absTick & 0x800 != 0) price = (price * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\n if (absTick & 0x1000 != 0) price = (price * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\n if (absTick & 0x2000 != 0) price = (price * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\n if (absTick & 0x4000 != 0) price = (price * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\n if (absTick & 0x8000 != 0) price = (price * 0x31be135f97d08fd981231505542fcfa6) >> 128;\n if (absTick & 0x10000 != 0) price = (price * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\n if (absTick & 0x20000 != 0) price = (price * 0x5d6af8dedb81196699c329225ee604) >> 128;\n if (absTick & 0x40000 != 0) price = (price * 0x2216e584f5fa1ea926041bedfe98) >> 128;\n if (absTick & 0x80000 != 0) price = (price * 0x48a170391f7dc42444e8fa2) >> 128;\n\n assembly (\"memory-safe\") {\n // if (tick > 0) price = type(uint256).max / price;\n if sgt(tick, 0) { price := div(not(0), price) }\n\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\n // we round up in the division so getTickAtSqrtPrice of the output price is always consistent\n // `sub(shl(32, 1), 1)` is `type(uint32).max`\n // `price + type(uint32).max` will not overflow because `price` fits in 192 bits\n sqrtPriceX96 := shr(32, add(price, sub(shl(32, 1), 1)))\n }\n }\n }\n\n /// @notice Calculates the greatest tick value such that getSqrtPriceAtTick(tick) <= sqrtPriceX96\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_PRICE, as MIN_SQRT_PRICE is the lowest value getSqrtPriceAtTick may\n /// ever return.\n /// @param sqrtPriceX96 The sqrt price for which to compute the tick as a Q64.96\n /// @return tick The greatest tick for which the getSqrtPriceAtTick(tick) is less than or equal to the input sqrtPriceX96\n function getTickAtSqrtPrice(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\n unchecked {\n // Equivalent: if (sqrtPriceX96 < MIN_SQRT_PRICE || sqrtPriceX96 >= MAX_SQRT_PRICE) revert InvalidSqrtPrice();\n // second inequality must be >= because the price can never reach the price at the max tick\n // if sqrtPriceX96 < MIN_SQRT_PRICE, the `sub` underflows and `gt` is true\n // if sqrtPriceX96 >= MAX_SQRT_PRICE, sqrtPriceX96 - MIN_SQRT_PRICE > MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1\n if ((sqrtPriceX96 - MIN_SQRT_PRICE) > MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE) {\n InvalidSqrtPrice.selector.revertWith(sqrtPriceX96);\n }\n\n uint256 price = uint256(sqrtPriceX96) << 32;\n\n uint256 r = price;\n uint256 msb = BitMath.mostSignificantBit(r);\n\n if (msb >= 128) r = price >> (msb - 127);\n else r = price << (127 - msb);\n\n int256 log_2 = (int256(msb) - 128) << 64;\n\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(63, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(62, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(61, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(60, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(59, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(58, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(57, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(56, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(55, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(54, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(53, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(52, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(51, f))\n r := shr(f, r)\n }\n assembly (\"memory-safe\") {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(50, f))\n }\n\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // Q22.128 number\n\n // Magic number represents the ceiling of the maximum value of the error when approximating log_sqrt10001(x)\n int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\n\n // Magic number represents the minimum value of the error when approximating log_sqrt10001(x), when\n // sqrtPrice is from the range (2^-64, 2^64). This is safe as MIN_SQRT_PRICE is more than 2^-64. If MIN_SQRT_PRICE\n // is changed, this may need to be changed too\n int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\n\n tick = tickLow == tickHi ? tickLow : getSqrtPriceAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\n }\n }\n}\n", + "@uniswap/v4-core/src/types/BalanceDelta.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {SafeCast} from \"../libraries/SafeCast.sol\";\n\n/// @dev Two `int128` values packed into a single `int256` where the upper 128 bits represent the amount0\n/// and the lower 128 bits represent the amount1.\ntype BalanceDelta is int256;\n\nusing {add as +, sub as -, eq as ==, neq as !=} for BalanceDelta global;\nusing BalanceDeltaLibrary for BalanceDelta global;\nusing SafeCast for int256;\n\nfunction toBalanceDelta(int128 _amount0, int128 _amount1) pure returns (BalanceDelta balanceDelta) {\n assembly (\"memory-safe\") {\n balanceDelta := or(shl(128, _amount0), and(sub(shl(128, 1), 1), _amount1))\n }\n}\n\nfunction add(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {\n int256 res0;\n int256 res1;\n assembly (\"memory-safe\") {\n let a0 := sar(128, a)\n let a1 := signextend(15, a)\n let b0 := sar(128, b)\n let b1 := signextend(15, b)\n res0 := add(a0, b0)\n res1 := add(a1, b1)\n }\n return toBalanceDelta(res0.toInt128(), res1.toInt128());\n}\n\nfunction sub(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {\n int256 res0;\n int256 res1;\n assembly (\"memory-safe\") {\n let a0 := sar(128, a)\n let a1 := signextend(15, a)\n let b0 := sar(128, b)\n let b1 := signextend(15, b)\n res0 := sub(a0, b0)\n res1 := sub(a1, b1)\n }\n return toBalanceDelta(res0.toInt128(), res1.toInt128());\n}\n\nfunction eq(BalanceDelta a, BalanceDelta b) pure returns (bool) {\n return BalanceDelta.unwrap(a) == BalanceDelta.unwrap(b);\n}\n\nfunction neq(BalanceDelta a, BalanceDelta b) pure returns (bool) {\n return BalanceDelta.unwrap(a) != BalanceDelta.unwrap(b);\n}\n\n/// @notice Library for getting the amount0 and amount1 deltas from the BalanceDelta type\nlibrary BalanceDeltaLibrary {\n /// @notice A BalanceDelta of 0\n BalanceDelta public constant ZERO_DELTA = BalanceDelta.wrap(0);\n\n function amount0(BalanceDelta balanceDelta) internal pure returns (int128 _amount0) {\n assembly (\"memory-safe\") {\n _amount0 := sar(128, balanceDelta)\n }\n }\n\n function amount1(BalanceDelta balanceDelta) internal pure returns (int128 _amount1) {\n assembly (\"memory-safe\") {\n _amount1 := signextend(15, balanceDelta)\n }\n }\n}\n", + "@uniswap/v4-core/src/types/BeforeSwapDelta.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Return type of the beforeSwap hook.\n// Upper 128 bits is the delta in specified tokens. Lower 128 bits is delta in unspecified tokens (to match the afterSwap hook)\ntype BeforeSwapDelta is int256;\n\n// Creates a BeforeSwapDelta from specified and unspecified\nfunction toBeforeSwapDelta(int128 deltaSpecified, int128 deltaUnspecified)\n pure\n returns (BeforeSwapDelta beforeSwapDelta)\n{\n assembly (\"memory-safe\") {\n beforeSwapDelta := or(shl(128, deltaSpecified), and(sub(shl(128, 1), 1), deltaUnspecified))\n }\n}\n\n/// @notice Library for getting the specified and unspecified deltas from the BeforeSwapDelta type\nlibrary BeforeSwapDeltaLibrary {\n /// @notice A BeforeSwapDelta of 0\n BeforeSwapDelta public constant ZERO_DELTA = BeforeSwapDelta.wrap(0);\n\n /// extracts int128 from the upper 128 bits of the BeforeSwapDelta\n /// returned by beforeSwap\n function getSpecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaSpecified) {\n assembly (\"memory-safe\") {\n deltaSpecified := sar(128, delta)\n }\n }\n\n /// extracts int128 from the lower 128 bits of the BeforeSwapDelta\n /// returned by beforeSwap and afterSwap\n function getUnspecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaUnspecified) {\n assembly (\"memory-safe\") {\n deltaUnspecified := signextend(15, delta)\n }\n }\n}\n", + "@uniswap/v4-core/src/types/Currency.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20Minimal} from \"../interfaces/external/IERC20Minimal.sol\";\nimport {CustomRevert} from \"../libraries/CustomRevert.sol\";\n\ntype Currency is address;\n\nusing {greaterThan as >, lessThan as <, greaterThanOrEqualTo as >=, equals as ==} for Currency global;\nusing CurrencyLibrary for Currency global;\n\nfunction equals(Currency currency, Currency other) pure returns (bool) {\n return Currency.unwrap(currency) == Currency.unwrap(other);\n}\n\nfunction greaterThan(Currency currency, Currency other) pure returns (bool) {\n return Currency.unwrap(currency) > Currency.unwrap(other);\n}\n\nfunction lessThan(Currency currency, Currency other) pure returns (bool) {\n return Currency.unwrap(currency) < Currency.unwrap(other);\n}\n\nfunction greaterThanOrEqualTo(Currency currency, Currency other) pure returns (bool) {\n return Currency.unwrap(currency) >= Currency.unwrap(other);\n}\n\n/// @title CurrencyLibrary\n/// @dev This library allows for transferring and holding native tokens and ERC20 tokens\nlibrary CurrencyLibrary {\n /// @notice Additional context for ERC-7751 wrapped error when a native transfer fails\n error NativeTransferFailed();\n\n /// @notice Additional context for ERC-7751 wrapped error when an ERC20 transfer fails\n error ERC20TransferFailed();\n\n /// @notice A constant to represent the native currency\n Currency public constant ADDRESS_ZERO = Currency.wrap(address(0));\n\n function transfer(Currency currency, address to, uint256 amount) internal {\n // altered from https://github.com/transmissions11/solmate/blob/44a9963d4c78111f77caa0e65d677b8b46d6f2e6/src/utils/SafeTransferLib.sol\n // modified custom error selectors\n\n bool success;\n if (currency.isAddressZero()) {\n assembly (\"memory-safe\") {\n // Transfer the ETH and revert if it fails.\n success := call(gas(), to, amount, 0, 0, 0, 0)\n }\n // revert with NativeTransferFailed, containing the bubbled up error as an argument\n if (!success) {\n CustomRevert.bubbleUpAndRevertWith(to, bytes4(0), NativeTransferFailed.selector);\n }\n } else {\n assembly (\"memory-safe\") {\n // Get a pointer to some free memory.\n let fmp := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(fmp, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n mstore(add(fmp, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to\" argument.\n mstore(add(fmp, 36), amount) // Append the \"amount\" argument. Masking not required as it's a full 32 byte type.\n\n success :=\n and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), currency, 0, fmp, 68, 0, 32)\n )\n\n // Now clean the memory we used\n mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were stored here\n mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here\n mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored here\n }\n // revert with ERC20TransferFailed, containing the bubbled up error as an argument\n if (!success) {\n CustomRevert.bubbleUpAndRevertWith(\n Currency.unwrap(currency), IERC20Minimal.transfer.selector, ERC20TransferFailed.selector\n );\n }\n }\n }\n\n function balanceOfSelf(Currency currency) internal view returns (uint256) {\n if (currency.isAddressZero()) {\n return address(this).balance;\n } else {\n return IERC20Minimal(Currency.unwrap(currency)).balanceOf(address(this));\n }\n }\n\n function balanceOf(Currency currency, address owner) internal view returns (uint256) {\n if (currency.isAddressZero()) {\n return owner.balance;\n } else {\n return IERC20Minimal(Currency.unwrap(currency)).balanceOf(owner);\n }\n }\n\n function isAddressZero(Currency currency) internal pure returns (bool) {\n return Currency.unwrap(currency) == Currency.unwrap(ADDRESS_ZERO);\n }\n\n function toId(Currency currency) internal pure returns (uint256) {\n return uint160(Currency.unwrap(currency));\n }\n\n // If the upper 12 bytes are non-zero, they will be zero-ed out\n // Therefore, fromId() and toId() are not inverses of each other\n function fromId(uint256 id) internal pure returns (Currency) {\n return Currency.wrap(address(uint160(id)));\n }\n}\n", + "@uniswap/v4-core/src/types/PoolId.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {PoolKey} from \"./PoolKey.sol\";\n\ntype PoolId is bytes32;\n\n/// @notice Library for computing the ID of a pool\nlibrary PoolIdLibrary {\n /// @notice Returns value equal to keccak256(abi.encode(poolKey))\n function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) {\n assembly (\"memory-safe\") {\n // 0xa0 represents the total size of the poolKey struct (5 slots of 32 bytes)\n poolId := keccak256(poolKey, 0xa0)\n }\n }\n}\n", + "@uniswap/v4-core/src/types/PoolKey.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Currency} from \"./Currency.sol\";\nimport {IHooks} from \"../interfaces/IHooks.sol\";\nimport {PoolIdLibrary} from \"./PoolId.sol\";\n\nusing PoolIdLibrary for PoolKey global;\n\n/// @notice Returns the key for identifying a pool\nstruct PoolKey {\n /// @notice The lower currency of the pool, sorted numerically\n Currency currency0;\n /// @notice The higher currency of the pool, sorted numerically\n Currency currency1;\n /// @notice The pool LP fee, capped at 1_000_000. If the highest bit is 1, the pool has a dynamic fee and must be exactly equal to 0x800000\n uint24 fee;\n /// @notice Ticks that involve positions must be a multiple of tick spacing\n int24 tickSpacing;\n /// @notice The hooks of the pool\n IHooks hooks;\n}\n", + "@uniswap/v4-core/src/types/PoolOperation.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {PoolKey} from \"../types/PoolKey.sol\";\nimport {BalanceDelta} from \"../types/BalanceDelta.sol\";\n\n/// @notice Parameter struct for `ModifyLiquidity` pool operations\nstruct ModifyLiquidityParams {\n // the lower and upper tick of the position\n int24 tickLower;\n int24 tickUpper;\n // how to modify the liquidity\n int256 liquidityDelta;\n // a value to set if you want unique liquidity positions at the same range\n bytes32 salt;\n}\n\n/// @notice Parameter struct for `Swap` pool operations\nstruct SwapParams {\n /// Whether to swap token0 for token1 or vice versa\n bool zeroForOne;\n /// The desired input amount if negative (exactIn), or the desired output amount if positive (exactOut)\n int256 amountSpecified;\n /// The sqrt price at which, if reached, the swap will stop executing\n uint160 sqrtPriceLimitX96;\n}\n", + "@uniswap/v4-periphery/src/interfaces/IEIP712_v4.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title IEIP712_v4\n/// @notice Interface for the EIP712 contract\ninterface IEIP712_v4 {\n /// @notice Returns the domain separator for the current chain.\n /// @return bytes32 The domain separator\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n", + "@uniswap/v4-periphery/src/interfaces/IERC721Permit_v4.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title IERC721Permit_v4\n/// @notice Interface for the ERC721Permit_v4 contract\ninterface IERC721Permit_v4 {\n error SignatureDeadlineExpired();\n error NoSelfPermit();\n error Unauthorized();\n\n /// @notice Approve of a specific token ID for spending by spender via signature\n /// @param spender The account that is being approved\n /// @param tokenId The ID of the token that is being approved for spending\n /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\n /// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word\n /// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v)\n /// @dev payable so it can be multicalled with NATIVE related actions\n function permit(address spender, uint256 tokenId, uint256 deadline, uint256 nonce, bytes calldata signature)\n external\n payable;\n\n /// @notice Set an operator with full permission to an owner's tokens via signature\n /// @param owner The address that is setting the operator\n /// @param operator The address that will be set as an operator for the owner\n /// @param approved The permission to set on the operator\n /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\n /// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word\n /// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v)\n /// @dev payable so it can be multicalled with NATIVE related actions\n function permitForAll(\n address owner,\n address operator,\n bool approved,\n uint256 deadline,\n uint256 nonce,\n bytes calldata signature\n ) external payable;\n}\n", + "@uniswap/v4-periphery/src/interfaces/IImmutableState.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IPoolManager} from \"@uniswap/v4-core/src/interfaces/IPoolManager.sol\";\n\n/// @title IImmutableState\n/// @notice Interface for the ImmutableState contract\ninterface IImmutableState {\n /// @notice The Uniswap v4 PoolManager contract\n function poolManager() external view returns (IPoolManager);\n}\n", + "@uniswap/v4-periphery/src/interfaces/IMulticall_v4.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title IMulticall_v4\n/// @notice Interface for the Multicall_v4 contract\ninterface IMulticall_v4 {\n /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed\n /// @dev The `msg.value` is passed onto all subcalls, even if a previous subcall has consumed the ether.\n /// Subcalls can instead use `address(this).value` to see the available ETH, and consume it using {value: x}.\n /// @param data The encoded function data for each of the calls to make to this contract\n /// @return results The results from each of the calls passed in via data\n function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);\n}\n", + "@uniswap/v4-periphery/src/interfaces/INotifier.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {ISubscriber} from \"./ISubscriber.sol\";\n\n/// @title INotifier\n/// @notice Interface for the Notifier contract\ninterface INotifier {\n /// @notice Thrown when unsubscribing without a subscriber\n error NotSubscribed();\n /// @notice Thrown when a subscriber does not have code\n error NoCodeSubscriber();\n /// @notice Thrown when a user specifies a gas limit too low to avoid valid unsubscribe notifications\n error GasLimitTooLow();\n /// @notice Wraps the revert message of the subscriber contract on a reverting subscription\n error SubscriptionReverted(address subscriber, bytes reason);\n /// @notice Wraps the revert message of the subscriber contract on a reverting modify liquidity notification\n error ModifyLiquidityNotificationReverted(address subscriber, bytes reason);\n /// @notice Wraps the revert message of the subscriber contract on a reverting burn notification\n error BurnNotificationReverted(address subscriber, bytes reason);\n /// @notice Thrown when a tokenId already has a subscriber\n error AlreadySubscribed(uint256 tokenId, address subscriber);\n\n /// @notice Emitted on a successful call to subscribe\n event Subscription(uint256 indexed tokenId, address indexed subscriber);\n /// @notice Emitted on a successful call to unsubscribe\n event Unsubscription(uint256 indexed tokenId, address indexed subscriber);\n\n /// @notice Returns the subscriber for a respective position\n /// @param tokenId the ERC721 tokenId\n /// @return subscriber the subscriber contract\n function subscriber(uint256 tokenId) external view returns (ISubscriber subscriber);\n\n /// @notice Enables the subscriber to receive notifications for a respective position\n /// @param tokenId the ERC721 tokenId\n /// @param newSubscriber the address of the subscriber contract\n /// @param data caller-provided data that's forwarded to the subscriber contract\n /// @dev Calling subscribe when a position is already subscribed will revert\n /// @dev payable so it can be multicalled with NATIVE related actions\n /// @dev will revert if pool manager is locked\n function subscribe(uint256 tokenId, address newSubscriber, bytes calldata data) external payable;\n\n /// @notice Removes the subscriber from receiving notifications for a respective position\n /// @param tokenId the ERC721 tokenId\n /// @dev Callers must specify a high gas limit (remaining gas should be higher than unsubscriberGasLimit) such that the subscriber can be notified\n /// @dev payable so it can be multicalled with NATIVE related actions\n /// @dev Must always allow a user to unsubscribe. In the case of a malicious subscriber, a user can always unsubscribe safely, ensuring liquidity is always modifiable.\n /// @dev will revert if pool manager is locked\n function unsubscribe(uint256 tokenId) external payable;\n\n /// @notice Returns and determines the maximum allowable gas-used for notifying unsubscribe\n /// @return uint256 the maximum gas limit when notifying a subscriber's `notifyUnsubscribe` function\n function unsubscribeGasLimit() external view returns (uint256);\n}\n", + "@uniswap/v4-periphery/src/interfaces/IPermit2Forwarder.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IAllowanceTransfer} from \"permit2/src/interfaces/IAllowanceTransfer.sol\";\n\n/// @title IPermit2Forwarder\n/// @notice Interface for the Permit2Forwarder contract\ninterface IPermit2Forwarder {\n /// @notice allows forwarding a single permit to permit2\n /// @dev this function is payable to allow multicall with NATIVE based actions\n /// @param owner the owner of the tokens\n /// @param permitSingle the permit data\n /// @param signature the signature of the permit; abi.encodePacked(r, s, v)\n /// @return err the error returned by a reverting permit call, empty if successful\n function permit(address owner, IAllowanceTransfer.PermitSingle calldata permitSingle, bytes calldata signature)\n external\n payable\n returns (bytes memory err);\n\n /// @notice allows forwarding batch permits to permit2\n /// @dev this function is payable to allow multicall with NATIVE based actions\n /// @param owner the owner of the tokens\n /// @param _permitBatch a batch of approvals\n /// @param signature the signature of the permit; abi.encodePacked(r, s, v)\n /// @return err the error returned by a reverting permit call, empty if successful\n function permitBatch(address owner, IAllowanceTransfer.PermitBatch calldata _permitBatch, bytes calldata signature)\n external\n payable\n returns (bytes memory err);\n}\n", + "@uniswap/v4-periphery/src/interfaces/IPoolInitializer_v4.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {PoolKey} from \"@uniswap/v4-core/src/types/PoolKey.sol\";\n\n/// @title IPoolInitializer_v4\n/// @notice Interface for the PoolInitializer_v4 contract\ninterface IPoolInitializer_v4 {\n /// @notice Initialize a Uniswap v4 Pool\n /// @dev If the pool is already initialized, this function will not revert and just return type(int24).max\n /// @param key The PoolKey of the pool to initialize\n /// @param sqrtPriceX96 The initial starting price of the pool, expressed as a sqrtPriceX96\n /// @return The current tick of the pool, or type(int24).max if the pool creation failed, or the pool already existed\n function initializePool(PoolKey calldata key, uint160 sqrtPriceX96) external payable returns (int24);\n}\n", + "@uniswap/v4-periphery/src/interfaces/IPositionManager.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {PoolKey} from \"@uniswap/v4-core/src/types/PoolKey.sol\";\nimport {PositionInfo} from \"../libraries/PositionInfoLibrary.sol\";\n\nimport {INotifier} from \"./INotifier.sol\";\nimport {IImmutableState} from \"./IImmutableState.sol\";\nimport {IERC721Permit_v4} from \"./IERC721Permit_v4.sol\";\nimport {IEIP712_v4} from \"./IEIP712_v4.sol\";\nimport {IMulticall_v4} from \"./IMulticall_v4.sol\";\nimport {IPoolInitializer_v4} from \"./IPoolInitializer_v4.sol\";\nimport {IUnorderedNonce} from \"./IUnorderedNonce.sol\";\nimport {IPermit2Forwarder} from \"./IPermit2Forwarder.sol\";\n\n/// @title IPositionManager\n/// @notice Interface for the PositionManager contract\ninterface IPositionManager is\n INotifier,\n IImmutableState,\n IERC721Permit_v4,\n IEIP712_v4,\n IMulticall_v4,\n IPoolInitializer_v4,\n IUnorderedNonce,\n IPermit2Forwarder\n{\n /// @notice Thrown when the caller is not approved to modify a position\n error NotApproved(address caller);\n /// @notice Thrown when the block.timestamp exceeds the user-provided deadline\n error DeadlinePassed(uint256 deadline);\n /// @notice Thrown when calling transfer, subscribe, or unsubscribe when the PoolManager is unlocked.\n /// @dev This is to prevent hooks from being able to trigger notifications at the same time the position is being modified.\n error PoolManagerMustBeLocked();\n\n /// @notice Unlocks Uniswap v4 PoolManager and batches actions for modifying liquidity\n /// @dev This is the standard entrypoint for the PositionManager\n /// @param unlockData is an encoding of actions, and parameters for those actions\n /// @param deadline is the deadline for the batched actions to be executed\n function modifyLiquidities(bytes calldata unlockData, uint256 deadline) external payable;\n\n /// @notice Batches actions for modifying liquidity without unlocking v4 PoolManager\n /// @dev This must be called by a contract that has already unlocked the v4 PoolManager\n /// @param actions the actions to perform\n /// @param params the parameters to provide for the actions\n function modifyLiquiditiesWithoutUnlock(bytes calldata actions, bytes[] calldata params) external payable;\n\n /// @notice Used to get the ID that will be used for the next minted liquidity position\n /// @return uint256 The next token ID\n function nextTokenId() external view returns (uint256);\n\n /// @notice Returns the liquidity of a position\n /// @param tokenId the ERC721 tokenId\n /// @return liquidity the position's liquidity, as a liquidityAmount\n /// @dev this value can be processed as an amount0 and amount1 by using the LiquidityAmounts library\n function getPositionLiquidity(uint256 tokenId) external view returns (uint128 liquidity);\n\n /// @notice Returns the pool key and position info of a position\n /// @param tokenId the ERC721 tokenId\n /// @return poolKey the pool key of the position\n /// @return PositionInfo a uint256 packed value holding information about the position including the range (tickLower, tickUpper)\n function getPoolAndPositionInfo(uint256 tokenId) external view returns (PoolKey memory, PositionInfo);\n\n /// @notice Returns the position info of a position\n /// @param tokenId the ERC721 tokenId\n /// @return a uint256 packed value holding information about the position including the range (tickLower, tickUpper)\n function positionInfo(uint256 tokenId) external view returns (PositionInfo);\n}\n", + "@uniswap/v4-periphery/src/interfaces/ISubscriber.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {BalanceDelta} from \"@uniswap/v4-core/src/types/BalanceDelta.sol\";\nimport {PositionInfo} from \"../libraries/PositionInfoLibrary.sol\";\n\n/// @title ISubscriber\n/// @notice Interface that a Subscriber contract should implement to receive updates from the v4 position manager\ninterface ISubscriber {\n /// @notice Called when a position subscribes to this subscriber contract\n /// @param tokenId the token ID of the position\n /// @param data additional data passed in by the caller\n function notifySubscribe(uint256 tokenId, bytes memory data) external;\n\n /// @notice Called when a position unsubscribes from the subscriber\n /// @dev This call's gas is capped at `unsubscribeGasLimit` (set at deployment)\n /// @dev Because of EIP-150, solidity may only allocate 63/64 of gasleft()\n /// @param tokenId the token ID of the position\n function notifyUnsubscribe(uint256 tokenId) external;\n\n /// @notice Called when a position is burned\n /// @param tokenId the token ID of the position\n /// @param owner the current owner of the tokenId\n /// @param info information about the position\n /// @param liquidity the amount of liquidity decreased in the position, may be 0\n /// @param feesAccrued the fees accrued by the position if liquidity was decreased\n function notifyBurn(uint256 tokenId, address owner, PositionInfo info, uint256 liquidity, BalanceDelta feesAccrued)\n external;\n\n /// @notice Called when a position modifies its liquidity or collects fees\n /// @param tokenId the token ID of the position\n /// @param liquidityChange the change in liquidity on the underlying position\n /// @param feesAccrued the fees to be collected from the position as a result of the modifyLiquidity call\n /// @dev Note that feesAccrued can be artificially inflated by a malicious user\n /// Pools with a single liquidity position can inflate feeGrowthGlobal (and consequently feesAccrued) by donating to themselves;\n /// atomically donating and collecting fees within the same unlockCallback may further inflate feeGrowthGlobal/feesAccrued\n function notifyModifyLiquidity(uint256 tokenId, int256 liquidityChange, BalanceDelta feesAccrued) external;\n}\n", + "@uniswap/v4-periphery/src/interfaces/IUnorderedNonce.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title IUnorderedNonce\n/// @notice Interface for the UnorderedNonce contract\ninterface IUnorderedNonce {\n error NonceAlreadyUsed();\n\n /// @notice mapping of nonces consumed by each address, where a nonce is a single bit on the 256-bit bitmap\n /// @dev word is at most type(uint248).max\n function nonces(address owner, uint256 word) external view returns (uint256);\n\n /// @notice Revoke a nonce by spending it, preventing it from being used again\n /// @dev Used in cases where a valid nonce has not been broadcasted onchain, and the owner wants to revoke the validity of the nonce\n /// @dev payable so it can be multicalled with native-token related actions\n function revokeNonce(uint256 nonce) external payable;\n}\n", + "@uniswap/v4-periphery/src/libraries/Actions.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @notice Library to define different pool actions.\n/// @dev These are suggested common commands, however additional commands should be defined as required\n/// Some of these actions are not supported in the Router contracts or Position Manager contracts, but are left as they may be helpful commands for other peripheral contracts.\nlibrary Actions {\n // pool actions\n // liquidity actions\n uint256 internal constant INCREASE_LIQUIDITY = 0x00;\n uint256 internal constant DECREASE_LIQUIDITY = 0x01;\n uint256 internal constant MINT_POSITION = 0x02;\n uint256 internal constant BURN_POSITION = 0x03;\n uint256 internal constant INCREASE_LIQUIDITY_FROM_DELTAS = 0x04;\n uint256 internal constant MINT_POSITION_FROM_DELTAS = 0x05;\n\n // swapping\n uint256 internal constant SWAP_EXACT_IN_SINGLE = 0x06;\n uint256 internal constant SWAP_EXACT_IN = 0x07;\n uint256 internal constant SWAP_EXACT_OUT_SINGLE = 0x08;\n uint256 internal constant SWAP_EXACT_OUT = 0x09;\n\n // donate\n // note this is not supported in the position manager or router\n uint256 internal constant DONATE = 0x0a;\n\n // closing deltas on the pool manager\n // settling\n uint256 internal constant SETTLE = 0x0b;\n uint256 internal constant SETTLE_ALL = 0x0c;\n uint256 internal constant SETTLE_PAIR = 0x0d;\n // taking\n uint256 internal constant TAKE = 0x0e;\n uint256 internal constant TAKE_ALL = 0x0f;\n uint256 internal constant TAKE_PORTION = 0x10;\n uint256 internal constant TAKE_PAIR = 0x11;\n\n uint256 internal constant CLOSE_CURRENCY = 0x12;\n uint256 internal constant CLEAR_OR_TAKE = 0x13;\n uint256 internal constant SWEEP = 0x14;\n\n uint256 internal constant WRAP = 0x15;\n uint256 internal constant UNWRAP = 0x16;\n\n // minting/burning 6909s to close deltas\n // note this is not supported in the position manager or router\n uint256 internal constant MINT_6909 = 0x17;\n uint256 internal constant BURN_6909 = 0x18;\n}\n", + "@uniswap/v4-periphery/src/libraries/LiquidityAmounts.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {FullMath} from \"@uniswap/v4-core/src/libraries/FullMath.sol\";\nimport {FixedPoint96} from \"@uniswap/v4-core/src/libraries/FixedPoint96.sol\";\nimport {SafeCast} from \"@uniswap/v4-core/src/libraries/SafeCast.sol\";\n\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\nlibrary LiquidityAmounts {\n using SafeCast for uint256;\n\n /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\n /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\n /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary\n /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary\n /// @param amount0 The amount0 being sent in\n /// @return liquidity The amount of returned liquidity\n function getLiquidityForAmount0(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount0)\n internal\n pure\n returns (uint128 liquidity)\n {\n unchecked {\n if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);\n uint256 intermediate = FullMath.mulDiv(sqrtPriceAX96, sqrtPriceBX96, FixedPoint96.Q96);\n return FullMath.mulDiv(amount0, intermediate, sqrtPriceBX96 - sqrtPriceAX96).toUint128();\n }\n }\n\n /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\n /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\n /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary\n /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary\n /// @param amount1 The amount1 being sent in\n /// @return liquidity The amount of returned liquidity\n function getLiquidityForAmount1(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount1)\n internal\n pure\n returns (uint128 liquidity)\n {\n unchecked {\n if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);\n return FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtPriceBX96 - sqrtPriceAX96).toUint128();\n }\n }\n\n /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\n /// pool prices and the prices at the tick boundaries\n /// @param sqrtPriceX96 A sqrt price representing the current pool prices\n /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary\n /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary\n /// @param amount0 The amount of token0 being sent in\n /// @param amount1 The amount of token1 being sent in\n /// @return liquidity The maximum amount of liquidity received\n function getLiquidityForAmounts(\n uint160 sqrtPriceX96,\n uint160 sqrtPriceAX96,\n uint160 sqrtPriceBX96,\n uint256 amount0,\n uint256 amount1\n ) internal pure returns (uint128 liquidity) {\n if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);\n\n if (sqrtPriceX96 <= sqrtPriceAX96) {\n liquidity = getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0);\n } else if (sqrtPriceX96 < sqrtPriceBX96) {\n uint128 liquidity0 = getLiquidityForAmount0(sqrtPriceX96, sqrtPriceBX96, amount0);\n uint128 liquidity1 = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceX96, amount1);\n\n liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\n } else {\n liquidity = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceBX96, amount1);\n }\n }\n}\n", + "@uniswap/v4-periphery/src/libraries/PositionInfoLibrary.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {PoolKey} from \"@uniswap/v4-core/src/types/PoolKey.sol\";\nimport {PoolId} from \"@uniswap/v4-core/src/types/PoolId.sol\";\n\n/**\n * @dev PositionInfo is a packed version of solidity structure.\n * Using the packaged version saves gas and memory by not storing the structure fields in memory slots.\n *\n * Layout:\n * 200 bits poolId | 24 bits tickUpper | 24 bits tickLower | 8 bits hasSubscriber\n *\n * Fields in the direction from the least significant bit:\n *\n * A flag to know if the tokenId is subscribed to an address\n * uint8 hasSubscriber;\n *\n * The tickUpper of the position\n * int24 tickUpper;\n *\n * The tickLower of the position\n * int24 tickLower;\n *\n * The truncated poolId. Truncates a bytes32 value so the most signifcant (highest) 200 bits are used.\n * bytes25 poolId;\n *\n * Note: If more bits are needed, hasSubscriber can be a single bit.\n *\n */\ntype PositionInfo is uint256;\n\nusing PositionInfoLibrary for PositionInfo global;\n\nlibrary PositionInfoLibrary {\n PositionInfo internal constant EMPTY_POSITION_INFO = PositionInfo.wrap(0);\n\n uint256 internal constant MASK_UPPER_200_BITS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000;\n uint256 internal constant MASK_8_BITS = 0xFF;\n uint24 internal constant MASK_24_BITS = 0xFFFFFF;\n uint256 internal constant SET_UNSUBSCRIBE = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00;\n uint256 internal constant SET_SUBSCRIBE = 0x01;\n uint8 internal constant TICK_LOWER_OFFSET = 8;\n uint8 internal constant TICK_UPPER_OFFSET = 32;\n\n /// @dev This poolId is NOT compatible with the poolId used in UniswapV4 core. It is truncated to 25 bytes, and just used to lookup PoolKey in the poolKeys mapping.\n function poolId(PositionInfo info) internal pure returns (bytes25 _poolId) {\n assembly (\"memory-safe\") {\n _poolId := and(MASK_UPPER_200_BITS, info)\n }\n }\n\n function tickLower(PositionInfo info) internal pure returns (int24 _tickLower) {\n assembly (\"memory-safe\") {\n _tickLower := signextend(2, shr(TICK_LOWER_OFFSET, info))\n }\n }\n\n function tickUpper(PositionInfo info) internal pure returns (int24 _tickUpper) {\n assembly (\"memory-safe\") {\n _tickUpper := signextend(2, shr(TICK_UPPER_OFFSET, info))\n }\n }\n\n function hasSubscriber(PositionInfo info) internal pure returns (bool _hasSubscriber) {\n assembly (\"memory-safe\") {\n _hasSubscriber := and(MASK_8_BITS, info)\n }\n }\n\n /// @dev this does not actually set any storage\n function setSubscribe(PositionInfo info) internal pure returns (PositionInfo _info) {\n assembly (\"memory-safe\") {\n _info := or(info, SET_SUBSCRIBE)\n }\n }\n\n /// @dev this does not actually set any storage\n function setUnsubscribe(PositionInfo info) internal pure returns (PositionInfo _info) {\n assembly (\"memory-safe\") {\n _info := and(info, SET_UNSUBSCRIBE)\n }\n }\n\n /// @notice Creates the default PositionInfo struct\n /// @dev Called when minting a new position\n /// @param _poolKey the pool key of the position\n /// @param _tickLower the lower tick of the position\n /// @param _tickUpper the upper tick of the position\n /// @return info packed position info, with the truncated poolId and the hasSubscriber flag set to false\n function initialize(PoolKey memory _poolKey, int24 _tickLower, int24 _tickUpper)\n internal\n pure\n returns (PositionInfo info)\n {\n bytes25 _poolId = bytes25(PoolId.unwrap(_poolKey.toId()));\n assembly {\n info :=\n or(\n or(and(MASK_UPPER_200_BITS, _poolId), shl(TICK_UPPER_OFFSET, and(MASK_24_BITS, _tickUpper))),\n shl(TICK_LOWER_OFFSET, and(MASK_24_BITS, _tickLower))\n )\n }\n }\n}\n", + "DevLaunchERC20.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\n/*\n\n _ __ ______\n | |/ / | ____|\n | ' / | |__\n | < | __|\n | . \\ | |\n |_|\\_\\ |_|\n\n KOIN FORGE\n Clean ETH token launches forged for developers.\n\n Web: https://koinforge.xyz\n X: https://x.com/koinforgedev\n Deploys: https://t.me/KoinForge_deploys\n\n 0% token tax\n 0 pool fee\n no hooks\n no creator rewards\n 2% max buy per transaction\n\n*/\n\ninterface IERC20RescueTarget {\n function transfer(address to, uint256 value) external returns (bool);\n function balanceOf(address account) external view returns (uint256);\n}\n\n/// @title DevLaunchERC20\n/// @notice Fixed-supply ERC20 for no-tax Uniswap v4 launches with optional max-buy and delayed open trading.\n/// @dev No mint, no blacklist, no pause, no tax, no owner authority. Max-buy applies only to buys from marked v4/router sources.\ncontract DevLaunchERC20 {\n string private _name;\n string private _symbol;\n string public projectInfo;\n\n uint8 public constant decimals = 18;\n uint256 public constant MAX_BUY_BPS = 200;\n uint256 public constant BPS = 10_000;\n string public constant contractVersion = \"KoinForge DevLaunchERC20 v3\";\n string public constant forgeName = \"Koin Forge\";\n string public constant forgeWeb = \"https://koinforge.xyz\";\n string public constant forgeDeploys = \"https://t.me/KoinForge_deploys\";\n string public constant forgeX = \"https://x.com/koinforgedev\";\n\n address public immutable launcher;\n address public immutable rescueReceiver;\n bool public immutable maxBuyEnabled;\n uint256 public immutable maxBuyAmount;\n bool public tradingOpen;\n uint256 public totalSupply;\n\n mapping(address account => uint256) public balanceOf;\n mapping(address owner => mapping(address spender => uint256)) public allowance;\n mapping(address account => bool) public isMaxBuySource;\n mapping(address account => bool) public isMaxBuyExempt;\n mapping(address account => bool) public isTradingExempt;\n\n event Approval(address indexed owner, address indexed spender, uint256 value);\n event Transfer(address indexed from, address indexed to, uint256 value);\n event ETHReceived(address indexed sender, uint256 amount);\n event ETHRescued(address indexed receiver, uint256 amount);\n event ERC20Rescued(address indexed token, address indexed receiver, uint256 amount);\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n event TradingOpened(address indexed token, address indexed launcher);\n event MaxBuySourceSet(address indexed account, bool enabled);\n event MaxBuyExemptSet(address indexed account, bool exempt);\n event TradingExemptSet(address indexed account, bool exempt);\n\n error InsufficientAllowance();\n error InsufficientBalance();\n error InvalidAddress();\n error NotLauncher();\n error NotRescueReceiver();\n error RescueTransferFailed();\n error TradingAlreadyOpen();\n error TradingClosed();\n error MaxBuyExceeded(address buyer, uint256 amount, uint256 maxBuyAmount);\n\n constructor(\n string memory name_,\n string memory symbol_,\n uint256 supply_,\n address initialHolder_,\n address rescueReceiver_,\n string memory projectInfo_,\n bool maxBuyEnabled_,\n bool tradingOpenOnDeploy_,\n address[] memory maxBuySources_,\n address[] memory maxBuyExemptions_,\n address[] memory tradingExemptions_\n ) {\n if (bytes(name_).length == 0 || bytes(symbol_).length == 0) revert InvalidAddress();\n if (initialHolder_ == address(0) || rescueReceiver_ == address(0)) revert InvalidAddress();\n if (supply_ == 0) revert InvalidAddress();\n\n _name = name_;\n _symbol = symbol_;\n launcher = msg.sender;\n rescueReceiver = rescueReceiver_;\n projectInfo = projectInfo_;\n maxBuyEnabled = maxBuyEnabled_;\n tradingOpen = tradingOpenOnDeploy_;\n\n totalSupply = supply_;\n maxBuyAmount = (supply_ * MAX_BUY_BPS) / BPS;\n _setMaxBuyExempt(initialHolder_, true);\n _setMaxBuyExempt(rescueReceiver_, true);\n _setMaxBuyExempt(address(this), true);\n _setTradingExempt(initialHolder_, true);\n _setTradingExempt(rescueReceiver_, true);\n _setTradingExempt(address(this), true);\n for (uint256 index = 0; index < maxBuySources_.length; index += 1) {\n _setMaxBuySource(maxBuySources_[index], true);\n }\n for (uint256 index = 0; index < maxBuyExemptions_.length; index += 1) {\n _setMaxBuyExempt(maxBuyExemptions_[index], true);\n }\n for (uint256 index = 0; index < tradingExemptions_.length; index += 1) {\n _setTradingExempt(tradingExemptions_[index], true);\n }\n\n balanceOf[initialHolder_] = supply_;\n emit Transfer(address(0), initialHolder_, supply_);\n\n // Ownership is renounced by design. Rescue permission is separate and immutable.\n emit OwnershipTransferred(msg.sender, address(0));\n }\n\n receive() external payable {\n emit ETHReceived(msg.sender, msg.value);\n }\n\n function name() external view returns (string memory) {\n return _name;\n }\n\n function symbol() external view returns (string memory) {\n return _symbol;\n }\n\n function owner() external pure returns (address) {\n return address(0);\n }\n\n function renounceOwnership() external pure returns (bool) {\n return true;\n }\n\n function openTrading() external returns (bool) {\n if (msg.sender != launcher) revert NotLauncher();\n if (tradingOpen) revert TradingAlreadyOpen();\n tradingOpen = true;\n emit TradingOpened(address(this), launcher);\n return true;\n }\n\n function transfer(address to, uint256 value) external returns (bool) {\n _transfer(msg.sender, to, value);\n return true;\n }\n\n function approve(address spender, uint256 value) external returns (bool) {\n _approve(msg.sender, spender, value);\n return true;\n }\n\n function transferFrom(address from, address to, uint256 value) external returns (bool) {\n uint256 currentAllowance = allowance[from][msg.sender];\n if (currentAllowance != type(uint256).max) {\n if (currentAllowance < value) revert InsufficientAllowance();\n unchecked {\n allowance[from][msg.sender] = currentAllowance - value;\n }\n emit Approval(from, msg.sender, allowance[from][msg.sender]);\n }\n\n _transfer(from, to, value);\n return true;\n }\n\n function increaseAllowance(address spender, uint256 addedValue) external returns (bool) {\n _approve(msg.sender, spender, allowance[msg.sender][spender] + addedValue);\n return true;\n }\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) {\n uint256 currentAllowance = allowance[msg.sender][spender];\n if (currentAllowance < subtractedValue) revert InsufficientAllowance();\n unchecked {\n _approve(msg.sender, spender, currentAllowance - subtractedValue);\n }\n return true;\n }\n\n function burn(uint256 value) external {\n _burn(msg.sender, value);\n }\n\n function burnFrom(address account, uint256 value) external {\n uint256 currentAllowance = allowance[account][msg.sender];\n if (currentAllowance != type(uint256).max) {\n if (currentAllowance < value) revert InsufficientAllowance();\n unchecked {\n allowance[account][msg.sender] = currentAllowance - value;\n }\n emit Approval(account, msg.sender, allowance[account][msg.sender]);\n }\n _burn(account, value);\n }\n\n function rescueETH(uint256 amount) external returns (uint256 rescued) {\n _onlyRescueReceiver();\n rescued = amount == 0 ? address(this).balance : amount;\n (bool ok,) = rescueReceiver.call{value: rescued}(\"\");\n if (!ok) revert RescueTransferFailed();\n emit ETHRescued(rescueReceiver, rescued);\n }\n\n function rescueERC20(address token, uint256 amount) external returns (uint256 rescued) {\n _onlyRescueReceiver();\n if (token == address(0)) revert InvalidAddress();\n\n rescued = amount == 0 ? IERC20RescueTarget(token).balanceOf(address(this)) : amount;\n bool ok = IERC20RescueTarget(token).transfer(rescueReceiver, rescued);\n if (!ok) revert RescueTransferFailed();\n emit ERC20Rescued(token, rescueReceiver, rescued);\n }\n\n function _transfer(address from, address to, uint256 value) private {\n if (from == address(0) || to == address(0)) revert InvalidAddress();\n\n uint256 fromBalance = balanceOf[from];\n if (fromBalance < value) revert InsufficientBalance();\n if (from == to) {\n emit Transfer(from, to, value);\n return;\n }\n\n uint256 nextToBalance = balanceOf[to] + value;\n _enforceTradingOpen(from, to);\n _enforceMaxBuy(from, to, value);\n\n unchecked {\n balanceOf[from] = fromBalance - value;\n balanceOf[to] = nextToBalance;\n }\n\n emit Transfer(from, to, value);\n }\n\n function _burn(address account, uint256 value) private {\n if (account == address(0)) revert InvalidAddress();\n\n uint256 accountBalance = balanceOf[account];\n if (accountBalance < value) revert InsufficientBalance();\n\n unchecked {\n balanceOf[account] = accountBalance - value;\n totalSupply -= value;\n }\n\n emit Transfer(account, address(0), value);\n }\n\n function _approve(address owner_, address spender, uint256 value) private {\n if (owner_ == address(0) || spender == address(0)) revert InvalidAddress();\n allowance[owner_][spender] = value;\n emit Approval(owner_, spender, value);\n }\n\n function _onlyRescueReceiver() private view {\n if (msg.sender != rescueReceiver) revert NotRescueReceiver();\n }\n\n function _enforceTradingOpen(address from, address to) private view {\n if (tradingOpen) return;\n if (isTradingExempt[from] && isTradingExempt[to]) return;\n revert TradingClosed();\n }\n\n function _enforceMaxBuy(address from, address to, uint256 amount) private view {\n if (!maxBuyEnabled) return;\n if (!isMaxBuySource[from]) return;\n if (isMaxBuyExempt[to]) return;\n if (amount > maxBuyAmount) revert MaxBuyExceeded(to, amount, maxBuyAmount);\n }\n\n function _setMaxBuySource(address account, bool enabled) private {\n if (account == address(0)) revert InvalidAddress();\n isMaxBuySource[account] = enabled;\n emit MaxBuySourceSet(account, enabled);\n }\n\n function _setMaxBuyExempt(address account, bool exempt) private {\n if (account == address(0)) revert InvalidAddress();\n isMaxBuyExempt[account] = exempt;\n emit MaxBuyExemptSet(account, exempt);\n }\n\n function _setTradingExempt(address account, bool exempt) private {\n if (account == address(0)) revert InvalidAddress();\n isTradingExempt[account] = exempt;\n emit TradingExemptSet(account, exempt);\n }\n}\n", + "DevLaunchLauncher.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {DevLaunchERC20} from \"./DevLaunchERC20.sol\";\nimport {PoolKey} from \"@uniswap/v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"@uniswap/v4-core/src/types/Currency.sol\";\nimport {IHooks} from \"@uniswap/v4-core/src/interfaces/IHooks.sol\";\nimport {FullMath} from \"@uniswap/v4-core/src/libraries/FullMath.sol\";\nimport {TickMath} from \"@uniswap/v4-core/src/libraries/TickMath.sol\";\nimport {IPositionManager} from \"@uniswap/v4-periphery/src/interfaces/IPositionManager.sol\";\nimport {Actions} from \"@uniswap/v4-periphery/src/libraries/Actions.sol\";\nimport {LiquidityAmounts} from \"@uniswap/v4-periphery/src/libraries/LiquidityAmounts.sol\";\n\ninterface IERC20LauncherRescueTarget {\n function transfer(address to, uint256 value) external returns (bool);\n function balanceOf(address account) external view returns (uint256);\n}\n\ninterface IAllowanceTransferMinimal {\n function approve(address token, address spender, uint160 amount, uint48 expiration) external;\n}\n\ninterface IPositionManagerState {\n function poolManager() external view returns (address);\n}\n\n/// @title DevLaunchLauncher\n/// @notice CREATE2 launcher for zero-fee, no-hook Uniswap v4 token launches.\n/// @dev Instant launches mint 0 ETH + 100% token supply liquidity immediately. Open-later launches deploy first, then create/burn LP when trading is opened.\ncontract DevLaunchLauncher {\n address public constant DEAD = 0x000000000000000000000000000000000000dEaD;\n address public constant NATIVE = address(0);\n uint24 public constant POOL_FEE = 0;\n int24 public constant TICK_SPACING = 1;\n uint256 public constant MIN_SUPPLY = 1 ether;\n uint256 public constant MAX_SUPPLY = 100_000_000_000 ether;\n uint256 public constant Q192 = 2 ** 192;\n uint256 public constant MAX_REFERRAL_BPS = 2500;\n uint256 public constant BPS = 10_000;\n\n IPositionManager public immutable positionManager;\n IAllowanceTransferMinimal public immutable permit2;\n address public immutable poolManager;\n address public immutable universalRouter;\n address public immutable rescueReceiver;\n address public immutable botFeeReceiver;\n address public immutable referralTreasury;\n uint256 public immutable flatFeeWei;\n mapping(address token => address opener) public pendingTradingOpener;\n mapping(address token => uint256 virtualEthWei) public pendingTradingVirtualEthWei;\n\n event Launched(\n address indexed token,\n bytes32 indexed salt,\n uint256 indexed tokenId,\n address launcher,\n uint256 supply,\n uint256 virtualEthWei,\n uint160 sqrtPriceX96,\n int24 tickLower,\n int24 tickUpper,\n int24 tickSpacing,\n uint256 liquidity,\n uint256 referralBps,\n bool maxBuyEnabled,\n bool tradingOpen\n );\n event TradingPending(address indexed token, address indexed opener);\n event TradingOpened(address indexed token, address indexed opener);\n event PendingLaunchCreated(\n address indexed token, bytes32 indexed salt, address indexed opener, uint256 supply, uint256 virtualEthWei\n );\n event LiquidityActivated(\n address indexed token,\n uint256 indexed tokenId,\n address indexed opener,\n uint256 supply,\n uint256 virtualEthWei,\n uint160 sqrtPriceX96,\n int24 tickLower,\n int24 tickUpper,\n int24 tickSpacing,\n uint256 liquidity\n );\n event ETHRescued(address indexed receiver, uint256 amount);\n event ERC20Rescued(address indexed token, address indexed receiver, uint256 amount);\n\n error InvalidAddress();\n error InvalidAmount();\n error InvalidOpener();\n error InvalidTicks();\n error NotPendingTokenOpener();\n error FeeTooLow();\n error RescueTransferFailed();\n error TokenTransferFailed();\n error TokenLiquidityNotFull();\n\n struct LaunchParams {\n string name;\n string symbol;\n uint256 supply;\n string projectInfo;\n bytes32 salt;\n uint256 virtualEthWei;\n uint256 referralBps;\n address opener;\n bool maxBuyEnabled;\n bool startTradingOpen;\n }\n\n struct LaunchMath {\n uint160 sqrtPriceX96;\n int24 tickLower;\n int24 tickUpper;\n int24 tickSpacing;\n uint128 liquidity;\n }\n\n constructor(\n address positionManager_,\n address permit2_,\n address universalRouter_,\n address botFeeReceiver_,\n address referralTreasury_,\n uint256 flatFeeWei_\n ) {\n if (\n positionManager_ == address(0) || permit2_ == address(0) || universalRouter_ == address(0)\n || botFeeReceiver_ == address(0) || referralTreasury_ == address(0)\n ) revert InvalidAddress();\n\n positionManager = IPositionManager(positionManager_);\n permit2 = IAllowanceTransferMinimal(permit2_);\n poolManager = IPositionManagerState(positionManager_).poolManager();\n if (poolManager == address(0)) revert InvalidAddress();\n universalRouter = universalRouter_;\n rescueReceiver = botFeeReceiver_;\n botFeeReceiver = botFeeReceiver_;\n referralTreasury = referralTreasury_;\n flatFeeWei = flatFeeWei_;\n }\n\n receive() external payable {}\n\n function launch(LaunchParams calldata params) external payable returns (address token, uint256 tokenId) {\n LaunchMath memory math = quoteLaunch(params.supply, params.virtualEthWei);\n if (msg.value < flatFeeWei) revert FeeTooLow();\n if (!params.startTradingOpen && params.opener == address(0)) revert InvalidOpener();\n\n token = address(\n new DevLaunchERC20{salt: params.salt}(\n params.name,\n params.symbol,\n params.supply,\n address(this),\n rescueReceiver,\n _brandProjectInfo(params.projectInfo, params.maxBuyEnabled),\n params.maxBuyEnabled,\n params.startTradingOpen,\n _maxBuySources(),\n _maxBuyExemptions(),\n _tradingExemptions()\n )\n );\n\n if (params.startTradingOpen) {\n tokenId = _activateLiquidity(token, params.supply, math);\n } else {\n pendingTradingOpener[token] = params.opener;\n pendingTradingVirtualEthWei[token] = params.virtualEthWei;\n emit TradingPending(token, params.opener);\n emit PendingLaunchCreated(token, params.salt, params.opener, params.supply, params.virtualEthWei);\n }\n\n _collectFee(params.referralBps);\n _refundDust();\n\n if (params.startTradingOpen) {\n emit Launched(\n token,\n params.salt,\n tokenId,\n msg.sender,\n params.supply,\n params.virtualEthWei,\n math.sqrtPriceX96,\n math.tickLower,\n math.tickUpper,\n math.tickSpacing,\n math.liquidity,\n params.referralBps,\n params.maxBuyEnabled,\n true\n );\n }\n }\n\n function openTrading(address token) external returns (bool) {\n address opener = pendingTradingOpener[token];\n uint256 virtualEthWei = pendingTradingVirtualEthWei[token];\n if (opener == address(0) || msg.sender != opener) revert NotPendingTokenOpener();\n LaunchMath memory math = quoteLaunch(DevLaunchERC20(payable(token)).totalSupply(), virtualEthWei);\n uint256 tokenId = _activateLiquidity(token, DevLaunchERC20(payable(token)).totalSupply(), math);\n delete pendingTradingOpener[token];\n delete pendingTradingVirtualEthWei[token];\n bool ok = DevLaunchERC20(payable(token)).openTrading();\n if (ok) {\n emit LiquidityActivated(\n token,\n tokenId,\n msg.sender,\n DevLaunchERC20(payable(token)).totalSupply(),\n virtualEthWei,\n math.sqrtPriceX96,\n math.tickLower,\n math.tickUpper,\n math.tickSpacing,\n math.liquidity\n );\n emit TradingOpened(token, msg.sender);\n }\n return ok;\n }\n\n function quoteLaunch(uint256 supply, uint256 virtualEthWei) public pure returns (LaunchMath memory math) {\n if (supply < MIN_SUPPLY || supply > MAX_SUPPLY || supply > type(uint128).max) revert InvalidAmount();\n if (!_allowedTier(virtualEthWei)) revert InvalidAmount();\n\n math.sqrtPriceX96 = _sqrtPriceX96(supply, virtualEthWei);\n int24 currentTick = TickMath.getTickAtSqrtPrice(math.sqrtPriceX96);\n math.tickSpacing = TICK_SPACING;\n math.tickUpper = _floorUsableTick(currentTick, TICK_SPACING);\n math.tickLower = TickMath.minUsableTick(TICK_SPACING);\n if (math.tickLower >= math.tickUpper) revert InvalidTicks();\n math.liquidity = LiquidityAmounts.getLiquidityForAmount1(\n TickMath.getSqrtPriceAtTick(math.tickLower), TickMath.getSqrtPriceAtTick(math.tickUpper), supply\n );\n if (math.liquidity == 0) revert InvalidAmount();\n }\n\n function computeTokenAddress(\n string calldata name,\n string calldata symbol,\n uint256 supply,\n string calldata projectInfo,\n bytes32 salt,\n bool maxBuyEnabled,\n bool startTradingOpen\n ) external view returns (address) {\n bytes32 initCodeHash = keccak256(\n abi.encodePacked(\n type(DevLaunchERC20).creationCode,\n abi.encode(\n name,\n symbol,\n supply,\n address(this),\n rescueReceiver,\n _brandProjectInfo(projectInfo, maxBuyEnabled),\n maxBuyEnabled,\n startTradingOpen,\n _maxBuySources(),\n _maxBuyExemptions(),\n _tradingExemptions()\n )\n )\n );\n return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, initCodeHash)))));\n }\n\n function rescueETH(uint256 amount) external returns (uint256 rescued) {\n rescued = amount == 0 ? address(this).balance : amount;\n (bool ok,) = rescueReceiver.call{value: rescued}(\"\");\n if (!ok) revert RescueTransferFailed();\n emit ETHRescued(rescueReceiver, rescued);\n }\n\n function rescueERC20(address token, uint256 amount) external returns (uint256 rescued) {\n if (token == address(0)) revert InvalidAddress();\n rescued = amount == 0 ? IERC20LauncherRescueTarget(token).balanceOf(address(this)) : amount;\n bool ok = IERC20LauncherRescueTarget(token).transfer(rescueReceiver, rescued);\n if (!ok) revert TokenTransferFailed();\n emit ERC20Rescued(token, rescueReceiver, rescued);\n }\n\n function _approveForPositionManager(address token, uint256 amount) private {\n // Approve Permit2 at ERC20 layer, then approve PositionManager inside Permit2.\n (bool approved,) =\n token.call(abi.encodeWithSignature(\"approve(address,uint256)\", address(permit2), type(uint256).max));\n if (!approved) revert TokenTransferFailed();\n permit2.approve(token, address(positionManager), uint160(amount), type(uint48).max);\n }\n\n function _sendTokenDustToDead(address token, uint256 supply) private {\n uint256 dust = IERC20LauncherRescueTarget(token).balanceOf(address(this));\n if (dust == 0) return;\n uint256 maxDust = supply / 1_000_000;\n if (maxDust < 1_000) maxDust = 1_000;\n if (dust > maxDust) revert TokenLiquidityNotFull();\n bool ok = IERC20LauncherRescueTarget(token).transfer(DEAD, dust);\n if (!ok) revert TokenTransferFailed();\n }\n\n function _activateLiquidity(address token, uint256 supply, LaunchMath memory math) private returns (uint256 tokenId) {\n PoolKey memory key = PoolKey({\n currency0: Currency.wrap(NATIVE),\n currency1: Currency.wrap(token),\n fee: POOL_FEE,\n tickSpacing: math.tickSpacing,\n hooks: IHooks(address(0))\n });\n\n positionManager.initializePool(key, math.sqrtPriceX96);\n\n _approveForPositionManager(token, supply);\n\n tokenId = positionManager.nextTokenId();\n bytes memory actions = abi.encodePacked(bytes1(uint8(Actions.MINT_POSITION)), bytes1(uint8(Actions.SETTLE_PAIR)));\n bytes[] memory mintParams = new bytes[](2);\n mintParams[0] = abi.encode(\n key,\n math.tickLower,\n math.tickUpper,\n math.liquidity,\n uint128(0),\n uint128(supply),\n DEAD,\n bytes(\"\")\n );\n mintParams[1] = abi.encode(key.currency0, key.currency1);\n\n positionManager.modifyLiquidities(abi.encode(actions, mintParams), block.timestamp);\n _sendTokenDustToDead(token, supply);\n }\n\n function _collectFee(uint256 referralBps) private {\n if (flatFeeWei == 0) return;\n if (referralBps > 0) {\n if (referralBps > MAX_REFERRAL_BPS) revert InvalidAmount();\n uint256 referralAmount = (flatFeeWei * referralBps) / BPS;\n uint256 botAmount = flatFeeWei - referralAmount;\n _sendETH(botFeeReceiver, botAmount);\n _sendETH(referralTreasury, referralAmount);\n } else {\n _sendETH(botFeeReceiver, flatFeeWei);\n }\n }\n\n function _refundDust() private {\n uint256 dust = address(this).balance;\n if (dust > 0) _sendETH(msg.sender, dust);\n }\n\n function _sendETH(address to, uint256 amount) private {\n if (amount == 0) return;\n (bool ok,) = to.call{value: amount}(\"\");\n if (!ok) revert RescueTransferFailed();\n }\n\n function _allowedTier(uint256 virtualEthWei) private pure returns (bool) {\n return virtualEthWei == 500_000_000_000_000_000 || virtualEthWei == 1 ether || virtualEthWei == 2 ether\n || virtualEthWei == 5 ether || virtualEthWei == 10 ether;\n }\n\n function _sqrtPriceX96(uint256 supply, uint256 virtualEthWei) private pure returns (uint160) {\n uint256 ratioX192 = FullMath.mulDiv(supply, Q192, virtualEthWei);\n uint256 sqrtRatio = _sqrt(ratioX192);\n if (sqrtRatio == 0 || sqrtRatio > type(uint160).max) revert InvalidAmount();\n return uint160(sqrtRatio);\n }\n\n function _floorUsableTick(int24 tick, int24 tickSpacing) private pure returns (int24) {\n int24 compressed = tick / tickSpacing;\n if (tick < 0 && tick % tickSpacing != 0) compressed--;\n return compressed * tickSpacing;\n }\n\n function _brandProjectInfo(string calldata projectInfo, bool maxBuyEnabled) private pure returns (string memory) {\n string memory brand = maxBuyEnabled\n ? \"Koin Forge\\nWeb: https://koinforge.xyz\\nX: https://x.com/koinforgedev\\nDeploys: https://t.me/KoinForge_deploys\\nMax buy: 2% per transaction\"\n : \"Koin Forge\\nWeb: https://koinforge.xyz\\nX: https://x.com/koinforgedev\\nDeploys: https://t.me/KoinForge_deploys\\nMax buy: off\";\n if (bytes(projectInfo).length == 0) return brand;\n return string.concat(brand, \"\\nProject: \", projectInfo);\n }\n\n function _maxBuySources() private view returns (address[] memory sources) {\n sources = new address[](3);\n sources[0] = poolManager;\n sources[1] = universalRouter;\n sources[2] = address(positionManager);\n }\n\n function _maxBuyExemptions() private view returns (address[] memory exemptions) {\n exemptions = new address[](8);\n exemptions[0] = address(this);\n exemptions[1] = rescueReceiver;\n exemptions[2] = referralTreasury;\n exemptions[3] = address(positionManager);\n exemptions[4] = address(permit2);\n exemptions[5] = poolManager;\n exemptions[6] = universalRouter;\n exemptions[7] = DEAD;\n }\n\n function _tradingExemptions() private view returns (address[] memory exemptions) {\n exemptions = new address[](8);\n exemptions[0] = address(this);\n exemptions[1] = rescueReceiver;\n exemptions[2] = referralTreasury;\n exemptions[3] = address(positionManager);\n exemptions[4] = address(permit2);\n exemptions[5] = poolManager;\n exemptions[6] = universalRouter;\n exemptions[7] = DEAD;\n }\n\n function _sqrt(uint256 x) private pure returns (uint256 z) {\n if (x == 0) return 0;\n uint256 y = x;\n z = 1;\n if (y >= 2 ** 128) {\n y >>= 128;\n z <<= 64;\n }\n if (y >= 2 ** 64) {\n y >>= 64;\n z <<= 32;\n }\n if (y >= 2 ** 32) {\n y >>= 32;\n z <<= 16;\n }\n if (y >= 2 ** 16) {\n y >>= 16;\n z <<= 8;\n }\n if (y >= 2 ** 8) {\n y >>= 8;\n z <<= 4;\n }\n if (y >= 2 ** 4) {\n y >>= 4;\n z <<= 2;\n }\n if (y >= 2 ** 2) z <<= 1;\n\n unchecked {\n z = (z + x / z) >> 1;\n z = (z + x / z) >> 1;\n z = (z + x / z) >> 1;\n z = (z + x / z) >> 1;\n z = (z + x / z) >> 1;\n z = (z + x / z) >> 1;\n z = (z + x / z) >> 1;\n uint256 roundedDown = x / z;\n return z < roundedDown ? z : roundedDown;\n }\n }\n}\n", + "permit2/src/interfaces/IAllowanceTransfer.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IEIP712} from \"./IEIP712.sol\";\n\n/// @title AllowanceTransfer\n/// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts\n/// @dev Requires user's token approval on the Permit2 contract\ninterface IAllowanceTransfer is IEIP712 {\n /// @notice Thrown when an allowance on a token has expired.\n /// @param deadline The timestamp at which the allowed amount is no longer valid\n error AllowanceExpired(uint256 deadline);\n\n /// @notice Thrown when an allowance on a token has been depleted.\n /// @param amount The maximum amount allowed\n error InsufficientAllowance(uint256 amount);\n\n /// @notice Thrown when too many nonces are invalidated.\n error ExcessiveInvalidation();\n\n /// @notice Emits an event when the owner successfully invalidates an ordered nonce.\n event NonceInvalidation(\n address indexed owner, address indexed token, address indexed spender, uint48 newNonce, uint48 oldNonce\n );\n\n /// @notice Emits an event when the owner successfully sets permissions on a token for the spender.\n event Approval(\n address indexed owner, address indexed token, address indexed spender, uint160 amount, uint48 expiration\n );\n\n /// @notice Emits an event when the owner successfully sets permissions using a permit signature on a token for the spender.\n event Permit(\n address indexed owner,\n address indexed token,\n address indexed spender,\n uint160 amount,\n uint48 expiration,\n uint48 nonce\n );\n\n /// @notice Emits an event when the owner sets the allowance back to 0 with the lockdown function.\n event Lockdown(address indexed owner, address token, address spender);\n\n /// @notice The permit data for a token\n struct PermitDetails {\n // ERC20 token address\n address token;\n // the maximum amount allowed to spend\n uint160 amount;\n // timestamp at which a spender's token allowances become invalid\n uint48 expiration;\n // an incrementing value indexed per owner,token,and spender for each signature\n uint48 nonce;\n }\n\n /// @notice The permit message signed for a single token allowance\n struct PermitSingle {\n // the permit data for a single token alownce\n PermitDetails details;\n // address permissioned on the allowed tokens\n address spender;\n // deadline on the permit signature\n uint256 sigDeadline;\n }\n\n /// @notice The permit message signed for multiple token allowances\n struct PermitBatch {\n // the permit data for multiple token allowances\n PermitDetails[] details;\n // address permissioned on the allowed tokens\n address spender;\n // deadline on the permit signature\n uint256 sigDeadline;\n }\n\n /// @notice The saved permissions\n /// @dev This info is saved per owner, per token, per spender and all signed over in the permit message\n /// @dev Setting amount to type(uint160).max sets an unlimited approval\n struct PackedAllowance {\n // amount allowed\n uint160 amount;\n // permission expiry\n uint48 expiration;\n // an incrementing value indexed per owner,token,and spender for each signature\n uint48 nonce;\n }\n\n /// @notice A token spender pair.\n struct TokenSpenderPair {\n // the token the spender is approved\n address token;\n // the spender address\n address spender;\n }\n\n /// @notice Details for a token transfer.\n struct AllowanceTransferDetails {\n // the owner of the token\n address from;\n // the recipient of the token\n address to;\n // the amount of the token\n uint160 amount;\n // the token to be transferred\n address token;\n }\n\n /// @notice A mapping from owner address to token address to spender address to PackedAllowance struct, which contains details and conditions of the approval.\n /// @notice The mapping is indexed in the above order see: allowance[ownerAddress][tokenAddress][spenderAddress]\n /// @dev The packed slot holds the allowed amount, expiration at which the allowed amount is no longer valid, and current nonce thats updated on any signature based approvals.\n function allowance(address user, address token, address spender)\n external\n view\n returns (uint160 amount, uint48 expiration, uint48 nonce);\n\n /// @notice Approves the spender to use up to amount of the specified token up until the expiration\n /// @param token The token to approve\n /// @param spender The spender address to approve\n /// @param amount The approved amount of the token\n /// @param expiration The timestamp at which the approval is no longer valid\n /// @dev The packed allowance also holds a nonce, which will stay unchanged in approve\n /// @dev Setting amount to type(uint160).max sets an unlimited approval\n function approve(address token, address spender, uint160 amount, uint48 expiration) external;\n\n /// @notice Permit a spender to a given amount of the owners token via the owner's EIP-712 signature\n /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce\n /// @param owner The owner of the tokens being approved\n /// @param permitSingle Data signed over by the owner specifying the terms of approval\n /// @param signature The owner's signature over the permit data\n function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;\n\n /// @notice Permit a spender to the signed amounts of the owners tokens via the owner's EIP-712 signature\n /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce\n /// @param owner The owner of the tokens being approved\n /// @param permitBatch Data signed over by the owner specifying the terms of approval\n /// @param signature The owner's signature over the permit data\n function permit(address owner, PermitBatch memory permitBatch, bytes calldata signature) external;\n\n /// @notice Transfer approved tokens from one address to another\n /// @param from The address to transfer from\n /// @param to The address of the recipient\n /// @param amount The amount of the token to transfer\n /// @param token The token address to transfer\n /// @dev Requires the from address to have approved at least the desired amount\n /// of tokens to msg.sender.\n function transferFrom(address from, address to, uint160 amount, address token) external;\n\n /// @notice Transfer approved tokens in a batch\n /// @param transferDetails Array of owners, recipients, amounts, and tokens for the transfers\n /// @dev Requires the from addresses to have approved at least the desired amount\n /// of tokens to msg.sender.\n function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external;\n\n /// @notice Enables performing a \"lockdown\" of the sender's Permit2 identity\n /// by batch revoking approvals\n /// @param approvals Array of approvals to revoke.\n function lockdown(TokenSpenderPair[] calldata approvals) external;\n\n /// @notice Invalidate nonces for a given (token, spender) pair\n /// @param token The token to invalidate nonces for\n /// @param spender The spender to invalidate nonces for\n /// @param newNonce The new nonce to set. Invalidates all nonces less than it.\n /// @dev Can't invalidate more than 2**16 nonces per transaction.\n function invalidateNonces(address token, address spender, uint48 newNonce) external;\n}\n", + "permit2/src/interfaces/IEIP712.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IEIP712 {\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "target": "DevLaunchLauncher.sol", + "version": "0.8.34" +} diff --git a/tests/sourcify-sweep/fixtures/contracts/1_0x060527b96597fb3a619b178d07b70af7a5c119de.json b/tests/sourcify-sweep/fixtures/contracts/1_0x060527b96597fb3a619b178d07b70af7a5c119de.json new file mode 100644 index 000000000..d337f7464 --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/1_0x060527b96597fb3a619b178d07b70af7a5c119de.json @@ -0,0 +1,22 @@ +{ + "chain_id": 1, + "name": "0x060527b96597fb3a619b178d07b70af7a5c119de", + "remappings": [], + "settings": { + "evmVersion": "osaka", + "libraries": {}, + "metadata": { + "bytecodeHash": "ipfs" + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "remappings": [] + }, + "sources": { + "pairData3.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.0;\r\n\r\ncontract PairDataUltraSafe {\r\n struct PairInfo {\r\n address pairAddress;\r\n address token0;\r\n address token1;\r\n uint8 decimals0;\r\n uint8 decimals1;\r\n uint256 pooled0;\r\n uint256 pooled1;\r\n }\r\n\r\n // --- function selectors (gas optimized)\r\n bytes4 private constant TOKEN0 = 0x0dfe1681;\r\n bytes4 private constant TOKEN1 = 0xd21220a7;\r\n bytes4 private constant DECIMALS = 0x313ce567;\r\n bytes4 private constant BALANCE_OF = 0x70a08231;\r\n bytes4 private constant GET_RESERVES = 0x0902f1ac;\r\n\r\n function getPairInfo(address[] memory pairAddresses, bool[] memory isV3)\r\n external\r\n view\r\n returns (PairInfo[] memory)\r\n {\r\n require(pairAddresses.length == isV3.length, \"Length mismatch\");\r\n\r\n PairInfo[] memory temp = new PairInfo[](pairAddresses.length);\r\n uint256 validCount = 0;\r\n\r\n for (uint256 i = 0; i < pairAddresses.length; i++) {\r\n address pairAddr = pairAddresses[i];\r\n\r\n address t0;\r\n address t1;\r\n\r\n // --- token0()\r\n {\r\n (bool success, bytes memory data) = pairAddr.staticcall(\r\n abi.encodeWithSelector(TOKEN0)\r\n );\r\n if (!success || data.length < 32) continue;\r\n t0 = abi.decode(data, (address));\r\n }\r\n\r\n // --- token1()\r\n {\r\n (bool success, bytes memory data) = pairAddr.staticcall(\r\n abi.encodeWithSelector(TOKEN1)\r\n );\r\n if (!success || data.length < 32) continue;\r\n t1 = abi.decode(data, (address));\r\n }\r\n\r\n uint8 d0 = 18;\r\n uint8 d1 = 18;\r\n\r\n // --- decimals0()\r\n {\r\n (bool success, bytes memory data) = t0.staticcall(\r\n abi.encodeWithSelector(DECIMALS)\r\n );\r\n if (success && data.length >= 32) {\r\n d0 = abi.decode(data, (uint8));\r\n }\r\n }\r\n\r\n // --- decimals1()\r\n {\r\n (bool success, bytes memory data) = t1.staticcall(\r\n abi.encodeWithSelector(DECIMALS)\r\n );\r\n if (success && data.length >= 32) {\r\n d1 = abi.decode(data, (uint8));\r\n }\r\n }\r\n\r\n uint256 pooled0 = 0;\r\n uint256 pooled1 = 0;\r\n\r\n if (!isV3[i]) {\r\n // --- V2: getReserves()\r\n (bool success, bytes memory data) = pairAddr.staticcall(\r\n abi.encodeWithSelector(GET_RESERVES)\r\n );\r\n\r\n if (!success || data.length < 96) continue;\r\n\r\n (uint112 r0, uint112 r1, ) = abi.decode(\r\n data,\r\n (uint112, uint112, uint32)\r\n );\r\n\r\n pooled0 = uint256(r0);\r\n pooled1 = uint256(r1);\r\n } else {\r\n // --- V3: balanceOf fallback\r\n\r\n // token0 balance\r\n {\r\n (bool success, bytes memory data) = t0.staticcall(\r\n abi.encodeWithSelector(BALANCE_OF, pairAddr)\r\n );\r\n if (success && data.length >= 32) {\r\n pooled0 = abi.decode(data, (uint256));\r\n }\r\n }\r\n\r\n // token1 balance\r\n {\r\n (bool success, bytes memory data) = t1.staticcall(\r\n abi.encodeWithSelector(BALANCE_OF, pairAddr)\r\n );\r\n if (success && data.length >= 32) {\r\n pooled1 = abi.decode(data, (uint256));\r\n }\r\n }\r\n }\r\n\r\n temp[validCount] = PairInfo({\r\n pairAddress: pairAddr,\r\n token0: t0,\r\n token1: t1,\r\n decimals0: d0,\r\n decimals1: d1,\r\n pooled0: pooled0,\r\n pooled1: pooled1\r\n });\r\n\r\n validCount++;\r\n }\r\n\r\n PairInfo[] memory result = new PairInfo[](validCount);\r\n for (uint256 j = 0; j < validCount; j++) {\r\n result[j] = temp[j];\r\n }\r\n\r\n return result;\r\n }\r\n}" + }, + "target": "pairData3.sol", + "version": "0.8.34" +} diff --git a/tests/sourcify-sweep/fixtures/contracts/1_0x0a048fc373deab2188106abab08995c42402ee72.json b/tests/sourcify-sweep/fixtures/contracts/1_0x0a048fc373deab2188106abab08995c42402ee72.json new file mode 100644 index 000000000..505857170 --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/1_0x0a048fc373deab2188106abab08995c42402ee72.json @@ -0,0 +1,17 @@ +{ + "chain_id": 1, + "name": "0x0a048fc373deab2188106abab08995c42402ee72", + "remappings": [], + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "remappings": [] + }, + "sources": { + "CryptoGangsStakeBurnV2.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\ninterface IERC721V2 {\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n}\n\n/**\n * CryptoGangs StakeBurn V2\n *\n * CryptoGangs uses Limit Break's transfer validator. The NFT owner must be the\n * caller when depositing, so the web app calls CryptoGangs.safeTransferFrom\n * directly for each selected token. This receiver records the requested action\n * from the transfer data; it never needs collection-wide approval.\n */\ncontract CryptoGangsStakeBurnV2 {\n IERC721V2 public constant NFT = IERC721V2(0x361E3C0cdC8888BE48CDe2821Ba4173582593Fd9);\n address public constant DEAD = 0x000000000000000000000000000000000000dEaD;\n\n uint8 private constant ACTION_STAKE = 1;\n uint8 private constant ACTION_BURN = 2;\n\n struct Position {\n address owner;\n uint64 lockedAt;\n uint64 unlockAt;\n }\n\n address public owner;\n uint256 private locked;\n mapping(uint256 => Position) public positions;\n mapping(address => uint256) public currentStaked;\n mapping(address => uint256) public lifetimeBurned;\n\n event Staked(address indexed wallet, uint256 indexed tokenId, uint64 unlockAt);\n event Unstaked(address indexed wallet, uint256 indexed tokenId);\n event Burned(address indexed wallet, uint256 indexed tokenId);\n event OwnerWithdrawal(address indexed wallet, uint256 indexed tokenId);\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n error InvalidNFT();\n error InvalidSender();\n error InvalidAction();\n error InvalidLockPeriod();\n error TokenNotStaked();\n error NotTokenOwner();\n error StillLocked(uint64 unlockAt);\n error OnlyOwner();\n error ZeroAddress();\n error Reentrancy();\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert OnlyOwner();\n _;\n }\n\n modifier nonReentrant() {\n if (locked == 1) revert Reentrancy();\n locked = 1;\n _;\n locked = 0;\n }\n\n constructor() {\n owner = msg.sender;\n emit OwnershipTransferred(address(0), msg.sender);\n }\n\n function onERC721Received(address, address from, uint256 tokenId, bytes calldata data)\n external\n nonReentrant\n returns (bytes4)\n {\n if (msg.sender != address(NFT)) revert InvalidNFT();\n if (from == address(0)) revert InvalidSender();\n\n (uint8 action, uint64 durationDays) = abi.decode(data, (uint8, uint64));\n\n if (action == ACTION_STAKE) {\n if (!_validDuration(durationDays)) revert InvalidLockPeriod();\n uint64 lockedAt = uint64(block.timestamp);\n uint64 unlockAt = lockedAt + durationDays * uint64(1 days);\n positions[tokenId] = Position({owner: from, lockedAt: lockedAt, unlockAt: unlockAt});\n currentStaked[from] += 1;\n emit Staked(from, tokenId, unlockAt);\n } else if (action == ACTION_BURN) {\n if (durationDays != 0) revert InvalidLockPeriod();\n lifetimeBurned[from] += 1;\n NFT.safeTransferFrom(address(this), DEAD, tokenId);\n emit Burned(from, tokenId);\n } else {\n revert InvalidAction();\n }\n\n return this.onERC721Received.selector;\n }\n\n function unstake(uint256 tokenId) external nonReentrant {\n Position memory position = positions[tokenId];\n if (position.owner == address(0)) revert TokenNotStaked();\n if (position.owner != msg.sender) revert NotTokenOwner();\n if (block.timestamp < position.unlockAt) revert StillLocked(position.unlockAt);\n\n delete positions[tokenId];\n currentStaked[msg.sender] -= 1;\n NFT.safeTransferFrom(address(this), msg.sender, tokenId);\n emit Unstaked(msg.sender, tokenId);\n }\n\n function ownerWithdraw(uint256 tokenId) external onlyOwner nonReentrant {\n Position memory position = positions[tokenId];\n if (position.owner != address(0)) {\n delete positions[tokenId];\n currentStaked[position.owner] -= 1;\n }\n NFT.safeTransferFrom(address(this), msg.sender, tokenId);\n emit OwnerWithdrawal(msg.sender, tokenId);\n }\n\n function scoreOf(address wallet) external view returns (uint256) {\n return currentStaked[wallet] + lifetimeBurned[wallet];\n }\n\n function transferOwnership(address newOwner) external onlyOwner {\n if (newOwner == address(0)) revert ZeroAddress();\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n }\n\n function _validDuration(uint64 durationDays) private pure returns (bool) {\n return durationDays == 7 || durationDays == 30 || durationDays == 90 || durationDays == 180\n || durationDays == 365;\n }\n}\n" + }, + "target": "CryptoGangsStakeBurnV2.sol", + "version": "0.8.34" +} diff --git a/tests/sourcify-sweep/fixtures/contracts/1_0x222fc1366a01973d788575322fcb53ae1954742a.json b/tests/sourcify-sweep/fixtures/contracts/1_0x222fc1366a01973d788575322fcb53ae1954742a.json new file mode 100644 index 000000000..1ffc51cdf --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/1_0x222fc1366a01973d788575322fcb53ae1954742a.json @@ -0,0 +1,26 @@ +{ + "chain_id": 1, + "name": "0x222fc1366a01973d788575322fcb53ae1954742a", + "remappings": [], + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "remappings": [] + }, + "sources": { + "project/project/contracts/library/IRandomSeedProvider.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.0;\r\n\r\n/// @title Interface for providing a random seed.\r\ninterface IRandomSeedProvider {\r\n /// @dev Returns a seed for pseudo-random generation.\r\n function randomSeed() external view returns (uint256);\r\n}", + "project/project/contracts/library/RandomLib.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.20;\r\n\r\n/// @dev Structure for pseudo-random generator state.\r\nstruct Random {\r\n uint seed;\r\n uint nonce;\r\n}\r\n\r\n/// @dev Library for pseudo-random number generation.\r\nlibrary RandomLibrary {\r\n /// @dev Generates the next pseudo-random number.\r\n /// @param random Generator state struct.\r\n function next(Random memory random) internal pure returns (uint) {\r\n return uint(keccak256(abi.encodePacked(random.seed, ++random.nonce)));\r\n }\r\n}\r\n", + "project/project/contracts/pepegs/Ipepeg.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.20;\r\n\r\n/// @dev pepeg data structure.\r\nstruct pepegSeedData {\r\n /// @dev pepeg ID.\r\n uint256 id;\r\n /// @dev pepeg seed.\r\n uint256 seed;\r\n}\r\n\r\n/// @dev pepeg collection interface.\r\n/// Each owner has a list of pepegs with unique IDs and seed values.\r\ninterface Ipepeg {\r\n /// @dev Error when the caller doesn't own the pepeg.\r\n error NotpepegOwner();\r\n /// @dev Error when pepeg index is out of range.\r\n error pepegIndexOutOfRange();\r\n\r\n /// @dev pepeg mint event.\r\n event OnpepegMinted(address indexed owner, uint pepegId);\r\n /// @dev pepeg burn event.\r\n event OnpepegBurned(address indexed owner, uint pepegId);\r\n /// @dev pepeg transfer event.\r\n event OnpepegTransfer(address indexed from, address indexed to, uint pepegId);\r\n\r\n /// @dev Total pepeg count.\r\n function pepegsTotalCount() external view returns (uint);\r\n /// @dev Total holder count.\r\n function HoldersCount() external view returns (uint);\r\n /// @dev pepeg count for an owner.\r\n function OwnerpepegsCount(address owner) external view returns (uint);\r\n /// @dev Returns a paginated list of pepegs.\r\n /// @param owner Owner address\r\n /// @param page Page number\r\n /// @param pageSize Page size\r\n function OwnerpepegsPage(address owner, uint page, uint pageSize) external view returns (pepegSeedData[] memory pepegs);\r\n /// @dev pepeg for an owner by index.\r\n /// @param owner Owner address\r\n /// @param index pepeg index\r\n function Ownerpepeg(address owner, uint index) external view returns (pepegSeedData memory);\r\n /// @dev pepeg index for an owner by ID.\r\n /// @param owner Owner address\r\n /// @param pepegId pepeg ID\r\n function OwnerpepegIndex(address owner, uint pepegId) external view returns (uint index);\r\n /// @dev Reorders the caller's pepeg. Shifts all items left/right (may be gas-inefficient).\r\n /// @param pepegId pepeg ID to reorder\r\n /// @param newIndex New index\r\n function Reorderpepeg(uint pepegId, uint newIndex) external;\r\n /// @dev Reorders the caller's pepeg. Gas-optimized swap without shifting.\r\n /// @param pepegId pepeg ID to reorder\r\n /// @param newIndex New index or swap index\r\n function ReorderpepegPair(uint pepegId, uint newIndex) external;\r\n /// @dev Checks if the owner owns a pepeg by ID.\r\n function OwnerOwns(address owner, uint pepegId) external view returns (bool);\r\n /// @dev Checks if the owner is a holder.\r\n function IsHolder(address owner) external view returns (bool);\r\n /// @dev Holder by index.\r\n function Holder(uint index) external view returns (address);\r\n /// @dev Holder number by address.\r\n function HolderNumber(address owner) external view returns (uint);\r\n\r\n /// @dev Transfers a pepeg to an address. One token is transferred with the pepeg.\r\n /// @param to Recipient address\r\n /// @param pepegId pepeg ID\r\n function transferpepeg(address to, uint pepegId) external;\r\n /// @dev Transfers multiple pepegs. Transfers the same number of tokens.\r\n /// @param to Recipient address\r\n /// @param pepegIds Array of pepeg IDs\r\n function transferpepegsList(\r\n address to,\r\n uint[] calldata pepegIds\r\n ) external;\r\n}", + "project/project/contracts/pepegs/pepeg.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.20;\r\n\r\nimport \"./Ipepeg.sol\";\r\nimport \"../svg_generation/pepegMetadata.sol\";\r\nimport \"../svg_generation/IImageParams.sol\";\r\nimport \"../library/RandomLib.sol\";\r\nimport \"../library/IRandomSeedProvider.sol\";\r\n\r\n/// @dev Allows creating and storing pepegs by owner address.\r\n/// @notice pepeg is a set of data that defines the token appearance.\r\n/// @notice To save storage, pepeg is stored as an encoded uint256 (non-zero).\r\n/// @notice A list of pepeg holders is maintained.\r\n/// Each pepeg has a unique non-zero ID.\r\n/// By ID you can get the encoded pepeg and decode it into pepegMetadata.\r\ncontract pepeg is Ipepeg {\r\n using RandomLibrary for Random;\r\n\r\n // all pepegs\r\n mapping(uint pepegId => uint256 seed) _pepegs; // encoded pepegs by ID\r\n\r\n // pepegs for each owner\r\n mapping(address owner => uint) _counts; // pepeg count per owner\r\n mapping(address owner => mapping(uint index => uint256 pepegId)) _ownedpepegs; // pepeg by owner index\r\n mapping(address owner => mapping(uint pepegId => uint index)) _ownedpepegsIndexes; // pepeg indices by ID\r\n mapping(address owner => mapping(uint pepegId => bool isOwn)) _owns; // ownership by pepeg ID\r\n\r\n // pepeg holders list\r\n mapping(uint index => address user) _holderList;\r\n mapping(address user => uint index) _holderListNumbers; // holder number in list (0 means not a holder)\r\n\r\n uint _pepegsTotalCount; // total pepeg count\r\n uint _holdersCount; // total holder count\r\n IRandomSeedProvider public randomSeedProvider; // random seed provider\r\n\r\n /// @dev Image parameters provider (element counts and palette sizes).\r\n IImageParams public imageParams;\r\n\r\n /// @dev Inserts an existing pepeg (by pepegId) into the owner's list.\r\n /// @notice Seed must already exist in _pepegs[pepegId].\r\n function _insertExistingpepegToOwner(address owner, uint pepegId) internal {\r\n // add to owner's list\r\n _ownedpepegs[owner][_counts[owner]] = pepegId;\r\n _ownedpepegsIndexes[owner][pepegId] = _counts[owner];\r\n _counts[owner]++;\r\n _owns[owner][pepegId] = true;\r\n\r\n // add owner to holder list if not present\r\n if (!IsHolder(owner)) {\r\n _holderList[_holdersCount] = owner;\r\n _holderListNumbers[owner] = ++_holdersCount;\r\n }\r\n }\r\n\r\n /// @dev Removes pepeg from owner's list (but does NOT delete the seed).\r\n function _removepepegFromOwner(address owner, uint pepegId) internal {\r\n // index of the removed item\r\n uint idx = _ownedpepegsIndexes[owner][pepegId];\r\n uint lastIdx = _counts[owner] - 1;\r\n\r\n if (idx != lastIdx) {\r\n // swap-with-last to keep list compact\r\n uint256 lastId = _ownedpepegs[owner][lastIdx];\r\n _ownedpepegs[owner][idx] = lastId;\r\n _ownedpepegsIndexes[owner][lastId] = idx;\r\n }\r\n\r\n // clear last slot and indices\r\n delete _ownedpepegs[owner][lastIdx];\r\n delete _ownedpepegsIndexes[owner][pepegId];\r\n\r\n _counts[owner]--;\r\n _owns[owner][pepegId] = false;\r\n\r\n // remove owner from holder list if they own none\r\n if (_counts[owner] == 0 && IsHolder(owner)) {\r\n _removeHolder(owner);\r\n }\r\n }\r\n\r\n /// @dev Restricts function to the pepeg owner.\r\n modifier onlypepegOwner(uint pepegId) {\r\n if (!_owns[msg.sender][pepegId]) revert NotpepegOwner();\r\n _;\r\n }\r\n /// @dev Ensures index is valid for the caller's pepeg list.\r\n modifier onlyMypepegIndex(uint index) {\r\n if (index >= _counts[msg.sender]) revert pepegIndexOutOfRange();\r\n _;\r\n }\r\n\r\n /// @dev Sets the random seed provider.\r\n /// @param newRandomSeedProvider Contract implementing IRandomSeedProvider\r\n function _setRandomSeedProvider(address newRandomSeedProvider) internal {\r\n randomSeedProvider = IRandomSeedProvider(newRandomSeedProvider);\r\n }\r\n\r\n /// @dev Creates a random generator state struct.\r\n function createRandom() internal view returns (Random memory) {\r\n return Random(randomSeedProvider.randomSeed(), 0);\r\n }\r\n\r\n /// @dev Sets the image parameters provider.\r\n /// @param imageParamsProvider Contract implementing IImageParams\r\n function _setImageParamsProvider(address imageParamsProvider) internal {\r\n imageParams = IImageParams(imageParamsProvider);\r\n }\r\n\r\n /// @dev Returns true with probability prob% (0..100).\r\n function _chance(\r\n uint prob,\r\n Random memory random\r\n ) internal pure returns (bool) {\r\n return (random.next() % 100) < prob;\r\n }\r\n\r\n /// @dev Picks id in 1..count (0 if count == 0).\r\n function _pickId(\r\n uint count,\r\n Random memory random\r\n ) internal pure returns (uint8) {\r\n if (count == 0) return 0;\r\n return uint8((random.next() % count) + 1);\r\n }\r\n\r\n /// @dev Picks a color index in 0..(max-1).\r\n function _pickColor(\r\n uint8 max,\r\n Random memory random\r\n ) internal pure returns (uint8) {\r\n if (max == 0) return 0;\r\n return uint8(random.next() % max);\r\n }\r\n\r\n function IsHolder(address owner) public view returns (bool) {\r\n return _holderListNumbers[owner] > 0;\r\n }\r\n\r\n function pepegsTotalCount() external view returns (uint) {\r\n return _pepegsTotalCount;\r\n }\r\n\r\n function HoldersCount() external view returns (uint) {\r\n return _holdersCount;\r\n }\r\n\r\n function OwnerpepegsCount(address owner) public view returns (uint) {\r\n return _counts[owner];\r\n }\r\n\r\n function Ownerpepeg(\r\n address owner,\r\n uint index\r\n ) external view returns (pepegSeedData memory) {\r\n if (index >= _counts[owner]) revert pepegIndexOutOfRange();\r\n uint256 id = _ownedpepegs[owner][index];\r\n return pepegSeedData({id: id, seed: _pepegs[id]});\r\n }\r\n\r\n function OwnerpepegIndex(\r\n address owner,\r\n uint pepegId\r\n ) external view returns (uint index) {\r\n if (!_owns[owner][pepegId]) revert NotpepegOwner();\r\n return _ownedpepegsIndexes[owner][pepegId];\r\n }\r\n\r\n function OwnerOwns(\r\n address owner,\r\n uint pepegId\r\n ) external view returns (bool) {\r\n return _owns[owner][pepegId];\r\n }\r\n\r\n function Holder(uint index) external view returns (address) {\r\n return _holderList[index];\r\n }\r\n\r\n function HolderNumber(address owner) external view returns (uint) {\r\n return _holderListNumbers[owner];\r\n }\r\n\r\n /// @notice returns a page of pepeg IDs and seeds for a given owner\r\n /// @param owner owner address\r\n /// @param page zero-based page index\r\n /// @param pageSize number of items per page\r\n function OwnerpepegsPage(\r\n address owner,\r\n uint page,\r\n uint pageSize\r\n ) external view override returns (pepegSeedData[] memory pepegs) {\r\n uint count = _counts[owner];\r\n if (pageSize == 0) return new pepegSeedData[](0);\r\n\r\n uint start = page * pageSize;\r\n if (start >= count) return new pepegSeedData[](0);\r\n\r\n uint end = start + pageSize;\r\n if (end > count) end = count;\r\n\r\n uint len = end - start;\r\n pepegs = new pepegSeedData[](len);\r\n for (uint i = 0; i < len; i++) {\r\n uint idx = start + i;\r\n uint256 inscId = _ownedpepegs[owner][idx];\r\n pepegs[i] = pepegSeedData({id: inscId, seed: _pepegs[inscId]});\r\n }\r\n }\r\n\r\n /// @dev Reorders caller's pepeg: pepegId goes to newIndex, others shift.\r\n function Reorderpepeg(\r\n uint pepegId,\r\n uint newIndex\r\n ) external override onlypepegOwner(pepegId) onlyMypepegIndex(newIndex) {\r\n uint currentIndex = _ownedpepegsIndexes[msg.sender][pepegId];\r\n if (newIndex == currentIndex) return;\r\n\r\n // take out element\r\n uint256 id = _ownedpepegs[msg.sender][currentIndex];\r\n\r\n // shift based on direction\r\n if (newIndex < currentIndex) {\r\n // shift right: [newIndex .. currentIndex-1] -> +1\r\n for (uint i = currentIndex; i > newIndex; i--) {\r\n _ownedpepegs[msg.sender][i] = _ownedpepegs[msg.sender][i - 1];\r\n _ownedpepegsIndexes[msg.sender][_ownedpepegs[msg.sender][i]] = i;\r\n }\r\n } else {\r\n // newIndex > currentIndex: shift left: [currentIndex+1 .. newIndex] -> -1\r\n for (uint i = currentIndex; i < newIndex; i++) {\r\n _ownedpepegs[msg.sender][i] = _ownedpepegs[msg.sender][i + 1];\r\n _ownedpepegsIndexes[msg.sender][_ownedpepegs[msg.sender][i]] = i;\r\n }\r\n }\r\n\r\n // place element into new slot\r\n _ownedpepegs[msg.sender][newIndex] = id;\r\n _ownedpepegsIndexes[msg.sender][id] = newIndex;\r\n }\r\n\r\n /// @dev Swaps pepegId with the element at newIndex without shifting (gas-optimized).\r\n function ReorderpepegPair(\r\n uint pepegId,\r\n uint newIndex\r\n ) external override onlypepegOwner(pepegId) onlyMypepegIndex(newIndex) {\r\n uint currentIndex = _ownedpepegsIndexes[msg.sender][pepegId];\r\n if (newIndex == currentIndex) return;\r\n\r\n uint256 otherId = _ownedpepegs[msg.sender][newIndex];\r\n\r\n // swap in array\r\n _ownedpepegs[msg.sender][newIndex] = pepegId;\r\n _ownedpepegs[msg.sender][currentIndex] = otherId;\r\n\r\n // update indices\r\n _ownedpepegsIndexes[msg.sender][pepegId] = newIndex;\r\n _ownedpepegsIndexes[msg.sender][otherId] = currentIndex;\r\n }\r\n\r\n /// @notice Creates a new pepeg for the owner.\r\n /// @param owner Owner address\r\n /// @param seed Encoded pepeg value\r\n function _mintpepeg(address owner, uint256 seed) internal {\r\n pepegSeedData memory seedData = _createpepeg(owner, seed);\r\n emit OnpepegMinted(owner, seedData.id);\r\n }\r\n\r\n /// @notice Creates a new pepeg for the owner.\r\n /// @param owner Owner address\r\n function _mintpepeg(address owner, Random memory random) internal {\r\n _mintpepeg(owner, _nextpepeg(random));\r\n }\r\n\r\n function _createpepeg(\r\n address owner,\r\n uint256 seed\r\n ) private returns (pepegSeedData memory seedData) {\r\n uint pepegId = ++_pepegsTotalCount;\r\n _pepegs[pepegId] = seed;\r\n _insertExistingpepegToOwner(owner, pepegId);\r\n return pepegSeedData({id: pepegId, seed: seed});\r\n }\r\n\r\n /// @notice Generates a random pepeg.\r\n /// @param random Generator state struct\r\n function _nextpepeg(\r\n Random memory random\r\n ) internal view returns (uint256 seed) {\r\n // get aggregated parameters (element counts and palette sizes)\r\n ImageParams memory p = imageParams.getImageParams();\r\n\r\n pepegMetadata memory s;\r\n\r\n // background (100%) \u2014 index in 0..backgroundColorsCount-1\r\n s.backGroundColor = p.backgroundColorsCount == 0\r\n ? 0\r\n : uint8(random.next() % p.backgroundColorsCount);\r\n\r\n // horn (20%)\r\n if (_chance(20, random)) {\r\n s.horn = _pickId(p.hornCount, random);\r\n if (s.horn > 0) {\r\n s.hornColor = _pickColor(p.colorsCount, random);\r\n }\r\n }\r\n\r\n // accessories (30%)\r\n if (_chance(30, random)) {\r\n s.accessories = _pickId(p.accessoriesCount, random);\r\n if (s.accessories > 0) {\r\n s.accessoriesColor = _pickColor(p.colorsCount, random);\r\n }\r\n }\r\n\r\n // hair (80%)\r\n if (_chance(80, random)) {\r\n s.hair = _pickId(p.hairCount, random);\r\n if (s.hair > 0) {\r\n s.hairColor = _pickColor(p.colorsCount, random);\r\n }\r\n }\r\n\r\n // wings (30%) \u2014 use body color, no separate color\r\n if (_chance(30, random)) {\r\n s.wings = _pickId(p.wingsCount, random);\r\n }\r\n\r\n // tail (80%)\r\n if (_chance(80, random)) {\r\n s.tail = _pickId(p.tailCount, random);\r\n if (s.tail > 0) {\r\n s.tailColor = _pickColor(p.colorsCount, random);\r\n }\r\n }\r\n\r\n // front legs (100%)\r\n s.legsFront = _pickId(p.legsFrontCount, random);\r\n\r\n // back legs (100%)\r\n s.legsBack = _pickId(p.legsBackCount, random);\r\n\r\n // eyes (100%)\r\n s.eyes = _pickId(p.eyesCount, random);\r\n if (s.eyes > 0) {\r\n s.eyesColor = _pickColor(p.colorsCount, random);\r\n }\r\n\r\n // body (100%)\r\n s.body = _pickId(p.bodyCount, random);\r\n if (s.body > 0) {\r\n s.bodyColor = _pickColor(p.colorsCount, random);\r\n }\r\n\r\n // ground (100%)\r\n s.ground = _pickId(p.groundCount, random);\r\n if (s.ground > 0) {\r\n s.groundColor = _pickColor(p.colorsCount, random);\r\n }\r\n\r\n // encode struct into uint256\r\n seed = pepegMetadataLibrary.encode(s);\r\n return seed;\r\n }\r\n\r\n /// @notice Removes a pepeg from the owner.\r\n /// @param owner Owner address\r\n /// @param pepegId pepeg ID\r\n function _burnpepeg(\r\n address owner,\r\n uint pepegId\r\n ) internal returns (uint256 seed) {\r\n uint256 deletedSeed = _deletepepeg(owner, pepegId);\r\n emit OnpepegBurned(owner, pepegId);\r\n return deletedSeed;\r\n }\r\n\r\n function _deletepepeg(\r\n address owner,\r\n uint pepegId\r\n ) internal returns (uint256 seed) {\r\n // remove ownership and delete from owner's list\r\n _removepepegFromOwner(owner, pepegId);\r\n\r\n // delete seed\r\n seed = _pepegs[pepegId];\r\n delete _pepegs[pepegId];\r\n\r\n return seed;\r\n }\r\n\r\n /// @notice Transfers a pepeg from one owner to another.\r\n /// @param from Sender address\r\n /// @param to Recipient address\r\n /// @param pepegId pepeg ID\r\n function _transferpepeg(address from, address to, uint pepegId) internal {\r\n // remove pepegId from sender list, keep seed\r\n _removepepegFromOwner(from, pepegId);\r\n // insert same pepegId into receiver list (ID preserved)\r\n _insertExistingpepegToOwner(to, pepegId);\r\n emit OnpepegTransfer(from, to, pepegId);\r\n }\r\n\r\n /// @notice Removes a holder from the global holder list.\r\n /// @param owner Owner address\r\n function _removeHolder(address owner) internal {\r\n // _holderListNumbers is 1-based; _holderList indices are 0-based\r\n uint idx = _holderListNumbers[owner] - 1;\r\n uint lastIdx = _holdersCount - 1;\r\n\r\n // fill the gap: move the last entry into the removed slot (swap-with-last)\r\n if (idx != lastIdx) {\r\n address lastHolder = _holderList[lastIdx];\r\n _holderList[idx] = lastHolder;\r\n _holderListNumbers[lastHolder] = idx + 1; // update 1-based slot number\r\n }\r\n\r\n delete _holderList[lastIdx];\r\n delete _holderListNumbers[owner];\r\n _holdersCount--;\r\n }\r\n\r\n function transferpepeg(\r\n address to,\r\n uint pepegId\r\n ) external override onlypepegOwner(pepegId) {\r\n _transferpepeg(msg.sender, to, pepegId);\r\n _afterpepegTransferred(msg.sender, to, pepegId);\r\n }\r\n\r\n function transferpepegsList(\r\n address to,\r\n uint[] calldata pepegIds\r\n ) external override {\r\n uint len = pepegIds.length;\r\n if (len == 0) return;\r\n\r\n for (uint i = 0; i < len; ++i) {\r\n if (!_owns[msg.sender][pepegIds[i]]) revert NotpepegOwner();\r\n _transferpepeg(msg.sender, to, pepegIds[i]);\r\n }\r\n\r\n _afterpepegsListTransferred(msg.sender, to, pepegIds);\r\n }\r\n\r\n function _afterpepegTransferred(\r\n address from,\r\n address to,\r\n uint pepegId\r\n ) internal virtual {}\r\n\r\n function _afterpepegsListTransferred(\r\n address from,\r\n address to,\r\n uint[] calldata pepegIds\r\n ) internal virtual {}\r\n}\r\n", + "project/project/contracts/svg_generation/IImageParams.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.20;\r\n\r\n/// @dev Generation parameters (element counts and palette sizes).\r\nstruct ImageParams {\r\n // palette sizes\r\n uint8 colorsCount; // full color palette\r\n uint8 backgroundColorsCount; // background palette\r\n\r\n // element counts per layer\r\n uint accessoriesCount;\r\n uint bodyCount;\r\n uint eyesCount;\r\n uint hairCount;\r\n uint hornCount;\r\n uint legsFrontCount;\r\n uint legsBackCount;\r\n uint tailCount;\r\n uint groundCount;\r\n uint wingsCount;\r\n}\r\n\r\ninterface IImageParams {\r\n /// @dev Returns aggregated parameters for seed/pepeg generation.\r\n function getImageParams() external view returns (ImageParams memory);\r\n}\r\n\r\n\r\n", + "project/project/contracts/svg_generation/pepegMetadata.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.20;\r\n\r\n/// @dev Metadata structure for pepeg.\r\n/// If a value is 0, the item is absent in pepeg.\r\nstruct pepegMetadata {\r\n uint8 backGroundColor; // background color (can be 0)\r\n uint8 body;\r\n uint8 eyes;\r\n uint8 hair;\r\n uint8 horn;\r\n uint8 legsBack;\r\n uint8 legsFront;\r\n uint8 wings;\r\n uint8 tail;\r\n uint8 accessories;\r\n uint8 ground;\r\n uint8 bodyColor; // body color index (legs and wings use the same color)\r\n uint8 eyesColor;\r\n uint8 hairColor;\r\n uint8 hornColor;\r\n uint8 groundColor;\r\n uint8 accessoriesColor;\r\n uint8 tailColor;\r\n}\r\n\r\n/// @dev Library for encoding/decoding pepegMetadata into uint256.\r\n/// Each item is omitted if its value is 0.\r\n/// 1 byte - background color (can be 0)\r\n/// 2 byte - horn\r\n/// 3 byte - accessories\r\n/// 4 byte - hair\r\n/// 5 byte - wings\r\n/// 6 byte - tail\r\n/// 7 byte - front legs\r\n/// 8 byte - back legs\r\n/// 9 byte - eyes\r\n/// 10 byte - body\r\n/// 11 byte - ground\r\n/// 12 byte - body color (legs and wings use the same color)\r\n/// 13 byte - eyes color\r\n/// 14 byte - hair color\r\n/// 15 byte - horn color\r\n/// 16 byte - ground color\r\n/// 17 byte - accessories color\r\n/// 18 byte - tail color\r\nlibrary pepegMetadataLibrary {\r\n /// @dev Encodes pepegMetadata into uint256.\r\n function encode(pepegMetadata memory seed) internal pure returns (uint256 result) {\r\n result |= uint256(seed.backGroundColor) << 0;\r\n result |= uint256(seed.horn) << 8;\r\n result |= uint256(seed.accessories) << 16;\r\n result |= uint256(seed.hair) << 24;\r\n result |= uint256(seed.wings) << 32;\r\n result |= uint256(seed.tail) << 40;\r\n result |= uint256(seed.legsFront) << 48;\r\n result |= uint256(seed.legsBack) << 56;\r\n result |= uint256(seed.eyes) << 64;\r\n result |= uint256(seed.body) << 72;\r\n result |= uint256(seed.ground) << 80;\r\n result |= uint256(seed.bodyColor) << 88;\r\n result |= uint256(seed.eyesColor) << 96;\r\n result |= uint256(seed.hairColor) << 104;\r\n result |= uint256(seed.hornColor) << 112;\r\n result |= uint256(seed.groundColor) << 120;\r\n result |= uint256(seed.accessoriesColor) << 128;\r\n result |= uint256(seed.tailColor) << 136;\r\n }\r\n\r\n /// @dev Decodes uint256 into pepegMetadata.\r\n function decode(uint256 seed) internal pure returns (pepegMetadata memory) {\r\n return\r\n pepegMetadata({\r\n backGroundColor: uint8(seed & 0xFF),\r\n body: uint8((seed >> 72) & 0xFF),\r\n eyes: uint8((seed >> 64) & 0xFF),\r\n hair: uint8((seed >> 24) & 0xFF),\r\n horn: uint8((seed >> 8) & 0xFF),\r\n legsBack: uint8((seed >> 56) & 0xFF),\r\n legsFront: uint8((seed >> 48) & 0xFF),\r\n wings: uint8((seed >> 32) & 0xFF),\r\n tail: uint8((seed >> 40) & 0xFF),\r\n accessories: uint8((seed >> 16) & 0xFF),\r\n ground: uint8((seed >> 80) & 0xFF),\r\n bodyColor: uint8((seed >> 88) & 0xFF),\r\n eyesColor: uint8((seed >> 96) & 0xFF),\r\n hairColor: uint8((seed >> 104) & 0xFF),\r\n hornColor: uint8((seed >> 112) & 0xFF),\r\n groundColor: uint8((seed >> 120) & 0xFF),\r\n accessoriesColor: uint8((seed >> 128) & 0xFF),\r\n tailColor: uint8((seed >> 136) & 0xFF)\r\n });\r\n }\r\n}\r\n", + "project/project/contracts/token/IStartableToken.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.20;\r\n\r\n/// @dev Interface for a token with a start action.\r\ninterface IStartableToken {\r\n /// @notice Sets the liquidity pool address and enables buying.\r\n function start(address newPool) external;\r\n /// @notice Checks whether the token is started.\r\n function isStarted() external view returns (bool);\r\n}", + "project/project/contracts/token/pepeg.sol": "// SPDX-License-Identifier: MIT\r\n// https://pepeg.art\r\n// https://x.com/pePEG_art\r\n// https://t.me/PepegEntry\r\n// first pePEG GIFs Collection\r\npragma solidity ^0.8.20;\r\n\r\nimport \"../pepegs/pepeg.sol\";\r\nimport {ERC20} from \"solady/src/tokens/ERC20.sol\";\r\nimport {Ownable} from \"solady/src/auth/Ownable.sol\";\r\nimport {IStartableToken} from \"./IStartableToken.sol\";\r\n\r\n/// @title pepeg token\r\n/// @notice ERC20 token that syncs pepeg with balances, excluding the liquidity pool address.\r\n/// - Mints pepegs on transfers from the pool\r\n/// - Burns pepegs when sending to the pool or zero address\r\n/// - Transfers pepegs 1:1 on user-to-user transfers\r\n/// All operations use UNIT_PER_pepeg (tokens per pepeg) to avoid excessive minting.\r\ncontract pepegToken is pepeg, ERC20, Ownable, IStartableToken {\r\n error AddressCanNotReceivepepeg();\r\n\r\n uint256 public constant UNIT_PER_pepeg = 1e18; // tokens per pepeg\r\n uint256 public constant INITIAL_SUPPLY = 10_000e18; // initial supply to owner\r\n\r\n // max buy configuration\r\n uint256 constant MAX_BUY_PRECISION = 100000;\r\n uint256 constant _startMaxBuyCount =\r\n (INITIAL_SUPPLY * 250) / MAX_BUY_PRECISION; // 0.25% of initial supply\r\n uint256 constant _addMaxBuyPercentPerSec = 3; // add 0.003%/second\r\n\r\n address immutable _notMintableAccount; // deployer cannot mint pepegs to prevent abuse\r\n uint256 _startTime;\r\n address public hook;\r\n\r\n // settings\r\n address public pool; // excluded address (liquidity pool)\r\n\r\n // constructors\r\n constructor(address owner_) {\r\n _initializeOwner(owner_);\r\n _mint(owner_, INITIAL_SUPPLY);\r\n _notMintableAccount = owner_;\r\n }\r\n\r\n modifier canReceivepepegs(address addr) {\r\n if (!_canReceivepepegs(addr)) revert AddressCanNotReceivepepeg();\r\n _;\r\n }\r\n\r\n /// @notice Ensures the call is made only by the Uniswap v4 hook.\r\n modifier onlyHook() {\r\n require(msg.sender == hook, \"only for hook\");\r\n _;\r\n }\r\n\r\n function name() public pure override returns (string memory) {\r\n return \"Pepeg\";\r\n }\r\n\r\n function symbol() public pure override returns (string memory) {\r\n return \"pePEG\";\r\n }\r\n\r\n /// @notice Sets the liquidity pool address and enables buying.\r\n function start(address newPool) external onlyHook {\r\n pool = newPool;\r\n _startTime = block.timestamp;\r\n }\r\n\r\n function isStarted() public view returns (bool) {\r\n return pool != address(0);\r\n }\r\n\r\n function maxBuy() public view returns (uint256) {\r\n if (!isStarted()) return 0;\r\n uint256 count = _startMaxBuyCount +\r\n (INITIAL_SUPPLY *\r\n (block.timestamp - _startTime) *\r\n _addMaxBuyPercentPerSec) /\r\n MAX_BUY_PRECISION;\r\n if (count > INITIAL_SUPPLY) count = INITIAL_SUPPLY;\r\n return count;\r\n }\r\n\r\n /// @notice Sets the Uniswap v4 hook address.\r\n function setHook(address newHook) external onlyOwner {\r\n hook = newHook;\r\n }\r\n\r\n /// @dev Sets the image parameters provider.\r\n /// @param imageParamsProvider Contract implementing IImageParams\r\n function setImageParamsProvider(\r\n address imageParamsProvider\r\n ) public onlyOwner {\r\n _setImageParamsProvider(imageParamsProvider);\r\n }\r\n\r\n /// @dev Sets the random seed provider.\r\n /// @param randomSeedProvider Contract implementing IRandomSeed\r\n function setRandomSeedProvider(\r\n address randomSeedProvider\r\n ) public onlyOwner {\r\n _setRandomSeedProvider(randomSeedProvider);\r\n }\r\n\r\n // methods\r\n /// @dev Reacts to token transfers and syncs pepeg.\r\n function _afterTokenTransfer(\r\n address from,\r\n address to,\r\n uint256 amount\r\n ) internal override {\r\n super._afterTokenTransfer(from, to, amount);\r\n if (pool == address(0)) return;\r\n _onTokenTransfer(from, to, amount, createRandom());\r\n }\r\n\r\n // ----- internals -----\r\n function _onTokenTransfer(\r\n address from,\r\n address to,\r\n uint256 amount,\r\n Random memory random\r\n ) internal {\r\n // If pool is not set yet, do not sync (e.g. during initial mint).\r\n if (pool == address(0)) return;\r\n\r\n // pool -> user: mint pepegs\r\n if (from == pool && to != address(0)) {\r\n // deployer will not have hooks to prevent the abuse\r\n if (_notMintableAccount == to) return;\r\n require(isStarted(), \"not started\");\r\n // max buy limit (grows over time)\r\n require(amount <= maxBuy(), \"buy limit\");\r\n _mintpepegs(to, amount / UNIT_PER_pepeg, random);\r\n return;\r\n }\r\n\r\n // determine how many pepegs to remove from sender\r\n uint256 from_max_allowed = balanceOf(from) / UNIT_PER_pepeg;\r\n uint256 from_count = this.OwnerpepegsCount(from);\r\n uint256 from_remove_cnount = from_count > from_max_allowed\r\n ? from_count - from_max_allowed\r\n : 0;\r\n\r\n // determine how many pepegs the receiver can accept\r\n uint256 to_max_allowed = balanceOf(to) / UNIT_PER_pepeg;\r\n uint256 to_count = this.OwnerpepegsCount(to);\r\n uint256 to_receive_allowed = to_count < to_max_allowed\r\n ? to_max_allowed - to_count\r\n : 0;\r\n\r\n // if no pepegs to move, do nothing\r\n if (from_remove_cnount == 0) return;\r\n\r\n // if receiver cannot receive pepegs\r\n if (!_canReceivepepegs(to)) {\r\n to_receive_allowed = 0;\r\n }\r\n\r\n // user -> user: move pepegs\r\n uint256 move_qty = from_remove_cnount < to_receive_allowed\r\n ? from_remove_cnount\r\n : to_receive_allowed;\r\n if (move_qty > 0) _movepepegs(from, to, move_qty);\r\n\r\n // burn remaining pepegs from sender\r\n _burnpepegs(from, from_remove_cnount - move_qty);\r\n }\r\n\r\n function _mintpepegs(\r\n address user,\r\n uint256 qty,\r\n Random memory random\r\n ) internal {\r\n for (uint256 i = 0; i < qty; i++) {\r\n _mintpepeg(user, random);\r\n }\r\n }\r\n\r\n function _burnpepegs(address user, uint256 qty) internal {\r\n for (uint256 i = 0; i < qty; i++) {\r\n uint count = this.OwnerpepegsCount(user);\r\n if (count == 0) break; // nothing to burn\r\n uint lastIdx = count - 1;\r\n uint pepegId = this.Ownerpepeg(user, lastIdx).id;\r\n _burnpepeg(user, pepegId);\r\n }\r\n }\r\n\r\n function _movepepegs(\r\n address from,\r\n address to,\r\n uint256 qty\r\n ) internal canReceivepepegs(to) {\r\n for (uint256 i = 0; i < qty; i++) {\r\n uint count = this.OwnerpepegsCount(from);\r\n if (count == 0) break; // nothing to move\r\n uint lastIdx = count - 1;\r\n uint pepegId = this.Ownerpepeg(from, lastIdx).id;\r\n _transferpepeg(from, to, pepegId);\r\n }\r\n }\r\n\r\n function _canReceivepepegs(address addr) internal view returns (bool) {\r\n return addr != pool && addr != address(0);\r\n }\r\n\r\n function _afterpepegTransferred(\r\n address from,\r\n address to,\r\n uint pepegId\r\n ) internal override {\r\n _transfer(from, to, UNIT_PER_pepeg);\r\n }\r\n\r\n function _afterpepegsListTransferred(\r\n address from,\r\n address to,\r\n uint[] calldata pepegIds\r\n ) internal override {\r\n _transfer(from, to, UNIT_PER_pepeg * pepegIds.length);\r\n }\r\n}\r\n", + "solady/src/auth/Ownable.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)\n///\n/// @dev Note:\n/// This implementation does NOT auto-initialize the owner to `msg.sender`.\n/// You MUST call the `_initializeOwner` in the constructor / initializer.\n///\n/// While the ownable portion follows\n/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,\n/// the nomenclature for the 2-step ownership handover may be unique to this codebase.\nabstract contract Ownable {\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* CUSTOM ERRORS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev The caller is not authorized to call the function.\n error Unauthorized();\n\n /// @dev The `newOwner` cannot be the zero address.\n error NewOwnerIsZeroAddress();\n\n /// @dev The `pendingOwner` does not have a valid handover request.\n error NoHandoverRequest();\n\n /// @dev Cannot double-initialize.\n error AlreadyInitialized();\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* EVENTS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev The ownership is transferred from `oldOwner` to `newOwner`.\n /// This event is intentionally kept the same as OpenZeppelin's Ownable to be\n /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),\n /// despite it not being as lightweight as a single argument event.\n event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);\n\n /// @dev An ownership handover to `pendingOwner` has been requested.\n event OwnershipHandoverRequested(address indexed pendingOwner);\n\n /// @dev The ownership handover to `pendingOwner` has been canceled.\n event OwnershipHandoverCanceled(address indexed pendingOwner);\n\n /// @dev `keccak256(bytes(\"OwnershipTransferred(address,address)\"))`.\n uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =\n 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;\n\n /// @dev `keccak256(bytes(\"OwnershipHandoverRequested(address)\"))`.\n uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =\n 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;\n\n /// @dev `keccak256(bytes(\"OwnershipHandoverCanceled(address)\"))`.\n uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =\n 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* STORAGE */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev The owner slot is given by:\n /// `bytes32(~uint256(uint32(bytes4(keccak256(\"_OWNER_SLOT_NOT\")))))`.\n /// It is intentionally chosen to be a high value\n /// to avoid collision with lower slots.\n /// The choice of manual storage layout is to enable compatibility\n /// with both regular and upgradeable contracts.\n bytes32 internal constant _OWNER_SLOT =\n 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;\n\n /// The ownership handover slot of `newOwner` is given by:\n /// ```\n /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))\n /// let handoverSlot := keccak256(0x00, 0x20)\n /// ```\n /// It stores the expiry timestamp of the two-step ownership handover.\n uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* INTERNAL FUNCTIONS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.\n function _guardInitializeOwner() internal pure virtual returns (bool guard) {}\n\n /// @dev Initializes the owner directly without authorization guard.\n /// This function must be called upon initialization,\n /// regardless of whether the contract is upgradeable or not.\n /// This is to enable generalization to both regular and upgradeable contracts,\n /// and to save gas in case the initial owner is not the caller.\n /// For performance reasons, this function will not check if there\n /// is an existing owner.\n function _initializeOwner(address newOwner) internal virtual {\n if (_guardInitializeOwner()) {\n /// @solidity memory-safe-assembly\n assembly {\n let ownerSlot := _OWNER_SLOT\n if sload(ownerSlot) {\n mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.\n revert(0x1c, 0x04)\n }\n // Clean the upper 96 bits.\n newOwner := shr(96, shl(96, newOwner))\n // Store the new value.\n sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))\n // Emit the {OwnershipTransferred} event.\n log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)\n }\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n // Clean the upper 96 bits.\n newOwner := shr(96, shl(96, newOwner))\n // Store the new value.\n sstore(_OWNER_SLOT, newOwner)\n // Emit the {OwnershipTransferred} event.\n log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)\n }\n }\n }\n\n /// @dev Sets the owner directly without authorization guard.\n function _setOwner(address newOwner) internal virtual {\n if (_guardInitializeOwner()) {\n /// @solidity memory-safe-assembly\n assembly {\n let ownerSlot := _OWNER_SLOT\n // Clean the upper 96 bits.\n newOwner := shr(96, shl(96, newOwner))\n // Emit the {OwnershipTransferred} event.\n log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)\n // Store the new value.\n sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))\n }\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n let ownerSlot := _OWNER_SLOT\n // Clean the upper 96 bits.\n newOwner := shr(96, shl(96, newOwner))\n // Emit the {OwnershipTransferred} event.\n log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)\n // Store the new value.\n sstore(ownerSlot, newOwner)\n }\n }\n }\n\n /// @dev Throws if the sender is not the owner.\n function _checkOwner() internal view virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // If the caller is not the stored owner, revert.\n if iszero(eq(caller(), sload(_OWNER_SLOT))) {\n mstore(0x00, 0x82b42900) // `Unauthorized()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Returns how long a two-step ownership handover is valid for in seconds.\n /// Override to return a different value if needed.\n /// Made internal to conserve bytecode. Wrap it in a public function if needed.\n function _ownershipHandoverValidFor() internal view virtual returns (uint64) {\n return 48 * 3600;\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* PUBLIC UPDATE FUNCTIONS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Allows the owner to transfer the ownership to `newOwner`.\n function transferOwnership(address newOwner) public payable virtual onlyOwner {\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(shl(96, newOwner)) {\n mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.\n revert(0x1c, 0x04)\n }\n }\n _setOwner(newOwner);\n }\n\n /// @dev Allows the owner to renounce their ownership.\n function renounceOwnership() public payable virtual onlyOwner {\n _setOwner(address(0));\n }\n\n /// @dev Request a two-step ownership handover to the caller.\n /// The request will automatically expire in 48 hours (172800 seconds) by default.\n function requestOwnershipHandover() public payable virtual {\n unchecked {\n uint256 expires = block.timestamp + _ownershipHandoverValidFor();\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and set the handover slot to `expires`.\n mstore(0x0c, _HANDOVER_SLOT_SEED)\n mstore(0x00, caller())\n sstore(keccak256(0x0c, 0x20), expires)\n // Emit the {OwnershipHandoverRequested} event.\n log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())\n }\n }\n }\n\n /// @dev Cancels the two-step ownership handover to the caller, if any.\n function cancelOwnershipHandover() public payable virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and set the handover slot to 0.\n mstore(0x0c, _HANDOVER_SLOT_SEED)\n mstore(0x00, caller())\n sstore(keccak256(0x0c, 0x20), 0)\n // Emit the {OwnershipHandoverCanceled} event.\n log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())\n }\n }\n\n /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.\n /// Reverts if there is no existing ownership handover requested by `pendingOwner`.\n function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and set the handover slot to 0.\n mstore(0x0c, _HANDOVER_SLOT_SEED)\n mstore(0x00, pendingOwner)\n let handoverSlot := keccak256(0x0c, 0x20)\n // If the handover does not exist, or has expired.\n if gt(timestamp(), sload(handoverSlot)) {\n mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.\n revert(0x1c, 0x04)\n }\n // Set the handover slot to 0.\n sstore(handoverSlot, 0)\n }\n _setOwner(pendingOwner);\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* PUBLIC READ FUNCTIONS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Returns the owner of the contract.\n function owner() public view virtual returns (address result) {\n /// @solidity memory-safe-assembly\n assembly {\n result := sload(_OWNER_SLOT)\n }\n }\n\n /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.\n function ownershipHandoverExpiresAt(address pendingOwner)\n public\n view\n virtual\n returns (uint256 result)\n {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the handover slot.\n mstore(0x0c, _HANDOVER_SLOT_SEED)\n mstore(0x00, pendingOwner)\n // Load the handover slot.\n result := sload(keccak256(0x0c, 0x20))\n }\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* MODIFIERS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Marks a function as only callable by the owner.\n modifier onlyOwner() virtual {\n _checkOwner();\n _;\n }\n}\n", + "solady/src/tokens/ERC20.sol": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Simple ERC20 + EIP-2612 implementation.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)\n///\n/// @dev Note:\n/// - The ERC20 standard allows minting and transferring to and from the zero address,\n/// minting and transferring zero tokens, as well as self-approvals.\n/// For performance, this implementation WILL NOT revert for such actions.\n/// Please add any checks with overrides if desired.\n/// - The `permit` function uses the ecrecover precompile (0x1).\n///\n/// If you are overriding:\n/// - NEVER violate the ERC20 invariant:\n/// the total sum of all balances must be equal to `totalSupply()`.\n/// - Check that the overridden function is actually used in the function you want to\n/// change the behavior of. Much of the code has been manually inlined for performance.\nabstract contract ERC20 {\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* CUSTOM ERRORS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev The total supply has overflowed.\n error TotalSupplyOverflow();\n\n /// @dev The allowance has overflowed.\n error AllowanceOverflow();\n\n /// @dev The allowance has underflowed.\n error AllowanceUnderflow();\n\n /// @dev Insufficient balance.\n error InsufficientBalance();\n\n /// @dev Insufficient allowance.\n error InsufficientAllowance();\n\n /// @dev The permit is invalid.\n error InvalidPermit();\n\n /// @dev The permit has expired.\n error PermitExpired();\n\n /// @dev The allowance of Permit2 is fixed at infinity.\n error Permit2AllowanceIsFixedAtInfinity();\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* EVENTS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Emitted when `amount` tokens is transferred from `from` to `to`.\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`.\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /// @dev `keccak256(bytes(\"Transfer(address,address,uint256)\"))`.\n uint256 private constant _TRANSFER_EVENT_SIGNATURE =\n 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;\n\n /// @dev `keccak256(bytes(\"Approval(address,address,uint256)\"))`.\n uint256 private constant _APPROVAL_EVENT_SIGNATURE =\n 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* STORAGE */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev The storage slot for the total supply.\n uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c;\n\n /// @dev The balance slot of `owner` is given by:\n /// ```\n /// mstore(0x0c, _BALANCE_SLOT_SEED)\n /// mstore(0x00, owner)\n /// let balanceSlot := keccak256(0x0c, 0x20)\n /// ```\n uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2;\n\n /// @dev The allowance slot of (`owner`, `spender`) is given by:\n /// ```\n /// mstore(0x20, spender)\n /// mstore(0x0c, _ALLOWANCE_SLOT_SEED)\n /// mstore(0x00, owner)\n /// let allowanceSlot := keccak256(0x0c, 0x34)\n /// ```\n uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20;\n\n /// @dev The nonce slot of `owner` is given by:\n /// ```\n /// mstore(0x0c, _NONCES_SLOT_SEED)\n /// mstore(0x00, owner)\n /// let nonceSlot := keccak256(0x0c, 0x20)\n /// ```\n uint256 private constant _NONCES_SLOT_SEED = 0x38377508;\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* CONSTANTS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev `(_NONCES_SLOT_SEED << 16) | 0x1901`.\n uint256 private constant _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX = 0x383775081901;\n\n /// @dev `keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\")`.\n bytes32 private constant _DOMAIN_TYPEHASH =\n 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\n\n /// @dev `keccak256(\"1\")`.\n /// If you need to use a different version, override `_versionHash`.\n bytes32 private constant _DEFAULT_VERSION_HASH =\n 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;\n\n /// @dev `keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\")`.\n bytes32 private constant _PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n\n /// @dev The canonical Permit2 address.\n /// For signature-based allowance granting for single transaction ERC20 `transferFrom`.\n /// Enabled by default. To disable, override `_givePermit2InfiniteAllowance()`.\n /// [Github](https://github.com/Uniswap/permit2)\n /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)\n address internal constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* ERC20 METADATA */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Returns the name of the token.\n function name() public view virtual returns (string memory);\n\n /// @dev Returns the symbol of the token.\n function symbol() public view virtual returns (string memory);\n\n /// @dev Returns the decimals places of the token.\n function decimals() public view virtual returns (uint8) {\n return 18;\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* ERC20 */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Returns the amount of tokens in existence.\n function totalSupply() public view virtual returns (uint256 result) {\n /// @solidity memory-safe-assembly\n assembly {\n result := sload(_TOTAL_SUPPLY_SLOT)\n }\n }\n\n /// @dev Returns the amount of tokens owned by `owner`.\n function balanceOf(address owner) public view virtual returns (uint256 result) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x0c, _BALANCE_SLOT_SEED)\n mstore(0x00, owner)\n result := sload(keccak256(0x0c, 0x20))\n }\n }\n\n /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`.\n function allowance(address owner, address spender)\n public\n view\n virtual\n returns (uint256 result)\n {\n if (_givePermit2InfiniteAllowance()) {\n if (spender == _PERMIT2) return type(uint256).max;\n }\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x20, spender)\n mstore(0x0c, _ALLOWANCE_SLOT_SEED)\n mstore(0x00, owner)\n result := sload(keccak256(0x0c, 0x34))\n }\n }\n\n /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n ///\n /// Emits a {Approval} event.\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n if (_givePermit2InfiniteAllowance()) {\n /// @solidity memory-safe-assembly\n assembly {\n // If `spender == _PERMIT2 && amount != type(uint256).max`.\n if iszero(or(xor(shr(96, shl(96, spender)), _PERMIT2), iszero(not(amount)))) {\n mstore(0x00, 0x3f68539a) // `Permit2AllowanceIsFixedAtInfinity()`.\n revert(0x1c, 0x04)\n }\n }\n }\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the allowance slot and store the amount.\n mstore(0x20, spender)\n mstore(0x0c, _ALLOWANCE_SLOT_SEED)\n mstore(0x00, caller())\n sstore(keccak256(0x0c, 0x34), amount)\n // Emit the {Approval} event.\n mstore(0x00, amount)\n log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c)))\n }\n return true;\n }\n\n /// @dev Transfer `amount` tokens from the caller to `to`.\n ///\n /// Requirements:\n /// - `from` must at least have `amount`.\n ///\n /// Emits a {Transfer} event.\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n _beforeTokenTransfer(msg.sender, to, amount);\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the balance slot and load its value.\n mstore(0x0c, _BALANCE_SLOT_SEED)\n mstore(0x00, caller())\n let fromBalanceSlot := keccak256(0x0c, 0x20)\n let fromBalance := sload(fromBalanceSlot)\n // Revert if insufficient balance.\n if gt(amount, fromBalance) {\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated balance.\n sstore(fromBalanceSlot, sub(fromBalance, amount))\n // Compute the balance slot of `to`.\n mstore(0x00, to)\n let toBalanceSlot := keccak256(0x0c, 0x20)\n // Add and store the updated balance of `to`.\n // Will not overflow because the sum of all user balances\n // cannot exceed the maximum uint256 value.\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\n // Emit the {Transfer} event.\n mstore(0x20, amount)\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c)))\n }\n _afterTokenTransfer(msg.sender, to, amount);\n return true;\n }\n\n /// @dev Transfers `amount` tokens from `from` to `to`.\n ///\n /// Note: Does not update the allowance if it is the maximum uint256 value.\n ///\n /// Requirements:\n /// - `from` must at least have `amount`.\n /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`.\n ///\n /// Emits a {Transfer} event.\n function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {\n _beforeTokenTransfer(from, to, amount);\n // Code duplication is for zero-cost abstraction if possible.\n if (_givePermit2InfiniteAllowance()) {\n /// @solidity memory-safe-assembly\n assembly {\n let from_ := shl(96, from)\n if iszero(eq(caller(), _PERMIT2)) {\n // Compute the allowance slot and load its value.\n mstore(0x20, caller())\n mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED))\n let allowanceSlot := keccak256(0x0c, 0x34)\n let allowance_ := sload(allowanceSlot)\n // If the allowance is not the maximum uint256 value.\n if not(allowance_) {\n // Revert if the amount to be transferred exceeds the allowance.\n if gt(amount, allowance_) {\n mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated allowance.\n sstore(allowanceSlot, sub(allowance_, amount))\n }\n }\n // Compute the balance slot and load its value.\n mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))\n let fromBalanceSlot := keccak256(0x0c, 0x20)\n let fromBalance := sload(fromBalanceSlot)\n // Revert if insufficient balance.\n if gt(amount, fromBalance) {\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated balance.\n sstore(fromBalanceSlot, sub(fromBalance, amount))\n // Compute the balance slot of `to`.\n mstore(0x00, to)\n let toBalanceSlot := keccak256(0x0c, 0x20)\n // Add and store the updated balance of `to`.\n // Will not overflow because the sum of all user balances\n // cannot exceed the maximum uint256 value.\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\n // Emit the {Transfer} event.\n mstore(0x20, amount)\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))\n }\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n let from_ := shl(96, from)\n // Compute the allowance slot and load its value.\n mstore(0x20, caller())\n mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED))\n let allowanceSlot := keccak256(0x0c, 0x34)\n let allowance_ := sload(allowanceSlot)\n // If the allowance is not the maximum uint256 value.\n if not(allowance_) {\n // Revert if the amount to be transferred exceeds the allowance.\n if gt(amount, allowance_) {\n mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated allowance.\n sstore(allowanceSlot, sub(allowance_, amount))\n }\n // Compute the balance slot and load its value.\n mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))\n let fromBalanceSlot := keccak256(0x0c, 0x20)\n let fromBalance := sload(fromBalanceSlot)\n // Revert if insufficient balance.\n if gt(amount, fromBalance) {\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated balance.\n sstore(fromBalanceSlot, sub(fromBalance, amount))\n // Compute the balance slot of `to`.\n mstore(0x00, to)\n let toBalanceSlot := keccak256(0x0c, 0x20)\n // Add and store the updated balance of `to`.\n // Will not overflow because the sum of all user balances\n // cannot exceed the maximum uint256 value.\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\n // Emit the {Transfer} event.\n mstore(0x20, amount)\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))\n }\n }\n _afterTokenTransfer(from, to, amount);\n return true;\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* EIP-2612 */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev For more performance, override to return the constant value\n /// of `keccak256(bytes(name()))` if `name()` will never change.\n function _constantNameHash() internal view virtual returns (bytes32 result) {}\n\n /// @dev If you need a different value, override this function.\n function _versionHash() internal view virtual returns (bytes32 result) {\n result = _DEFAULT_VERSION_HASH;\n }\n\n /// @dev For inheriting contracts to increment the nonce.\n function _incrementNonce(address owner) internal virtual {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x0c, _NONCES_SLOT_SEED)\n mstore(0x00, owner)\n let nonceSlot := keccak256(0x0c, 0x20)\n sstore(nonceSlot, add(1, sload(nonceSlot)))\n }\n }\n\n /// @dev Returns the current nonce for `owner`.\n /// This value is used to compute the signature for EIP-2612 permit.\n function nonces(address owner) public view virtual returns (uint256 result) {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the nonce slot and load its value.\n mstore(0x0c, _NONCES_SLOT_SEED)\n mstore(0x00, owner)\n result := sload(keccak256(0x0c, 0x20))\n }\n }\n\n /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`,\n /// authorized by a signed approval by `owner`.\n ///\n /// Emits a {Approval} event.\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual {\n if (_givePermit2InfiniteAllowance()) {\n /// @solidity memory-safe-assembly\n assembly {\n // If `spender == _PERMIT2 && value != type(uint256).max`.\n if iszero(or(xor(shr(96, shl(96, spender)), _PERMIT2), iszero(not(value)))) {\n mstore(0x00, 0x3f68539a) // `Permit2AllowanceIsFixedAtInfinity()`.\n revert(0x1c, 0x04)\n }\n }\n }\n bytes32 nameHash = _constantNameHash();\n // We simply calculate it on-the-fly to allow for cases where the `name` may change.\n if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));\n bytes32 versionHash = _versionHash();\n /// @solidity memory-safe-assembly\n assembly {\n // Revert if the block timestamp is greater than `deadline`.\n if gt(timestamp(), deadline) {\n mstore(0x00, 0x1a15a3cc) // `PermitExpired()`.\n revert(0x1c, 0x04)\n }\n let m := mload(0x40) // Grab the free memory pointer.\n // Clean the upper 96 bits.\n owner := shr(96, shl(96, owner))\n spender := shr(96, shl(96, spender))\n // Compute the nonce slot and load its value.\n mstore(0x0e, _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX)\n mstore(0x00, owner)\n let nonceSlot := keccak256(0x0c, 0x20)\n let nonceValue := sload(nonceSlot)\n // Prepare the domain separator.\n mstore(m, _DOMAIN_TYPEHASH)\n mstore(add(m, 0x20), nameHash)\n mstore(add(m, 0x40), versionHash)\n mstore(add(m, 0x60), chainid())\n mstore(add(m, 0x80), address())\n mstore(0x2e, keccak256(m, 0xa0))\n // Prepare the struct hash.\n mstore(m, _PERMIT_TYPEHASH)\n mstore(add(m, 0x20), owner)\n mstore(add(m, 0x40), spender)\n mstore(add(m, 0x60), value)\n mstore(add(m, 0x80), nonceValue)\n mstore(add(m, 0xa0), deadline)\n mstore(0x4e, keccak256(m, 0xc0))\n // Prepare the ecrecover calldata.\n mstore(0x00, keccak256(0x2c, 0x42))\n mstore(0x20, and(0xff, v))\n mstore(0x40, r)\n mstore(0x60, s)\n let t := staticcall(gas(), 1, 0x00, 0x80, 0x20, 0x20)\n // If the ecrecover fails, the returndatasize will be 0x00,\n // `owner` will be checked if it equals the hash at 0x00,\n // which evaluates to false (i.e. 0), and we will revert.\n // If the ecrecover succeeds, the returndatasize will be 0x20,\n // `owner` will be compared against the returned address at 0x20.\n if iszero(eq(mload(returndatasize()), owner)) {\n mstore(0x00, 0xddafbaef) // `InvalidPermit()`.\n revert(0x1c, 0x04)\n }\n // Increment and store the updated nonce.\n sstore(nonceSlot, add(nonceValue, t)) // `t` is 1 if ecrecover succeeds.\n // Compute the allowance slot and store the value.\n // The `owner` is already at slot 0x20.\n mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender))\n sstore(keccak256(0x2c, 0x34), value)\n // Emit the {Approval} event.\n log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender)\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero pointer.\n }\n }\n\n /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit.\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) {\n bytes32 nameHash = _constantNameHash();\n // We simply calculate it on-the-fly to allow for cases where the `name` may change.\n if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));\n bytes32 versionHash = _versionHash();\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Grab the free memory pointer.\n mstore(m, _DOMAIN_TYPEHASH)\n mstore(add(m, 0x20), nameHash)\n mstore(add(m, 0x40), versionHash)\n mstore(add(m, 0x60), chainid())\n mstore(add(m, 0x80), address())\n result := keccak256(m, 0xa0)\n }\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* INTERNAL MINT FUNCTIONS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Mints `amount` tokens to `to`, increasing the total supply.\n ///\n /// Emits a {Transfer} event.\n function _mint(address to, uint256 amount) internal virtual {\n _beforeTokenTransfer(address(0), to, amount);\n /// @solidity memory-safe-assembly\n assembly {\n let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT)\n let totalSupplyAfter := add(totalSupplyBefore, amount)\n // Revert if the total supply overflows.\n if lt(totalSupplyAfter, totalSupplyBefore) {\n mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`.\n revert(0x1c, 0x04)\n }\n // Store the updated total supply.\n sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter)\n // Compute the balance slot and load its value.\n mstore(0x0c, _BALANCE_SLOT_SEED)\n mstore(0x00, to)\n let toBalanceSlot := keccak256(0x0c, 0x20)\n // Add and store the updated balance.\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\n // Emit the {Transfer} event.\n mstore(0x20, amount)\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c)))\n }\n _afterTokenTransfer(address(0), to, amount);\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* INTERNAL BURN FUNCTIONS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Burns `amount` tokens from `from`, reducing the total supply.\n ///\n /// Emits a {Transfer} event.\n function _burn(address from, uint256 amount) internal virtual {\n _beforeTokenTransfer(from, address(0), amount);\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the balance slot and load its value.\n mstore(0x0c, _BALANCE_SLOT_SEED)\n mstore(0x00, from)\n let fromBalanceSlot := keccak256(0x0c, 0x20)\n let fromBalance := sload(fromBalanceSlot)\n // Revert if insufficient balance.\n if gt(amount, fromBalance) {\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated balance.\n sstore(fromBalanceSlot, sub(fromBalance, amount))\n // Subtract and store the updated total supply.\n sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount))\n // Emit the {Transfer} event.\n mstore(0x00, amount)\n log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0)\n }\n _afterTokenTransfer(from, address(0), amount);\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* INTERNAL TRANSFER FUNCTIONS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Moves `amount` of tokens from `from` to `to`.\n function _transfer(address from, address to, uint256 amount) internal virtual {\n _beforeTokenTransfer(from, to, amount);\n /// @solidity memory-safe-assembly\n assembly {\n let from_ := shl(96, from)\n // Compute the balance slot and load its value.\n mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))\n let fromBalanceSlot := keccak256(0x0c, 0x20)\n let fromBalance := sload(fromBalanceSlot)\n // Revert if insufficient balance.\n if gt(amount, fromBalance) {\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated balance.\n sstore(fromBalanceSlot, sub(fromBalance, amount))\n // Compute the balance slot of `to`.\n mstore(0x00, to)\n let toBalanceSlot := keccak256(0x0c, 0x20)\n // Add and store the updated balance of `to`.\n // Will not overflow because the sum of all user balances\n // cannot exceed the maximum uint256 value.\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\n // Emit the {Transfer} event.\n mstore(0x20, amount)\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))\n }\n _afterTokenTransfer(from, to, amount);\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* INTERNAL ALLOWANCE FUNCTIONS */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`.\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n if (_givePermit2InfiniteAllowance()) {\n if (spender == _PERMIT2) return; // Do nothing, as allowance is infinite.\n }\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the allowance slot and load its value.\n mstore(0x20, spender)\n mstore(0x0c, _ALLOWANCE_SLOT_SEED)\n mstore(0x00, owner)\n let allowanceSlot := keccak256(0x0c, 0x34)\n let allowance_ := sload(allowanceSlot)\n // If the allowance is not the maximum uint256 value.\n if not(allowance_) {\n // Revert if the amount to be transferred exceeds the allowance.\n if gt(amount, allowance_) {\n mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated allowance.\n sstore(allowanceSlot, sub(allowance_, amount))\n }\n }\n }\n\n /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`.\n ///\n /// Emits a {Approval} event.\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n if (_givePermit2InfiniteAllowance()) {\n /// @solidity memory-safe-assembly\n assembly {\n // If `spender == _PERMIT2 && amount != type(uint256).max`.\n if iszero(or(xor(shr(96, shl(96, spender)), _PERMIT2), iszero(not(amount)))) {\n mstore(0x00, 0x3f68539a) // `Permit2AllowanceIsFixedAtInfinity()`.\n revert(0x1c, 0x04)\n }\n }\n }\n /// @solidity memory-safe-assembly\n assembly {\n let owner_ := shl(96, owner)\n // Compute the allowance slot and store the amount.\n mstore(0x20, spender)\n mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED))\n sstore(keccak256(0x0c, 0x34), amount)\n // Emit the {Approval} event.\n mstore(0x00, amount)\n log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c)))\n }\n }\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* HOOKS TO OVERRIDE */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Hook that is called before any transfer of tokens.\n /// This includes minting and burning.\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /// @dev Hook that is called after any transfer of tokens.\n /// This includes minting and burning.\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /*\u00b4:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0\u2022.*\u2022\u00b4.*:\u02da.\u00b0*.\u02da\u2022\u00b4.\u00b0:\u00b0\u2022.\u00b0+.*\u2022\u00b4.*:*/\n /* PERMIT2 */\n /*.\u2022\u00b0:\u00b0.\u00b4+\u02da.*\u00b0.\u02da:*.\u00b4\u2022*.+\u00b0.\u2022\u00b0:\u00b4*.\u00b4\u2022*.\u2022\u00b0.\u2022\u00b0:\u00b0.\u00b4:\u2022\u02da\u00b0.*\u00b0.\u02da:*.\u00b4+\u00b0.\u2022*/\n\n /// @dev Returns whether to fix the Permit2 contract's allowance at infinity.\n ///\n /// This value should be kept constant after contract initialization,\n /// or else the actual allowance values may not match with the {Approval} events.\n /// For best performance, return a compile-time constant for zero-cost abstraction.\n function _givePermit2InfiniteAllowance() internal view virtual returns (bool) {\n return true;\n }\n}\n" + }, + "target": "project/project/contracts/token/pepeg.sol", + "version": "0.8.34" +} diff --git a/tests/sourcify-sweep/fixtures/contracts/56_0x7742ae0735c954e49aa7abaa6be5a50f3503c3f9.json b/tests/sourcify-sweep/fixtures/contracts/56_0x7742ae0735c954e49aa7abaa6be5a50f3503c3f9.json new file mode 100644 index 000000000..ccd11181e --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/56_0x7742ae0735c954e49aa7abaa6be5a50f3503c3f9.json @@ -0,0 +1,18 @@ +{ + "chain_id": 56, + "name": "0x7742ae0735c954e49aa7abaa6be5a50f3503c3f9", + "remappings": [], + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "remappings": [], + "viaIR": true + }, + "sources": { + "contracts/LadderSettlement.sol": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.20;\r\n\r\n/// @title Minimal IERC20 interface\r\ninterface IERC20 {\r\n function totalSupply() external view returns (uint256);\r\n function balanceOf(address account) external view returns (uint256);\r\n function transfer(address to, uint256 value) external returns (bool);\r\n function allowance(address owner, address spender) external view returns (uint256);\r\n function approve(address spender, uint256 value) external returns (bool);\r\n function transferFrom(address from, address to, uint256 value) external returns (bool);\r\n event Transfer(address indexed from, address indexed to, uint256 value);\r\n event Approval(address indexed owner, address indexed spender, uint256 value);\r\n}\r\n\r\n/// @title SafeERC20 - minimal safe wrappers for ERC20 ops\r\nlibrary SafeERC20 {\r\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\r\n (bool success, bytes memory data) = address(token).call(\r\n abi.encodeWithSelector(token.transfer.selector, to, value)\r\n );\r\n require(success, \"SafeERC20: transfer failed\");\r\n if (data.length > 0) {\r\n require(abi.decode(data, (bool)), \"SafeERC20: transfer false\");\r\n }\r\n }\r\n\r\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\r\n (bool success, bytes memory data) = address(token).call(\r\n abi.encodeWithSelector(token.transferFrom.selector, from, to, value)\r\n );\r\n require(success, \"SafeERC20: transferFrom failed\");\r\n if (data.length > 0) {\r\n require(abi.decode(data, (bool)), \"SafeERC20: transfer false\");\r\n }\r\n }\r\n\r\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\r\n (bool success, bytes memory data) = address(token).call(\r\n abi.encodeWithSelector(token.approve.selector, spender, value)\r\n );\r\n require(success, \"SafeERC20: approve failed\");\r\n if (data.length > 0) {\r\n require(abi.decode(data, (bool)), \"SafeERC20: approve false\");\r\n }\r\n }\r\n}\r\n\r\n/// @title ReentrancyGuard - protection against reentrancy attacks\r\nabstract contract ReentrancyGuard {\r\n uint256 private constant NOT_ENTERED = 1;\r\n uint256 private constant ENTERED = 2;\r\n uint256 private _status;\r\n\r\n constructor() {\r\n _status = NOT_ENTERED;\r\n }\r\n\r\n modifier nonReentrant() {\r\n require(_status != ENTERED, \"ReentrancyGuard: reentrant call\");\r\n _status = ENTERED;\r\n _;\r\n _status = NOT_ENTERED;\r\n }\r\n}\r\n\r\n/// @title Pausable - emergency pause functionality\r\nabstract contract Pausable {\r\n event Paused(address account);\r\n event Unpaused(address account);\r\n\r\n bool private _paused;\r\n\r\n constructor() {\r\n _paused = false;\r\n }\r\n\r\n modifier whenNotPaused() {\r\n require(!_paused, \"Pausable: paused\");\r\n _;\r\n }\r\n\r\n modifier whenPaused() {\r\n require(_paused, \"Pausable: not paused\");\r\n _;\r\n }\r\n\r\n function paused() public view returns (bool) {\r\n return _paused;\r\n }\r\n\r\n function _pause() internal whenNotPaused {\r\n _paused = true;\r\n emit Paused(msg.sender);\r\n }\r\n\r\n function _unpause() internal whenPaused {\r\n _paused = false;\r\n emit Unpaused(msg.sender);\r\n }\r\n}\r\n\r\n/// @title LadderSettlementHybrid - Hybrid orderbook with commit-reveal and on-chain partial fills\r\n/// @notice Designed for hybrid DEX: off-chain orderbook, on-chain settlement\r\n/// @dev Features:\r\n/// - Commit-reveal to prevent front-running\r\n/// - Only ladder partial fills stored on-chain\r\n/// - Regular orders: verified and executed, no storage\r\ncontract LadderSettlementHybrid is ReentrancyGuard, Pausable {\r\n using SafeERC20 for IERC20;\r\n\r\n // ============ EIP-712 domain ==========\r\n bytes32 private constant EIP712_DOMAIN_TYPEHASH =\r\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\r\n bytes32 private constant NAME_HASH = keccak256(bytes(\"LadderSettlementHybrid\"));\r\n bytes32 private constant VERSION_HASH = keccak256(bytes(\"1\"));\r\n\r\n bytes32 public immutable DOMAIN_SEPARATOR;\r\n\r\n // ============ Commit-Reveal ============\r\n uint256 public commitDuration = 10 minutes; // Time for commit phase\r\n uint256 public revealDuration = 5 minutes; // Time for reveal phase\r\n mapping(bytes32 => bool) public commits; // commitHash => revealed\r\n mapping(bytes32 => bool) public revealed; // commitHash => revealed\r\n mapping(bytes32 => RevealedOrder) public revealedOrders; // commitHash => order data\r\n\r\n struct RevealedOrder {\r\n address maker;\r\n address tokenIn;\r\n address tokenOut;\r\n uint256 amountIn;\r\n uint256 amountOutMin;\r\n uint256 expiration;\r\n uint256 nonce;\r\n address receiver;\r\n uint256 salt;\r\n bool isLadder;\r\n uint256 priceStart;\r\n uint256 priceEnd;\r\n uint256 levels;\r\n }\r\n\r\n event Committed(bytes32 indexed commitHash, address indexed maker, uint256 revealBy);\r\n event Revealed(bytes32 indexed commitHash, address indexed maker);\r\n event CommitExpired(bytes32 indexed commitHash);\r\n\r\n // ============ Regular Order Struct ============\r\n struct Order {\r\n address maker;\r\n address tokenIn;\r\n address tokenOut;\r\n uint256 amountIn;\r\n uint256 amountOutMin;\r\n uint256 expiration;\r\n uint256 nonce;\r\n address receiver;\r\n uint256 salt;\r\n }\r\n\r\n bytes32 public constant ORDER_TYPEHASH = keccak256(\r\n \"Order(address maker,address tokenIn,address tokenOut,uint256 amountIn,uint256 amountOutMin,uint256 expiration,uint256 nonce,address receiver,uint256 salt)\"\r\n );\r\n\r\n // ============ Ladder Authorization Struct ============\r\n struct LadderAuth {\r\n address maker;\r\n address tokenIn;\r\n address tokenOut;\r\n uint256 totalAmount;\r\n uint256 priceStart;\r\n uint256 priceEnd;\r\n uint256 levels;\r\n uint256 expiration;\r\n uint256 nonce;\r\n uint256 salt;\r\n }\r\n\r\n bytes32 public constant LADDER_TYPEHASH = keccak256(\r\n \"LadderAuth(address maker,address tokenIn,address tokenOut,uint256 totalAmount,uint256 priceStart,uint256 priceEnd,uint256 levels,uint256 expiration,uint256 nonce,uint256 salt)\"\r\n );\r\n\r\n // ============ Ladder Partial Fill Storage (only for ladders) ============\r\n mapping(bytes32 => uint256) public ladderTotalFilled; // ladderHash => total filled\r\n mapping(bytes32 => mapping(uint256 => uint256)) public ladderLevelFilled; // ladderHash => levelIndex => filled\r\n\r\n // ============ State ============\r\n address public owner;\r\n\r\n // ============ Events ============\r\n event LadderMatched(\r\n bytes32 indexed ladderHash,\r\n address indexed maker,\r\n address indexed matcher,\r\n uint256 levelIndex,\r\n uint256 amountBase,\r\n uint256 amountQuote\r\n );\r\n\r\n event OrderFilled(bytes32 indexed orderHash, address indexed maker, address indexed taker, uint256 amountIn, uint256 amountOut);\r\n\r\n event Matched(\r\n bytes32 indexed buyHash,\r\n bytes32 indexed sellHash,\r\n address indexed matcher,\r\n uint256 amountBase,\r\n uint256 amountQuote\r\n );\r\n\r\n // Owner events\r\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r\n\r\n // ============ Errors ============\r\n error InvalidLadderAuth();\r\n error BadLadderSignature();\r\n error LadderExpired();\r\n error InvalidLevel();\r\n error AmountExceedsTotal();\r\n error LadderAlreadyFilled();\r\n error PriceTooLow();\r\n error Overfill();\r\n\r\n // Regular order errors\r\n error BadSignature();\r\n error Expired();\r\n error InvalidOrder();\r\n\r\n // Commit-Reveal errors\r\n error CommitNotFound();\r\n error AlreadyRevealed();\r\n error CommitNotActive();\r\n error RevealTooLate();\r\n\r\n // Owner error\r\n error OnlyOwner();\r\n\r\n // ============ Constructor ============\r\n constructor() {\r\n owner = msg.sender;\r\n \r\n uint256 chainId;\r\n assembly {\r\n chainId := chainid()\r\n }\r\n DOMAIN_SEPARATOR = keccak256(\r\n abi.encode(\r\n EIP712_DOMAIN_TYPEHASH,\r\n NAME_HASH,\r\n VERSION_HASH,\r\n chainId,\r\n address(this)\r\n )\r\n );\r\n \r\n emit OwnershipTransferred(address(0), msg.sender);\r\n }\r\n\r\n // ============ Owner Controls ============\r\n function transferOwnership(address newOwner) external {\r\n require(msg.sender == owner, \"OnlyOwner\");\r\n require(newOwner != address(0), \"Invalid owner\");\r\n emit OwnershipTransferred(owner, newOwner);\r\n owner = newOwner;\r\n }\r\n\r\n function pause() external {\r\n require(msg.sender == owner, \"OnlyOwner\");\r\n _pause();\r\n }\r\n\r\n function unpause() external {\r\n require(msg.sender == owner, \"OnlyOwner\");\r\n _unpause();\r\n }\r\n\r\n function setCommitRevealDurations(uint256 _commitDuration, uint256 _revealDuration) external {\r\n require(msg.sender == owner, \"OnlyOwner\");\r\n commitDuration = _commitDuration;\r\n revealDuration = _revealDuration;\r\n }\r\n\r\n // ============ Commit-Reveal Functions ============\r\n\r\n /// @notice Commit a hash of the order (prevents front-running)\r\n /// @param commitHash The hash of (order + secret)\r\n function commitOrder(bytes32 commitHash) external whenNotPaused {\r\n require(!commits[commitHash], \"already committed\");\r\n commits[commitHash] = true;\r\n \r\n uint256 revealBy = block.timestamp + commitDuration;\r\n emit Committed(commitHash, msg.sender, revealBy);\r\n }\r\n\r\n /// @notice Reveal the actual order after commit\r\n /// @param commitHash The original commit hash\r\n /// @param order The actual order details\r\n /// @param signature The maker's signature\r\n /// @param secret The secret used to create commitHash\r\n function revealOrder(\r\n bytes32 commitHash,\r\n Order memory order,\r\n bytes calldata signature,\r\n bytes32 secret\r\n ) external whenNotPaused {\r\n // Verify commit exists and not yet revealed\r\n if (!commits[commitHash]) revert CommitNotFound();\r\n if (revealed[commitHash]) revert AlreadyRevealed();\r\n \r\n // Verify the secret produces the commitHash\r\n bytes32 expectedCommit = keccak256(abi.encode(\r\n order.maker,\r\n order.tokenIn,\r\n order.tokenOut,\r\n order.amountIn,\r\n order.amountOutMin,\r\n order.expiration,\r\n order.nonce,\r\n order.receiver,\r\n order.salt,\r\n msg.sender,\r\n secret\r\n ));\r\n if (expectedCommit != commitHash) revert CommitNotFound();\r\n \r\n // Mark as revealed\r\n revealed[commitHash] = true;\r\n \r\n // Store the revealed order\r\n revealedOrders[commitHash] = RevealedOrder({\r\n maker: order.maker,\r\n tokenIn: order.tokenIn,\r\n tokenOut: order.tokenOut,\r\n amountIn: order.amountIn,\r\n amountOutMin: order.amountOutMin,\r\n expiration: order.expiration,\r\n nonce: order.nonce,\r\n receiver: order.receiver,\r\n salt: order.salt,\r\n isLadder: false,\r\n priceStart: 0,\r\n priceEnd: 0,\r\n levels: 0\r\n });\r\n \r\n // Verify signature\r\n if (!verifySignature(order, signature)) revert BadSignature();\r\n \r\n emit Revealed(commitHash, order.maker);\r\n }\r\n\r\n /// @notice Reveal a ladder order after commit\r\n /// @param commitHash The original commit hash\r\n /// @param auth The actual ladder authorization\r\n /// @param signature The maker's signature\r\n /// @param secret The secret used to create commitHash\r\n function revealLadder(\r\n bytes32 commitHash,\r\n LadderAuth memory auth,\r\n bytes calldata signature,\r\n bytes32 secret\r\n ) external whenNotPaused {\r\n if (!commits[commitHash]) revert CommitNotFound();\r\n if (revealed[commitHash]) revert AlreadyRevealed();\r\n \r\n bytes32 expectedCommit = keccak256(abi.encode(\r\n auth.maker,\r\n auth.tokenIn,\r\n auth.tokenOut,\r\n auth.totalAmount,\r\n auth.priceStart,\r\n auth.priceEnd,\r\n auth.levels,\r\n auth.expiration,\r\n auth.nonce,\r\n auth.salt,\r\n msg.sender,\r\n secret\r\n ));\r\n if (expectedCommit != commitHash) revert CommitNotFound();\r\n \r\n revealed[commitHash] = true;\r\n \r\n revealedOrders[commitHash] = RevealedOrder({\r\n maker: auth.maker,\r\n tokenIn: auth.tokenIn,\r\n tokenOut: auth.tokenOut,\r\n amountIn: auth.totalAmount,\r\n amountOutMin: 0,\r\n expiration: auth.expiration,\r\n nonce: auth.nonce,\r\n receiver: auth.maker,\r\n salt: auth.salt,\r\n isLadder: true,\r\n priceStart: auth.priceStart,\r\n priceEnd: auth.priceEnd,\r\n levels: auth.levels\r\n });\r\n \r\n if (!verifyLadderSignature(auth, signature)) revert BadLadderSignature();\r\n \r\n emit Revealed(commitHash, auth.maker);\r\n }\r\n\r\n /// @notice Clean up expired commits (anyone can call)\r\n /// @param commitHashes Array of commit hashes to clean\r\n function cleanupExpiredCommits(bytes32[] calldata commitHashes) external {\r\n for (uint256 i = 0; i < commitHashes.length; i++) {\r\n bytes32 hash = commitHashes[i];\r\n if (commits[hash] && !revealed[hash]) {\r\n delete commits[hash];\r\n emit CommitExpired(hash);\r\n }\r\n }\r\n }\r\n\r\n // ============ Regular Order Functions ============\r\n\r\n function hashOrder(Order memory o) public pure returns (bytes32) {\r\n return keccak256(\r\n abi.encode(\r\n ORDER_TYPEHASH,\r\n o.maker,\r\n o.tokenIn,\r\n o.tokenOut,\r\n o.amountIn,\r\n o.amountOutMin,\r\n o.expiration,\r\n o.nonce,\r\n o.receiver,\r\n o.salt\r\n )\r\n );\r\n }\r\n\r\n function getOrderDigest(Order memory o) public view returns (bytes32) {\r\n return keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR, hashOrder(o)));\r\n }\r\n\r\n function verifySignature(Order memory o, bytes memory signature) public view returns (bool) {\r\n bytes32 hash = hashOrder(o);\r\n bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR, hash));\r\n return _recover(digest, signature) == o.maker;\r\n }\r\n\r\n // ============ Ladder Functions ============\r\n\r\n function hashLadderAuth(LadderAuth memory auth) public pure returns (bytes32) {\r\n return keccak256(\r\n abi.encode(\r\n LADDER_TYPEHASH,\r\n auth.maker,\r\n auth.tokenIn,\r\n auth.tokenOut,\r\n auth.totalAmount,\r\n auth.priceStart,\r\n auth.priceEnd,\r\n auth.levels,\r\n auth.expiration,\r\n auth.nonce,\r\n auth.salt\r\n )\r\n );\r\n }\r\n\r\n function getLadderDigest(LadderAuth memory auth) public view returns (bytes32) {\r\n return keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR, hashLadderAuth(auth)));\r\n }\r\n\r\n function verifyLadderSignature(LadderAuth memory auth, bytes memory signature) public view returns (bool) {\r\n bytes32 hash = hashLadderAuth(auth);\r\n bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR, hash));\r\n return _recover(digest, signature) == auth.maker;\r\n }\r\n\r\n function isLadderValid(LadderAuth memory auth) public view returns (bool) {\r\n if (auth.maker == address(0)) return false;\r\n if (auth.totalAmount == 0) return false;\r\n if (auth.levels == 0) return false;\r\n if (auth.expiration != 0 && block.timestamp > auth.expiration) return false;\r\n return true;\r\n }\r\n\r\n // ============ Ladder Calculations ============\r\n\r\n function calculateLevelAmount(uint256 totalAmount, uint256 levels, uint256 levelIndex) public pure returns (uint256) {\r\n if (levelIndex >= levels) revert InvalidLevel();\r\n return totalAmount / levels;\r\n }\r\n\r\n function calculateLevelPrice(uint256 priceStart, uint256 priceEnd, uint256 levels, uint256 levelIndex) public pure returns (uint256) {\r\n if (levelIndex >= levels) revert InvalidLevel();\r\n if (levels == 1) return priceStart;\r\n return priceStart + (priceEnd - priceStart) * levelIndex / (levels - 1);\r\n }\r\n\r\n function calculateLevelAmountOutMin(LadderAuth memory auth, uint256 levelIndex, uint256 amountIn) public pure returns (uint256) {\r\n uint256 levelPrice = calculateLevelPrice(auth.priceStart, auth.priceEnd, auth.levels, levelIndex);\r\n return (amountIn * levelPrice) / 1e8;\r\n }\r\n\r\n function availableLadderFill(LadderAuth memory auth, uint256 levelIndex) public view returns (uint256) {\r\n if (!isLadderValid(auth)) return 0;\r\n if (levelIndex >= auth.levels) return 0;\r\n \r\n bytes32 h = hashLadderAuth(auth);\r\n uint256 levelAmount = auth.totalAmount / auth.levels;\r\n uint256 filled = ladderLevelFilled[h][levelIndex];\r\n \r\n if (filled >= levelAmount) return 0;\r\n return levelAmount - filled;\r\n }\r\n\r\n // ============ Match Functions ============\r\n\r\n /// @notice Match a revealed regular order with a taker\r\n /// @param commitHash The commit hash from reveal\r\n /// @param taker The taker filling the order\r\n /// @param amountIn Amount taker wants to pay\r\n /// @param takerMinAmountOut Minimum taker expects (slippage protection)\r\n function fillRevealedOrder(\r\n bytes32 commitHash,\r\n address taker,\r\n uint256 amountIn,\r\n uint256 takerMinAmountOut\r\n ) external nonReentrant whenNotPaused {\r\n RevealedOrder memory order = revealedOrders[commitHash];\r\n \r\n if (order.maker == address(0)) revert InvalidOrder();\r\n if (!revealed[commitHash]) revert CommitNotFound();\r\n if (order.expiration != 0 && block.timestamp > order.expiration) revert Expired();\r\n \r\n // Get minimum output\r\n uint256 amountOutMin = (amountIn * order.amountOutMin) / order.amountIn;\r\n if (amountOutMin < takerMinAmountOut) revert PriceTooLow();\r\n \r\n // Execute transfer: taker pays tokenIn, receives tokenOut from maker\r\n address receiver = order.receiver == address(0) ? order.maker : order.receiver;\r\n \r\n IERC20(order.tokenIn).safeTransferFrom(taker, order.maker, amountIn);\r\n IERC20(order.tokenOut).safeTransferFrom(order.maker, receiver, amountOutMin);\r\n \r\n emit OrderFilled(commitHash, order.maker, taker, amountIn, amountOutMin);\r\n }\r\n\r\n /// @notice Fill a ladder order at specific level\r\n /// @param auth The ladder authorization\r\n /// @param signature The signature\r\n /// @param levelIndex The level to fill\r\n /// @param amountIn Amount to fill\r\n /// @param takerMinAmountOut Minimum output (slippage protection)\r\n function fillLadderOrder(\r\n LadderAuth memory auth,\r\n bytes calldata signature,\r\n uint256 levelIndex,\r\n uint256 amountIn,\r\n uint256 takerMinAmountOut\r\n ) external nonReentrant whenNotPaused {\r\n // Validate first\r\n if (!isLadderValid(auth)) revert InvalidLadderAuth();\r\n if (!verifyLadderSignature(auth, signature)) revert BadLadderSignature();\r\n \r\n uint256 levels = auth.levels;\r\n if (levelIndex >= levels) revert InvalidLevel();\r\n \r\n bytes32 h = hashLadderAuth(auth);\r\n uint256 levelAmount = auth.totalAmount / levels;\r\n uint256 filled = ladderLevelFilled[h][levelIndex];\r\n \r\n if (amountIn == 0 || amountIn > (levelAmount - filled)) revert Overfill();\r\n \r\n // Calculate output\r\n uint256 price = levels == 1 ? auth.priceStart : auth.priceStart + (auth.priceEnd - auth.priceStart) * levelIndex / (levels - 1);\r\n uint256 amountOutMin = (amountIn * price) / 1e8;\r\n \r\n if (amountOutMin < takerMinAmountOut) revert PriceTooLow();\r\n \r\n // Use external call to avoid stack issues\r\n _transferLadder(auth.maker, auth.tokenIn, auth.tokenOut, amountIn, amountOutMin);\r\n \r\n // Update fill state\r\n ladderLevelFilled[h][levelIndex] += amountIn;\r\n ladderTotalFilled[h] += amountIn;\r\n \r\n emit LadderMatched(h, auth.maker, msg.sender, levelIndex, amountIn, amountOutMin);\r\n }\r\n \r\n /// @dev Internal function to handle transfers\r\n function _transferLadder(\r\n address maker,\r\n address tokenIn,\r\n address tokenOut,\r\n uint256 amountIn,\r\n uint256 amountOut\r\n ) internal {\r\n IERC20(tokenOut).safeTransferFrom(msg.sender, maker, amountOut);\r\n IERC20(tokenIn).safeTransferFrom(maker, msg.sender, amountIn);\r\n }\r\n\r\n /// @notice Match two regular orders (buy and sell, maker-to-maker)\r\n /// @dev The executor finds a buy order and a sell order at matching prices and settles them\r\n /// @param buyOrder The buy order (maker wants to buy baseToken, paying quoteToken)\r\n /// @param sigBuy Signature of the buy order maker\r\n /// @param sellOrder The sell order (maker wants to sell baseToken, receiving quoteToken)\r\n /// @param sigSell Signature of the sell order maker\r\n /// @param amountBase Amount of base token to swap (in base token's native decimals)\r\n function matchOrders(\r\n Order memory buyOrder,\r\n bytes calldata sigBuy,\r\n Order memory sellOrder,\r\n bytes calldata sigSell,\r\n uint256 amountBase\r\n ) external nonReentrant whenNotPaused {\r\n // Validate signatures\r\n if (!verifySignature(buyOrder, sigBuy)) revert BadSignature();\r\n if (!verifySignature(sellOrder, sigSell)) revert BadSignature();\r\n\r\n // Validate orders are not expired\r\n if (buyOrder.expiration != 0 && block.timestamp > buyOrder.expiration) revert Expired();\r\n if (sellOrder.expiration != 0 && block.timestamp > sellOrder.expiration) revert Expired();\r\n\r\n // Validate token pairing:\r\n // For BUY: tokenIn = quote (WBNB), tokenOut = base (SIREN)\r\n // For SELL: tokenIn = base (SIREN), tokenOut = quote (WBNB)\r\n // So: buy.tokenIn (quote) == sell.tokenOut (quote)\r\n // buy.tokenOut (base) == sell.tokenIn (base)\r\n if (buyOrder.tokenIn != sellOrder.tokenOut) revert InvalidOrder();\r\n if (buyOrder.tokenOut != sellOrder.tokenIn) revert InvalidOrder();\r\n\r\n // For BUY orders: amountIn = quote token max to pay, amountOutMin = base token min to receive\r\n // For SELL orders: amountIn = base token to sell, amountOutMin = quote token min to receive\r\n // amountBase = base token amount to swap\r\n // Validate amountBase doesn't exceed sell order's available base tokens\r\n if (amountBase == 0 || amountBase > sellOrder.amountIn) revert InvalidOrder();\r\n // Also check buy order can receive this much base (buyOrder.amountOutMin is min base they'll accept)\r\n if (amountBase > buyOrder.amountOutMin && buyOrder.amountOutMin > 0) {\r\n // This is okay if partial fill, but check we're not overfilling\r\n }\r\n\r\n // Calculate quote amount using SELL order's price\r\n // sellOrder.amountIn = base tokens to sell\r\n // sellOrder.amountOutMin = min quote tokens to receive\r\n // Price = amountOutMin / amountIn (quote per base)\r\n // For amountBase base tokens, seller receives: amountBase * amountOutMin / amountIn quote\r\n uint256 amountQuote = (amountBase * sellOrder.amountOutMin) / sellOrder.amountIn;\r\n\r\n // Validate buyer pays no more than their max\r\n // buyOrder.amountIn = max quote they'll pay for buyOrder.amountOutMin base\r\n // So for amountBase base, they pay: amountBase * amountIn / amountOutMin quote\r\n // But we use sell order's price, so check amountQuote <= buyOrder.amountIn\r\n if (amountQuote > buyOrder.amountIn) revert PriceTooLow();\r\n\r\n // Execute transfers\r\n // quoteToken = buyOrder.tokenIn (what buyer pays)\r\n // baseToken = buyOrder.tokenOut (what buyer receives) = sellOrder.tokenIn\r\n address quoteToken = buyOrder.tokenIn;\r\n address baseToken = buyOrder.tokenOut;\r\n\r\n address buyReceiver = buyOrder.receiver == address(0) ? buyOrder.maker : buyOrder.receiver;\r\n address sellReceiver = sellOrder.receiver == address(0) ? sellOrder.maker : sellOrder.receiver;\r\n\r\n // Buyer pays quote token to seller, receives base token from seller\r\n IERC20(quoteToken).safeTransferFrom(buyOrder.maker, sellReceiver, amountQuote);\r\n IERC20(baseToken).safeTransferFrom(sellOrder.maker, buyReceiver, amountBase);\r\n\r\n emit Matched(\r\n keccak256(abi.encodePacked(buyOrder.maker, buyOrder.nonce)),\r\n keccak256(abi.encodePacked(sellOrder.maker, sellOrder.nonce)),\r\n msg.sender,\r\n amountBase,\r\n amountQuote\r\n );\r\n }\r\n\r\n /// @notice Match two ladder orders (maker-to-maker, no taker)\r\n /// @param buyAuth Buy ladder\r\n /// @param sigBuy Buy signature\r\n /// @param sellAuth Sell ladder\r\n /// @param sigSell Sell signature\r\n /// @notice Match two ladder orders (maker-to-maker, no taker)\r\n /// @dev Simplified version to avoid stack too deep\r\n function matchLadderOrders(\r\n LadderAuth memory buyAuth,\r\n bytes calldata sigBuy,\r\n LadderAuth memory sellAuth,\r\n bytes calldata sigSell,\r\n uint256 buyLevelIndex,\r\n uint256 sellLevelIndex,\r\n uint256 amountBase\r\n ) external nonReentrant whenNotPaused {\r\n // Validate signatures first\r\n if (!verifyLadderSignature(buyAuth, sigBuy)) revert BadLadderSignature();\r\n if (!verifyLadderSignature(sellAuth, sigSell)) revert BadLadderSignature();\r\n \r\n // Inline validation\r\n if (buyAuth.tokenIn != sellAuth.tokenOut || buyAuth.tokenOut != sellAuth.tokenIn) revert InvalidLadderAuth();\r\n if (buyAuth.expiration != 0 && block.timestamp > buyAuth.expiration) revert LadderExpired();\r\n if (sellAuth.expiration != 0 && block.timestamp > sellAuth.expiration) revert InvalidLadderAuth();\r\n if (buyAuth.maker == address(0) || sellAuth.maker == address(0)) revert InvalidLadderAuth();\r\n if (buyAuth.totalAmount == 0 || sellAuth.totalAmount == 0) revert InvalidLadderAuth();\r\n uint256 buyLevels = buyAuth.levels;\r\n uint256 sellLevels = sellAuth.levels;\r\n if (buyLevels == 0 || sellLevels == 0) revert InvalidLadderAuth();\r\n \r\n if (buyLevelIndex >= buyLevels) revert InvalidLevel();\r\n if (sellLevelIndex >= sellLevels) revert InvalidLevel();\r\n \r\n // Compute hashes\r\n bytes32 hB = hashLadderAuth(buyAuth);\r\n bytes32 hS = hashLadderAuth(sellAuth);\r\n \r\n // Calculate amounts - use stored auth levels\r\n uint256 buyLevelAmt = buyAuth.totalAmount / buyAuth.levels;\r\n uint256 sellLevelAmt = sellAuth.totalAmount / sellAuth.levels;\r\n \r\n uint256 buyFilled = ladderLevelFilled[hB][buyLevelIndex];\r\n uint256 sellFilled = ladderLevelFilled[hS][sellLevelIndex];\r\n \r\n require(amountBase <= buyLevelAmt - buyFilled, \"bad amount\");\r\n \r\n // Calculate quote inline\r\n uint256 buyPriceStart = buyAuth.priceStart;\r\n uint256 buyPriceEnd = buyAuth.priceEnd;\r\n uint256 buyPrice = buyLevels == 1 ? buyPriceStart : buyPriceStart + (buyPriceEnd - buyPriceStart) * buyLevelIndex / (buyLevels - 1);\r\n uint256 quote = (amountBase * buyPrice) / 1e8;\r\n \r\n require(quote <= sellLevelAmt - sellFilled, \"insufficient sell\");\r\n \r\n // Price check inline\r\n uint256 sellPriceStart = sellAuth.priceStart;\r\n uint256 sellPriceEnd = sellAuth.priceEnd;\r\n uint256 sellPrice = sellLevels == 1 ? sellPriceStart : sellPriceStart + (sellPriceEnd - sellPriceStart) * sellLevelIndex / (sellLevels - 1);\r\n uint256 sellMinBase = (quote * sellPrice) / 1e8;\r\n \r\n if (amountBase < sellMinBase) revert PriceTooLow();\r\n \r\n // Execute transfer\r\n IERC20(sellAuth.tokenIn).safeTransferFrom(sellAuth.maker, buyAuth.maker, quote);\r\n IERC20(buyAuth.tokenIn).safeTransferFrom(buyAuth.maker, sellAuth.maker, amountBase);\r\n \r\n // Update fills\r\n ladderLevelFilled[hB][buyLevelIndex] += amountBase;\r\n ladderLevelFilled[hS][sellLevelIndex] += quote;\r\n \r\n emit LadderMatched(hB, buyAuth.maker, msg.sender, buyLevelIndex, amountBase, quote);\r\n emit LadderMatched(hS, sellAuth.maker, msg.sender, sellLevelIndex, quote, amountBase);\r\n }\r\n\r\n // ============ Helper Functions ============\r\n\r\n function _getTokenDecimals(address token) internal view returns (uint256 decimals) {\r\n (bool success, bytes memory data) = token.staticcall(abi.encodeWithSignature(\"decimals()\"));\r\n if (success && data.length == 32) {\r\n decimals = abi.decode(data, (uint256));\r\n } else {\r\n decimals = 18;\r\n }\r\n }\r\n\r\n function _recover(bytes32 digest, bytes memory signature) internal pure returns (address) {\r\n require(signature.length == 65, \"bad sig length\");\r\n bytes32 r;\r\n bytes32 s;\r\n uint8 v;\r\n assembly {\r\n r := mload(add(signature, 0x20))\r\n s := mload(add(signature, 0x40))\r\n v := byte(0, mload(add(signature, 0x60)))\r\n }\r\n if (v < 27) v += 27;\r\n require(v == 27 || v == 28, \"bad v\");\r\n address signer = ecrecover(digest, v, r, s);\r\n require(signer != address(0), \"ecrecover failed\");\r\n return signer;\r\n }\r\n}\r\n" + }, + "target": "contracts/LadderSettlement.sol", + "version": "0.8.34" +} diff --git a/tests/sourcify-sweep/fixtures/contracts/56_0xc72b4fcbacdae012b8e198c4116f571503890c4b.json b/tests/sourcify-sweep/fixtures/contracts/56_0xc72b4fcbacdae012b8e198c4116f571503890c4b.json new file mode 100644 index 000000000..8d1ad4b81 --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/56_0xc72b4fcbacdae012b8e198c4116f571503890c4b.json @@ -0,0 +1,31 @@ +{ + "chain_id": 56, + "name": "0xc72b4fcbacdae012b8e198c4116f571503890c4b", + "remappings": [], + "settings": { + "libraries": { + "contracts/LunaHH.sol": { + "IterableMapping": "0x4b272AF59690255e69a2690D494C68743cb7f785" + } + }, + "optimizer": { + "enabled": true, + "runs": 200 + }, + "remappings": [] + }, + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n", + "@openzeppelin/contracts/interfaces/draft-IERC6093.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/draft-IERC6093.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC20InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC20InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `spender`\u2019s `allowance`. Used in transfers.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC20InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n /**\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-721.\n * Used in balance queries.\n * @param owner Address of the current owner of a token.\n */\n error ERC721InvalidOwner(address owner);\n\n /**\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\n * @param tokenId Identifier number of a token.\n */\n error ERC721NonexistentToken(uint256 tokenId);\n\n /**\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param tokenId Identifier number of a token.\n * @param owner Address of the current owner of a token.\n */\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC721InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC721InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`\u2019s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param tokenId Identifier number of a token.\n */\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC721InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n * @param tokenId Identifier number of a token.\n */\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC1155InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC1155InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`\u2019s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param owner Address of the current owner of a token.\n */\n error ERC1155MissingApprovalForAll(address operator, address owner);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC1155InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC1155InvalidOperator(address operator);\n\n /**\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n * Used in batch transfers.\n * @param idsLength Length of the array of token identifiers\n * @param valuesLength Length of the array of token amounts\n */\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n", + "@openzeppelin/contracts/token/ERC20/ERC20.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./extensions/IERC20Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {IERC20Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\n mapping(address account => uint256) private _balances;\n\n mapping(address account => mapping(address spender => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * Both values are immutable: they can only be set once during construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return 18;\n }\n\n /// @inheritdoc IERC20\n function totalSupply() public view virtual returns (uint256) {\n return _totalSupply;\n }\n\n /// @inheritdoc IERC20\n function balanceOf(address account) public view virtual returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `value`.\n */\n function transfer(address to, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, value);\n return true;\n }\n\n /// @inheritdoc IERC20\n function allowance(address owner, address spender) public view virtual returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, value);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Skips emitting an {Approval} event indicating an allowance update. This is not\n * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `value`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `value`.\n */\n function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, value);\n _transfer(from, to, value);\n return true;\n }\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _transfer(address from, address to, uint256 value) internal {\n if (from == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n if (to == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(from, to, value);\n }\n\n /**\n * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n * this function.\n *\n * Emits a {Transfer} event.\n */\n function _update(address from, address to, uint256 value) internal virtual {\n if (from == address(0)) {\n // Overflow check required: The rest of the code assumes that totalSupply never overflows\n _totalSupply += value;\n } else {\n uint256 fromBalance = _balances[from];\n if (fromBalance < value) {\n revert ERC20InsufficientBalance(from, fromBalance, value);\n }\n unchecked {\n // Overflow not possible: value <= fromBalance <= totalSupply.\n _balances[from] = fromBalance - value;\n }\n }\n\n if (to == address(0)) {\n unchecked {\n // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n _totalSupply -= value;\n }\n } else {\n unchecked {\n // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n _balances[to] += value;\n }\n }\n\n emit Transfer(from, to, value);\n }\n\n /**\n * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n * Relies on the `_update` mechanism\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _mint(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(address(0), account, value);\n }\n\n /**\n * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n * Relies on the `_update` mechanism.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead\n */\n function _burn(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n _update(account, address(0), value);\n }\n\n /**\n * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n *\n * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n */\n function _approve(address owner, address spender, uint256 value) internal {\n _approve(owner, spender, value, true);\n }\n\n /**\n * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n *\n * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n * `_spendAllowance` during the `transferFrom` operation sets the flag to false. This saves gas by not emitting any\n * `Approval` event during `transferFrom` operations.\n *\n * Anyone who wishes to continue emitting `Approval` events on the `transferFrom` operation can force the flag to\n * true using the following override:\n *\n * ```solidity\n * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n * super._approve(owner, spender, value, true);\n * }\n * ```\n *\n * Requirements are the same as {_approve}.\n */\n function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n if (owner == address(0)) {\n revert ERC20InvalidApprover(address(0));\n }\n if (spender == address(0)) {\n revert ERC20InvalidSpender(address(0));\n }\n _allowances[owner][spender] = value;\n if (emitEvent) {\n emit Approval(owner, spender, value);\n }\n }\n\n /**\n * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\n *\n * Does not update the allowance value in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Does not emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance < type(uint256).max) {\n if (currentAllowance < value) {\n revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n }\n unchecked {\n _approve(owner, spender, currentAllowance - value, false);\n }\n }\n }\n}\n", + "@openzeppelin/contracts/token/ERC20/IERC20.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n", + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC20} from \"../ERC20.sol\";\nimport {Context} from \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys a `value` amount of tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 value) public virtual {\n _burn(_msgSender(), value);\n }\n\n /**\n * @dev Destroys a `value` amount of tokens from `account`, deducting from\n * the caller's allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `value`.\n */\n function burnFrom(address account, uint256 value) public virtual {\n _spendAllowance(account, _msgSender(), value);\n _burn(account, value);\n }\n}\n", + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC20} from \"../ERC20.sol\";\nimport {Pausable} from \"../../../utils/Pausable.sol\";\n\n/**\n * @dev ERC-20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * IMPORTANT: This contract does not include public pause and unpause functions. In\n * addition to inheriting this contract, you must define both functions, invoking the\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\n * make the contract pause mechanism of the contract unreachable, and thus unusable.\n */\nabstract contract ERC20Pausable is ERC20, Pausable {\n /**\n * @dev See {ERC20-_update}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _update(address from, address to, uint256 value) internal virtual override whenNotPaused {\n super._update(from, to, value);\n }\n}\n", + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n", + "@openzeppelin/contracts/utils/Context.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n", + "@openzeppelin/contracts/utils/Pausable.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n bool private _paused;\n\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n /**\n * @dev The operation failed because the contract is paused.\n */\n error EnforcedPause();\n\n /**\n * @dev The operation failed because the contract is not paused.\n */\n error ExpectedPause();\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n if (paused()) {\n revert EnforcedPause();\n }\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n if (!paused()) {\n revert ExpectedPause();\n }\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n", + "contracts/Token.sol": "\n// SPDX-License-Identifier: MIT\n// Compatible with OpenZeppelin Contracts ^5.4.0\npragma solidity ^0.8.27;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport {ERC20Pausable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MyToken is ERC20, ERC20Burnable, ERC20Pausable, Ownable {\n constructor(address initialOwner)\n ERC20(\"tR2.0\", \"tR2.0\")\n Ownable(initialOwner)\n {\n _mint(msg.sender, 10000000000000 * 10 ** decimals());\n }\n\n function pause() public onlyOwner {\n _pause();\n }\n\n function unpause() public onlyOwner {\n _unpause();\n }\n\n function mint(address to, uint256 amount) public onlyOwner {\n _mint(to, amount);\n }\n\n // The following functions are overrides required by Solidity.\n\n function _update(address from, address to, uint256 value)\n internal\n override(ERC20, ERC20Pausable)\n {\n super._update(from, to, value);\n }\n}" + }, + "target": "contracts/Token.sol", + "version": "0.8.34" +} diff --git a/tests/sourcify-sweep/fixtures/contracts/97_0xe7979a289e7864f2d90bd09542450c8c5e740d9f.json b/tests/sourcify-sweep/fixtures/contracts/97_0xe7979a289e7864f2d90bd09542450c8c5e740d9f.json new file mode 100644 index 000000000..c59af9371 --- /dev/null +++ b/tests/sourcify-sweep/fixtures/contracts/97_0xe7979a289e7864f2d90bd09542450c8c5e740d9f.json @@ -0,0 +1,19 @@ +{ + "chain_id": 97, + "name": "0xe7979a289e7864f2d90bd09542450c8c5e740d9f", + "remappings": [], + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "remappings": [], + "viaIR": true + }, + "sources": { + "@openzeppelin/contracts@4.9.3/security/ReentrancyGuard.sol": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n}\n", + "astorworldupdate.sol": " \r\n\r\n \r\n// SPDX-License-Identifier: MIT\r\n// File: @openzeppelin/contracts/utils/math/SafeMath.sol\r\n \r\n \r\npragma solidity ^0.8.0;\r\n \r\nabstract contract Context {\r\n function _msgSender() internal view virtual returns (address) {\r\n return msg.sender;\r\n }\r\n\r\n function _msgData() internal view virtual returns (bytes calldata) {\r\n return msg.data;\r\n }\r\n}\r\n\r\n \r\n\r\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\r\n\r\npragma solidity ^0.8.0;\r\n \r\nabstract contract Ownable is Context {\r\n address private _owner;\r\n\r\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r\n\r\n constructor() {\r\n\r\n _transferOwnership(_msgSender());\r\n \r\n }\r\n\r\n modifier onlyOwner() {\r\n require(_owner == _msgSender(), \"Ownable: caller is not the owner\");\r\n _;\r\n }\r\n\r\n function owner() public view virtual returns (address) {\r\n return _owner;\r\n }\r\n\r\n function transferOwnership(address newOwner) public virtual onlyOwner {\r\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\r\n _transferOwnership(newOwner);\r\n }\r\n\r\n function _transferOwnership(address newOwner) internal virtual {\r\n address oldOwner = _owner;\r\n _owner = newOwner;\r\n emit OwnershipTransferred(oldOwner, newOwner);\r\n }\r\n function renounceOwnership() public onlyOwner {\r\n emit OwnershipTransferred(_owner, address(0));\r\n _owner = address(0); // Contract becomes ownerless\r\n}\r\n}\r\n \r\n\r\npragma solidity ^ 0.8 .0;\r\n \r\ninterface IERC20 {\r\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\r\n function transfer(address to, uint256 amount) external returns (bool);\r\n function balanceOf(address account) external view returns (uint256);\r\n}\r\ninterface IOldContract {\r\n\r\n // USERS\r\n function ids() external view returns(uint);\r\n function userId(address) external view returns(uint);\r\n function userIdtoAddress(uint) external view returns(address);\r\n function referal(address) external view returns(address);\r\n function directCount(address) external view returns(uint);\r\n function isRegistered(address) external view returns(bool);\r\n\r\n // USER STRUCT\r\n function users(uint256) external view returns (\r\n uint userId_,\r\n address userAddress,\r\n uint refferid,\r\n uint totalinvest,\r\n uint totalslotincome,\r\n uint totaldirectincome,\r\n uint totallevelincome,\r\n uint totalautopoolincome,\r\n uint retopupcount,\r\n uint IsFoundermember,\r\n uint timestamp\r\n );\r\n\r\n // PACKAGES\r\n function packagesr() external view returns(uint);\r\n\r\n function incomes(uint256) external view returns (\r\n uint packagesr_,\r\n address userAddress,\r\n uint userPackageid,\r\n uint packageamount,\r\n uint posa,\r\n uint posb,\r\n uint posc,\r\n uint timeStamp\r\n );\r\n\r\n function hasPackage(address,uint) external view returns(bool);\r\n\r\n function userPackageSr(address,uint)\r\n external\r\n view\r\n returns(uint);\r\n\r\n // TREE\r\n function packageTree(address,uint,uint)\r\n external\r\n view\r\n returns(uint);\r\n\r\n // PLACEMENTS\r\n function placements(uint,uint)\r\n external\r\n view\r\n returns(\r\n uint userId_,\r\n uint parentId,\r\n uint packageId,\r\n uint position\r\n );\r\n\r\n // AUTOPOOL\r\n function userLevel(uint) external view returns(uint);\r\n\r\n function userInLevel(uint,uint)\r\n external\r\n view\r\n returns(bool);\r\n\r\n function autopoolIndex(uint)\r\n external\r\n view\r\n returns(uint);\r\n\r\n function autopoolQueue(uint,uint)\r\n external\r\n view\r\n returns(uint);\r\n\r\n function autopoolTree(uint,uint,uint)\r\n external\r\n view\r\n returns(uint);\r\n\r\n function autopoolDirectCount(uint,uint)\r\n external\r\n view\r\n returns(uint);\r\n\r\n function autopoolSecondLevelCount(uint,uint)\r\n external\r\n view\r\n returns(uint);\r\n}\r\n// package purchase fee\r\n// admin wallet reawrd transfer\r\n \r\nimport \"@openzeppelin/contracts@4.9.3/security/ReentrancyGuard.sol\"; \r\n\r\ncontract Astorworldd is Ownable, ReentrancyGuard {\r\n//1==.0001\r\n\r\n\r\n IERC20 public immutable token; \r\n \r\n uint[] public packages = [ 20, 40, 80, 160, 320, 800, 2000, 5000, 12500,30000,75000,150000 ]; \r\n struct User \r\n {\r\n uint userId;\r\n address userAddress; \r\n uint refferid; \r\n uint totalinvest; \r\n uint totalslotincome; \r\n uint totaldirectincome; \r\n uint totallevelincome; \r\n uint totalautopoolincome; \r\n uint retopupcount; \r\n uint IsFoundermember; \r\n uint timestamp; \r\n }\r\n struct foundermember \r\n {\r\n uint founderid;\r\n address founderaddress; \r\n uint isactive; \r\n uint totalincome; \r\n uint updatestamp; \r\n uint lastpaidtamp; \r\n uint timestamp; \r\n }\r\n struct UserIncome \r\n {\r\n uint packagesr;\r\n address userAddress; \r\n uint userPackageid; \r\n uint packageamount;\r\n uint posa;\r\n uint posb;\r\n uint posc;\r\n uint timeStamp;\r\n }\r\n \r\n struct Placement \r\n {\r\n uint userId;\r\n uint parentId;\r\n uint packageId;\r\n uint position; \r\n }\r\n struct AllIncomedata\r\n {\r\n uint AllIncomesr;\r\n uint userid;\r\n address userAddress;\r\n address ByuserAddress;\r\n uint incomeamount; \r\n uint bylevel; \r\n uint IncomeByType; \r\n uint incomeper; \r\n uint timeStamp;\r\n }\r\n \r\n \r\n mapping(address => uint) public userId;\r\n mapping(address => uint) public founderid;\r\n mapping(uint => address) public userIdtoAddress;\r\n mapping(address => address) public referal; \r\n mapping(uint => UserIncome) public incomes; \r\n mapping(uint => AllIncomedata) public AllIncome; \r\n mapping(address => mapping(uint => uint[3])) public packageTree;\r\n mapping(address => mapping(uint => bool)) public hasPackage;\r\n mapping(address => mapping(uint => uint)) public userPackageSr; \r\n mapping(uint => mapping(uint => Placement)) public placements;\r\n mapping(address => uint) public directCount;\r\n uint public constant MAX_LEVEL = 5;\r\n IOldContract public oldContract; \r\n\r\n mapping(uint => uint[]) public autopoolQueue;\r\n mapping(uint => mapping(uint => uint[3])) public autopoolTree;\r\n mapping(uint => uint) public autopoolIndex; \r\n mapping(uint => uint) public userLevel;\r\n mapping(uint => mapping(uint => bool)) public userInLevel;\r\n mapping(uint => mapping(uint => uint)) public autopoolDirectCount;\r\n mapping(uint => mapping(uint => uint)) public autopoolSecondLevelCount; \r\n mapping(uint => mapping(uint => uint)) public userPackageRetopup; \r\n// userId => level => hold amount\r\n uint ids = 1;\r\n uint founderids=0;\r\n uint packagesr = 0; \r\n uint AllIncomesr = 0;\r\n uint unpaidfounderincome=0;\r\n uint topayfounderincome=0;\r\n uint l1paid = 1;\r\n uint l2paid = 1;\r\n uint l3paid = 1;\r\n uint l4paid = 1;\r\n uint l5paid = 1;\r\n uint l1count = 0; \r\n uint l2count = 0;\r\n uint l3count = 0;\r\n uint l4count = 0;\r\n uint l5count = 0; \r\n \r\n \r\n mapping(address => bool) public isRegistered; \r\n mapping(address => bool) public IsFounder; \r\n mapping(uint => User) public users; \r\n mapping(uint => foundermember) public foundermembers; \r\n \r\n \r\n \r\n \r\n constructor() {\r\n // Initialize a user for the contract deployer (you can call this function as needed) \r\n \r\n token = IERC20(0x55d398326f99059fF775485246999027B3197955); \r\n User memory newUser;\r\n newUser.userId = ids;\r\n newUser.userAddress = 0xAE511bA52984AF3930A5110716AeF4b2bb18968D; \r\n newUser.refferid = 0; \r\n \r\n // newUser.direct = 0; \r\n referal[0xAE511bA52984AF3930A5110716AeF4b2bb18968D] = 0xAE511bA52984AF3930A5110716AeF4b2bb18968D;\r\n userIdtoAddress[1] = 0xAE511bA52984AF3930A5110716AeF4b2bb18968D;\r\n userId[0xAE511bA52984AF3930A5110716AeF4b2bb18968D] = ids;\r\n isRegistered[0xAE511bA52984AF3930A5110716AeF4b2bb18968D] = true; \r\n newUser.timestamp = block.timestamp;\r\n \r\n users[ids] = newUser; \r\n address rootUser = 0xAE511bA52984AF3930A5110716AeF4b2bb18968D;\r\n\r\n for (uint packageid = 1; packageid <= packages.length; packageid++) {\r\n\r\n packagesr++;\r\n\r\n UserIncome memory newIncome;\r\n newIncome.packagesr = packagesr;\r\n newIncome.userAddress = rootUser;\r\n newIncome.userPackageid = packageid; \r\n newIncome.packageamount = packages[packageid - 1] * 1e18;\r\n newIncome.timeStamp = block.timestamp;\r\n\r\n incomes[packagesr] = newIncome;\r\n users[userId[rootUser]].totalinvest += packages[packageid - 1] * 1e18; \r\n // initialize tree\r\n packageTree[rootUser][packageid] = [uint(0), uint(0), uint(0)];\r\n\r\n // mark active package (recommended)\r\n hasPackage[rootUser][packageid] = true;\r\n userPackageSr[rootUser][packageid] = packagesr;\r\n placements[ids][packageid] = Placement({\r\n userId: ids,\r\n parentId: 0,\r\n packageId: packageid,\r\n position: 0\r\n }); \r\n }\r\n\r\n userLevel[1] = MAX_LEVEL; \r\n for (uint lvl = 1; lvl <= MAX_LEVEL; lvl++) { \r\n autopoolQueue[lvl].push(1); \r\n autopoolTree[lvl][1] = [uint(0), uint(0), uint(0)]; \r\n userInLevel[1][lvl] = true;\r\n } \r\n \r\n }\r\n function RegisteredFrom(address _oldCont) onlyOwner external\r\n {\r\n oldContract = IOldContract(_oldCont);\r\n }\r\n function updatfounder( uint _founderid, uint status) public onlyOwner nonReentrant returns(bool)\r\n { \r\n require(IsFounder[foundermembers[_founderid].founderaddress] == true, \"founder not exist !\");\r\n if (status==1 || status==0)\r\n {\r\n \r\n foundermembers[_founderid].isactive = status; \r\n foundermembers[_founderid].updatestamp = block.timestamp; \r\n }\r\n return true;\r\n \r\n }\r\n function distributefounderincome(uint fromid , uint toid) public onlyOwner nonReentrant returns(bool)\r\n {\r\n require(founderids > 0, \"founder required !\");\r\n uint income=topayfounderincome;\r\n for (fromid; fromid<=toid && toid<=founderids && topayfounderincome<=unpaidfounderincome; fromid++ ) \r\n { \r\n if (foundermembers[fromid].isactive==0 && foundermembers[fromid].lastpaidtamp + 24 hours <= block.timestamp) \r\n {\r\n address payaddress=foundermembers[fromid].founderaddress;\r\n if (income<=2000 * 1e18-foundermembers[fromid].totalincome)\r\n {\r\n foundermembers[fromid].totalincome +=income;\r\n foundermembers[fromid].lastpaidtamp =block.timestamp;\r\n require(token.transfer(address(payaddress), income ), \"Transfer failed\");\r\n \r\n }\r\n else \r\n {\r\n uint payincome=2000 * 1e18-foundermembers[fromid].totalincome;\r\n foundermembers[fromid].totalincome += payincome;\r\n foundermembers[fromid].lastpaidtamp =block.timestamp;\r\n require(token.transfer(address(payaddress), income ), \"Transfer failed\");\r\n }\r\n \r\n if (foundermembers[fromid].totalincome>=2000 * 1e18)\r\n {\r\n foundermembers[fromid].isactive = 1; \r\n foundermembers[fromid].updatestamp = block.timestamp; \r\n }\r\n unpaidfounderincome-=topayfounderincome;\r\n }\r\n } \r\n \r\n return true;\r\n \r\n }\r\n function updateold(address _referal,address newaddress) public onlyOwner nonReentrant returns(bool)\r\n { \r\n require(ids<=55, \"founder not exist !\");\r\n // STEP 1: Create User\r\n ids++;\r\n\r\n userId[newaddress] = ids;\r\n userIdtoAddress[ids] =newaddress;\r\n isRegistered[newaddress] = true;\r\n referal[newaddress] = _referal;\r\n\r\n User memory newUser;\r\n newUser.userId = ids;\r\n newUser.userAddress = newaddress;\r\n newUser.refferid = userId[_referal];\r\n newUser.timestamp = block.timestamp;\r\n\r\n users[ids] = newUser;\r\n directCount[_referal] += 1;\r\n uint packageId = 1;\r\n\r\n (uint parentId, uint pos) = _findParent(ids, packageId);\r\n placements[ids][packageId] = Placement({\r\n userId: ids,\r\n parentId: parentId,\r\n packageId: packageId,\r\n position: pos\r\n }); \r\n\r\n address parentAddr = userIdtoAddress[parentId];\r\n \r\n packageTree[parentAddr][packageId][pos] = ids;\r\n uint parentPackageSr = userPackageSr[parentAddr][packageId]; \r\n if (pos == 0) {\r\n incomes[parentPackageSr].posa = ids;\r\n } else if (pos == 1) {\r\n incomes[parentPackageSr].posb = ids;\r\n } else {\r\n incomes[parentPackageSr].posc = ids;\r\n }\r\n hasPackage[newaddress][packageId] = true; \r\n packagesr++;\r\n \r\n UserIncome memory newIncome;\r\n newIncome.packagesr = packagesr;\r\n newIncome.userAddress = newaddress;\r\n newIncome.userPackageid = packageId; \r\n newIncome.packageamount = packages[packageId - 1] * 1e18;\r\n newIncome.posa = 0;\r\n newIncome.posb = 0;\r\n newIncome.posc = 0;\r\n newIncome.timeStamp = block.timestamp;\r\n \r\n incomes[packagesr] = newIncome;\r\n\r\n users[userId[newaddress]].totalinvest += (packages[0]+ 32) * 1e18; \r\n userPackageSr[newaddress][packageId] = packagesr;\r\n _enterAutopoolonupdate(ids); \r\n \r\n \r\n return true;\r\n \r\n }\r\n function registerfounder() public nonReentrant returns(bool)\r\n {\r\n\r\n require(isRegistered[msg.sender] == true, \"user not exist !\"); \r\n require(IERC20(token).transferFrom(msg.sender, address(this),1000 * 1e18), \"Transfer Failed\");\r\n \r\n founderids++;\r\n\r\n founderid[msg.sender] = founderids; \r\n foundermember memory newfounder;\r\n newfounder.founderid = founderids;\r\n newfounder.founderaddress = msg.sender; \r\n newfounder.lastpaidtamp = block.timestamp;\r\n newfounder.timestamp = block.timestamp;\r\n \r\n foundermembers[founderids] = newfounder; \r\n IsFounder[msg.sender] = true; \r\n users[userId[msg.sender]].IsFoundermember=1;\r\n if (founderids>0 && unpaidfounderincome>0){topayfounderincome=unpaidfounderincome/founderids;}\r\n require(token.transfer(address(0xe5A58510Be5F2Dc2Dcab4995B313FeC3fa4D30B6), 1000 * 1e18 ), \"Transfer failed\");\r\n return true;\r\n \r\n }\r\nfunction register(address _referal) public nonReentrant returns(bool)\r\n {\r\n\r\n require(isRegistered[msg.sender] == false, \"You are already registered !\");\r\n require(referal[_referal] != address(0), \"Referal is not valid !\");\r\n require(isRegistered[_referal] == true, \"Referal is not valid !\");\r\n require(IERC20(token).transferFrom(msg.sender, address(this),(packages[0]+ 80) * 1e18), \"Transfer Failed\");\r\n // STEP 1: Create User\r\n ids++;\r\n\r\n userId[msg.sender] = ids;\r\n userIdtoAddress[ids] = msg.sender;\r\n isRegistered[msg.sender] = true;\r\n referal[msg.sender] = _referal;\r\n\r\n User memory newUser;\r\n newUser.userId = ids;\r\n newUser.userAddress = msg.sender;\r\n newUser.refferid = userId[_referal];\r\n newUser.timestamp = block.timestamp;\r\n\r\n users[ids] = newUser;\r\n directCount[_referal] += 1;\r\n uint packageId = 1;\r\n\r\n (uint parentId, uint pos) = _findParent(ids, packageId);\r\n placements[ids][packageId] = Placement({\r\n userId: ids,\r\n parentId: parentId,\r\n packageId: packageId,\r\n position: pos\r\n }); \r\n\r\n address parentAddr = userIdtoAddress[parentId];\r\n \r\n packageTree[parentAddr][packageId][pos] = ids;\r\n uint parentPackageSr = userPackageSr[parentAddr][packageId]; \r\n if (pos == 0) {\r\n incomes[parentPackageSr].posa = ids;\r\n } else if (pos == 1) {\r\n incomes[parentPackageSr].posb = ids;\r\n } else {\r\n incomes[parentPackageSr].posc = ids;\r\n }\r\n hasPackage[msg.sender][packageId] = true; \r\n packagesr++;\r\n \r\n UserIncome memory newIncome;\r\n newIncome.packagesr = packagesr;\r\n newIncome.userAddress = msg.sender;\r\n newIncome.userPackageid = packageId; \r\n newIncome.packageamount = packages[packageId - 1] * 1e18;\r\n newIncome.posa = 0;\r\n newIncome.posb = 0;\r\n newIncome.posc = 0;\r\n newIncome.timeStamp = block.timestamp;\r\n \r\n incomes[packagesr] = newIncome;\r\n\r\n users[userId[msg.sender]].totalinvest += (packages[0]+ 80) * 1e18; \r\n _enterAutopool(ids); \r\n uint totalpaid =0;\r\n userPackageSr[msg.sender][packageId] = packagesr;\r\n totalpaid += distributeslotincome(packagesr);\r\n totalpaid += distributeLevelIncome(packagesr);\r\n totalpaid += distributdirectIncome(packagesr);\r\n \r\n uint lapsincome = (packages[0] + 70) * 1e18 - totalpaid; \r\n TransferLaps (lapsincome) ;\r\n \r\n if (founderids>0 && unpaidfounderincome>0){topayfounderincome=unpaidfounderincome/founderids;}\r\n \r\n return true;\r\n \r\n }\r\nfunction _enterAutopool(uint _userId) internal {\r\n\r\n uint level = userLevel[_userId];\r\n\r\n if (level == 0) {\r\n level = 1;\r\n userLevel[_userId] = 1;\r\n }\r\n\r\n if (level > MAX_LEVEL) return;\r\n\r\n // prevent duplicate entry\r\n if (userInLevel[_userId][level]) return;\r\n\r\n userInLevel[_userId][level] = true;\r\n\r\n autopoolQueue[level].push(_userId);\r\n\r\n uint index = autopoolIndex[level];\r\n\r\n while (true) {\r\n\r\n if (index >= autopoolQueue[level].length) break;\r\n\r\n uint parentId = autopoolQueue[level][index];\r\n uint[3] storage childs = autopoolTree[level][parentId];\r\n\r\n // POS A\r\n if (childs[0] == 0) {\r\n childs[0] = _userId;\r\n\r\n autopoolDirectCount[parentId][level]++;\r\n _updateSecondLevel(parentId, level);\r\n\r\n break;\r\n }\r\n\r\n // POS B\r\n else if (childs[1] == 0) {\r\n childs[1] = _userId;\r\n\r\n autopoolDirectCount[parentId][level]++;\r\n _updateSecondLevel(parentId, level);\r\n\r\n break;\r\n }\r\n\r\n // POS C\r\n else if (childs[2] == 0) {\r\n childs[2] = _userId;\r\n\r\n autopoolDirectCount[parentId][level]++;\r\n _updateSecondLevel(parentId, level);\r\n\r\n autopoolIndex[level]++;\r\n break;\r\n }\r\n\r\n else {\r\n autopoolIndex[level]++;\r\n index = autopoolIndex[level];\r\n }\r\n }\r\n distributeautopoolIncome(_userId);\r\n}\r\n\r\nfunction _enterAutopoolonupdate(uint _userId) internal {\r\n\r\n uint level = userLevel[_userId];\r\n\r\n if (level == 0) {\r\n level = 1;\r\n userLevel[_userId] = 1;\r\n }\r\n\r\n if (level > MAX_LEVEL) return;\r\n\r\n // prevent duplicate entry\r\n if (userInLevel[_userId][level]) return;\r\n\r\n userInLevel[_userId][level] = true;\r\n\r\n autopoolQueue[level].push(_userId);\r\n\r\n uint index = autopoolIndex[level];\r\n\r\n while (true) {\r\n\r\n if (index >= autopoolQueue[level].length) break;\r\n\r\n uint parentId = autopoolQueue[level][index];\r\n uint[3] storage childs = autopoolTree[level][parentId];\r\n\r\n // POS A\r\n if (childs[0] == 0) {\r\n childs[0] = _userId;\r\n\r\n autopoolDirectCount[parentId][level]++;\r\n _updateSecondLevel(parentId, level);\r\n\r\n break;\r\n }\r\n\r\n // POS B\r\n else if (childs[1] == 0) {\r\n childs[1] = _userId;\r\n\r\n autopoolDirectCount[parentId][level]++;\r\n _updateSecondLevel(parentId, level);\r\n\r\n break;\r\n }\r\n\r\n // POS C\r\n else if (childs[2] == 0) {\r\n childs[2] = _userId;\r\n\r\n autopoolDirectCount[parentId][level]++;\r\n _updateSecondLevel(parentId, level);\r\n\r\n autopoolIndex[level]++;\r\n break;\r\n }\r\n\r\n else {\r\n autopoolIndex[level]++;\r\n index = autopoolIndex[level];\r\n }\r\n }\r\n \r\n}\r\n\r\nfunction _updateSecondLevel(uint parentId, uint level) internal {\r\n\r\n (uint upline,) = getAutopoolParent(parentId, level);\r\n\r\n if (upline > 0) {\r\n\r\n autopoolSecondLevelCount[upline][level]++;\r\n\r\n _checkPromotion(upline, level);\r\n }\r\n}\r\nfunction _checkPromotion(uint userId_, uint level) internal {\r\n\r\n if (userId_ == 1) return; \r\n if (level >= MAX_LEVEL) return;\r\n uint count = autopoolSecondLevelCount[userId_][level];\r\n\r\n if (count >= 9) {\r\n\r\n uint nextLevel = level + 1;\r\n\r\n if (nextLevel > MAX_LEVEL) return;\r\n\r\n if (!userInLevel[userId_][nextLevel]) {\r\n\r\n userLevel[userId_] = nextLevel;\r\n\r\n _enterAutopool(userId_);\r\n }\r\n }\r\n}\r\nfunction getAutopoolPositions(uint _level, uint _userId)\r\n public\r\n view\r\n returns (\r\n uint posaId,\r\n address posaAddr,\r\n uint posbId,\r\n address posbAddr,\r\n uint poscId,\r\n address poscAddr\r\n )\r\n {\r\n if (_level == 0 || _level > 10) {\r\n return (0, address(0), 0, address(0), 0, address(0));\r\n }\r\n\r\n uint[3] memory childs = autopoolTree[_level][_userId];\r\n\r\n posaId = childs[0];\r\n posaAddr = posaId > 0 ? userIdtoAddress[posaId] : address(0);\r\n\r\n posbId = childs[1];\r\n posbAddr = posbId > 0 ? userIdtoAddress[posbId] : address(0);\r\n\r\n poscId = childs[2];\r\n poscAddr = poscId > 0 ? userIdtoAddress[poscId] : address(0);\r\n}\r\n \r\n \r\n function clearance(address _to, uint256 _amount) external onlyOwner {\r\n require(_to != address(0), \"Invalid address\");\r\n require(_amount > 0, \"Amount must be greater than 0\");\r\n require(token.balanceOf(address(this)) >= _amount, \"Insufficient balance\"); \r\n bool success = token.transfer(_to, _amount);\r\n require(success, \"Transfer failed\");\r\n}\r\n \r\n \r\nfunction _getSecondLevelCount(uint userId_, uint level) internal view returns (uint count) {\r\n\r\n uint[3] memory first = autopoolTree[level][userId_];\r\n\r\n for (uint i = 0; i < 3; i++) {\r\n\r\n if (first[i] != 0) {\r\n\r\n uint[3] memory second = autopoolTree[level][first[i]];\r\n\r\n for (uint j = 0; j < 3; j++) {\r\n\r\n if (second[j] != 0) {\r\n count++;\r\n }\r\n }\r\n }\r\n }\r\n}\r\nfunction getAutopoolParent(uint _userId, uint _level)\r\n public\r\n view\r\n returns (uint parentId, uint position)\r\n{\r\n if (_level == 0 || _level > MAX_LEVEL) {\r\n return (0, 0);\r\n }\r\n\r\n for (uint i = 0; i < autopoolQueue[_level].length; i++) {\r\n\r\n uint upline = autopoolQueue[_level][i];\r\n uint[3] memory childs = autopoolTree[_level][upline];\r\n\r\n if (childs[0] == _userId) return (upline, 0);\r\n if (childs[1] == _userId) return (upline, 1);\r\n if (childs[2] == _userId) return (upline, 2);\r\n }\r\n\r\n return (0, 0);\r\n}\r\n function getAutopoolChildren(uint _userId, uint _level)\r\n public\r\n view\r\n returns (uint posa, uint posb, uint posc)\r\n{\r\n uint[3] memory childs = autopoolTree[_level][_userId];\r\n\r\n return (childs[0], childs[1], childs[2]);\r\n}\r\nfunction distributeautopoolIncome(uint _userid) internal {\r\n\r\n \r\n uint income=0;\r\n uint eligible=0;\r\n uint eligiblecount=0;\r\n uint secondcount=0;\r\n \r\n for (uint _level = 1; _level <= 5; _level++) {\r\n \r\n if (_level==1) \r\n {\r\n income=10 * 1e18;\r\n eligible=l1paid;\r\n eligiblecount=l1count;\r\n }\r\n if (_level==2)\r\n {\r\n income=40 * 1e18;\r\n eligible=l2paid;\r\n eligiblecount=l2count;\r\n }\r\n if (_level==3) \r\n {\r\n income=160 * 1e18;\r\n eligible=l3paid;\r\n eligiblecount=l3count;\r\n }\r\n if (_level==4) \r\n {\r\n income=640 * 1e18;\r\n eligible=l4paid;\r\n eligiblecount=l4count;\r\n }\r\n if (_level==5)\r\n {\r\n income=2560 * 1e18;\r\n eligible=l5paid;\r\n eligiblecount=l5count;\r\n }\r\n secondcount=0;\r\n secondcount = autopoolSecondLevelCount[eligible][_level];\r\n if (secondcount<=5 && secondcount>0 && eligiblecount13) \r\n {\r\n token.transfer(address(eligibleaddress), (income ) );\r\n }\r\n else \r\n {\r\n TransferLaps( income) ;\r\n }\r\n if (_level==1) \r\n {\r\n l1count+=1;\r\n }\r\n if (_level==2)\r\n {\r\n l2count+=1;\r\n }\r\n if (_level==3) \r\n {\r\n l3count+=1;\r\n }\r\n if (_level==4) \r\n {\r\n l4count+=1;\r\n }\r\n if (_level==5)\r\n {\r\n l5count+=1;\r\n }\r\n }\r\n if (secondcount==9 )\r\n {\r\n if (_level==1) \r\n {\r\n l1paid+=1;\r\n l1count=0;\r\n }\r\n if (_level==2)\r\n {\r\n l2paid+=1;\r\n l2count=0;\r\n }\r\n if (_level==3) \r\n {\r\n l3paid+=1;\r\n l3count=0;\r\n }\r\n if (_level==4) \r\n {\r\n l4paid+=1;\r\n l4count=0;\r\n }\r\n if (_level==5)\r\n {\r\n l5paid+=1;\r\n l5count=0;\r\n } \r\n }\r\n\r\n} \r\n \r\n}\r\nfunction getldetails() \r\n public \r\n view \r\n returns (uint _founderids,uint _packagesr,uint _ids, uint _unpaidfounderincome,uint _topayfounderincome,\r\n uint _l1paid, uint _l2paid, uint _l3paid, uint _l4paid, uint _l5paid,\r\n uint _l1count, uint _l2count, uint _l3count, uint _l4count, uint _l5count\r\n ) \r\n{\r\n return (founderids,packagesr,ids,unpaidfounderincome,topayfounderincome,l1paid, l2paid, l3paid, l4paid, l5paid, l1count, l2count, l3count, l4count, l5count);\r\n}\r\n function distributeLevelIncome(uint _packageSr) internal returns (uint paid) {\r\n\r\n paid=0;\r\n address userAddr = incomes[_packageSr].userAddress; \r\n\r\n address currentRef = referal[userAddr];\r\n\r\n for (uint level = 1; level <= 20; level++) \r\n {\r\n uint currentUserId = userId[currentRef];\r\n\r\n if (currentRef == address(0) || currentUserId==0) {\r\n break;\r\n }\r\n \r\n uint requiredDirect = (level + 1) / 2;\r\n \r\n if (directCount[currentRef] >= requiredDirect) {\r\n \r\n users[currentUserId].totallevelincome += 1 * 10 ** 18;\r\n _recordIncome(\r\n currentUserId,\r\n currentRef,\r\n userAddr,\r\n 1 * 10 ** 18,\r\n level,\r\n 3, \r\n 1 \r\n ); \r\n if (currentUserId>13)\r\n {\r\n require(token.transfer(address(currentRef),1 * 10 ** 18), \"Transfer failed\");\r\n paid+=1 * 10 ** 18;\r\n }\r\n }\r\n \r\n currentRef = referal[currentRef];\r\n }\r\n return paid;\r\n}\r\n function distributdirectIncome(uint _packageSr) internal returns (uint paid) {\r\n\r\n paid=0;\r\n address userAddr = incomes[_packageSr].userAddress; \r\n\r\n address currentRef = referal[userAddr]; \r\n uint currentUserId = userId[currentRef];\r\n if (currentRef == address(0) || currentUserId==0) {\r\n return 0;\r\n }\r\n \r\n uint directincome =0 ;\r\n if (directCount[currentRef] % 3 == 0 )\r\n { \r\n directincome = 50 * 1e18;\r\n }\r\n else \r\n { \r\n directincome =20 *1e18 ;\r\n unpaidfounderincome+=15*1e18; \r\n paid+=15*1e18; \r\n }\r\n\r\n \r\n users[currentUserId].totaldirectincome += directincome;\r\n _recordIncome(\r\n currentUserId,\r\n currentRef,\r\n userAddr,\r\n directincome,\r\n 0,\r\n 1, \r\n 25 \r\n ); \r\n if (currentUserId>13)\r\n {\r\n require(token.transfer(address(currentRef),directincome), \"Transfer failed\");\r\n paid+=directincome;\r\n }\r\n \r\n \r\n \r\n return paid;\r\n}\r\nfunction getPlacement(uint _userId, uint _packageId) \r\n public \r\n view \r\n returns (uint parentId, uint position) \r\n{\r\n Placement memory p = placements[_userId][_packageId];\r\n\r\n require(p.userId != 0, \"Placement not found\");\r\n\r\n return (p.parentId, p.position);\r\n}\r\n function TransferLaps(uint lapsincome) internal { \r\n\r\n require(token.transfer(address(0x32478772b8358dd7C8348dBc04CD8C02dB03C959), (lapsincome / 5 ) ), \"Transfer failed\");\r\n require(token.transfer(address(0x3E09123AA88F2c0990CA45FB08b28225825F75Ef), (lapsincome / 5 ) ), \"Transfer failed\");\r\n require(token.transfer(address(0xe96036c273E0B001c333C5fCe44a3E2df1427703), (lapsincome / 5 ) ), \"Transfer failed\");\r\n require(token.transfer(address(0xfaCE5E3276d3502bf3A9eF3B12cA1114C2BE750F), (lapsincome / 5 ) ), \"Transfer failed\");\r\n require(token.transfer(address(0xd75D6068A31059602d2dA8c90a1689a10A2fb34D), (lapsincome / 5 ) ), \"Transfer failed\");\r\n }\r\n \r\n function _findParent(uint _userId, uint _packageId) \r\n internal \r\n view \r\n returns (uint parentId, uint position) \r\n{\r\n require(_userId > 0, \"Invalid user\");\r\n\r\n uint current = users[_userId].refferid;\r\n uint mainreffer=current;\r\n \r\n while (current > 0) {\r\n address addr = userIdtoAddress[current];\r\n\r\n if (hasPackage[addr][_packageId]) {\r\n break;\r\n }\r\n\r\n current = users[current].refferid;\r\n }\r\n\r\n // \ud83d\udd25 fallback to root\r\n if (current == 0) {\r\n current = 1;\r\n }\r\n\r\n address currentAddr = userIdtoAddress[current];\r\n uint[3] memory children = packageTree[currentAddr][_packageId];\r\n\r\n \r\n if (children[0] == 0) return (current, 0);\r\n if (children[1] == 0) return (current, 1);\r\n if (mainreffer==current && children[2] == 0) return (current, 2);\r\n \r\n\r\n \r\n uint[1000] memory queue;\r\n uint front = 0;\r\n uint back = 0;\r\n \r\n queue[back++] = children[0];\r\n queue[back++] = children[1];\r\n \r\n if (users[children[2]].refferid == current) {\r\n queue[back++] = children[2];\r\n }\r\n\r\n uint loop = 0;\r\n\r\n while (front < back) {\r\n\r\n loop++;\r\n if (loop > 1000) break;\r\n\r\n uint nodeId = queue[front++];\r\n address nodeAddr = userIdtoAddress[nodeId];\r\n\r\n uint[3] memory childNodes = packageTree[nodeAddr][_packageId];\r\n \r\n if (childNodes[0] == 0) return (nodeId, 0);\r\n if (childNodes[1] == 0) return (nodeId, 1);\r\n \r\n if (childNodes[0] != 0) queue[back++] = childNodes[0];\r\n if (childNodes[1] != 0) queue[back++] = childNodes[1];\r\n \r\n if (\r\n childNodes[2] != 0 &&\r\n users[childNodes[2]].refferid == nodeId\r\n ) {\r\n queue[back++] = childNodes[2];\r\n }\r\n\r\n if (back >= 999) break;\r\n }\r\n \r\n return (1, 0);\r\n}\r\n \r\n \r\nfunction getPositions(uint _userId, uint _packageId)\r\n public\r\n view\r\n returns (\r\n uint posaId,\r\n address posaAddr,\r\n uint posbId,\r\n address posbAddr,\r\n uint poscId,\r\n address poscAddr\r\n )\r\n{\r\n address userAddr = userIdtoAddress[_userId];\r\n\r\n uint[3] memory childs = packageTree[userAddr][_packageId];\r\n \r\n posaId = childs[0];\r\n posaAddr = posaId > 0 ? userIdtoAddress[posaId] : address(0);\r\n \r\n posbId = childs[1];\r\n posbAddr = posbId > 0 ? userIdtoAddress[posbId] : address(0);\r\n \r\n poscId = childs[2];\r\n poscAddr = poscId > 0 ? userIdtoAddress[poscId] : address(0);\r\n}\r\n \r\nfunction getmaxpackage(address useraddress) public view returns (uint maxPackage) {\r\n \r\n maxPackage = 0; \r\n\r\n for (uint i = 1; i <= packagesr; i++) {\r\n if (incomes[i].userAddress == useraddress && incomes[i].userPackageid > maxPackage) {\r\n maxPackage = incomes[i].userPackageid;\r\n }\r\n }\r\n\r\n }\r\n \r\n \r\nfunction getContractBalance() public view returns (uint256) {\r\n return token.balanceOf(address(this));\r\n }\r\n \r\n \r\n\r\nfunction buyPackage(uint packageId) public nonReentrant returns(bool) \r\n{\r\n\r\n require(isRegistered[msg.sender] == true, \"user not exist !\");\r\n require(packageId == getmaxpackage(msg.sender) + 1, \"Enter correct package !\"); \r\n require(IERC20(token).transferFrom(msg.sender, address(this), packages[packageId-1] * 1e18), \"Transfer Failed\");\r\n uint Psrno=userId[msg.sender]; \r\n \r\n (uint parentId, uint pos) = _findParent(Psrno, packageId) ; \r\n placements[Psrno][packageId] = Placement({\r\n userId: Psrno,\r\n parentId: parentId,\r\n packageId: packageId,\r\n position: pos\r\n }); \r\n address parentAddr = userIdtoAddress[parentId];\r\n \r\n packageTree[parentAddr][packageId][pos] = Psrno;\r\n uint parentPackageSr = userPackageSr[parentAddr][packageId]; \r\n if (pos == 0) {\r\n incomes[parentPackageSr].posa = Psrno;\r\n } else if (pos == 1) {\r\n incomes[parentPackageSr].posb = Psrno;\r\n } else {\r\n incomes[parentPackageSr].posc = Psrno;\r\n }\r\n hasPackage[msg.sender][packageId] = true; \r\n packagesr++;\r\n \r\n UserIncome memory newIncome;\r\n newIncome.packagesr = packagesr;\r\n newIncome.userAddress = msg.sender;\r\n newIncome.userPackageid = packageId; \r\n newIncome.packageamount = packages[packageId - 1] * 1e18;\r\n newIncome.posa = 0;\r\n newIncome.posb = 0;\r\n newIncome.posc = 0;\r\n newIncome.timeStamp = block.timestamp;\r\n \r\n incomes[packagesr] = newIncome;\r\n users[userId[msg.sender]].totalinvest += packages[packageId - 1] * 1e18;\r\n uint totalpaid =0;\r\n userPackageSr[msg.sender][packageId] = packagesr;\r\n totalpaid += distributeslotincome(packagesr);\r\n uint lapsincome = packages[packageId - 1] * 1e18 - totalpaid; \r\n TransferLaps (lapsincome) ;\r\n \r\n \r\n return true;\r\n} \r\n \r\n \r\n\r\n function updateoldslot(address oldaddress ,uint packageId) public onlyOwner nonReentrant returns(bool) {\r\n require(packagesr<=130, \"founder not exist !\");\r\n \r\n uint Psrno=userId[oldaddress]; \r\n \r\n (uint parentId, uint pos) = _findParent(Psrno, packageId) ; \r\n placements[Psrno][packageId] = Placement({\r\n userId: Psrno,\r\n parentId: parentId,\r\n packageId: packageId,\r\n position: pos\r\n }); \r\n address parentAddr = userIdtoAddress[parentId];\r\n \r\n packageTree[parentAddr][packageId][pos] = Psrno;\r\n uint parentPackageSr = userPackageSr[parentAddr][packageId]; \r\n if (pos == 0) {\r\n incomes[parentPackageSr].posa = Psrno;\r\n } else if (pos == 1) {\r\n incomes[parentPackageSr].posb = Psrno;\r\n } else {\r\n incomes[parentPackageSr].posc = Psrno;\r\n }\r\n hasPackage[oldaddress][packageId] = true; \r\n packagesr++;\r\n \r\n UserIncome memory newIncome;\r\n newIncome.packagesr = packagesr;\r\n newIncome.userAddress =oldaddress;\r\n newIncome.userPackageid = packageId; \r\n newIncome.packageamount = packages[packageId - 1] * 1e18;\r\n newIncome.posa = 0;\r\n newIncome.posb = 0;\r\n newIncome.posc = 0;\r\n newIncome.timeStamp = block.timestamp;\r\n \r\n incomes[packagesr] = newIncome;\r\n users[userId[oldaddress]].totalinvest += packages[packageId - 1] * 1e18;\r\n userPackageSr[oldaddress][packageId] = packagesr;\r\n \r\n return true;\r\n } \r\n \r\n \r\nfunction _recordIncome( uint _userid, address _userAddr, address _byUserAddr, uint _amount, uint _level, uint _incometype, uint _percent\r\n) internal {\r\n AllIncomesr++;\r\n AllIncomedata storage inc = AllIncome[AllIncomesr];\r\n inc.AllIncomesr = AllIncomesr;\r\n inc.userid = _userid;\r\n inc.userAddress = _userAddr;\r\n inc.ByuserAddress = _byUserAddr; \r\n inc.incomeamount = _amount; \r\n inc.bylevel = _level; \r\n inc.IncomeByType = _incometype; \r\n inc.incomeper = _percent; \r\n inc.timeStamp = block.timestamp; \r\n} \r\n \r\n\r\n function getRemainder(address orgrefferaddr) public view returns(uint) {\r\n \r\n return directCount[orgrefferaddr] % 3;\r\n }\r\n \r\n function distributeslotincome(uint _packageSr) internal returns (uint paid) {\r\n\r\n // STEP 1: Get user + package details\r\n address userAddr = incomes[_packageSr].userAddress;\r\n uint currentUser = userId[userAddr];\r\n uint packageId = incomes[_packageSr].userPackageid;\r\n uint amount = incomes[_packageSr].packageamount;\r\n paid=0;\r\n uint retop=0;\r\n uint loop = 0;\r\n\r\n while (true) {\r\n\r\n loop++;\r\n require(loop < 50, \"Loop overflow\");\r\n\r\n // STEP 2: Get placement\r\n Placement memory p = placements[currentUser][packageId];\r\n \r\n uint parentId = p.parentId;\r\n uint position = p.position;\r\n if (parentId == 0) break;\r\n \r\n uint orgreffer=0; \r\n if (retop==0) \r\n {\r\n orgreffer= users[userId[userAddr]].refferid; \r\n }\r\n else \r\n {\r\n orgreffer=users[currentUser].refferid;\r\n \r\n }\r\n // STEP 3: If position is A (0) or B (1)\r\n \r\n\r\n if (position == 0 || position == 1) {\r\n \r\n \r\n address orgrefferaddr= userIdtoAddress[orgreffer];\r\n \r\n uint income1 = (amount * 25) / 100;\r\n \r\n uint checkno=packageTree[orgrefferaddr][packageId][2];\r\n if (checkno==0 && retop>0)\r\n {\r\n income1=0;\r\n }\r\n if (orgreffer>13 && income1>0)\r\n {\r\n require(token.transfer(address(orgrefferaddr),income1), \"Transfer failed\");\r\n paid+=income1;\r\n }\r\n users[orgreffer].totaldirectincome += income1;\r\n AllIncomesr++;\r\n AllIncome[AllIncomesr] = AllIncomedata({ \r\n AllIncomesr: AllIncomesr,\r\n userid: orgreffer,\r\n userAddress: orgrefferaddr,\r\n ByuserAddress: userAddr,\r\n incomeamount: income1,\r\n bylevel: 1,\r\n IncomeByType: 1,\r\n incomeper: 25,\r\n timeStamp: block.timestamp\r\n });\r\n\r\n // STEP 4: Parent of parent\r\n Placement memory p2 = placements[parentId][packageId];\r\n uint parent2Id = p2.parentId;\r\n\r\n if (parent2Id > 0) {\r\n\r\n address parent2Addr = userIdtoAddress[parent2Id];\r\n \r\n uint income2 = (amount * 75) / 100;\r\n checkno=packageTree[parent2Addr][packageId][2];\r\n if (checkno==0 && retop>0)\r\n {\r\n income2=0;\r\n }\r\n if (parent2Id>13 && income2>0)\r\n { \r\n require(token.transfer(address(parent2Addr),income2), \"Transfer failed\");\r\n paid+=income2;\r\n }\r\n users[parent2Id].totalslotincome +=income2;\r\n AllIncomesr++;\r\n AllIncome[AllIncomesr] = AllIncomedata({\r\n AllIncomesr: AllIncomesr,\r\n userid: parent2Id,\r\n userAddress: parent2Addr,\r\n ByuserAddress: userAddr,\r\n incomeamount: income2,\r\n bylevel: 2,\r\n IncomeByType: 2,\r\n incomeper: 75,\r\n timeStamp: block.timestamp\r\n });\r\n }\r\n\r\n break; // STOP after distribution\r\n }\r\n\r\n // STEP 5: If position is C (2) \u2192 move up\r\n else if (position == 2) {\r\n \r\n users[orgreffer].retopupcount += 1; \r\n userPackageRetopup[orgreffer][packageId] += 1;\r\n retop+=1;\r\n currentUser = orgreffer;\r\n }\r\n\r\n // safety fallback\r\n else {\r\n break;\r\n }\r\n }\r\n return paid;\r\n}\r\n\r\nfunction getRetopupCount(uint _userId, uint _packageId) \r\n public \r\n view \r\n returns (uint) \r\n{\r\n return userPackageRetopup[_userId][_packageId];\r\n}\r\nfunction getAllIncomeByUser(uint IncomeByType,address _userAddress) public view returns (AllIncomedata[] memory) {\r\n uint count = 0;\r\n\r\n for (uint i = 1; i <= AllIncomesr; i++) {\r\n if (AllIncome[i].userAddress == _userAddress && AllIncome[i].IncomeByType == IncomeByType) {\r\n count++;\r\n }\r\n }\r\n\r\n AllIncomedata[] memory userData = new AllIncomedata[](count);\r\n uint index = 0;\r\n\r\n for (uint i = 1; i <= AllIncomesr; i++) {\r\n if (AllIncome[i].userAddress == _userAddress && AllIncome[i].IncomeByType == IncomeByType) {\r\n userData[index] = AllIncome[i];\r\n index++;\r\n }\r\n }\r\n\r\n return userData;\r\n}\r\n function getMembersByReffer(uint refferid) public view returns (User[] memory) {\r\n uint count = 0;\r\n\r\n // First pass: Count how many users have this parentId\r\n for (uint i = 1; i <= ids; i++) {\r\n if (users[i].refferid == refferid) {\r\n count++;\r\n }\r\n }\r\n\r\n // Create an array to hold the matching users\r\n User[] memory memberList = new User[](count);\r\n uint index = 0;\r\n\r\n // Second pass: Populate the array with matching users\r\n for (uint i = 1; i <= ids; i++) {\r\n if (users[i].refferid == refferid) {\r\n memberList[index] = users[i];\r\n index++;\r\n }\r\n }\r\n\r\n return memberList;\r\n}\r\n function getpackageDetailsByUser(address _userAddress) public view returns (\r\n UserIncome[] memory\r\n ) {\r\n uint count = 0;\r\n \r\n for (uint i = 1; i <= packagesr; i++) {\r\n if (incomes[i].userAddress == _userAddress) {\r\n count++;\r\n }\r\n }\r\n \r\n UserIncome[] memory packagedetailsData = new UserIncome[](count);\r\n uint index = 0;\r\n \r\n for (uint i = 1; i <= packagesr; i++) {\r\n if (incomes[i].userAddress == _userAddress) {\r\n packagedetailsData[index] = incomes[i];\r\n index++;\r\n }\r\n }\r\n\r\n return packagedetailsData;\r\n }\r\n \r\n \r\n function getFounderdata(address _userAddress) public view returns (foundermember[] memory) {\r\n uint count = 0;\r\n\r\n // First pass: Count how many users have this parentId\r\n for (uint i = 1; i <= founderids; i++) {\r\n if (foundermembers[i].founderaddress == _userAddress) {\r\n count++;\r\n }\r\n }\r\n\r\n // Create an array to hold the matching users\r\n foundermember[] memory memberList = new foundermember[](count);\r\n uint index = 0;\r\n\r\n // Second pass: Populate the array with matching users\r\n for (uint i = 1; i <= founderids; i++) {\r\n if (foundermembers[i].founderaddress == _userAddress) {\r\n memberList[index] = foundermembers[i];\r\n index++;\r\n }\r\n }\r\n\r\n return memberList;\r\n}\r\nfunction importUsers(uint fromId, uint toId)\r\n external\r\n onlyOwner\r\n{\r\n require(address(oldContract) != address(0), \"Old contract not set\");\r\n\r\n for(uint i = fromId; i <= toId; i++) {\r\n\r\n // SKIP ROOT USER\r\n if(i == 1) {\r\n continue;\r\n }\r\n\r\n (\r\n uint uid,\r\n address userAddress,\r\n uint refferid,\r\n uint totalinvest,\r\n uint totalslotincome,\r\n uint totaldirectincome,\r\n uint totallevelincome,\r\n uint totalautopoolincome,\r\n uint retopupcount,\r\n uint IsFoundermember,\r\n uint timestamp\r\n ) = oldContract.users(i);\r\n\r\n // SKIP EMPTY USERS\r\n if(userAddress == address(0)) {\r\n continue;\r\n }\r\n\r\n // PREVENT DUPLICATE\r\n if(isRegistered[userAddress]) {\r\n continue;\r\n }\r\n\r\n // SAVE USER\r\n users[uid] = User({\r\n userId: uid,\r\n userAddress: userAddress,\r\n refferid: refferid,\r\n totalinvest: totalinvest,\r\n totalslotincome: totalslotincome,\r\n totaldirectincome: totaldirectincome,\r\n totallevelincome: totallevelincome,\r\n totalautopoolincome: totalautopoolincome,\r\n retopupcount: retopupcount,\r\n IsFoundermember: IsFoundermember,\r\n timestamp: timestamp\r\n });\r\n\r\n // SAVE MAPPINGS\r\n userId[userAddress] = uid;\r\n userIdtoAddress[uid] = userAddress;\r\n\r\n referal[userAddress] =\r\n oldContract.referal(userAddress);\r\n\r\n isRegistered[userAddress] = true;\r\n\r\n // IMPORTANT FIX\r\n directCount[userAddress] =\r\n oldContract.directCount(userAddress);\r\n\r\n // IMPORT LEVEL\r\n userLevel[uid] =\r\n oldContract.userLevel(uid);\r\n\r\n // IMPORTANT\r\n if(uid > ids) {\r\n ids = uid;\r\n }\r\n }\r\n}\r\n\r\nfunction importPackages(uint fromSr, uint toSr)\r\n external\r\n onlyOwner\r\n{\r\n\r\n for(uint i = fromSr; i <= toSr; i++) {\r\n\r\n (\r\n uint packagesr_,\r\n address userAddress,\r\n uint userPackageid,\r\n uint packageamount,\r\n uint posa,\r\n uint posb,\r\n uint posc,\r\n uint timeStamp\r\n ) = oldContract.incomes(i);\r\n\r\n incomes[packagesr_] = UserIncome({\r\n packagesr: packagesr_,\r\n userAddress: userAddress,\r\n userPackageid: userPackageid,\r\n packageamount: packageamount,\r\n posa: posa,\r\n posb: posb,\r\n posc: posc,\r\n timeStamp: timeStamp\r\n });\r\n\r\n hasPackage[userAddress][userPackageid] =\r\n true;\r\n\r\n userPackageSr[userAddress][userPackageid] =\r\n packagesr_;\r\n\r\n uint uid = userId[userAddress];\r\n\r\n (\r\n uint puid,\r\n uint parentId,\r\n uint packageId,\r\n uint position\r\n ) = oldContract.placements(uid, userPackageid);\r\n\r\n placements[uid][userPackageid] = Placement({\r\n userId: puid,\r\n parentId: parentId,\r\n packageId: packageId,\r\n position: position\r\n });\r\n\r\n address parentAddr =\r\n userIdtoAddress[parentId];\r\n\r\n packageTree[parentAddr][packageId][position]\r\n = uid;\r\n }\r\n}\r\n function importAutopool(uint fromId, uint toId)\r\n external\r\n onlyOwner\r\n{\r\n\r\n for(uint uid = fromId; uid <= toId; uid++) {\r\n\r\n for(uint lvl = 1; lvl <= 5; lvl++) {\r\n\r\n userInLevel[uid][lvl] =\r\n oldContract.userInLevel(uid, lvl);\r\n\r\n autopoolDirectCount[uid][lvl] =\r\n oldContract.autopoolDirectCount(uid, lvl);\r\n\r\n autopoolSecondLevelCount[uid][lvl] =\r\n oldContract.autopoolSecondLevelCount(uid, lvl);\r\n\r\n for(uint pos = 0; pos < 3; pos++) {\r\n\r\n autopoolTree[lvl][uid][pos] =\r\n oldContract.autopoolTree(\r\n lvl,\r\n uid,\r\n pos\r\n );\r\n }\r\n }\r\n }\r\n}\r\nfunction importAutopoolQueue(\r\n uint level,\r\n uint fromIndex,\r\n uint toIndex\r\n)\r\nexternal\r\nonlyOwner\r\n{\r\n for(uint i = fromIndex; i <= toIndex; i++) {\r\n\r\n autopoolQueue[level].push(\r\n oldContract.autopoolQueue(level, i)\r\n );\r\n }\r\n\r\n autopoolIndex[level] =\r\n oldContract.autopoolIndex(level);\r\n} \r\n}" + }, + "target": "astorworldupdate.sol", + "version": "0.8.34" +}